diff --git a/Front-End/next.config.mjs b/Front-End/next.config.mjs index 7653014..2a18797 100644 --- a/Front-End/next.config.mjs +++ b/Front-End/next.config.mjs @@ -5,31 +5,12 @@ const withNextIntl = createNextIntlPlugin(); /** @type {import('next').NextConfig} */ const nextConfig = { - output: 'standalone', - webpack: (config, { isServer }) => { - // Configuration pour améliorer le hot reload dans Docker - config.watchOptions = { - poll: 1000, - aggregateTimeout: 300, - } - return config - }, experimental: { instrumentationHook: true, }, env: { NEXT_PUBLIC_APP_VERSION: pkg.version, }, - images: { - remotePatterns: [ - { - protocol: 'https', - hostname: 'i.pravatar.cc', - port: '', - pathname: '/**', - }, - ], - }, }; export default withNextIntl(nextConfig); \ No newline at end of file diff --git a/Front-End/src/app/[locale]/admin/layout.js b/Front-End/src/app/[locale]/admin/layout.js index 5ab5dcf..3f86c1c 100644 --- a/Front-End/src/app/[locale]/admin/layout.js +++ b/Front-End/src/app/[locale]/admin/layout.js @@ -26,7 +26,6 @@ import { import { disconnect } from '@/app/lib/authAction'; import { fetchEstablishment } from '@/app/lib/schoolAction'; -import Image from 'next/image'; export default function Layout({ children, @@ -76,13 +75,13 @@ export default function Layout({ <> {!isLoading && (
- +
{/* Header - h-16 = 64px */}
{headerTitle}
} + buttonContent={Profile} items={dropdownItems} buttonClassName="" menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg" diff --git a/Front-End/src/app/[locale]/admin/page.js b/Front-End/src/app/[locale]/admin/page.js index 767be6e..c48ed4b 100644 --- a/Front-End/src/app/[locale]/admin/page.js +++ b/Front-End/src/app/[locale]/admin/page.js @@ -154,8 +154,8 @@ export default function DashboardPage() {
{classes.map((classe) => ( -
- +
+
))}
diff --git a/Front-End/src/app/[locale]/admin/subscriptions/page.js b/Front-End/src/app/[locale]/admin/subscriptions/page.js index a7e0094..9c09fca 100644 --- a/Front-End/src/app/[locale]/admin/subscriptions/page.js +++ b/Front-End/src/app/[locale]/admin/subscriptions/page.js @@ -239,7 +239,7 @@ const registerFormArchivedDataHandler = (data) => { fetchDataAndSetState(); - }, [reloadFetch, itemsPerPage, currentPage,activeTab, searchTerm]); + }, [reloadFetch, currentPage]); useEffect(() => { const fetchDataAndSetState = () => { @@ -271,7 +271,7 @@ const timeoutId = setTimeout(() => { fetchDataAndSetState(); }, 500); // Debounce la recherche return () => clearTimeout(timeoutId); -}, [currentPage,itemsPerPage,searchTerm]); +}, [searchTerm]); /** * UseEffect to update page count of tab @@ -284,7 +284,7 @@ useEffect(()=>{ } else if (activeTab === 'archived') { setTotalPages(Math.ceil(totalArchives / itemsPerPage)); } -},[currentPage,activeTab,itemsPerPage,totalPending,totalSubscribed,totalArchives]); +},[currentPage]); /** * Archives a registration form after user confirmation. * diff --git a/Front-End/src/app/[locale]/parents/layout.js b/Front-End/src/app/[locale]/parents/layout.js index ed69eac..b7f2f1a 100644 --- a/Front-End/src/app/[locale]/parents/layout.js +++ b/Front-End/src/app/[locale]/parents/layout.js @@ -35,7 +35,7 @@ export default function Layout({ .finally(() => { setIsLoading(false); }); - }, [setUserId, userId]); + }, [userId]); if (isLoading) { return
Loading...
; diff --git a/Front-End/src/app/[locale]/parents/messagerie/page.js b/Front-End/src/app/[locale]/parents/messagerie/page.js index 9f8196f..34bfc00 100644 --- a/Front-End/src/app/[locale]/parents/messagerie/page.js +++ b/Front-End/src/app/[locale]/parents/messagerie/page.js @@ -1,7 +1,6 @@ 'use client' import React, { useState, useRef, useEffect } from 'react'; import { SendHorizontal } from 'lucide-react'; -import Image from 'next/image'; const contacts = [ { id: 1, name: 'Facturation', profilePic: 'https://i.pravatar.cc/32' }, @@ -62,7 +61,7 @@ export default function MessageriePage() { className={`p-2 cursor-pointer ${selectedContact?.id === contact.id ? 'bg-gray-200' : ''}`} onClick={() => setSelectedContact(contact)} > - {`${contact.name}'s + {`${contact.name}'s {contact.name}
))} @@ -76,7 +75,7 @@ export default function MessageriePage() { style={{ borderRadius: message.isResponse ? '20px 20px 0 20px' : '20px 20px 20px 0', minWidth: '25%' }} >
- {`${selectedContact.name}'s + {`${selectedContact.name}'s {selectedContact.name} {new Date(message.date).toLocaleTimeString()}
diff --git a/Front-End/src/app/[locale]/users/password/reset/page.js b/Front-End/src/app/[locale]/users/password/reset/page.js index 3e19b8c..cae7a16 100644 --- a/Front-End/src/app/[locale]/users/password/reset/page.js +++ b/Front-End/src/app/[locale]/users/password/reset/page.js @@ -52,7 +52,7 @@ export default function Page() { console.error('Error fetching data:', error); }); } - }, [uuid]); + }, []); function validate(formData) { if (useFakeData) { diff --git a/Front-End/src/app/_error/page.js b/Front-End/src/app/_error/page.js deleted file mode 100644 index f5fb071..0000000 --- a/Front-End/src/app/_error/page.js +++ /dev/null @@ -1,17 +0,0 @@ -'use client'; - -import Link from 'next/link'; -import Logo from '@/components/Logo'; - -export default function Error() { - return ( -
-
- -

Une erreur est survenue

-

Désolé, une erreur s'est produite.

- Retour Accueil -
-
- ); -} \ No newline at end of file diff --git a/Front-End/src/app/layout.js b/Front-End/src/app/layout.js index 2ab20a5..d290675 100644 --- a/Front-End/src/app/layout.js +++ b/Front-End/src/app/layout.js @@ -1,5 +1,6 @@ import React from 'react'; import { NextIntlClientProvider } from 'next-intl'; + import {getMessages} from 'next-intl/server'; import "@/css/tailwind.css"; @@ -21,13 +22,12 @@ export const metadata = { }; export default async function RootLayout({ children, params: { locale } }) { - - const messages = await getMessages(locale); + const messages = await getMessages(); return ( - + {children} diff --git a/Front-End/src/app/_not-found/page.js b/Front-End/src/app/not-found.js similarity index 71% rename from Front-End/src/app/_not-found/page.js rename to Front-End/src/app/not-found.js index c06ef63..fc0e9cd 100644 --- a/Front-End/src/app/_not-found/page.js +++ b/Front-End/src/app/not-found.js @@ -1,17 +1,15 @@ -'use client'; - -import Link from 'next/link'; -import Logo from '@/components/Logo'; +import Link from 'next/link' +import Logo from '../components/Logo' export default function NotFound() { return (
-
+

404 | Page non trouvée

-

La ressource que vous souhaitez consulter n'existe pas ou plus.

+

La ressource que vous souhaitez consulter n'existe pas ou plus.

Retour Accueil
- ); + ) } \ No newline at end of file diff --git a/Front-End/src/components/Calendar.js b/Front-End/src/components/Calendar.js index 0c9551a..6c87781 100644 --- a/Front-End/src/components/Calendar.js +++ b/Front-End/src/components/Calendar.js @@ -75,7 +75,7 @@ const Calendar = ({ onDateClick, onEventClick }) => { onClick={() => setCurrentDate(new Date())} className="px-3 py-1.5 text-sm font-medium text-gray-700 hover:text-gray-900 bg-gray-100 hover:bg-gray-200 rounded-md transition-colors" > - Aujourd'hui + Aujourd'hui
@@ -408,7 +408,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r ) : (

Attention! - Aucun frais d'inscription n'a été créé. + Aucun frais d'inscription n'a été créé.

)}
@@ -440,7 +440,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r ) : (

Information - Aucune réduction n'a été créée sur les frais de scolarité. + Aucune réduction n'a été créée sur les frais de scolarité.

)}
@@ -463,7 +463,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r ) : (

Attention! - Aucun frais de scolarité n'a été créé. + Aucun frais de scolarité n'a été créé.

)} @@ -501,7 +501,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r ) : (

Attention! - Aucun groupe de documents n'a été créé. + Aucun groupe de documents n'a été créé.

)} diff --git a/Front-End/src/components/Inscription/InscriptionFormShared.js b/Front-End/src/components/Inscription/InscriptionFormShared.js index 1f458fd..221e9b6 100644 --- a/Front-End/src/components/Inscription/InscriptionFormShared.js +++ b/Front-End/src/components/Inscription/InscriptionFormShared.js @@ -249,7 +249,7 @@ export default function InscriptionFormShared({ {/* Section Élève */}
-

Informations de l'élève

+

Informations de l'élève

{ - const updateDefaultDay = () => { - const currentDates = dates[selectedFrequency]; - if (currentDates && currentDates.length > 0) { - const days = currentDates.map(date => new Date(date).getDate()); - const allSameDay = days.every(day => day === days[0]); - if (allSameDay) { - setDefaultDay(days[0]); - } else { - setDefaultDay('-'); - setIsDefaultDayModified(false); - } - } else { - setDefaultDay('-'); - } - }; - updateDefaultDay(); }, [dates, selectedFrequency]); + const updateDefaultDay = () => { + const currentDates = dates[selectedFrequency]; + if (currentDates && currentDates.length > 0) { + const days = currentDates.map(date => new Date(date).getDate()); + const allSameDay = days.every(day => day === days[0]); + if (allSameDay) { + setDefaultDay(days[0]); + } else { + setDefaultDay('-'); + setIsDefaultDayModified(false); + } + } else { + setDefaultDay('-'); + } + }; + const handleActivationChange = (value) => { const selectedPlan = paymentPlans.find(plan => plan.frequency === paymentPlansOptions.find(p => p.id === value)?.frequency); if (!selectedPlan) return; @@ -79,7 +79,7 @@ const PaymentPlanSelector = ({ paymentPlans, setPaymentPlans, handleEdit, type } handleEdit(selectedPlan.id, updatedData) .then(() => { - setPaymentPlans(prevPlans => prevPlans.map(plan => + setPaymentPlans(prevPlans => prevPlans.map(plan => plan.id === selectedPlan.id ? { ...plan, is_active: updatedData.is_active } : plan )); setActiveFrequencies(prevFrequencies => { @@ -172,7 +172,7 @@ const PaymentPlanSelector = ({ paymentPlans, setPaymentPlans, handleEdit, type } }; handleEdit(selectedPlan.id, updatedData) - .then(() => { + .then(() => { setPopupMessage(`Mise à jour des dates d'échéances effectuée avec succès`); setPopupVisible(true); setIsDefaultDayModified(false); diff --git a/Front-End/src/components/RegistrationFileGroupList.js b/Front-End/src/components/RegistrationFileGroupList.js index c5e9e4f..cda824d 100644 --- a/Front-End/src/components/RegistrationFileGroupList.js +++ b/Front-End/src/components/RegistrationFileGroupList.js @@ -10,7 +10,7 @@ export default function RegistrationFileGroupList() { return (
-

Groupes de fichiers d'inscription

+

Groupes de fichiers d'inscription

    {groups.map(group => (
  • {group.name}
  • diff --git a/Front-End/src/components/Structure/Configuration/ClassesSection.js b/Front-End/src/components/Structure/Configuration/ClassesSection.js index 1b67be1..7380b36 100644 --- a/Front-End/src/components/Structure/Configuration/ClassesSection.js +++ b/Front-End/src/components/Structure/Configuration/ClassesSection.js @@ -7,8 +7,7 @@ import SelectChoice from '@/components/SelectChoice'; import TeacherItem from '@/components/Structure/Configuration/TeacherItem'; import MultiSelect from '@/components/MultiSelect'; import LevelLabel from '@/components/CustomLabels/LevelLabel'; -import { DndProvider, useDrop } from 'react-dnd'; -import { HTML5Backend } from 'react-dnd-html5-backend'; +import { DndProvider, HTML5Backend, useDrop } from 'react-dnd'; import { ESTABLISHMENT_ID } from '@/utils/Url'; const ItemTypes = { @@ -18,13 +17,16 @@ const ItemTypes = { const TeachersDropZone = ({ classe, handleTeachersChange, teachers, isEditing }) => { const [localTeachers, setLocalTeachers] = useState(classe.teachers_details || []); + useEffect(() => { + }, [teachers]); + useEffect(() => { setLocalTeachers(classe.teachers_details || []); }, [classe.teachers_details]); useEffect(() => { handleTeachersChange(localTeachers.map(teacher => teacher.id)); - }, [handleTeachersChange, localTeachers]); + }, [localTeachers]); const [{ isOver, canDrop }, drop] = useDrop({ accept: ItemTypes.TEACHER, @@ -103,20 +105,20 @@ const ClassesSection = ({ classes, setClasses, teachers, handleCreate, handleEdi { id: 3, name: 'MS', age: 4 }, { id: 4, name: 'GS', age: 5 }, ]; - + const niveauxSecondCycle = [ { id: 5, name: 'CP', age: 6 }, { id: 6, name: 'CE1', age: 7 }, { id: 7, name: 'CE2', age: 8 }, ]; - + const niveauxTroisiemeCycle = [ { id: 8, name: 'CM1', age: 9 }, { id: 9, name: 'CM2', age: 10 }, ]; - + const allNiveaux = [...niveauxPremierCycle, ...niveauxSecondCycle, ...niveauxTroisiemeCycle]; - + const getNiveauxLabels = (levels) => { return levels.map(niveauId => { const niveau = allNiveaux.find(n => n.id === niveauId); @@ -129,10 +131,10 @@ const ClassesSection = ({ classes, setClasses, teachers, handleCreate, handleEdi const currentDate = new Date(); const currentYear = currentDate.getFullYear(); const currentMonth = currentDate.getMonth() + 1; // Les mois sont indexés à partir de 0 - + // Si nous sommes avant septembre, l'année scolaire en cours a commencé l'année précédente const startYear = currentMonth >= 9 ? currentYear : currentYear - 1; - + const choices = []; for (let i = 0; i < 3; i++) { const year = startYear + i; @@ -230,7 +232,7 @@ const ClassesSection = ({ classes, setClasses, teachers, handleCreate, handleEdi const handleMultiSelectChange = (selectedOptions) => { const levels = selectedOptions.map(option => option.id); - + if (editingClass) { setFormData((prevData) => ({ ...prevData, @@ -346,7 +348,7 @@ const ClassesSection = ({ classes, setClasses, teachers, handleCreate, handleEdi const levelLabels = Array.isArray(classe.levels) ? getNiveauxLabels(classe.levels) : []; return (
    - {levelLabels.length > 0 + {levelLabels.length > 0 ? levelLabels.map((label, index) => ( )) diff --git a/Front-End/src/components/Structure/Configuration/TeachersSection.js b/Front-End/src/components/Structure/Configuration/TeachersSection.js index f5ca14b..01d979c 100644 --- a/Front-End/src/components/Structure/Configuration/TeachersSection.js +++ b/Front-End/src/components/Structure/Configuration/TeachersSection.js @@ -27,7 +27,7 @@ const SpecialitiesDropZone = ({ teacher, handleSpecialitiesChange, specialities, useEffect(() => { handleSpecialitiesChange(localSpecialities.map(speciality => speciality.id)); - }, [localSpecialities,handleSpecialitiesChange]); + }, [localSpecialities]); const [{ isOver, canDrop }, drop] = useDrop({ accept: ItemTypes.SPECIALITY, diff --git a/Front-End/src/components/Structure/Planning/PlanningClassView.js b/Front-End/src/components/Structure/Planning/PlanningClassView.js index 176a1c4..63ef1b0 100644 --- a/Front-End/src/components/Structure/Planning/PlanningClassView.js +++ b/Front-End/src/components/Structure/Planning/PlanningClassView.js @@ -21,7 +21,7 @@ const PlanningClassView = ({ schedule, onDrop, selectedLevel, handleUpdatePlanni if (schedule?.emploiDuTemps) { setCurrentPeriod(determineInitialPeriod(schedule.emploiDuTemps)); } - }, [schedule, determineInitialPeriod]); + }, [schedule]); if (!schedule || !schedule.emploiDuTemps) { return ( @@ -62,7 +62,7 @@ const PlanningClassView = ({ schedule, onDrop, selectedLevel, handleUpdatePlanni const [eventHour, eventMinute] = event.heure.split(':').map(Number); const eventStartTime = eventHour + eventMinute / 60; const eventEndTime = eventStartTime + parseFloat(event.duree); - + // Filtrer en fonction du selectedLevel return schedule.niveau === level && startTime >= eventStartTime && startTime < eventEndTime; }) || []; @@ -78,10 +78,10 @@ const PlanningClassView = ({ schedule, onDrop, selectedLevel, handleUpdatePlanni const renderTimeSlots = () => { const timeSlots = []; - + for (let hour = parseInt(formData.time_range[0], 10); hour <= parseInt(formData.time_range[1], 10); hour++) { const hourString = hour.toString().padStart(2, '0'); - + timeSlots.push(
    @@ -160,7 +160,7 @@ const PlanningClassView = ({ schedule, onDrop, selectedLevel, handleUpdatePlanni
    ))}
    - + {/* Contenu du planning */}
    diff --git a/Front-End/src/components/Structure/Planning/ScheduleManagement.js b/Front-End/src/components/Structure/Planning/ScheduleManagement.js index a9d363e..a3a3283 100644 --- a/Front-End/src/components/Structure/Planning/ScheduleManagement.js +++ b/Front-End/src/components/Structure/Planning/ScheduleManagement.js @@ -22,7 +22,7 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => { const [schedule, setSchedule] = useState(null); const { getNiveauxTabs } = useClasses(); - const niveauxLabels = useMemo(() => Array.isArray(selectedClass?.levels) ? getNiveauxTabs(selectedClass.levels) : [], [selectedClass, getNiveauxTabs]); + const niveauxLabels = Array.isArray(selectedClass?.levels) ? getNiveauxTabs(selectedClass.levels) : []; const [isModalOpen, setIsModalOpen] = useState(false); const handleOpenModal = () => setIsModalOpen(true); @@ -38,7 +38,7 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => { const currentPlanning = selectedClass.plannings_read?.find(planning => planning.niveau === niveau); setSchedule(currentPlanning ? currentPlanning.planning : {}); } - }, [selectedClass, niveauxLabels, selectedLevel]); + }, [selectedClass, niveauxLabels]); useEffect(() => { if (selectedClass && selectedLevel) { diff --git a/Front-End/src/components/Structure/Tarification/FeesManagement.js b/Front-End/src/components/Structure/Tarification/FeesManagement.js index 685ec72..f7f6f7a 100644 --- a/Front-End/src/components/Structure/Tarification/FeesManagement.js +++ b/Front-End/src/components/Structure/Tarification/FeesManagement.js @@ -6,14 +6,14 @@ import PaymentModeSelector from '@/components/PaymentModeSelector'; import { BE_SCHOOL_FEES_URL, BE_SCHOOL_DISCOUNTS_URL, BE_SCHOOL_PAYMENT_PLANS_URL, BE_SCHOOL_PAYMENT_MODES_URL } from '@/utils/Url'; import { set } from 'lodash'; -const FeesManagement = ({ registrationDiscounts, - setRegistrationDiscounts, - tuitionDiscounts, - setTuitionDiscounts, - registrationFees, - setRegistrationFees, - tuitionFees, - setTuitionFees, +const FeesManagement = ({ registrationDiscounts, + setRegistrationDiscounts, + tuitionDiscounts, + setTuitionDiscounts, + registrationFees, + setRegistrationFees, + tuitionFees, + setTuitionFees, registrationPaymentPlans, setRegistrationPaymentPlans, tuitionPaymentPlans, @@ -22,20 +22,20 @@ const FeesManagement = ({ registrationDiscounts, setRegistrationPaymentModes, tuitionPaymentModes, setTuitionPaymentModes, - handleCreate, - handleEdit, + handleCreate, + handleEdit, handleDelete }) => { const handleDiscountDelete = (id, type) => { if (type === 0) { - setRegistrationFees(prevFees => + setRegistrationFees(prevFees => prevFees.map(fee => ({ ...fee, discounts: fee.discounts.filter(discountId => discountId !== id) })) ); } else { - setTuitionFees(prevFees => + setTuitionFees(prevFees => prevFees.map(fee => ({ ...fee, discounts: fee.discounts.filter(discountId => discountId !== id) @@ -47,7 +47,7 @@ const FeesManagement = ({ registrationDiscounts, return (
    -

    Frais d'inscription

    +

    Frais d'inscription

    { .catch(error => { console.error('Error fetching CSRF token:', error); }); - }, [token]); + }, []); return token; };