fix: Ajout du mode Visu

This commit is contained in:
N3WT DE COMPET
2025-05-04 14:32:06 +02:00
parent 4ecf25a6ab
commit e1c607308c
29 changed files with 531 additions and 414 deletions

View File

@ -102,7 +102,8 @@ class ChildrenListView(APIView):
RegistrationForm.RegistrationFormStatus.RF_SENT, RegistrationForm.RegistrationFormStatus.RF_SENT,
RegistrationForm.RegistrationFormStatus.RF_UNDER_REVIEW, RegistrationForm.RegistrationFormStatus.RF_UNDER_REVIEW,
RegistrationForm.RegistrationFormStatus.RF_SEPA_SENT, RegistrationForm.RegistrationFormStatus.RF_SEPA_SENT,
RegistrationForm.RegistrationFormStatus.RF_SEPA_TO_SEND RegistrationForm.RegistrationFormStatus.RF_SEPA_TO_SEND,
RegistrationForm.RegistrationFormStatus.RF_VALIDATED
] ]
).distinct() ).distinct()
students_serializer = RegistrationFormByParentSerializer(students, many=True) students_serializer = RegistrationFormByParentSerializer(students, many=True)

View File

@ -143,7 +143,6 @@ export default function Layout({ children }) {
return ( return (
<ProtectedRoute requiredRight={[RIGHTS.ADMIN, RIGHTS.TEACHER]}> <ProtectedRoute requiredRight={[RIGHTS.ADMIN, RIGHTS.TEACHER]}>
{/* Topbar */} {/* Topbar */}
<header className="absolute top-0 left-0 right-0 h-16 bg-white border-b border-gray-200 px-4 md:px-8 flex items-center justify-between z-10 box-border"> <header className="absolute top-0 left-0 right-0 h-16 bg-white border-b border-gray-200 px-4 md:px-8 flex items-center justify-between z-10 box-border">
<div className="flex items-center"> <div className="flex items-center">
@ -201,11 +200,7 @@ export default function Layout({ children }) {
{/* Footer */} {/* Footer */}
<Footer <Footer softwareName={softwareName} softwareVersion={softwareVersion} />
softwareName={softwareName}
softwareVersion={softwareVersion}
/>
<Popup <Popup
visible={isPopupVisible} visible={isPopupVisible}

View File

@ -1,5 +1,9 @@
'use client'; 'use client';
import { PlanningModes, PlanningProvider, RecurrenceType } from '@/context/PlanningContext'; import {
PlanningModes,
PlanningProvider,
RecurrenceType,
} from '@/context/PlanningContext';
import Calendar from '@/components/Calendar/Calendar'; import Calendar from '@/components/Calendar/Calendar';
import EventModal from '@/components/Calendar/EventModal'; import EventModal from '@/components/Calendar/EventModal';
import ScheduleNavigation from '@/components/Calendar/ScheduleNavigation'; import ScheduleNavigation from '@/components/Calendar/ScheduleNavigation';
@ -47,7 +51,10 @@ export default function Page() {
}; };
return ( return (
<PlanningProvider establishmentId={selectedEstablishmentId} modeSet={PlanningModes.PLANNING}> <PlanningProvider
establishmentId={selectedEstablishmentId}
modeSet={PlanningModes.PLANNING}
>
{/* <div className="flex h-full overflow-hidden"> */} {/* <div className="flex h-full overflow-hidden"> */}
<div className="flex h-full overflow-hidden"> <div className="flex h-full overflow-hidden">
<ScheduleNavigation /> <ScheduleNavigation />

View File

@ -60,7 +60,6 @@ export default function Page() {
// Fetch data for classes // Fetch data for classes
handleClasses(); handleClasses();
// Fetch data for registration discounts // Fetch data for registration discounts
handleRegistrationDiscounts(); handleRegistrationDiscounts();
@ -126,7 +125,6 @@ export default function Page() {
.catch((error) => logger.error('Error fetching classes:', error)); .catch((error) => logger.error('Error fetching classes:', error));
}; };
const handleRegistrationDiscounts = () => { const handleRegistrationDiscounts = () => {
fetchRegistrationDiscounts(selectedEstablishmentId) fetchRegistrationDiscounts(selectedEstablishmentId)
.then((data) => { .then((data) => {
@ -337,11 +335,13 @@ export default function Page() {
return ( return (
<> <>
<PlanningProvider establishmentId={selectedEstablishmentId} modeSet={PlanningModes.CLASS_SCHEDULE}> <PlanningProvider
establishmentId={selectedEstablishmentId}
modeSet={PlanningModes.CLASS_SCHEDULE}
>
<DjangoCSRFToken csrfToken={csrfToken} /> <DjangoCSRFToken csrfToken={csrfToken} />
<SidebarTabs tabs={tabs} /> <SidebarTabs tabs={tabs} />
</PlanningProvider> </PlanningProvider>
</> </>
); );
} }

View File

@ -5,7 +5,7 @@ import InscriptionFormShared from '@/components/Inscription/InscriptionFormShare
import { FE_ADMIN_SUBSCRIPTIONS_URL } from '@/utils/Url'; import { FE_ADMIN_SUBSCRIPTIONS_URL } from '@/utils/Url';
import { useCsrfToken } from '@/context/CsrfContext'; import { useCsrfToken } from '@/context/CsrfContext';
import { useEstablishment } from '@/context/EstablishmentContext'; import { useEstablishment } from '@/context/EstablishmentContext';
import { editRegisterFormWithBinaryFile } from '@/app/actions/subscriptionAction'; import { editRegisterForm } from '@/app/actions/subscriptionAction';
import logger from '@/utils/logger'; import logger from '@/utils/logger';
import Loader from '@/components/Loader'; import Loader from '@/components/Loader';

View File

@ -10,8 +10,8 @@ import logger from '@/utils/logger';
export default function Page() { export default function Page() {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const idProfil = searchParams.get('id');
const studentId = searchParams.get('studentId'); const studentId = searchParams.get('studentId');
const enable = searchParams.get('enabled') === 'true';
const router = useRouter(); const router = useRouter();
const csrfToken = useCsrfToken(); const csrfToken = useCsrfToken();
const { selectedEstablishmentId } = useEstablishment(); const { selectedEstablishmentId } = useEstablishment();
@ -37,6 +37,7 @@ export default function Page() {
selectedEstablishmentId={selectedEstablishmentId} selectedEstablishmentId={selectedEstablishmentId}
onSubmit={handleSubmit} onSubmit={handleSubmit}
cancelUrl={FE_PARENTS_HOME_URL} cancelUrl={FE_PARENTS_HOME_URL}
enable={enable}
/> />
); );
} }

View File

@ -17,7 +17,6 @@ import { useCsrfToken } from '@/context/CsrfContext';
export default function ParentHomePage() { export default function ParentHomePage() {
const [children, setChildren] = useState([]); const [children, setChildren] = useState([]);
const [userId, setUserId] = useState(null);
const { user, selectedEstablishmentId } = useEstablishment(); const { user, selectedEstablishmentId } = useEstablishment();
const [uploadingStudentId, setUploadingStudentId] = useState(null); // ID de l'étudiant pour l'upload const [uploadingStudentId, setUploadingStudentId] = useState(null); // ID de l'étudiant pour l'upload
const [uploadedFile, setUploadedFile] = useState(null); // Fichier uploadé const [uploadedFile, setUploadedFile] = useState(null); // Fichier uploadé
@ -29,7 +28,6 @@ export default function ParentHomePage() {
useEffect(() => { useEffect(() => {
if (user !== null) { if (user !== null) {
const userIdFromSession = user.user_id; const userIdFromSession = user.user_id;
setUserId(userIdFromSession);
fetchChildren(userIdFromSession, selectedEstablishmentId).then((data) => { fetchChildren(userIdFromSession, selectedEstablishmentId).then((data) => {
setChildren(data); setChildren(data);
}); });
@ -40,14 +38,14 @@ export default function ParentHomePage() {
function handleView(eleveId) { function handleView(eleveId) {
logger.debug(`View dossier for student id: ${eleveId}`); logger.debug(`View dossier for student id: ${eleveId}`);
router.push( 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) { function handleEdit(eleveId) {
logger.debug(`Edit dossier for student id: ${eleveId}`); logger.debug(`Edit dossier for student id: ${eleveId}`);
router.push( 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() {
</button> </button>
</> </>
)} )}
{row.status === 5 && (
<button
className="text-purple-500 hover:text-purple-700"
onClick={(e) => {
e.stopPropagation();
handleView(row.student.id);
}}
aria-label="Visualiser le dossier"
>
<Eye className="h-5 w-5" />
</button>
)}
</div> </div>
), ),
}, },

View File

@ -53,7 +53,10 @@ const removeDatas = (url, csrfToken) => {
}).then(requestResponseHandler); }).then(requestResponseHandler);
}; };
export const fetchPlannings = (establishment_id=null,planningMode=null) => { export const fetchPlannings = (
establishment_id = null,
planningMode = null
) => {
let url = `${BE_PLANNING_PLANNINGS_URL}`; let url = `${BE_PLANNING_PLANNINGS_URL}`;
if (establishment_id) { if (establishment_id) {
url += `?establishment_id=${establishment_id}`; url += `?establishment_id=${establishment_id}`;
@ -90,7 +93,6 @@ export const fetchEvents = (establishment_id=null, planningMode=null) => {
} }
return getData(url); return getData(url);
}; };
export const getEvent = (id) => { export const getEvent = (id) => {

View File

@ -28,7 +28,7 @@ export default async function RootLayout({ children, params }) {
return ( return (
<html lang={locale}> <html lang={locale}>
<body className='p-0 m-0'> <body className="p-0 m-0">
<Providers messages={messages} locale={locale} session={params.session}> <Providers messages={messages} locale={locale} session={params.session}>
{children} {children}
</Providers> </Providers>

View File

@ -2,7 +2,6 @@ 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'; 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 { const {
schedules, schedules,
@ -65,7 +64,11 @@ export default function ScheduleNavigation({classes, modeSet='event'}) {
return ( return (
<nav className="w-64 border-r p-4"> <nav className="w-64 border-r p-4">
<div className="flex items-center justify-between mb-4"> <div className="flex items-center justify-between mb-4">
<h2 className="font-semibold">{(planningMode === PlanningModes.CLASS_SCHEDULE)?"Emplois du temps":"Plannings"}</h2> <h2 className="font-semibold">
{planningMode === PlanningModes.CLASS_SCHEDULE
? 'Emplois du temps'
: 'Plannings'}
</h2>
<button <button
onClick={() => setIsAddingNew(true)} onClick={() => setIsAddingNew(true)}
className="p-1 hover:bg-gray-100 rounded" className="p-1 hover:bg-gray-100 rounded"
@ -83,7 +86,11 @@ export default function ScheduleNavigation({classes, modeSet='event'}) {
setNewSchedule((prev) => ({ ...prev, name: e.target.value })) setNewSchedule((prev) => ({ ...prev, name: e.target.value }))
} }
className="w-full p-1 mb-2 border rounded" className="w-full p-1 mb-2 border rounded"
placeholder={(planningMode===PlanningModes.CLASS_SCHEDULE)?"Nom de l'emplois du temps":"Nom du planning"} placeholder={
planningMode === PlanningModes.CLASS_SCHEDULE
? "Nom de l'emplois du temps"
: 'Nom du planning'
}
/> />
<div className="flex gap-2 items-center mb-2"> <div className="flex gap-2 items-center mb-2">
<label className="text-sm">Couleur:</label> <label className="text-sm">Couleur:</label>
@ -110,13 +117,14 @@ export default function ScheduleNavigation({classes, modeSet='event'}) {
className="w-full p-1 border rounded" className="w-full p-1 border rounded"
> >
<option value="">Aucune</option> <option value="">Aucune</option>
{classes.map((classe) => { console.log({classe}); {classes.map((classe) => {
console.log({ classe });
return ( return (
<option key={classe.id} value={classe.id}> <option key={classe.id} value={classe.id}>
{classe.atmosphere_name} {classe.atmosphere_name}
</option> </option>
)} );
)} })}
</select> </select>
</div> </div>
)} )}
@ -138,8 +146,7 @@ export default function ScheduleNavigation({classes, modeSet='event'}) {
)} )}
<ul className="space-y-2"> <ul className="space-y-2">
{schedules {schedules.map((schedule) => (
.map((schedule) => (
<li <li
key={schedule.id} key={schedule.id}
className={`p-2 rounded ${ className={`p-2 rounded ${
@ -171,7 +178,6 @@ export default function ScheduleNavigation({classes, modeSet='event'}) {
<select <select
value={editedSchoolClass} value={editedSchoolClass}
onChange={(e) => setEditedSchoolClass(e.target.value)} onChange={(e) => setEditedSchoolClass(e.target.value)}
className="w-full p-1 border rounded" className="w-full p-1 border rounded"
> >
<option value="">Aucune</option> <option value="">Aucune</option>

View File

@ -44,7 +44,7 @@ const WeekView = ({ onDateClick, onEventClick, events }) => {
const hours = currentTime.getHours(); const hours = currentTime.getHours();
const minutes = currentTime.getMinutes(); const minutes = currentTime.getMinutes();
const rowHeight = 5; // Hauteur des lignes en rem (h-20 = 5rem) 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 // Utiliser les événements déjà filtrés passés en props

View File

@ -1,7 +1,6 @@
import React, { useState, useRef } from 'react'; import React, { useState, useRef } from 'react';
import { CloudUpload } from 'lucide-react'; import { CloudUpload } from 'lucide-react';
import logger from '@/utils/logger'; import logger from '@/utils/logger';
import { BASE_URL } from '@/utils/Url';
export default function FileUpload({ export default function FileUpload({
selectionMessage, selectionMessage,
@ -10,57 +9,78 @@ export default function FileUpload({
existingFile, existingFile,
required, required,
errorMsg, errorMsg,
enable = true, // Nouvelle prop pour activer/désactiver le champ
}) { }) {
const [localFileName, setLocalFileName] = useState(uploadedFileName || ''); const [localFileName, setLocalFileName] = useState(uploadedFileName || '');
const fileInputRef = useRef(null); // Utilisation de useRef pour cibler l'input const fileInputRef = useRef(null);
const handleFileChange = (e) => { const handleFileChange = (e) => {
const file = e.target.files[0]; const file = e.target.files[0];
if (file) { if (file) {
setLocalFileName(file.name); setLocalFileName(file.name);
logger.debug('Fichier sélectionné:', file.name); logger.debug('Fichier sélectionné:', file.name);
onFileSelect(file); // Appelle la fonction passée en prop onFileSelect(file);
} }
}; };
const handleFileDrop = (e) => { const handleFileDrop = (e) => {
e.preventDefault(); e.preventDefault();
if (!enable) return; // Empêcher le dépôt si désactivé
const file = e.dataTransfer.files[0]; const file = e.dataTransfer.files[0];
if (file) { if (file) {
setLocalFileName(file.name); setLocalFileName(file.name);
logger.debug('Fichier déposé:', file.name); logger.debug('Fichier déposé:', file.name);
onFileSelect(file); // Appelle la fonction passée en prop onFileSelect(file);
} }
}; };
return ( return (
<div className="border p-4 rounded-md shadow-md"> <div
className={`border p-4 rounded-md shadow-md ${
!enable ? 'bg-gray-100 cursor-not-allowed' : ''
}`}
>
<h3 className="text-lg font-semibold mb-4"> <h3 className="text-lg font-semibold mb-4">
{`${selectionMessage}`} {`${selectionMessage}`}
{required && <span className="text-red-500 ml-1">*</span>} {required && <span className="text-red-500 ml-1">*</span>}
</h3> </h3>
<div <div
className="border-2 border-dashed border-gray-500 p-6 rounded-lg flex flex-col items-center justify-center cursor-pointer hover:border-emerald-500" className={`border-2 border-dashed p-6 rounded-lg flex flex-col items-center justify-center ${
onClick={() => fileInputRef.current.click()} // Utilisation de la référence pour ouvrir l'explorateur !enable
onDragOver={(e) => e.preventDefault()} ? '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} onDrop={handleFileDrop}
> >
<CloudUpload className="w-12 h-12 text-emerald-500 mb-4" />{' '} <CloudUpload
{/* Icône de cloud */} className={`w-12 h-12 mb-4 ${
!enable ? 'text-gray-400' : 'text-emerald-500'
}`}
/>
<input <input
type="file" type="file"
accept=".pdf, .png, .jpg, .jpeg, .gif, .bmp" accept=".pdf, .png, .jpg, .jpeg, .gif, .bmp"
onChange={handleFileChange} onChange={handleFileChange}
className="hidden" className="hidden"
ref={fileInputRef} // Attachement de la référence ref={fileInputRef}
disabled={!enable} // Désactiver l'input si `enable` est false
/> />
<label htmlFor="fileInput" className="text-center text-gray-500"> <label
<p className="text-lg font-semibold text-gray-800"> htmlFor="fileInput"
Déposez votre fichier ici className={`text-center ${
!enable ? 'text-gray-400' : 'text-gray-500'
}`}
>
<p className="text-lg font-semibold">
{enable ? 'Déposez votre fichier ici' : 'Téléversement désactivé'}
</p> </p>
{enable && (
<p className="text-sm text-gray-500 mt-2"> <p className="text-sm text-gray-500 mt-2">
ou cliquez pour sélectionner un fichier ou cliquez pour sélectionner un fichier
</p> </p>
)}
</label> </label>
</div> </div>
@ -70,18 +90,10 @@ export default function FileUpload({
<CloudUpload className="w-6 h-6 text-emerald-500" /> <CloudUpload className="w-6 h-6 text-emerald-500" />
<p className="text-sm font-medium text-gray-800"> <p className="text-sm font-medium text-gray-800">
<span className="font-semibold"> <span className="font-semibold">
{typeof existingFile === 'string' ? ( {typeof existingFile === 'string'
<a ? existingFile.split('/').pop() // Si c'est une chaîne, utilisez split
href={`${BASE_URL}${existingFile}`} : existingFile?.name || 'Nom de fichier inconnu'}{' '}
target="_blank" // Sinon, utilisez une propriété ou un fallback
rel="noopener noreferrer"
className="text-blue-500 hover:text-blue-700 underline"
>
{existingFile.split('/').pop()}
</a>
) : (
existingFile?.name || 'Fichier inconnu'
)}
</span> </span>
</p> </p>
</div> </div>

View File

@ -10,10 +10,10 @@ export default function InputPhone({
errorMsg, errorMsg,
className, className,
required, required,
enable = true, // Par défaut, le champ est activé
}) { }) {
const handlePhoneChange = (phone) => { const handlePhoneChange = (phone) => {
// Appeler onChange avec un objet personnalisé if (enable && onChange) {
if (onChange) {
if (phone && phone.target) { if (phone && phone.target) {
const { name, value } = phone.target; const { name, value } = phone.target;
onChange({ target: { name: name, value: value } }); onChange({ target: { name: name, value: value } });
@ -37,11 +37,20 @@ export default function InputPhone({
inputProps={{ inputProps={{
name: name, name: name,
required: required, required: required,
disabled: !enable, // Désactiver l'input si enable est false
}} }}
className="!w-full mt-1 !h-[38px]" className={`!w-full mt-1 !h-[38px] ${
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 !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" 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 && <p className="mt-2 text-sm text-red-600">{errorMsg}</p>} {errorMsg && <p className="mt-2 text-sm text-red-600">{errorMsg}</p>}

View File

@ -9,6 +9,7 @@ export default function InputText({
placeholder, placeholder,
className, className,
required, required,
enable = true, // Nouvelle prop pour activer/désactiver le champ
}) { }) {
return ( return (
<> <>
@ -25,7 +26,9 @@ export default function InputText({
errorMsg || errorLocalMsg errorMsg || errorLocalMsg
? 'border-red-500 hover:border-red-700' ? 'border-red-500 hover:border-red-700'
: 'border-gray-200 hover:border-gray-400' : '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' : ''
}`}
> >
<input <input
type={type} type={type}
@ -33,9 +36,12 @@ export default function InputText({
placeholder={placeholder} placeholder={placeholder}
name={name} name={name}
value={value} value={value}
onChange={onChange} onChange={enable ? onChange : undefined} // Désactiver onChange si enable est false
className="flex-1 px-3 py-2 block w-full sm:text-sm border-none focus:ring-0 outline-none rounded-md" className={`flex-1 px-3 py-2 block w-full sm:text-sm border-none focus:ring-0 outline-none rounded-md ${
!enable ? 'bg-gray-100 cursor-not-allowed' : ''
}`}
required={required} required={required}
readOnly={!enable ? 'readOnly' : ''} // Activer le mode readonly si enable est false
/> />
</div> </div>
{errorMsg && <p className="mt-2 text-sm text-red-600">{errorMsg}</p>} {errorMsg && <p className="mt-2 text-sm text-red-600">{errorMsg}</p>}

View File

@ -11,6 +11,7 @@ export default function FilesToUpload({
uploadedFiles, uploadedFiles,
onFileUpload, onFileUpload,
onFileDelete, onFileDelete,
enable = true,
}) { }) {
const [selectedFile, setSelectedFile] = useState(null); // État pour le fichier sélectionné const [selectedFile, setSelectedFile] = useState(null); // État pour le fichier sélectionné
const [actionType, setActionType] = useState(null); const [actionType, setActionType] = useState(null);
@ -124,6 +125,7 @@ export default function FilesToUpload({
> >
<Eye className="w-5 h-5" /> <Eye className="w-5 h-5" />
</button> </button>
{enable && (
<button <button
className="flex items-center justify-center w-8 h-8 rounded-full text-red-500 hover:text-red-700" className="flex items-center justify-center w-8 h-8 rounded-full text-red-500 hover:text-red-700"
onClick={() => { onClick={() => {
@ -159,6 +161,7 @@ export default function FilesToUpload({
> >
<Trash2 className="w-5 h-5" /> <Trash2 className="w-5 h-5" />
</button> </button>
)}
</> </>
)} )}
{!uploadedFile && ( {!uploadedFile && (
@ -218,7 +221,7 @@ export default function FilesToUpload({
border: 'none', border: 'none',
}} }}
/> />
) : actionType === 'upload' ? ( ) : actionType === 'upload' && enable ? (
<FileUpload <FileUpload
selectionMessage={`Téléversez le fichier ${selectedFile.master_name}`} selectionMessage={`Téléversez le fichier ${selectedFile.master_name}`}
onFileSelect={(file) => handleUpload(file, selectedFile)} onFileSelect={(file) => handleUpload(file, selectedFile)}

View File

@ -17,7 +17,7 @@ import {
fetchRegistrationPaymentPlans, fetchRegistrationPaymentPlans,
fetchTuitionPaymentPlans, fetchTuitionPaymentPlans,
} from '@/app/actions/schoolAction'; } 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 logger from '@/utils/logger';
import FilesToUpload from '@/components/Inscription/FilesToUpload'; import FilesToUpload from '@/components/Inscription/FilesToUpload';
import { DocusealForm } from '@docuseal/react'; import { DocusealForm } from '@docuseal/react';
@ -27,6 +27,7 @@ import SiblingInputFields from '@/components/Inscription/SiblingInputFields';
import PaymentMethodSelector from '@/components/Inscription/PaymentMethodSelector'; import PaymentMethodSelector from '@/components/Inscription/PaymentMethodSelector';
import ProgressStep from '@/components/ProgressStep'; import ProgressStep from '@/components/ProgressStep';
import { CheckCircle, Hourglass } from 'lucide-react'; import { CheckCircle, Hourglass } from 'lucide-react';
import { useRouter } from 'next/navigation';
/** /**
* Composant de formulaire d'inscription partagé * Composant de formulaire d'inscription partagé
@ -42,6 +43,7 @@ export default function InscriptionFormShared({
selectedEstablishmentId, selectedEstablishmentId,
onSubmit, onSubmit,
errors = {}, // Nouvelle prop pour les erreurs errors = {}, // Nouvelle prop pour les erreurs
enable = true,
}) { }) {
// États pour gérer les données du formulaire // États pour gérer les données du formulaire
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@ -85,6 +87,20 @@ export default function InscriptionFormShared({
// État pour suivre l'index du fichier en cours // État pour suivre l'index du fichier en cours
const [currentTemplateIndex, setCurrentTemplateIndex] = useState(0); 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(() => { useEffect(() => {
// Trouver le premier template non signé // Trouver le premier template non signé
const firstUnsignedIndex = schoolFileTemplates.findIndex( const firstUnsignedIndex = schoolFileTemplates.findIndex(
@ -465,10 +481,7 @@ export default function InscriptionFormShared({
setStep={setCurrentPage} setStep={setCurrentPage}
isStepValid={isStepValid} isStepValid={isStepValid}
/> />
<div <div className="flex-1 h-full mt-12 ">
className="flex-1 overflow-y-auto mt-12 "
style={{ maxHeight: 'calc(100vh - 400px)' }}
>
{/* Page 1 : Informations sur l'élève */} {/* Page 1 : Informations sur l'élève */}
{currentPage === 1 && ( {currentPage === 1 && (
<StudentInfoForm <StudentInfoForm
@ -482,6 +495,7 @@ export default function InscriptionFormShared({
setIsPageValid={setIsPage1Valid} setIsPageValid={setIsPage1Valid}
hasInteracted={hasInteracted} hasInteracted={hasInteracted}
setHasInteracted={setHasInteracted} setHasInteracted={setHasInteracted}
enable={enable}
/> />
)} )}
@ -492,6 +506,7 @@ export default function InscriptionFormShared({
setGuardians={setGuardians} setGuardians={setGuardians}
errors={errors} errors={errors}
setIsPageValid={setIsPage2Valid} setIsPageValid={setIsPage2Valid}
enable={enable}
/> />
)} )}
@ -503,6 +518,7 @@ export default function InscriptionFormShared({
setFormData={setFormData} setFormData={setFormData}
errors={errors.siblings || []} errors={errors.siblings || []}
setIsPageValid={setIsPage3Valid} setIsPageValid={setIsPage3Valid}
enable={enable}
/> />
)} )}
@ -518,6 +534,7 @@ export default function InscriptionFormShared({
tuitionPaymentPlans={tuitionPaymentPlans} tuitionPaymentPlans={tuitionPaymentPlans}
errors={errors} errors={errors}
setIsPageValid={setIsPage4Valid} setIsPageValid={setIsPage4Valid}
enable={enable}
/> />
</> </>
)} )}
@ -605,18 +622,21 @@ export default function InscriptionFormShared({
)} )}
{/* Dernière page : Section Fichiers parents */} {/* Dernière page : Section Fichiers parents */}
{currentPage === 5 && ( {currentPage === 6 && (
<FilesToUpload <FilesToUpload
parentFileTemplates={parentFileTemplates} parentFileTemplates={parentFileTemplates}
uploadedFiles={uploadedFiles} uploadedFiles={uploadedFiles}
onFileUpload={handleFileUpload} onFileUpload={handleFileUpload}
onFileDelete={handleDeleteFile} onFileDelete={handleDeleteFile}
enable={enable}
/> />
)} )}
</div> </div>
{/* Boutons de contrôle */} {/* Boutons de contrôle */}
<div className="flex justify-center space-x-4 mt-12"> <div className="flex justify-center space-x-4 mt-12">
{enable ? (
<>
{currentPage > 1 && ( {currentPage > 1 && (
<Button <Button
text="Précédent" text="Précédent"
@ -639,7 +659,8 @@ export default function InscriptionFormShared({
(currentPage === 2 && !isPage2Valid) || (currentPage === 2 && !isPage2Valid) ||
(currentPage === 3 && !isPage3Valid) || (currentPage === 3 && !isPage3Valid) ||
(currentPage === 4 && !isPage4Valid) || (currentPage === 4 && !isPage4Valid) ||
(currentPage === 5 && !isPage5Valid) (currentPage === 5 && !isPage5Valid) ||
(currentPage === 6 && !isPage6Valid)
? 'bg-gray-300 text-gray-700 cursor-not-allowed' ? 'bg-gray-300 text-gray-700 cursor-not-allowed'
: 'bg-emerald-500 text-white hover:bg-emerald-600' : 'bg-emerald-500 text-white hover:bg-emerald-600'
}`} }`}
@ -648,23 +669,20 @@ export default function InscriptionFormShared({
(currentPage === 2 && !isPage2Valid) || (currentPage === 2 && !isPage2Valid) ||
(currentPage === 3 && !isPage3Valid) || (currentPage === 3 && !isPage3Valid) ||
(currentPage === 4 && !isPage4Valid) || (currentPage === 4 && !isPage4Valid) ||
(currentPage === 5 && !isPage5Valid) (currentPage === 5 && !isPage5Valid) ||
(currentPage === 6 && !isPage6Valid)
} }
primary primary
name="Next" name="Next"
/> />
)} )}
{currentPage === steps.length && ( </>
) : (
<Button <Button
onClick={handleSubmit} onClick={() => router.push(FE_PARENTS_HOME_URL)}
text="Valider" text="Quitter"
primary primary
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${ className="bg-emerald-500 text-white hover:bg-emerald-600"
currentPage === 6 && !isPage6Valid
? 'bg-gray-300 text-gray-700 cursor-not-allowed'
: 'bg-emerald-500 text-white hover:bg-emerald-600'
}`}
disabled={currentPage === 6 && !isPage6Valid}
/> />
)} )}
</div> </div>

View File

@ -11,6 +11,7 @@ export default function PaymentMethodSelector({
tuitionPaymentPlans, tuitionPaymentPlans,
errors, errors,
setIsPageValid, setIsPageValid,
enable = true,
}) { }) {
useEffect(() => { useEffect(() => {
const isValid = !Object.keys(formData).some( const isValid = !Object.keys(formData).some(
@ -94,6 +95,7 @@ export default function PaymentMethodSelector({
errorMsg={getError('registration_payment')} errorMsg={getError('registration_payment')}
errorLocalMsg={getLocalError('registration_payment')} errorLocalMsg={getLocalError('registration_payment')}
required required
disabled={!enable}
/> />
<RadioList <RadioList
@ -122,6 +124,7 @@ export default function PaymentMethodSelector({
}} }}
fieldName="registration_payment_plan" fieldName="registration_payment_plan"
className="mt-4" className="mt-4"
disabled={!enable}
/> />
</div> </div>
@ -155,6 +158,7 @@ export default function PaymentMethodSelector({
errorMsg={getError('tuition_payment')} errorMsg={getError('tuition_payment')}
errorLocalMsg={getLocalError('tuition_payment')} errorLocalMsg={getLocalError('tuition_payment')}
required required
disabled={!enable}
/> />
<RadioList <RadioList
@ -179,6 +183,7 @@ export default function PaymentMethodSelector({
getError('tuition_payment_plan') || getError('tuition_payment_plan') ||
getLocalError('tuition_payment_plan') getLocalError('tuition_payment_plan')
} }
disabled={!enable}
/> />
</div> </div>
</> </>

View File

@ -11,6 +11,7 @@ export default function ResponsableInputFields({
setGuardians, setGuardians,
errors, errors,
setIsPageValid, setIsPageValid,
enable = true,
}) { }) {
const t = useTranslations('ResponsableInputFields'); const t = useTranslations('ResponsableInputFields');
const { selectedEstablishmentId } = useEstablishment(); const { selectedEstablishmentId } = useEstablishment();
@ -145,6 +146,7 @@ export default function ResponsableInputFields({
errorMsg={getError('last_name')} errorMsg={getError('last_name')}
errorLocalMsg={getLocalError(index, 'last_name')} errorLocalMsg={getLocalError(index, 'last_name')}
required required
enable={enable}
/> />
<InputText <InputText
name="prenomResponsable" name="prenomResponsable"
@ -157,6 +159,7 @@ export default function ResponsableInputFields({
errorMsg={getError('first_name')} errorMsg={getError('first_name')}
errorLocalMsg={getLocalError(index, 'first_name')} errorLocalMsg={getLocalError(index, 'first_name')}
required required
enable={enable}
/> />
</div> </div>
@ -176,6 +179,7 @@ export default function ResponsableInputFields({
errorMsg={getError('associated_profile_email')} errorMsg={getError('associated_profile_email')}
errorLocalMsg={getLocalError(index, 'associated_profile_email')} errorLocalMsg={getLocalError(index, 'associated_profile_email')}
required required
enable={enable}
/> />
<InputPhone <InputPhone
name="telephoneResponsable" name="telephoneResponsable"
@ -187,6 +191,7 @@ export default function ResponsableInputFields({
errorMsg={getError('phone')} errorMsg={getError('phone')}
errorLocalMsg={getLocalError(index, 'phone')} errorLocalMsg={getLocalError(index, 'phone')}
required required
enable={enable}
/> />
</div> </div>
@ -202,6 +207,7 @@ export default function ResponsableInputFields({
errorMsg={getError('birth_date')} errorMsg={getError('birth_date')}
errorLocalMsg={getLocalError(index, 'birth_date')} errorLocalMsg={getLocalError(index, 'birth_date')}
required required
enable={enable}
/> />
<InputText <InputText
name="professionResponsable" name="professionResponsable"
@ -214,6 +220,7 @@ export default function ResponsableInputFields({
errorMsg={getError('profession')} errorMsg={getError('profession')}
errorLocalMsg={getLocalError(index, 'profession')} errorLocalMsg={getLocalError(index, 'profession')}
required required
enable={enable}
/> />
</div> </div>
@ -229,11 +236,13 @@ export default function ResponsableInputFields({
errorMsg={getError('address')} errorMsg={getError('address')}
errorLocalMsg={getLocalError(index, 'address')} errorLocalMsg={getLocalError(index, 'address')}
required required
enable={enable}
/> />
</div> </div>
</div> </div>
))} ))}
{enable && (
<div className="flex justify-center"> <div className="flex justify-center">
<Plus <Plus
className={`w-8 h-8 ${ className={`w-8 h-8 ${
@ -252,6 +261,7 @@ export default function ResponsableInputFields({
}} }}
/> />
</div> </div>
)}
</div> </div>
); );
} }

View File

@ -10,6 +10,7 @@ export default function SiblingInputFields({
setFormData, setFormData,
errors, errors,
setIsPageValid, setIsPageValid,
enable = true,
}) { }) {
const getError = (index, field) => { const getError = (index, field) => {
return errors[index]?.[field]?.[0]; return errors[index]?.[field]?.[0];
@ -121,6 +122,7 @@ export default function SiblingInputFields({
errorMsg={getError('last_name')} errorMsg={getError('last_name')}
errorLocalMsg={getLocalError(index, 'last_name')} errorLocalMsg={getLocalError(index, 'last_name')}
required required
enable={enable}
/> />
<InputText <InputText
name="first_name" name="first_name"
@ -133,6 +135,7 @@ export default function SiblingInputFields({
errorMsg={getError('first_name')} errorMsg={getError('first_name')}
errorLocalMsg={getLocalError(index, 'first_name')} errorLocalMsg={getLocalError(index, 'first_name')}
required required
enable={enable}
/> />
</div> </div>
@ -148,17 +151,20 @@ export default function SiblingInputFields({
errorMsg={getError('birth_date')} errorMsg={getError('birth_date')}
errorLocalMsg={getLocalError(index, 'birth_date')} errorLocalMsg={getLocalError(index, 'birth_date')}
required required
enable={enable}
/> />
</div> </div>
</div> </div>
))} ))}
{enable && (
<div className="flex justify-center"> <div className="flex justify-center">
<Plus <Plus
className="w-8 h-8 text-green-500 cursor-pointer hover:text-green-700 transition-colors border-2 border-green-500 hover:border-green-700 rounded-full p-1" className="w-8 h-8 text-green-500 cursor-pointer hover:text-green-700 transition-colors border-2 border-green-500 hover:border-green-700 rounded-full p-1"
onClick={addSibling} onClick={addSibling}
/> />
</div> </div>
)}
</div> </div>
); );
} }

View File

@ -36,6 +36,7 @@ export default function StudentInfoForm({
setIsPageValid, setIsPageValid,
hasInteracted, hasInteracted,
setHasInteracted, setHasInteracted,
enable = true,
}) { }) {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
@ -181,6 +182,7 @@ export default function StudentInfoForm({
required required
errorMsg={getError('last_name')} errorMsg={getError('last_name')}
errorLocalMsg={getLocalError('last_name')} errorLocalMsg={getLocalError('last_name')}
enable={enable}
/> />
<InputText <InputText
name="first_name" name="first_name"
@ -190,6 +192,7 @@ export default function StudentInfoForm({
errorMsg={getError('first_name')} errorMsg={getError('first_name')}
errorLocalMsg={getLocalError('first_name')} errorLocalMsg={getLocalError('first_name')}
required required
enable={enable}
/> />
<SelectChoice <SelectChoice
name="gender" name="gender"
@ -201,6 +204,7 @@ export default function StudentInfoForm({
required required
errorMsg={getError('gender')} errorMsg={getError('gender')}
errorLocalMsg={getLocalError('gender')} errorLocalMsg={getLocalError('gender')}
disabled={!enable}
/> />
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8"> <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
@ -213,6 +217,7 @@ export default function StudentInfoForm({
required required
errorMsg={getError('birth_date')} errorMsg={getError('birth_date')}
errorLocalMsg={getLocalError('birth_date')} errorLocalMsg={getLocalError('birth_date')}
enable={enable}
/> />
<InputText <InputText
name="birth_place" name="birth_place"
@ -222,6 +227,7 @@ export default function StudentInfoForm({
required required
errorMsg={getError('birth_place')} errorMsg={getError('birth_place')}
errorLocalMsg={getLocalError('birth_place')} errorLocalMsg={getLocalError('birth_place')}
enable={enable}
/> />
<InputText <InputText
name="birth_postal_code" name="birth_postal_code"
@ -231,6 +237,7 @@ export default function StudentInfoForm({
required required
errorMsg={getError('birth_postal_code')} errorMsg={getError('birth_postal_code')}
errorLocalMsg={getLocalError('birth_postal_code')} errorLocalMsg={getLocalError('birth_postal_code')}
enable={enable}
/> />
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
@ -242,6 +249,7 @@ export default function StudentInfoForm({
onChange={(e) => onChange('nationality', e.target.value)} onChange={(e) => onChange('nationality', e.target.value)}
errorMsg={getError('nationality')} errorMsg={getError('nationality')}
errorLocalMsg={getLocalError('nationality')} errorLocalMsg={getLocalError('nationality')}
enable={enable}
/> />
<InputText <InputText
name="address" name="address"
@ -251,6 +259,7 @@ export default function StudentInfoForm({
required required
errorMsg={getError('address')} errorMsg={getError('address')}
errorLocalMsg={getLocalError('address')} errorLocalMsg={getLocalError('address')}
enable={enable}
/> />
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
@ -262,6 +271,7 @@ export default function StudentInfoForm({
required required
errorMsg={getError('attending_physician')} errorMsg={getError('attending_physician')}
errorLocalMsg={getLocalError('attending_physician')} errorLocalMsg={getLocalError('attending_physician')}
enable={enable}
/> />
<SelectChoice <SelectChoice
name="level" name="level"
@ -273,6 +283,7 @@ export default function StudentInfoForm({
required required
errorMsg={getError('level')} errorMsg={getError('level')}
errorLocalMsg={getLocalError('level')} errorLocalMsg={getLocalError('level')}
disabled={!enable}
/> />
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-1 gap-8"> <div className="grid grid-cols-1 md:grid-cols-1 gap-8">
@ -281,6 +292,7 @@ export default function StudentInfoForm({
onFileSelect={(file) => handlePhotoUpload(file)} onFileSelect={(file) => handlePhotoUpload(file)}
existingFile={formData.photo} existingFile={formData.photo}
errorMsg={getError('photo')} errorMsg={getError('photo')}
enable={enable}
/> />
</div> </div>
</div> </div>

View File

@ -9,6 +9,7 @@ const RadioList = ({
className, className,
sectionLabel, sectionLabel,
required, required,
disabled = false,
}) => { }) => {
return ( return (
<div className={`mb-4 ${className}`}> <div className={`mb-4 ${className}`}>
@ -20,7 +21,12 @@ const RadioList = ({
)} )}
<div className="grid grid-cols-1 gap-4"> <div className="grid grid-cols-1 gap-4">
{items.map((item) => ( {items.map((item) => (
<div key={item.id} className="flex items-center"> <div
key={item.id}
className={`flex items-center ${
disabled ? 'opacity-50 cursor-not-allowed' : ''
}`}
>
<input <input
key={`${item.id}-${Math.random()}`} key={`${item.id}-${Math.random()}`}
type="radio" type="radio"
@ -31,10 +37,13 @@ const RadioList = ({
onChange={handleChange} onChange={handleChange}
className="form-radio h-4 w-4 text-emerald-600 focus:ring-emerald-500 hover:ring-emerald-400 checked:bg-emerald-600 cursor-pointer" className="form-radio h-4 w-4 text-emerald-600 focus:ring-emerald-500 hover:ring-emerald-400 checked:bg-emerald-600 cursor-pointer"
style={{ outline: 'none', boxShadow: 'none' }} style={{ outline: 'none', boxShadow: 'none' }}
disabled={disabled}
/> />
<label <label
htmlFor={`${fieldName}-${item.id}`} htmlFor={`${fieldName}-${item.id}`}
className="ml-2 block text-sm text-gray-900 flex items-center cursor-pointer" className={`ml-2 block text-sm text-gray-900 flex items-center ${
disabled ? 'cursor-not-allowed' : 'cursor-pointer'
}`}
> >
{item.label} {item.label}
</label> </label>

View File

@ -10,6 +10,7 @@ const StatusLabel = ({ status, onChange, showDropdown = true, parent }) => {
? [ ? [
{ value: 2, label: 'Nouveau' }, { value: 2, label: 'Nouveau' },
{ value: 3, label: 'En validation' }, { value: 3, label: 'En validation' },
{ value: 5, label: 'Validé' },
{ value: 7, label: 'SEPA reçu' }, { value: 7, label: 'SEPA reçu' },
{ value: 8, label: 'En validation' }, { value: 8, label: 'En validation' },
] ]
@ -32,6 +33,7 @@ const StatusLabel = ({ status, onChange, showDropdown = true, parent }) => {
return ( return (
(status === 2 && 'bg-orange-50 text-orange-600') || (status === 2 && 'bg-orange-50 text-orange-600') ||
((status === 3 || status === 8) && 'bg-purple-50 text-purple-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') (status === 7 && 'bg-yellow-50 text-yellow-600')
); );
} }

View File

@ -15,7 +15,7 @@ import { useEstablishment } from '@/context/EstablishmentContext';
import { FE_ADMIN_STRUCTURE_SCHOOLCLASS_MANAGEMENT_URL } from '@/utils/Url'; import { FE_ADMIN_STRUCTURE_SCHOOLCLASS_MANAGEMENT_URL } from '@/utils/Url';
import { usePlanning } from '@/context/PlanningContext'; import { usePlanning } from '@/context/PlanningContext';
import { useClasses } from '@/context/ClassesContext'; import { useClasses } from '@/context/ClassesContext';
import { useRouter } from 'next/navigation';
const ItemTypes = { const ItemTypes = {
TEACHER: 'teacher', TEACHER: 'teacher',
@ -119,7 +119,6 @@ const ClassesSection = ({
handleCreate, handleCreate,
handleEdit, handleEdit,
handleDelete, handleDelete,
}) => { }) => {
const [formData, setFormData] = useState({}); const [formData, setFormData] = useState({});
const [editingClass, setEditingClass] = useState(null); const [editingClass, setEditingClass] = useState(null);
@ -135,7 +134,7 @@ const ClassesSection = ({
const { selectedEstablishmentId } = useEstablishment(); const { selectedEstablishmentId } = useEstablishment();
const { addSchedule, reloadPlanning, reloadEvents } = usePlanning(); 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 // Fonction pour générer les années scolaires
const getSchoolYearChoices = () => { const getSchoolYearChoices = () => {
@ -222,10 +221,9 @@ const ClassesSection = ({
name: planningName, name: planningName,
color: '#FF5733', // Couleur par défaut color: '#FF5733', // Couleur par défaut
school_class: createdClass.id, school_class: createdClass.id,
} };
addSchedule(newPlanning) addSchedule(newPlanning);
}); });
}) })
.catch((error) => { .catch((error) => {
logger.error('Error:', error.message); logger.error('Error:', error.message);

View File

@ -9,12 +9,12 @@ export default function ScheduleEventModal({
setEventData, setEventData,
specialities, specialities,
teachers, teachers,
classes classes,
}) { }) {
const { addEvent, handleUpdateEvent, handleDeleteEvent, schedules } = usePlanning(); const { addEvent, handleUpdateEvent, handleDeleteEvent, schedules } =
usePlanning();
React.useEffect(() => { React.useEffect(() => {
if (!eventData?.planning && schedules.length > 0) { if (!eventData?.planning && schedules.length > 0) {
const defaultSchedule = schedules[0]; const defaultSchedule = schedules[0];
if (eventData?.planning !== defaultSchedule.id) { if (eventData?.planning !== defaultSchedule.id) {
@ -26,9 +26,10 @@ export default function ScheduleEventModal({
} }
}, [schedules, eventData?.planning]); }, [schedules, eventData?.planning]);
const handleSpecialityChange = (specialityId) => { 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) { if (selectedSpeciality) {
setEventData((prev) => ({ setEventData((prev) => ({
...prev, ...prev,
@ -40,7 +41,9 @@ export default function ScheduleEventModal({
}; };
const handleTeacherChange = (teacherId) => { 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) { if (selectedTeacher) {
setEventData((prev) => ({ setEventData((prev) => ({
...prev, ...prev,
@ -51,7 +54,9 @@ export default function ScheduleEventModal({
}; };
const handlePlanningChange = (planningId) => { 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) { if (selectedSchedule) {
setEventData((prev) => ({ setEventData((prev) => ({
...prev, ...prev,

View File

@ -8,9 +8,11 @@ import Calendar from '@/components/Calendar/Calendar';
import ScheduleEventModal from '@/components/Structure/Planning/ScheduleEventModal'; import ScheduleEventModal from '@/components/Structure/Planning/ScheduleEventModal';
import ScheduleNavigation from '@/components/Calendar/ScheduleNavigation'; import ScheduleNavigation from '@/components/Calendar/ScheduleNavigation';
export default function ScheduleManagement({
classes,
export default function ScheduleManagement({classes,specialities,teachers}) { specialities,
teachers,
}) {
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [eventData, setEventData] = useState({ const [eventData, setEventData] = useState({
title: '', title: '',
@ -71,4 +73,3 @@ export default function ScheduleManagement({classes,specialities,teachers}) {
</div> </div>
); );
} }

View File

@ -116,7 +116,6 @@ export const ClassesProvider = ({ children }) => {
} }
}; };
const groupSpecialitiesBySubject = (teachers) => { const groupSpecialitiesBySubject = (teachers) => {
const groupedSpecialities = {}; const groupedSpecialities = {};
@ -142,7 +141,6 @@ export const ClassesProvider = ({ children }) => {
return Object.values(groupedSpecialities); return Object.values(groupedSpecialities);
}; };
return ( return (
<ClassesContext.Provider <ClassesContext.Provider
value={{ value={{

View File

@ -33,11 +33,13 @@ export const RecurrenceType = Object.freeze({
export const PlanningModes = Object.freeze({ export const PlanningModes = Object.freeze({
CLASS_SCHEDULE: 'classSchedule', CLASS_SCHEDULE: 'classSchedule',
PLANNING: 'planning' PLANNING: 'planning',
}); });
export function PlanningProvider({ children, modeSet=PlanningModes.PLANNING}) { export function PlanningProvider({
children,
modeSet = PlanningModes.PLANNING,
}) {
const [events, setEvents] = useState([]); const [events, setEvents] = useState([]);
const [schedules, setSchedules] = useState([]); const [schedules, setSchedules] = useState([]);
const [selectedSchedule, setSelectedSchedule] = useState(0); const [selectedSchedule, setSelectedSchedule] = useState(0);
@ -53,12 +55,11 @@ export function PlanningProvider({ children, modeSet=PlanningModes.PLANNING}) {
reloadEvents(); reloadEvents();
}, [planningMode, selectedEstablishmentId]); }, [planningMode, selectedEstablishmentId]);
const reloadEvents = () => { const reloadEvents = () => {
fetchEvents(selectedEstablishmentId, planningMode).then((data) => { fetchEvents(selectedEstablishmentId, planningMode).then((data) => {
setEvents(data); setEvents(data);
}); });
} };
const reloadPlanning = () => { const reloadPlanning = () => {
fetchPlannings(selectedEstablishmentId, planningMode).then((data) => { fetchPlannings(selectedEstablishmentId, planningMode).then((data) => {
@ -67,7 +68,7 @@ const reloadPlanning = () =>{
setSelectedSchedule(data[0].id); setSelectedSchedule(data[0].id);
} }
}); });
} };
const addEvent = (newEvent) => { const addEvent = (newEvent) => {
createEvent(newEvent).then(() => { createEvent(newEvent).then(() => {
reloadEvents(); reloadEvents();

View File

@ -1,4 +1,3 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;