diff --git a/Back-End/Subscriptions/views/student_views.py b/Back-End/Subscriptions/views/student_views.py index 70c590d..3f11974 100644 --- a/Back-End/Subscriptions/views/student_views.py +++ b/Back-End/Subscriptions/views/student_views.py @@ -102,7 +102,8 @@ class ChildrenListView(APIView): RegistrationForm.RegistrationFormStatus.RF_SENT, RegistrationForm.RegistrationFormStatus.RF_UNDER_REVIEW, RegistrationForm.RegistrationFormStatus.RF_SEPA_SENT, - RegistrationForm.RegistrationFormStatus.RF_SEPA_TO_SEND + RegistrationForm.RegistrationFormStatus.RF_SEPA_TO_SEND, + RegistrationForm.RegistrationFormStatus.RF_VALIDATED ] ).distinct() students_serializer = RegistrationFormByParentSerializer(students, many=True) diff --git a/Front-End/src/app/[locale]/admin/layout.js b/Front-End/src/app/[locale]/admin/layout.js index 1232a70..2bb4b5b 100644 --- a/Front-End/src/app/[locale]/admin/layout.js +++ b/Front-End/src/app/[locale]/admin/layout.js @@ -143,69 +143,64 @@ export default function Layout({ children }) { return ( - - {/* Topbar */} -
-
- -
{headerTitle}
-
- - } - items={dropdownItems} - buttonClassName="" - menuClassName="absolute right-0 mt-2 w-64 bg-white border border-gray-200 rounded shadow-lg" - /> -
- - {/* Sidebar */} -
- -
- - {/* Overlay for mobile */} - {isSidebarOpen && ( -
+
+ +
{headerTitle}
+ + } + items={dropdownItems} + buttonClassName="" + menuClassName="absolute right-0 mt-2 w-64 bg-white border border-gray-200 rounded shadow-lg" + /> + - {/* Footer */} + {/* Sidebar */} +
+ +
-
+ {/* Overlay for mobile */} + {isSidebarOpen && ( +
+ )} + {/* Main container */} +
+ {children} +
+ + {/* Footer */} + +
+ {/*
*/}
diff --git a/Front-End/src/app/[locale]/admin/structure/page.js b/Front-End/src/app/[locale]/admin/structure/page.js index 72b5a9f..422acb1 100644 --- a/Front-End/src/app/[locale]/admin/structure/page.js +++ b/Front-End/src/app/[locale]/admin/structure/page.js @@ -60,7 +60,6 @@ export default function Page() { // Fetch data for classes handleClasses(); - // Fetch data for registration discounts handleRegistrationDiscounts(); @@ -126,7 +125,6 @@ export default function Page() { .catch((error) => logger.error('Error fetching classes:', error)); }; - const handleRegistrationDiscounts = () => { fetchRegistrationDiscounts(selectedEstablishmentId) .then((data) => { @@ -336,12 +334,14 @@ export default function Page() { ]; return ( - <> - - - + <> + + + - - + ); } diff --git a/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js b/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js index e7884b6..3ad2f96 100644 --- a/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js +++ b/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js @@ -5,7 +5,7 @@ import InscriptionFormShared from '@/components/Inscription/InscriptionFormShare import { FE_ADMIN_SUBSCRIPTIONS_URL } from '@/utils/Url'; import { useCsrfToken } from '@/context/CsrfContext'; import { useEstablishment } from '@/context/EstablishmentContext'; -import { editRegisterFormWithBinaryFile } from '@/app/actions/subscriptionAction'; +import { editRegisterForm } from '@/app/actions/subscriptionAction'; import logger from '@/utils/logger'; import Loader from '@/components/Loader'; diff --git a/Front-End/src/app/[locale]/parents/editInscription/page.js b/Front-End/src/app/[locale]/parents/editInscription/page.js index 1a90772..915ae84 100644 --- a/Front-End/src/app/[locale]/parents/editInscription/page.js +++ b/Front-End/src/app/[locale]/parents/editInscription/page.js @@ -10,8 +10,8 @@ import logger from '@/utils/logger'; export default function Page() { const searchParams = useSearchParams(); - const idProfil = searchParams.get('id'); const studentId = searchParams.get('studentId'); + const enable = searchParams.get('enabled') === 'true'; const router = useRouter(); const csrfToken = useCsrfToken(); const { selectedEstablishmentId } = useEstablishment(); @@ -37,6 +37,7 @@ export default function Page() { selectedEstablishmentId={selectedEstablishmentId} onSubmit={handleSubmit} cancelUrl={FE_PARENTS_HOME_URL} + enable={enable} /> ); } diff --git a/Front-End/src/app/[locale]/parents/page.js b/Front-End/src/app/[locale]/parents/page.js index 363edf1..4e5fd9d 100644 --- a/Front-End/src/app/[locale]/parents/page.js +++ b/Front-End/src/app/[locale]/parents/page.js @@ -17,7 +17,6 @@ import { useCsrfToken } from '@/context/CsrfContext'; export default function ParentHomePage() { const [children, setChildren] = useState([]); - const [userId, setUserId] = useState(null); const { user, selectedEstablishmentId } = useEstablishment(); const [uploadingStudentId, setUploadingStudentId] = useState(null); // ID de l'étudiant pour l'upload const [uploadedFile, setUploadedFile] = useState(null); // Fichier uploadé @@ -29,7 +28,6 @@ export default function ParentHomePage() { useEffect(() => { if (user !== null) { const userIdFromSession = user.user_id; - setUserId(userIdFromSession); fetchChildren(userIdFromSession, selectedEstablishmentId).then((data) => { setChildren(data); }); @@ -40,14 +38,14 @@ export default function ParentHomePage() { function handleView(eleveId) { logger.debug(`View dossier for student id: ${eleveId}`); router.push( - `${FE_PARENTS_EDIT_INSCRIPTION_URL}?id=${userId}&studentId=${eleveId}&view=true` + `${FE_PARENTS_EDIT_INSCRIPTION_URL}?studentId=${eleveId}&enabled=false` ); } function handleEdit(eleveId) { logger.debug(`Edit dossier for student id: ${eleveId}`); router.push( - `${FE_PARENTS_EDIT_INSCRIPTION_URL}?id=${userId}&studentId=${eleveId}` + `${FE_PARENTS_EDIT_INSCRIPTION_URL}?studentId=${eleveId}&enabled=true` ); } @@ -176,6 +174,19 @@ export default function ParentHomePage() { )} + + {row.status === 5 && ( + + )}
), }, diff --git a/Front-End/src/app/actions/planningAction.js b/Front-End/src/app/actions/planningAction.js index 48c10db..f2fed5e 100644 --- a/Front-End/src/app/actions/planningAction.js +++ b/Front-End/src/app/actions/planningAction.js @@ -53,8 +53,11 @@ const removeDatas = (url, csrfToken) => { }).then(requestResponseHandler); }; -export const fetchPlannings = (establishment_id=null,planningMode=null) => { - let url = `${BE_PLANNING_PLANNINGS_URL}`; +export const fetchPlannings = ( + establishment_id = null, + planningMode = null +) => { + let url = `${BE_PLANNING_PLANNINGS_URL}`; if (establishment_id) { url += `?establishment_id=${establishment_id}`; } @@ -80,7 +83,7 @@ export const deletePlanning = (id, csrfToken) => { return removeDatas(`${BE_PLANNING_PLANNINGS_URL}/${id}`, csrfToken); }; -export const fetchEvents = (establishment_id=null, planningMode=null) => { +export const fetchEvents = (establishment_id = null, planningMode = null) => { let url = `${BE_PLANNING_EVENTS_URL}`; if (establishment_id) { url += `?establishment_id=${establishment_id}`; @@ -90,7 +93,6 @@ export const fetchEvents = (establishment_id=null, planningMode=null) => { } return getData(url); - }; export const getEvent = (id) => { @@ -109,8 +111,8 @@ export const deleteEvent = (id, csrfToken) => { return removeDatas(`${BE_PLANNING_EVENTS_URL}/${id}`, csrfToken); }; -export const fetchUpcomingEvents = (establishment_id=null) => { - let url = `${BE_PLANNING_EVENTS_URL}/upcoming`; +export const fetchUpcomingEvents = (establishment_id = null) => { + let url = `${BE_PLANNING_EVENTS_URL}/upcoming`; if (establishment_id) { url += `?establishment_id=${establishment_id}`; } diff --git a/Front-End/src/app/layout.js b/Front-End/src/app/layout.js index e6d1c4c..19f8d28 100644 --- a/Front-End/src/app/layout.js +++ b/Front-End/src/app/layout.js @@ -28,7 +28,7 @@ export default async function RootLayout({ children, params }) { return ( - + {children} diff --git a/Front-End/src/components/Calendar/ScheduleNavigation.js b/Front-End/src/components/Calendar/ScheduleNavigation.js index 35cbefb..d390688 100644 --- a/Front-End/src/components/Calendar/ScheduleNavigation.js +++ b/Front-End/src/components/Calendar/ScheduleNavigation.js @@ -1,9 +1,8 @@ import { useState } from 'react'; -import { usePlanning,PlanningModes } from '@/context/PlanningContext'; +import { usePlanning, PlanningModes } from '@/context/PlanningContext'; import { Plus, Edit2, Eye, EyeOff, Check, X } from 'lucide-react'; - -export default function ScheduleNavigation({classes, modeSet='event'}) { +export default function ScheduleNavigation({ classes, modeSet = 'event' }) { const { schedules, selectedSchedule, @@ -46,7 +45,7 @@ export default function ScheduleNavigation({classes, modeSet='event'}) { const handleAddNew = () => { if (newSchedule.name) { - let payload = { + let payload = { name: newSchedule.name, color: newSchedule.color, }; @@ -65,7 +64,11 @@ export default function ScheduleNavigation({classes, modeSet='event'}) { return (
- ) : ( -
-
setSelectedSchedule(schedule.id)} + {planningMode === PlanningModes.CLASS_SCHEDULE && ( +
+ + +
+ )} +
+ - -
+ + +
- )} - - ))} +
+ ) : ( +
+
setSelectedSchedule(schedule.id)} + > +
+ + {schedule.name} + +
+
+ + +
+
+ )} + + ))} ); diff --git a/Front-End/src/components/Calendar/WeekView.js b/Front-End/src/components/Calendar/WeekView.js index 961dcf8..18d2072 100644 --- a/Front-End/src/components/Calendar/WeekView.js +++ b/Front-End/src/components/Calendar/WeekView.js @@ -44,7 +44,7 @@ const WeekView = ({ onDateClick, onEventClick, events }) => { const hours = currentTime.getHours(); const minutes = currentTime.getMinutes(); const rowHeight = 5; // Hauteur des lignes en rem (h-20 = 5rem) - return `${((hours + minutes / 60) * rowHeight)}rem`; + return `${(hours + minutes / 60) * rowHeight}rem`; }; // Utiliser les événements déjà filtrés passés en props diff --git a/Front-End/src/components/FileUpload.js b/Front-End/src/components/FileUpload.js index 665eeec..5d1f739 100644 --- a/Front-End/src/components/FileUpload.js +++ b/Front-End/src/components/FileUpload.js @@ -1,7 +1,6 @@ import React, { useState, useRef } from 'react'; import { CloudUpload } from 'lucide-react'; import logger from '@/utils/logger'; -import { BASE_URL } from '@/utils/Url'; export default function FileUpload({ selectionMessage, @@ -10,57 +9,78 @@ export default function FileUpload({ existingFile, required, errorMsg, + enable = true, // Nouvelle prop pour activer/désactiver le champ }) { const [localFileName, setLocalFileName] = useState(uploadedFileName || ''); - const fileInputRef = useRef(null); // Utilisation de useRef pour cibler l'input + const fileInputRef = useRef(null); const handleFileChange = (e) => { const file = e.target.files[0]; if (file) { setLocalFileName(file.name); logger.debug('Fichier sélectionné:', file.name); - onFileSelect(file); // Appelle la fonction passée en prop + onFileSelect(file); } }; const handleFileDrop = (e) => { e.preventDefault(); + if (!enable) return; // Empêcher le dépôt si désactivé const file = e.dataTransfer.files[0]; if (file) { setLocalFileName(file.name); logger.debug('Fichier déposé:', file.name); - onFileSelect(file); // Appelle la fonction passée en prop + onFileSelect(file); } }; return ( -
+

{`${selectionMessage}`} {required && *}

fileInputRef.current.click()} // Utilisation de la référence pour ouvrir l'explorateur - onDragOver={(e) => e.preventDefault()} + className={`border-2 border-dashed p-6 rounded-lg flex flex-col items-center justify-center ${ + !enable + ? 'border-gray-300 bg-gray-100 cursor-not-allowed' + : 'border-gray-500 hover:border-emerald-500' + }`} + onClick={() => enable && fileInputRef.current.click()} // Désactiver le clic si `enable` est false + onDragOver={(e) => enable && e.preventDefault()} onDrop={handleFileDrop} > - {' '} - {/* Icône de cloud */} + -
@@ -70,18 +90,10 @@ export default function FileUpload({

- {typeof existingFile === 'string' ? ( - - {existingFile.split('/').pop()} - - ) : ( - existingFile?.name || 'Fichier inconnu' - )} + {typeof existingFile === 'string' + ? existingFile.split('/').pop() // Si c'est une chaîne, utilisez split + : existingFile?.name || 'Nom de fichier inconnu'}{' '} + // Sinon, utilisez une propriété ou un fallback

diff --git a/Front-End/src/components/InputPhone.js b/Front-End/src/components/InputPhone.js index c62901e..96131f0 100644 --- a/Front-End/src/components/InputPhone.js +++ b/Front-End/src/components/InputPhone.js @@ -10,10 +10,10 @@ export default function InputPhone({ errorMsg, className, required, + enable = true, // Par défaut, le champ est activé }) { const handlePhoneChange = (phone) => { - // Appeler onChange avec un objet personnalisé - if (onChange) { + if (enable && onChange) { if (phone && phone.target) { const { name, value } = phone.target; onChange({ target: { name: name, value: value } }); @@ -37,11 +37,20 @@ export default function InputPhone({ inputProps={{ name: name, required: required, + disabled: !enable, // Désactiver l'input si enable est false }} - className="!w-full mt-1 !h-[38px]" - containerClassName="!w-full !h-[36px] !flex !items-center !rounded-md" - inputClassName={`flex-1 px-3 py-2 block w-full sm:text-sm border-none focus:ring-0 outline-none !rounded-r-md !outline-none items-center !border !border-gray-200 rounded-md ${errorMsg ? 'border-red-500' : ''} hover:border-gray-400 focus-within:border-gray-500`} - buttonClassName="!h-[38px] !flex !items-center !justify-center !rounded-l-md !border border-gray-200 !border-r-0" + className={`!w-full mt-1 !h-[38px] ${ + !enable ? 'bg-gray-100 cursor-not-allowed' : '' + }`} + containerClassName={`!w-full !h-[36px] !flex !items-center !rounded-md ${ + !enable ? 'bg-gray-100 cursor-not-allowed' : '' + }`} + inputClassName={`flex-1 px-3 py-2 block w-full sm:text-sm border-none focus:ring-0 outline-none !rounded-r-md items-center !border !border-gray-200 rounded-md ${ + errorMsg ? 'border-red-500' : '' + } ${!enable ? 'bg-gray-100 cursor-not-allowed' : 'hover:border-gray-400 focus-within:border-gray-500'}`} + buttonClassName={`!h-[38px] !flex !items-center !justify-center !rounded-l-md !border border-gray-200 !border-r-0 ${ + !enable ? 'cursor-not-allowed' : '' + }`} /> {errorMsg &&

{errorMsg}

} diff --git a/Front-End/src/components/InputText.js b/Front-End/src/components/InputText.js index 2ead301..7e5c6a2 100644 --- a/Front-End/src/components/InputText.js +++ b/Front-End/src/components/InputText.js @@ -9,6 +9,7 @@ export default function InputText({ placeholder, className, required, + enable = true, // Nouvelle prop pour activer/désactiver le champ }) { return ( <> @@ -25,7 +26,9 @@ export default function InputText({ errorMsg || errorLocalMsg ? 'border-red-500 hover:border-red-700' : 'border-gray-200 hover:border-gray-400' - } ${!errorMsg && !errorLocalMsg ? 'focus-within:border-gray-500' : ''}`} + } ${!errorMsg && !errorLocalMsg ? 'focus-within:border-gray-500' : ''} ${ + !enable ? 'bg-gray-100 cursor-not-allowed' : '' + }`} >
{errorMsg &&

{errorMsg}

} diff --git a/Front-End/src/components/Inscription/FilesToUpload.js b/Front-End/src/components/Inscription/FilesToUpload.js index 0218cb3..6d49479 100644 --- a/Front-End/src/components/Inscription/FilesToUpload.js +++ b/Front-End/src/components/Inscription/FilesToUpload.js @@ -11,6 +11,7 @@ export default function FilesToUpload({ uploadedFiles, onFileUpload, onFileDelete, + enable = true, }) { const [selectedFile, setSelectedFile] = useState(null); // État pour le fichier sélectionné const [actionType, setActionType] = useState(null); @@ -124,41 +125,43 @@ export default function FilesToUpload({ > - + {enable && ( + + )} )} {!uploadedFile && ( @@ -218,7 +221,7 @@ export default function FilesToUpload({ border: 'none', }} /> - ) : actionType === 'upload' ? ( + ) : actionType === 'upload' && enable ? ( handleUpload(file, selectedFile)} diff --git a/Front-End/src/components/Inscription/InscriptionFormShared.js b/Front-End/src/components/Inscription/InscriptionFormShared.js index 6c41476..caebb38 100644 --- a/Front-End/src/components/Inscription/InscriptionFormShared.js +++ b/Front-End/src/components/Inscription/InscriptionFormShared.js @@ -17,7 +17,7 @@ import { fetchRegistrationPaymentPlans, fetchTuitionPaymentPlans, } from '@/app/actions/schoolAction'; -import { BASE_URL } from '@/utils/Url'; +import { BASE_URL, FE_PARENTS_HOME_URL } from '@/utils/Url'; import logger from '@/utils/logger'; import FilesToUpload from '@/components/Inscription/FilesToUpload'; import { DocusealForm } from '@docuseal/react'; @@ -27,6 +27,7 @@ import SiblingInputFields from '@/components/Inscription/SiblingInputFields'; import PaymentMethodSelector from '@/components/Inscription/PaymentMethodSelector'; import ProgressStep from '@/components/ProgressStep'; import { CheckCircle, Hourglass } from 'lucide-react'; +import { useRouter } from 'next/navigation'; /** * Composant de formulaire d'inscription partagé @@ -42,6 +43,7 @@ export default function InscriptionFormShared({ selectedEstablishmentId, onSubmit, errors = {}, // Nouvelle prop pour les erreurs + enable = true, }) { // États pour gérer les données du formulaire const [formData, setFormData] = useState({ @@ -85,6 +87,20 @@ export default function InscriptionFormShared({ // État pour suivre l'index du fichier en cours const [currentTemplateIndex, setCurrentTemplateIndex] = useState(0); + const router = useRouter(); + + // Mettre à jour les états en fonction de la valeur de `enable` + useEffect(() => { + if (!enable) { + setIsPage1Valid(true); + setIsPage2Valid(true); + setIsPage3Valid(true); + setIsPage4Valid(true); + setIsPage5Valid(true); + setIsPage6Valid(true); + } + }, [enable]); + useEffect(() => { // Trouver le premier template non signé const firstUnsignedIndex = schoolFileTemplates.findIndex( @@ -465,10 +481,7 @@ export default function InscriptionFormShared({ setStep={setCurrentPage} isStepValid={isStepValid} /> -
+
{/* Page 1 : Informations sur l'élève */} {currentPage === 1 && ( )} @@ -492,6 +506,7 @@ export default function InscriptionFormShared({ setGuardians={setGuardians} errors={errors} setIsPageValid={setIsPage2Valid} + enable={enable} /> )} @@ -503,6 +518,7 @@ export default function InscriptionFormShared({ setFormData={setFormData} errors={errors.siblings || []} setIsPageValid={setIsPage3Valid} + enable={enable} /> )} @@ -518,6 +534,7 @@ export default function InscriptionFormShared({ tuitionPaymentPlans={tuitionPaymentPlans} errors={errors} setIsPageValid={setIsPage4Valid} + enable={enable} /> )} @@ -605,66 +622,67 @@ export default function InscriptionFormShared({ )} {/* Dernière page : Section Fichiers parents */} - {currentPage === 5 && ( + {currentPage === 6 && ( )}
{/* Boutons de contrôle */}
- {currentPage > 1 && ( + {enable ? ( + <> + {currentPage > 1 && ( +
diff --git a/Front-End/src/components/Inscription/PaymentMethodSelector.js b/Front-End/src/components/Inscription/PaymentMethodSelector.js index 4dbe83a..9dc4672 100644 --- a/Front-End/src/components/Inscription/PaymentMethodSelector.js +++ b/Front-End/src/components/Inscription/PaymentMethodSelector.js @@ -11,6 +11,7 @@ export default function PaymentMethodSelector({ tuitionPaymentPlans, errors, setIsPageValid, + enable = true, }) { useEffect(() => { const isValid = !Object.keys(formData).some( @@ -94,6 +95,7 @@ export default function PaymentMethodSelector({ errorMsg={getError('registration_payment')} errorLocalMsg={getLocalError('registration_payment')} required + disabled={!enable} />
@@ -155,6 +158,7 @@ export default function PaymentMethodSelector({ errorMsg={getError('tuition_payment')} errorLocalMsg={getLocalError('tuition_payment')} required + disabled={!enable} />
diff --git a/Front-End/src/components/Inscription/ResponsableInputFields.js b/Front-End/src/components/Inscription/ResponsableInputFields.js index 6fa55aa..dc5d303 100644 --- a/Front-End/src/components/Inscription/ResponsableInputFields.js +++ b/Front-End/src/components/Inscription/ResponsableInputFields.js @@ -11,6 +11,7 @@ export default function ResponsableInputFields({ setGuardians, errors, setIsPageValid, + enable = true, }) { const t = useTranslations('ResponsableInputFields'); const { selectedEstablishmentId } = useEstablishment(); @@ -145,6 +146,7 @@ export default function ResponsableInputFields({ errorMsg={getError('last_name')} errorLocalMsg={getLocalError(index, 'last_name')} required + enable={enable} />
@@ -176,6 +179,7 @@ export default function ResponsableInputFields({ errorMsg={getError('associated_profile_email')} errorLocalMsg={getLocalError(index, 'associated_profile_email')} required + enable={enable} />
@@ -202,6 +207,7 @@ export default function ResponsableInputFields({ errorMsg={getError('birth_date')} errorLocalMsg={getLocalError(index, 'birth_date')} required + enable={enable} /> @@ -229,29 +236,32 @@ export default function ResponsableInputFields({ errorMsg={getError('address')} errorLocalMsg={getLocalError(index, 'address')} required + enable={enable} /> ))} -
- = MAX_GUARDIANS - ? 'text-gray-400 cursor-not-allowed' - : 'text-green-500 cursor-pointer hover:text-green-700' - } transition-colors border-2 ${ - guardians.length >= MAX_GUARDIANS - ? 'border-gray-400' - : 'border-green-500 hover:border-green-700' - } rounded-full p-1`} - onClick={(e) => { - if (guardians.length < MAX_GUARDIANS) { - addGuardian(e); - } - }} - /> -
+ {enable && ( +
+ = MAX_GUARDIANS + ? 'text-gray-400 cursor-not-allowed' + : 'text-green-500 cursor-pointer hover:text-green-700' + } transition-colors border-2 ${ + guardians.length >= MAX_GUARDIANS + ? 'border-gray-400' + : 'border-green-500 hover:border-green-700' + } rounded-full p-1`} + onClick={(e) => { + if (guardians.length < MAX_GUARDIANS) { + addGuardian(e); + } + }} + /> +
+ )} ); } diff --git a/Front-End/src/components/Inscription/SiblingInputFields.js b/Front-End/src/components/Inscription/SiblingInputFields.js index 656a9f0..d900548 100644 --- a/Front-End/src/components/Inscription/SiblingInputFields.js +++ b/Front-End/src/components/Inscription/SiblingInputFields.js @@ -10,6 +10,7 @@ export default function SiblingInputFields({ setFormData, errors, setIsPageValid, + enable = true, }) { const getError = (index, field) => { return errors[index]?.[field]?.[0]; @@ -121,6 +122,7 @@ export default function SiblingInputFields({ errorMsg={getError('last_name')} errorLocalMsg={getLocalError(index, 'last_name')} required + enable={enable} /> @@ -148,17 +151,20 @@ export default function SiblingInputFields({ errorMsg={getError('birth_date')} errorLocalMsg={getLocalError(index, 'birth_date')} required + enable={enable} /> ))} -
- -
+ {enable && ( +
+ +
+ )} ); } diff --git a/Front-End/src/components/Inscription/StudentInfoForm.js b/Front-End/src/components/Inscription/StudentInfoForm.js index ac3e256..e0372e4 100644 --- a/Front-End/src/components/Inscription/StudentInfoForm.js +++ b/Front-End/src/components/Inscription/StudentInfoForm.js @@ -36,6 +36,7 @@ export default function StudentInfoForm({ setIsPageValid, hasInteracted, setHasInteracted, + enable = true, }) { const [isLoading, setIsLoading] = useState(true); @@ -181,6 +182,7 @@ export default function StudentInfoForm({ required errorMsg={getError('last_name')} errorLocalMsg={getLocalError('last_name')} + enable={enable} />
@@ -213,6 +217,7 @@ export default function StudentInfoForm({ required errorMsg={getError('birth_date')} errorLocalMsg={getLocalError('birth_date')} + enable={enable} />
@@ -242,6 +249,7 @@ export default function StudentInfoForm({ onChange={(e) => onChange('nationality', e.target.value)} errorMsg={getError('nationality')} errorLocalMsg={getLocalError('nationality')} + enable={enable} />
@@ -262,6 +271,7 @@ export default function StudentInfoForm({ required errorMsg={getError('attending_physician')} errorLocalMsg={getLocalError('attending_physician')} + enable={enable} />
@@ -281,6 +292,7 @@ export default function StudentInfoForm({ onFileSelect={(file) => handlePhotoUpload(file)} existingFile={formData.photo} errorMsg={getError('photo')} + enable={enable} />
diff --git a/Front-End/src/components/RadioList.js b/Front-End/src/components/RadioList.js index 90df256..703082c 100644 --- a/Front-End/src/components/RadioList.js +++ b/Front-End/src/components/RadioList.js @@ -9,6 +9,7 @@ const RadioList = ({ className, sectionLabel, required, + disabled = false, }) => { return (
@@ -20,7 +21,12 @@ const RadioList = ({ )}
{items.map((item) => ( -
+
diff --git a/Front-End/src/components/SidebarTabs.js b/Front-End/src/components/SidebarTabs.js index 46c10c4..5f965b4 100644 --- a/Front-End/src/components/SidebarTabs.js +++ b/Front-End/src/components/SidebarTabs.js @@ -20,14 +20,14 @@ const SidebarTabs = ({ tabs }) => { ))}
- {tabs.map((tab) => ( -
- {tab.content} -
- ))} + {tabs.map((tab) => ( +
+ {tab.content} +
+ ))} ); }; diff --git a/Front-End/src/components/StatusLabel.js b/Front-End/src/components/StatusLabel.js index 0899ce2..70ca3d3 100644 --- a/Front-End/src/components/StatusLabel.js +++ b/Front-End/src/components/StatusLabel.js @@ -10,6 +10,7 @@ const StatusLabel = ({ status, onChange, showDropdown = true, parent }) => { ? [ { value: 2, label: 'Nouveau' }, { value: 3, label: 'En validation' }, + { value: 5, label: 'Validé' }, { value: 7, label: 'SEPA reçu' }, { value: 8, label: 'En validation' }, ] @@ -32,6 +33,7 @@ const StatusLabel = ({ status, onChange, showDropdown = true, parent }) => { return ( (status === 2 && 'bg-orange-50 text-orange-600') || ((status === 3 || status === 8) && 'bg-purple-50 text-purple-600') || + (status === 5 && 'bg-green-50 text-green-600') || (status === 7 && 'bg-yellow-50 text-yellow-600') ); } diff --git a/Front-End/src/components/Structure/Configuration/ClassesSection.js b/Front-End/src/components/Structure/Configuration/ClassesSection.js index 8a7e0d3..c5cc851 100644 --- a/Front-End/src/components/Structure/Configuration/ClassesSection.js +++ b/Front-End/src/components/Structure/Configuration/ClassesSection.js @@ -15,7 +15,7 @@ import { useEstablishment } from '@/context/EstablishmentContext'; import { FE_ADMIN_STRUCTURE_SCHOOLCLASS_MANAGEMENT_URL } from '@/utils/Url'; import { usePlanning } from '@/context/PlanningContext'; import { useClasses } from '@/context/ClassesContext'; - +import { useRouter } from 'next/navigation'; const ItemTypes = { TEACHER: 'teacher', @@ -119,7 +119,6 @@ const ClassesSection = ({ handleCreate, handleEdit, handleDelete, - }) => { const [formData, setFormData] = useState({}); const [editingClass, setEditingClass] = useState(null); @@ -134,8 +133,8 @@ const ClassesSection = ({ const [selectedClass, setSelectedClass] = useState(null); const { selectedEstablishmentId } = useEstablishment(); const { addSchedule, reloadPlanning, reloadEvents } = usePlanning(); - const{ getNiveauxLabels, allNiveaux } = useClasses(); - + const { getNiveauxLabels, allNiveaux } = useClasses(); + const router = useRouter(); // Fonction pour générer les années scolaires const getSchoolYearChoices = () => { @@ -222,10 +221,9 @@ const ClassesSection = ({ name: planningName, color: '#FF5733', // Couleur par défaut school_class: createdClass.id, - } - addSchedule(newPlanning) + }; + addSchedule(newPlanning); }); - }) .catch((error) => { logger.error('Error:', error.message); diff --git a/Front-End/src/components/Structure/Planning/ScheduleEventModal.js b/Front-End/src/components/Structure/Planning/ScheduleEventModal.js index 8189896..9f2f69a 100644 --- a/Front-End/src/components/Structure/Planning/ScheduleEventModal.js +++ b/Front-End/src/components/Structure/Planning/ScheduleEventModal.js @@ -9,12 +9,12 @@ export default function ScheduleEventModal({ setEventData, specialities, teachers, - classes + classes, }) { - const { addEvent, handleUpdateEvent, handleDeleteEvent, schedules } = usePlanning(); + const { addEvent, handleUpdateEvent, handleDeleteEvent, schedules } = + usePlanning(); React.useEffect(() => { - if (!eventData?.planning && schedules.length > 0) { const defaultSchedule = schedules[0]; if (eventData?.planning !== defaultSchedule.id) { @@ -26,9 +26,10 @@ export default function ScheduleEventModal({ } }, [schedules, eventData?.planning]); - const handleSpecialityChange = (specialityId) => { - const selectedSpeciality = specialities.find((s) => s.id === parseInt(specialityId, 10)); + const selectedSpeciality = specialities.find( + (s) => s.id === parseInt(specialityId, 10) + ); if (selectedSpeciality) { setEventData((prev) => ({ ...prev, @@ -40,7 +41,9 @@ export default function ScheduleEventModal({ }; const handleTeacherChange = (teacherId) => { - const selectedTeacher = teachers.find((t) => t.id === parseInt(teacherId, 10)); + const selectedTeacher = teachers.find( + (t) => t.id === parseInt(teacherId, 10) + ); if (selectedTeacher) { setEventData((prev) => ({ ...prev, @@ -51,7 +54,9 @@ export default function ScheduleEventModal({ }; const handlePlanningChange = (planningId) => { - const selectedSchedule = schedules.find((s) => s.id === parseInt(planningId, 10)); + const selectedSchedule = schedules.find( + (s) => s.id === parseInt(planningId, 10) + ); if (selectedSchedule) { setEventData((prev) => ({ ...prev, diff --git a/Front-End/src/components/Structure/Planning/ScheduleManagement.js b/Front-End/src/components/Structure/Planning/ScheduleManagement.js index c77abc9..3526188 100644 --- a/Front-End/src/components/Structure/Planning/ScheduleManagement.js +++ b/Front-End/src/components/Structure/Planning/ScheduleManagement.js @@ -8,9 +8,11 @@ import Calendar from '@/components/Calendar/Calendar'; import ScheduleEventModal from '@/components/Structure/Planning/ScheduleEventModal'; import ScheduleNavigation from '@/components/Calendar/ScheduleNavigation'; - - -export default function ScheduleManagement({classes,specialities,teachers}) { +export default function ScheduleManagement({ + classes, + specialities, + teachers, +}) { const [isModalOpen, setIsModalOpen] = useState(false); const [eventData, setEventData] = useState({ title: '', @@ -50,25 +52,24 @@ export default function ScheduleManagement({classes,specialities,teachers}) { }; return ( -
- - { - setEventData(event); - setIsModalOpen(true); - }} - /> - setIsModalOpen(false)} - eventData={eventData} - setEventData={setEventData} - specialities={specialities} - teachers={teachers} - classes={classes} - /> -
+
+ + { + setEventData(event); + setIsModalOpen(true); + }} + /> + setIsModalOpen(false)} + eventData={eventData} + setEventData={setEventData} + specialities={specialities} + teachers={teachers} + classes={classes} + /> +
); } - diff --git a/Front-End/src/context/ClassesContext.js b/Front-End/src/context/ClassesContext.js index 8d2be61..ae52e87 100644 --- a/Front-End/src/context/ClassesContext.js +++ b/Front-End/src/context/ClassesContext.js @@ -116,7 +116,6 @@ export const ClassesProvider = ({ children }) => { } }; - const groupSpecialitiesBySubject = (teachers) => { const groupedSpecialities = {}; @@ -142,7 +141,6 @@ export const ClassesProvider = ({ children }) => { return Object.values(groupedSpecialities); }; - return ( { + fetchEvents(selectedEstablishmentId, planningMode).then((data) => { + setEvents(data); + }); + }; -const reloadEvents = () =>{ - fetchEvents(selectedEstablishmentId, planningMode).then((data) => { - setEvents(data); - }); -} - -const reloadPlanning = () =>{ - fetchPlannings(selectedEstablishmentId, planningMode).then((data) => { - setSchedules(data); - if (data.length > 0) { - setSelectedSchedule(data[0].id); - } - }); -} + const reloadPlanning = () => { + fetchPlannings(selectedEstablishmentId, planningMode).then((data) => { + setSchedules(data); + if (data.length > 0) { + setSelectedSchedule(data[0].id); + } + }); + }; const addEvent = (newEvent) => { createEvent(newEvent).then(() => { reloadEvents(); @@ -82,7 +83,7 @@ const reloadPlanning = () =>{ const handleDeleteEvent = (id) => { deleteEvent(id, csrfToken).then((data) => { - reloadEvents(); + reloadEvents(); }); }; diff --git a/Front-End/src/css/tailwind.css b/Front-End/src/css/tailwind.css index a90f074..b5c61c9 100644 --- a/Front-End/src/css/tailwind.css +++ b/Front-End/src/css/tailwind.css @@ -1,4 +1,3 @@ @tailwind base; @tailwind components; @tailwind utilities; -