pages/Courses.jsx

import {useTranslation} from 'react-i18next';
import {Card} from "../components/ui/Card";
import {CardContent} from "../components/ui/CardContent";
import {Disclosure} from '@headlessui/react';
import {ChevronDown} from 'lucide-react';
import {useState} from "react";
import PageSection from "../components/ui/PageSection";
import {ExpandableText} from "../components/ui/ExpandableText";
import {AnimatePresence, motion} from "framer-motion";

/**
 * Courses component.
 *
 * Displays a paginated list of programming courses, each with title, description,
 * duration, and technologies used.
 *
 * Features:
 * - Uses i18next for translations of titles, descriptions, and UI texts.
 * - Shows 6 courses per page with next/previous pagination buttons.
 * - Each course is displayed inside a Card with expandable technologies section.
 *
 * @component
 * @module pages/Courses
 * @returns {JSX.Element} The rendered Courses page section.
 */
export default function Courses() {
    const {t} = useTranslation();
    const coursesPerPage = 3;
    const [page, setPage] = useState(1);

    const courses = [
        {
            nameKey: "courses_page.git.title",
            descKey: "courses_page.git.description",
            durationKey: "courses_page.git.duration",
            tech: "Git",
            link: "https://www.udemy.com/course/corso-git/"
        },
        {
            nameKey: "courses_page.typescript.title",
            descKey: "courses_page.typescript.description",
            durationKey: "courses_page.typescript.duration",
            tech: "Typescript, data types, module, OOP ...",
            link: "https://www.udemy.com/course/typescript-da-zero/"
        },
        {
            nameKey: "courses_page.jQuery.title",
            descKey: "courses_page.jQuery.description",
            durationKey: "courses_page.jQuery.duration",
            tech: "jQuery, Selectors, Classes management, Traversing, Manipulating CSS, Bind, Events ...",
            link: "https://www.udemy.com/course/corso-jquery/"
        },
        {
            nameKey: "courses_page.php.title",
            descKey: "courses_page.php.description",
            durationKey: "courses_page.php.duration",
            tech: "Php, data types, Control flow statements, iterations, Regular expressions, Arrays, OOP, HTTP calls, File system ...",
            link: "https://www.udemy.com/course/corso-di-programmazione-php/"
        },
        {
            nameKey: "courses_page.cpp.title",
            descKey: "courses_page.cpp.description",
            durationKey: "courses_page.cpp.duration",
            tech: "C++, data types, control flow statements, iterations, I/O system, arrays and structs, OOP, lambda expressions ...",
            link: "https://www.udemy.com/course/corso-di-programmazione-c-plus-plus/"
        },
        {
            nameKey: "courses_page.html5.title",
            descKey: "courses_page.html5.description",
            durationKey: "courses_page.html5.duration",
            tech: "HTML5, APIs (WebStorage, Web Workers, Drag & Drop ...), Canvas & Multimedia, Header, Footer, Aside ...",
            link: "https://www.udemy.com/course/corso-html5/"
        },
        {
            nameKey: "courses_page.angularJS.title",
            descKey: "courses_page.angularJS.description",
            durationKey: "courses_page.angularJS.duration",
            tech: "AngularJS, scope (the hierarchy), services ($http), control flow statement, directives (bind, ng-class, ng-repeat...), filters, custom directives ...",
            link: "https://www.udemy.com/course/corso-angularjs/"
        },
        {
            nameKey: "courses_page.java.title",
            descKey: "courses_page.java.description",
            durationKey: "courses_page.java.duration",
            tech: "Java, Control flow statements, iterations, arrays, OOP, File management, Lambda expressions, MySQL, MongoDB  ...",
            link: "https://www.udemy.com/course/corso-di-programmazione-java/"
        },
        {
            nameKey: "courses_page.javascript.title",
            descKey: "courses_page.javascript.description",
            durationKey: "courses_page.javascript.duration",
            tech: "Javascript, control flow statements, iterations, arrays, DOM, Design patterns, Arrow function ...",
            link: "https://www.udemy.com/course/corso-di-programmazione-javascript/"
        },
        {
            nameKey: "courses_page.c.title",
            descKey: "courses_page.c.description",
            durationKey: "courses_page.c.duration",
            tech: "C, data types, control flow statements, iterations, arrays, structs ...",
            link: "https://www.udemy.com/course/corso-di-programmazione-c/"
        },
        {
            nameKey: "courses_page.assembler.title",
            descKey: "courses_page.assembler.description",
            durationKey: "courses_page.assembler.duration",
            tech: "AssemblerX86, data types, control flow statement, iterations, arrays ...",
            link: "https://www.udemy.com/course/corso-di-programmazione-assembler-8086/"
        },
        {
            nameKey: "courses_page.sql.title",
            descKey: "courses_page.sql.description",
            durationKey: "courses_page.sql.duration",
            tech: "SQL, C, E/R, DB design ...",
            link: "https://www.udemy.com/course/corso-sulle-basi-di-dati-dallo-schema-er-allsql/"
        }
    ];

    const totalPages = Math.ceil(courses.length / coursesPerPage);

    const displayedCourses = courses.slice(
        (page - 1) * coursesPerPage,
        page * coursesPerPage
    );

    return (
        <PageSection title={t("courses_page.title")}>

            <AnimatePresence mode="wait">
                <motion.div
                    key={`page-${page}`}
                    initial={{opacity: 0, y: 40}}
                    animate={{opacity: 1, y: 0}}
                    exit={{opacity: 0, y: -40}}
                    transition={{duration: 0.4}}
                    className="flex flex-wrap gap-6"
                >
                    {displayedCourses.map((course, idx) => (
                        <Card
                            key={idx}
                            className="bg-white border border-gray-200 text-gray-900 dark:bg-gray-900 dark:border-gray-700 dark:text-white transition-colors duration-300"
                        >
                            <CardContent>
                                <h3 className="text-lg font-semibold">
                                    <a
                                        href={course.link}
                                        target="_blank"
                                        rel="noopener noreferrer"
                                        className="hover:underline"
                                    >
                                        {t(course.nameKey)}
                                    </a>
                                </h3>

                                <ExpandableText
                                    value={t(course.descKey)}
                                    maxLines={3}
                                    className="mb-2 mt-2 cursor-default"
                                />

                                <p className="text-sm text-gray-500 dark:text-gray-400 font-mono mb-2">
                                    {t("courses_page.duration")}: {t(course.durationKey)}
                                </p>

                                <Disclosure>
                                    {({open}) => (
                                        <>
                                            <Disclosure.Button
                                                className="flex items-center text-sm text-blue-600 dark:text-blue-400 hover:underline focus:outline-none mt-2"
                                            >
                                                <span>{t("show_technologies")}</span>
                                                <ChevronDown
                                                    className={`ml-1 w-4 h-4 transition-transform ${open ? "rotate-180" : ""}`}
                                                />
                                            </Disclosure.Button>
                                            <Disclosure.Panel className="mt-2 text-sm text-gray-700 dark:text-gray-300">
                                                {course.tech}
                                            </Disclosure.Panel>
                                        </>
                                    )}
                                </Disclosure>
                            </CardContent>
                        </Card>
                    ))}
                </motion.div>
            </AnimatePresence>

            {/* Pagination Controls */}
            {totalPages > 1 && (
                <div className="flex justify-center mt-8 space-x-4">
                    <button
                        onClick={() => setPage(p => Math.max(p - 1, 1))}
                        disabled={page === 1}
                        className="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium
                               text-gray-800 dark:text-gray-200 bg-white dark:bg-gray-900
                               hover:bg-gray-100 dark:hover:bg-gray-800 disabled:opacity-50 transition"
                    >
                        ← {t("previous")}
                    </button>

                    <span data-testid="pagination-info" className="px-4 py-2 text-sm text-gray-600 dark:text-gray-300">
                        {page} / {totalPages}
                    </span>

                    <button
                        onClick={() => setPage(p => Math.min(p + 1, totalPages))}
                        disabled={page === totalPages}
                        className="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium
                               text-gray-800 dark:text-gray-200 bg-white dark:bg-gray-900
                               hover:bg-gray-100 dark:hover:bg-gray-800 disabled:opacity-50 transition"
                    >
                        {t("next")} →
                    </button>
                </div>
            )}
        </PageSection>
    );
}