refactor: refactoring du FRONT page subscribe

This commit is contained in:
Luc SORIGNET
2025-01-12 14:37:49 +01:00
parent 58fe509734
commit 427b6c7588
25 changed files with 671 additions and 652 deletions

View File

@ -16,15 +16,15 @@ import {
import DropdownMenu from '@/components/DropdownMenu'; import DropdownMenu from '@/components/DropdownMenu';
import Logo from '@/components/Logo'; import Logo from '@/components/Logo';
import { import {
FR_ADMIN_HOME_URL, FE_ADMIN_HOME_URL,
FR_ADMIN_SUBSCRIPTIONS_URL, FE_ADMIN_SUBSCRIPTIONS_URL,
FR_ADMIN_STRUCTURE_URL, FE_ADMIN_STRUCTURE_URL,
FR_ADMIN_GRADES_URL, FE_ADMIN_GRADES_URL,
FR_ADMIN_PLANNING_URL, FE_ADMIN_PLANNING_URL,
FR_ADMIN_SETTINGS_URL FE_ADMIN_SETTINGS_URL
} from '@/utils/Url'; } from '@/utils/Url';
import { disconnect } from '@/app/lib/actions'; import { disconnect } from '@/app/lib/authAction';
export default function Layout({ export default function Layout({
children, children,
@ -32,12 +32,12 @@ export default function Layout({
const t = useTranslations('sidebar'); const t = useTranslations('sidebar');
const sidebarItems = { const sidebarItems = {
"admin": { "id": "admin", "name": t('dashboard'), "url": FR_ADMIN_HOME_URL, "icon": Home }, "admin": { "id": "admin", "name": t('dashboard'), "url": FE_ADMIN_HOME_URL, "icon": Home },
"subscriptions": { "id": "subscriptions", "name": t('subscriptions'), "url": FR_ADMIN_SUBSCRIPTIONS_URL, "icon": Users }, "subscriptions": { "id": "subscriptions", "name": t('subscriptions'), "url": FE_ADMIN_SUBSCRIPTIONS_URL, "icon": Users },
"structure": { "id": "structure", "name": t('structure'), "url": FR_ADMIN_STRUCTURE_URL, "icon": Building }, "structure": { "id": "structure", "name": t('structure'), "url": FE_ADMIN_STRUCTURE_URL, "icon": Building },
"grades": { "id": "grades", "name": t('grades'), "url": FR_ADMIN_GRADES_URL, "icon": FileText }, "grades": { "id": "grades", "name": t('grades'), "url": FE_ADMIN_GRADES_URL, "icon": FileText },
"planning": { "id": "planning", "name": t('planning'), "url": FR_ADMIN_PLANNING_URL, "icon": Calendar }, "planning": { "id": "planning", "name": t('planning'), "url": FE_ADMIN_PLANNING_URL, "icon": Calendar },
"settings": { "id": "settings", "name": t('settings'), "url": FR_ADMIN_SETTINGS_URL, "icon": Settings } "settings": { "id": "settings", "name": t('settings'), "url": FE_ADMIN_SETTINGS_URL, "icon": Settings }
}; };
const pathname = usePathname(); const pathname = usePathname();

View File

@ -4,7 +4,7 @@ import React, { useState, useEffect } from 'react';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { Users, Clock, CalendarCheck, School, TrendingUp, UserCheck } from 'lucide-react'; import { Users, Clock, CalendarCheck, School, TrendingUp, UserCheck } from 'lucide-react';
import Loader from '@/components/Loader'; import Loader from '@/components/Loader';
import { BK_GESTIONENSEIGNANTS_CLASSES_URL } from '@/utils/Url'; import { BE_SCHOOL_SCHOOLCLASSES_URL } from '@/utils/Url';
import ClasseDetails from '@/components/ClasseDetails'; import ClasseDetails from '@/components/ClasseDetails';
// Composant StatCard pour afficher une statistique // Composant StatCard pour afficher une statistique
@ -59,7 +59,7 @@ export default function DashboardPage() {
const [classes, setClasses] = useState([]); const [classes, setClasses] = useState([]);
const fetchClasses = () => { const fetchClasses = () => {
fetch(`${BK_GESTIONENSEIGNANTS_CLASSES_URL}`) fetch(`${BE_SCHOOL_SCHOOLCLASSES_URL}`)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
setClasses(data); setClasses(data);

View File

@ -4,10 +4,10 @@ import { School, Calendar } from 'lucide-react';
import TabsStructure from '@/components/Structure/Configuration/TabsStructure'; import TabsStructure from '@/components/Structure/Configuration/TabsStructure';
import ScheduleManagement from '@/components/Structure/Planning/ScheduleManagement' import ScheduleManagement from '@/components/Structure/Planning/ScheduleManagement'
import StructureManagement from '@/components/Structure/Configuration/StructureManagement' import StructureManagement from '@/components/Structure/Configuration/StructureManagement'
import { BK_GESTIONENSEIGNANTS_SPECIALITES_URL, import { BE_SCHOOL_SPECIALITIES_URL,
BK_GESTIONENSEIGNANTS_CLASSES_URL, BE_SCHOOL_SCHOOLCLASSES_URL,
BK_GESTIONENSEIGNANTS_TEACHERS_URL, BE_SCHOOL_TEACHERS_URL,
BK_GESTIONENSEIGNANTS_PLANNINGS_URL } from '@/utils/Url'; BE_SCHOOL_PLANNINGS_URL } from '@/utils/Url';
import DjangoCSRFToken from '@/components/DjangoCSRFToken' import DjangoCSRFToken from '@/components/DjangoCSRFToken'
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
import { ClassesProvider } from '@/context/ClassesContext'; import { ClassesProvider } from '@/context/ClassesContext';
@ -34,13 +34,13 @@ export default function Page() {
// Fetch data for classes // Fetch data for classes
fetchClasses(); fetchClasses();
// Fetch data for schedules // Fetch data for schedules
fetchSchedules(); fetchSchedules();
}, []); }, []);
const fetchSpecialities = () => { const fetchSpecialities = () => {
fetch(`${BK_GESTIONENSEIGNANTS_SPECIALITES_URL}`) fetch(`${BE_SCHOOL_SPECIALITIES_URL}`)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
setSpecialities(data); setSpecialities(data);
@ -51,7 +51,7 @@ export default function Page() {
}; };
const fetchTeachers = () => { const fetchTeachers = () => {
fetch(`${BK_GESTIONENSEIGNANTS_TEACHERS_URL}`) fetch(`${BE_SCHOOL_TEACHERS_URL}`)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
setTeachers(data); setTeachers(data);
@ -62,7 +62,7 @@ export default function Page() {
}; };
const fetchClasses = () => { const fetchClasses = () => {
fetch(`${BK_GESTIONENSEIGNANTS_CLASSES_URL}`) fetch(`${BE_SCHOOL_SCHOOLCLASSES_URL}`)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
setClasses(data); setClasses(data);
@ -73,7 +73,7 @@ export default function Page() {
}; };
const fetchSchedules = () => { const fetchSchedules = () => {
fetch(`${BK_GESTIONENSEIGNANTS_PLANNINGS_URL}`) fetch(`${BE_SCHOOL_PLANNINGS_URL}`)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
setSchedules(data); setSchedules(data);
@ -141,13 +141,13 @@ export default function Page() {
console.error('Erreur :', error); console.error('Erreur :', error);
}); });
}; };
const handleDelete = (url, id, setDatas) => { const handleDelete = (url, id, setDatas) => {
fetch(`${url}/${id}`, { fetch(`${url}/${id}`, {
method:'DELETE', method:'DELETE',
headers: { headers: {
'Content-Type':'application/json', 'Content-Type':'application/json',
'X-CSRFToken': csrfToken 'X-CSRFToken': csrfToken
}, },
credentials: 'include' credentials: 'include'
@ -172,12 +172,12 @@ export default function Page() {
{activeTab === 'Configuration' && ( {activeTab === 'Configuration' && (
<> <>
<StructureManagement <StructureManagement
specialities={specialities} specialities={specialities}
setSpecialities={setSpecialities} setSpecialities={setSpecialities}
teachers={teachers} teachers={teachers}
setTeachers={setTeachers} setTeachers={setTeachers}
classes={classes} classes={classes}
setClasses={setClasses} setClasses={setClasses}
handleCreate={handleCreate} handleCreate={handleCreate}
handleEdit={handleEdit} handleEdit={handleEdit}
@ -190,7 +190,7 @@ export default function Page() {
<ScheduleManagement <ScheduleManagement
handleUpdatePlanning={handleUpdatePlanning} handleUpdatePlanning={handleUpdatePlanning}
classes={classes} classes={classes}
/> />
</ClassesProvider> </ClassesProvider>
)} )}
</div> </div>

View File

@ -34,11 +34,11 @@ export default function FileUpload({ onFileUpload }) {
}; };
const handleUpload = () => { const handleUpload = () => {
if (file) {
onFileUpload(file, fileName); onFileUpload(file, fileName);
setFile(null); setFile(null);
setFileName(''); setFileName('');
}
}; };
return ( return (
@ -66,8 +66,8 @@ export default function FileUpload({ onFileUpload }) {
/> />
<button <button
onClick={handleUpload} onClick={handleUpload}
className={`p-2 rounded-md shadow transition duration-200 ml-2 ${file ? 'bg-emerald-600 text-white hover:bg-emerald-900' : 'bg-gray-300 text-gray-500 cursor-not-allowed'}`} className={`p-2 rounded-md shadow transition duration-200 ml-2 ${fileName!="" ? 'bg-emerald-600 text-white hover:bg-emerald-900' : 'bg-gray-300 text-gray-500 cursor-not-allowed'}`}
disabled={!file} disabled={fileName==""}
> >
Ajouter Ajouter
</button> </button>

View File

@ -2,9 +2,9 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared'; import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared';
import { FR_ADMIN_SUBSCRIPTIONS_URL, import { FE_ADMIN_SUBSCRIPTIONS_URL,
BK_GESTIONINSCRIPTION_ELEVE_URL, BE_SUBSCRIPTION_STUDENT_URL,
BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL } from '@/utils/Url'; BE_SUBSCRIPTION_REGISTERFORM_URL } from '@/utils/Url';
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
import { mockStudent } from '@/data/mockStudent'; import { mockStudent } from '@/data/mockStudent';
@ -13,7 +13,7 @@ const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
export default function Page() { export default function Page() {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const idProfil = searchParams.get('id'); const idProfil = searchParams.get('id');
const idEleve = searchParams.get('idEleve'); // Changé de codeDI à idEleve const studentId = searchParams.get('studentId'); // Changé de codeDI à studentId
const [initialData, setInitialData] = useState(null); const [initialData, setInitialData] = useState(null);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
@ -24,7 +24,7 @@ export default function Page() {
setInitialData(mockStudent); setInitialData(mockStudent);
setIsLoading(false); setIsLoading(false);
} else { } else {
fetch(`${BK_GESTIONINSCRIPTION_ELEVE_URL}/${idEleve}`) // Utilisation de idEleve au lieu de codeDI fetch(`${BE_SUBSCRIPTION_STUDENT_URL}/${studentId}`) // Utilisation de studentId au lieu de codeDI
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
console.log('Fetched data:', data); // Pour le débogage console.log('Fetched data:', data); // Pour le débogage
@ -49,7 +49,7 @@ export default function Page() {
setIsLoading(false); setIsLoading(false);
}); });
} }
}, [idEleve]); // Dépendance changée à idEleve }, [studentId]); // Dépendance changée à studentId
const handleSubmit = async (data) => { const handleSubmit = async (data) => {
if (useFakeData) { if (useFakeData) {
@ -58,7 +58,7 @@ export default function Page() {
} }
try { try {
const response = await fetch(`${BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL}/${idEleve}`, { // Utilisation de idEleve const response = await fetch(`${BE_SUBSCRIPTION_REGISTERFORM_URL}/${studentId}`, { // Utilisation de studentId
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -72,7 +72,7 @@ export default function Page() {
const result = await response.json(); const result = await response.json();
console.log('Success:', result); console.log('Success:', result);
// Redirection après succès // Redirection après succès
window.location.href = FR_ADMIN_SUBSCRIPTIONS_URL; window.location.href = FE_ADMIN_SUBSCRIPTIONS_URL;
} catch (error) { } catch (error) {
console.error('Error:', error); console.error('Error:', error);
alert('Une erreur est survenue lors de la mise à jour des données'); alert('Une erreur est survenue lors de la mise à jour des données');
@ -84,7 +84,7 @@ export default function Page() {
initialData={initialData} initialData={initialData}
csrfToken={csrfToken} csrfToken={csrfToken}
onSubmit={handleSubmit} onSubmit={handleSubmit}
cancelUrl={FR_ADMIN_SUBSCRIPTIONS_URL} cancelUrl={FE_ADMIN_SUBSCRIPTIONS_URL}
isLoading={isLoading} isLoading={isLoading}
/> />
); );

View File

@ -9,25 +9,33 @@ import { Search } from 'lucide-react';
import Popup from '@/components/Popup'; import Popup from '@/components/Popup';
import Loader from '@/components/Loader'; import Loader from '@/components/Loader';
import AlertWithModal from '@/components/AlertWithModal'; import AlertWithModal from '@/components/AlertWithModal';
import Button from '@/components/Button';
import DropdownMenu from "@/components/DropdownMenu"; import DropdownMenu from "@/components/DropdownMenu";
import { swapFormatDate } from '@/utils/Date';
import { formatPhoneNumber } from '@/utils/Telephone'; import { formatPhoneNumber } from '@/utils/Telephone';
import { MoreVertical, Send, Edit, Trash2, FileText, ChevronUp, UserPlus, CheckCircle, Plus, Download } from 'lucide-react'; import { MoreVertical, Send, Edit, Trash2, FileText, CheckCircle, Plus, Download } from 'lucide-react';
import Modal from '@/components/Modal'; import Modal from '@/components/Modal';
import InscriptionForm from '@/components/Inscription/InscriptionForm' import InscriptionForm from '@/components/Inscription/InscriptionForm'
import AffectationClasseForm from '@/components/AffectationClasseForm' import AffectationClasseForm from '@/components/AffectationClasseForm'
import FileUpload from './components/FileUpload'; import FileUpload from './components/FileUpload';
import { BASE_URL, BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL, import {
BK_GESTIONINSCRIPTION_SEND_URL, PENDING,
FR_ADMIN_SUBSCRIPTIONS_EDIT_URL, SUBSCRIBED,
BK_GESTIONINSCRIPTION_ARCHIVE_URL, ARCHIVED,
BK_GESTIONENSEIGNANTS_CLASSES_URL, fetchRegisterForm,
BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL, createRegisterForm,
BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL , sendRegisterForm,
BK_GESTIONINSCRIPTION_ELEVES_URL, archiveRegisterForm,
BK_PROFILE_URL } from '@/utils/Url'; fetchRegisterFormFileTemplate,
deleteRegisterFormFileTemplate,
fetchStudents,
editRegisterForm } from "@/app/lib/subscriptionAction"
import { fetchClasses } from '@/app/lib/schoolAction';
import { createProfile } from '@/app/lib/authAction';
import {
BASE_URL,
FE_ADMIN_SUBSCRIPTIONS_EDIT_URL } from '@/utils/Url';
import DjangoCSRFToken from '@/components/DjangoCSRFToken' import DjangoCSRFToken from '@/components/DjangoCSRFToken'
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
@ -56,14 +64,13 @@ export default function Page({ params: { locale } }) {
const [itemsPerPage, setItemsPerPage] = useState(5); // Définir le nombre d'éléments par page const [itemsPerPage, setItemsPerPage] = useState(5); // Définir le nombre d'éléments par page
const [fichiers, setFichiers] = useState([]); const [fichiers, setFichiers] = useState([]);
const [nomFichier, setNomFichier] = useState('');
const [fichier, setFichier] = useState(null);
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [isOpenAffectationClasse, setIsOpenAffectationClasse] = useState(false); const [isOpenAffectationClasse, setIsOpenAffectationClasse] = useState(false);
const [eleve, setEleve] = useState(''); const [student, setStudent] = useState('');
const [classes, setClasses] = useState([]); const [classes, setClasses] = useState([]);
const [eleves, setEleves] = useState([]); const [students, setEleves] = useState([]);
const csrfToken = useCsrfToken(); const csrfToken = useCsrfToken();
@ -77,152 +84,90 @@ export default function Page({ params: { locale } }) {
const openModalAssociationEleve = (eleveSelected) => { const openModalAssociationEleve = (eleveSelected) => {
setIsOpenAffectationClasse(true); setIsOpenAffectationClasse(true);
setEleve(eleveSelected); setStudent(eleveSelected);
} }
// Modifier la fonction fetchData pour inclure le terme de recherche
const fetchData = (page, pageSize, search = '') => {
const url = `${BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL}/pending?page=${page}&page_size=${pageSize}&search=${search}`;
fetch(url, {
headers: {
'Content-Type': 'application/json',
},
}).then(response => response.json())
.then(data => {
setIsLoading(false);
if (data) {
const { fichesInscriptions, count } = data;
if (ficheInscriptions) {
setFichesInscriptionsDataEnCours(fichesInscriptions);
}
const calculatedTotalPages = count === 0 ? 1 : Math.ceil(count / pageSize);
setTotalPending(count);
setTotalPages(calculatedTotalPages);
}
console.log('Success PENDING:', data);
})
.catch(error => {
console.error('Error fetching data:', error);
setIsLoading(false);
});
};
const fetchDataSubscribed = () => { const requestErrorHandler = (err)=>{
fetch(`${BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL}/subscribed`, { setIsLoading(false);
headers: { }
'Content-Type': 'application/json',
},
}).then(response => response.json())
.then(data => {
setIsLoading(false);
if (data) {
const { fichesInscriptions, count } = data;
setTotalSubscribed(count);
if (fichesInscriptions) {
setFichesInscriptionsDataInscrits(fichesInscriptions);
}
}
console.log('Success SUBSCRIBED:', data);
})
.catch(error => {
console.error('Error fetching data:', error);
setIsLoading(false);
});
};
const fetchDataArchived = () => { const registerFormPendingDataHandler = (data) => {
fetch(`${BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL}/archived`, { setIsLoading(false);
headers: { if (data) {
'Content-Type': 'application/json', const { registerForms, count } = data;
}, if (registerForms) {
}).then(response => response.json()) setFichesInscriptionsDataEnCours(registerForms);
.then(data => { }
setIsLoading(false); const calculatedTotalPages = count === 0 ? 1 : Math.ceil(count / pageSize);
if (data) { setTotalPending(count);
const { fichesInscriptions, count } = data; setTotalPages(calculatedTotalPages);
setTotalArchives(count); }
if (fichesInscriptions) { }
setFichesInscriptionsDataArchivees(fichesInscriptions);
}
}
console.log('Success ARCHIVED:', data);
})
.catch(error => {
console.error('Error fetching data:', error);
setIsLoading(false);
});
};
const fetchClasses = () => { const registerFormSubscribedDataHandler = (data) => {
fetch(`${BK_GESTIONENSEIGNANTS_CLASSES_URL}`) setIsLoading(false);
.then(response => response.json()) if (data) {
.then(data => { const { registerForms, count } = data;
setTotalSubscribed(count);
if (registerForms) {
setFichesInscriptionsDataInscrits(registerForms);
}
}
}
const registerFormArchivedDataHandler = (data) => {
setIsLoading(false);
if (data) {
const { registerForms, count } = data;
setTotalArchives(count);
if (registerForms) {
setFichesInscriptionsDataArchivees(registerForms);
}
}
}
useEffect(() => {
fetchRegisterFormFileTemplate()
.then((data)=> {setFichiers(data)})
.catch((err)=>{ err = err.message; console.log(err);});
}, []);
useEffect(() => {
fetchClasses()
.then(data => {
setClasses(data); setClasses(data);
console.log("Success CLASSES : ", data) console.log("Success CLASSES : ", data)
}) })
.catch(error => { .catch(error => {
console.error('Error fetching classes:', error); console.error('Error fetching classes:', error);
}); });
}; fetchStudents()
.then(data => {
const fetchStudents = () => { console.log('Success STUDENTS:', data);
const request = new Request( setEleves(data);
`${BK_GESTIONINSCRIPTION_ELEVES_URL}`, })
{ .catch(error => {
method:'GET', console.error('Error fetching data:', error);
headers: { error = error.message;
'Content-Type':'application/json' console.log(error);
},
}
);
fetch(request).then(response => response.json())
.then(data => {
console.log('Success STUDENTS:', data);
setEleves(data);
})
.catch(error => {
console.error('Error fetching data:', error);
error = error.message;
console.log(error);
}); });
};
useEffect(() => {
const fetchFichiers = () => {
const request = new Request(
`${BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL}`,
{
method:'GET',
headers: {
'Content-Type':'application/json'
},
}
);
fetch(request).then(response => response.json())
.then(data => {
console.log('Success FILES:', data);
setFichiers(data);
})
.catch(error => {
console.error('Error fetching data:', error);
error = error.message;
console.log(error);
});
};
fetchFichiers();
}, []);
useEffect(() => {
fetchClasses();
fetchStudents();
}, [fichesInscriptionsDataEnCours]); }, [fichesInscriptionsDataEnCours]);
useEffect(() => { useEffect(() => {
const fetchDataAndSetState = () => { const fetchDataAndSetState = () => {
if (!useFakeData) { if (!useFakeData) {
fetchData(currentPage, itemsPerPage, searchTerm); fetchRegisterForm(PENDING, currentPage, itemsPerPage, searchTerm)
fetchDataSubscribed(); .then(registerFormPendingDataHandler)
fetchDataArchived(); .catch(requestErrorHandler)
fetchRegisterForm(SUBSCRIBED)
.then(registerFormSubscribedDataHandler)
.catch(requestErrorHandler)
fetchRegisterForm(ARCHIVED)
.then(registerFormArchivedDataHandler)
.catch(requestErrorHandler)
} else { } else {
setTimeout(() => { setTimeout(() => {
setFichesInscriptionsDataEnCours(mockFicheInscription); setFichesInscriptionsDataEnCours(mockFicheInscription);
@ -239,7 +184,9 @@ export default function Page({ params: { locale } }) {
// Modifier le useEffect pour la recherche // Modifier le useEffect pour la recherche
useEffect(() => { useEffect(() => {
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => {
fetchData(currentPage, itemsPerPage, searchTerm); fetchRegisterForm(PENDING, currentPage, itemsPerPage, searchTerm)
.then(registerFormPendingDataHandler)
.catch(requestErrorHandler)
}, 500); // Debounce la recherche }, 500); // Debounce la recherche
return () => clearTimeout(timeoutId); return () => clearTimeout(timeoutId);
@ -250,13 +197,7 @@ export default function Page({ params: { locale } }) {
visible: true, visible: true,
message: `Attentions ! \nVous êtes sur le point d'archiver le dossier d'inscription de ${nom} ${prenom}\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?`, message: `Attentions ! \nVous êtes sur le point d'archiver le dossier d'inscription de ${nom} ${prenom}\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?`,
onConfirm: () => { onConfirm: () => {
const url = `${BK_GESTIONINSCRIPTION_ARCHIVE_URL}/${id}`; archiveRegisterForm(id)
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
}).then(response => response.json())
.then(data => { .then(data => {
console.log('Success:', data); console.log('Success:', data);
setFicheInscriptions(ficheInscriptions.filter(fiche => fiche.id !== id)); setFicheInscriptions(ficheInscriptions.filter(fiche => fiche.id !== id));
@ -271,18 +212,12 @@ export default function Page({ params: { locale } }) {
}); });
}; };
const sendConfirmFicheInscription = (id, nom, prenom) => { const sendConfirmRegisterForm = (id, nom, prenom) => {
setPopup({ setPopup({
visible: true, visible: true,
message: `Avertissement ! \nVous êtes sur le point d'envoyer un dossier d'inscription à ${nom} ${prenom}\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?`, message: `Avertissement ! \nVous êtes sur le point d'envoyer un dossier d'inscription à ${nom} ${prenom}\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?`,
onConfirm: () => { onConfirm: () => {
const url = `${BK_GESTIONINSCRIPTION_SEND_URL}/${id}`; sendRegisterForm(id).then(data => {
fetch(url, {
headers: {
'Content-Type': 'application/json',
},
}).then(response => response.json())
.then(data => {
console.log('Success:', data); console.log('Success:', data);
setMailSent(true); setMailSent(true);
}) })
@ -292,15 +227,19 @@ export default function Page({ params: { locale } }) {
} }
}); });
}; };
const affectationClassFormSubmitHandler = (formdata)=> {
editRegisterForm(student.id,formData, csrfToken)
.then(data => {
console.log('Success:', data);
})
.catch(error => {
console.error('Error :', error);
});
}
const updateStatusAction = (id, newStatus) => { const updateStatusAction = (id, newStatus) => {
console.log('Edit fiche inscription with id:', id); console.log('Edit fiche inscription with id:', id);
}; };
const handleLetterClick = (letter) => {
setFilter(letter);
};
const handleSearchChange = (event) => { const handleSearchChange = (event) => {
setSearchTerm(event.target.value); setSearchTerm(event.target.value);
}; };
@ -310,28 +249,20 @@ export default function Page({ params: { locale } }) {
fetchData(newPage, itemsPerPage); // Appeler fetchData directement ici fetchData(newPage, itemsPerPage); // Appeler fetchData directement ici
}; };
const createDI = (updatedData) => { const createRF = (updatedData) => {
if (updatedData.selectedResponsables.length !== 0) { console.log("updateDATA",updatedData);
const selectedResponsablesIds = updatedData.selectedResponsables.map(responsableId => responsableId) if (updatedData.selectedGuardians.length !== 0) {
const selectedGuardiansIds = updatedData.selectedGuardians.map(guardianId => guardianId)
const data = { const data = {
eleve: { student: {
nom: updatedData.eleveNom, last_name: updatedData.studentLastName,
prenom: updatedData.elevePrenom, first_name: updatedData.studentFirstName,
}, },
idResponsables: selectedResponsablesIds idGuardians: selectedGuardiansIds
}; };
const url = `${BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL}`; createRegisterForm(data,csrfToken)
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify(data),
credentials: 'include'
})
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
console.log('Success:', data); console.log('Success:', data);
@ -343,7 +274,7 @@ export default function Page({ params: { locale } }) {
}); });
setTotalPending(totalPending+1); setTotalPending(totalPending+1);
if (updatedData.autoMail) { if (updatedData.autoMail) {
sendConfirmFicheInscription(data.eleve.id, updatedData.eleveNom, updatedData.elevePrenom); sendConfirmRegisterForm(data.student.id, updatedData.studentLastName, updatedData.studentFirstName);
} }
}) })
.catch((error) => { .catch((error) => {
@ -353,55 +284,35 @@ export default function Page({ params: { locale } }) {
else { else {
// Création d'un profil associé à l'adresse mail du responsable saisie // Création d'un profil associé à l'adresse mail du responsable saisie
// Le profil est inactif // Le profil est inactif
const request = new Request( const data = {
`${BK_PROFILE_URL}`, email: updatedData.guardianEmail,
{ password: 'Provisoire01!',
method:'POST', username: updatedData.guardianEmail,
headers: { is_active: 0, // On rend le profil inactif : impossible de s'y connecter dans la fenêtre du login tant qu'il ne s'est pas inscrit
'Content-Type':'application/json', droit:2 // Profil PARENT
'X-CSRFToken': csrfToken }
}, createProfile(data,csrfToken)
credentials: 'include',
body: JSON.stringify( {
email: updatedData.responsableEmail,
password: 'Provisoire01!',
username: updatedData.responsableEmail,
is_active: 0, // On rend le profil inactif : impossible de s'y connecter dans la fenêtre du login tant qu'il ne s'est pas inscrit
droit:2 // Profil PARENT
}),
}
);
fetch(request).then(response => response.json())
.then(response => { .then(response => {
console.log('Success:', response); console.log('Success:', response);
if (response.id) { if (response.id) {
let idProfil = response.id; let idProfile = response.id;
const data = { const data = {
eleve: { student: {
nom: updatedData.eleveNom, last_name: updatedData.studentLastName,
prenom: updatedData.elevePrenom, first_name: updatedData.studentFirstName,
responsables: [ guardians: [
{ {
mail: updatedData.responsableEmail, email: updatedData.guardianEmail,
telephone: updatedData.responsableTel, phone: updatedData.guardianPhone,
profilAssocie: idProfil // Association entre le reponsable de l'élève et le profil créé par défaut précédemment associated_profile: idProfile // Association entre le responsable de l'élève et le profil créé par défaut précédemment
} }
], ],
freres: [] sibling: []
} }
}; };
const url = `${BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL}`;
fetch(url, { createRegisterForm(data,csrfToken)
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify(data),
credentials: 'include'
})
.then(response => response.json())
.then(data => { .then(data => {
console.log('Success:', data); console.log('Success:', data);
setFichesInscriptionsDataEnCours(prevState => { setFichesInscriptionsDataEnCours(prevState => {
@ -412,7 +323,7 @@ export default function Page({ params: { locale } }) {
}); });
setTotalPending(totalPending+1); setTotalPending(totalPending+1);
if (updatedData.autoMail) { if (updatedData.autoMail) {
sendConfirmFicheInscription(data.eleve.id, updatedData.eleveNom, updatedData.elevePrenom); sendConfirmRegisterForm(data.student.id, updatedData.studentLastName, updatedData.studentFirstName);
} }
}) })
.catch((error) => { .catch((error) => {
@ -429,42 +340,26 @@ export default function Page({ params: { locale } }) {
closeModal(); closeModal();
} }
const validateAndAssociate = (updatedData) => {
fetch(`${BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL}/${eleve.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify(updatedData),
credentials: 'include'
})
.then(response => response.json())
.then(data => {
console.log('Succès :', data);
})
.catch(error => {
console.error('Erreur :', error);
});
}
const columns = [ const columns = [
{ name: t('studentName'), transform: (row) => row.eleve.nom }, { name: t('studentName'), transform: (row) => row.student.last_name },
{ name: t('studentFistName'), transform: (row) => row.eleve.prenom }, { name: t('studentFistName'), transform: (row) => row.student.first_name },
{ name: t('mainContactMail'), transform: (row) => row.eleve.responsables[0].mail }, { name: t('mainContactMail'), transform: (row) => row.student.guardians[0].email },
{ name: t('phone'), transform: (row) => formatPhoneNumber(row.eleve.responsables[0].telephone) }, { name: t('phone'), transform: (row) => formatPhoneNumber(row.student.guardians[0].phone) },
{ name: t('lastUpdateDate'), transform: (row) => row.dateMAJ_formattee}, { name: t('lastUpdateDate'), transform: (row) => row.formatted_last_update},
{ name: t('registrationFileStatus'), transform: (row) => ( { name: t('registrationFileStatus'), transform: (row) => (
<div className="flex justify-center items-center h-full"> <div className="flex justify-center items-center h-full">
<StatusLabel etat={row.etat} onChange={(newStatus) => updateStatusAction(row.eleve.id, newStatus)} showDropdown={false} /> <StatusLabel etat={row.status} onChange={(newStatus) => updateStatusAction(row.student.id, newStatus)} showDropdown={false} />
</div> </div>
) )
}, },
{ name: t('files'), transform: (row) => ( { name: t('files'), transform: (row) =>
(row.registerForms != null) &&(
<ul> <ul>
<li className="flex items-center gap-2"> <li className="flex items-center gap-2">
<FileText size={16} /> <FileText size={16} />
<a href={ `${BASE_URL}${row.fichierInscription}`} target='_blank'>{row.fichierInscription.split('/').pop()}</a> <a href={ `${BASE_URL}${row.registerForms}`} target='_blank'>{row.registerForms?.split('/').pop()}</a>
</li> </li>
</ul> </ul>
) }, ) },
@ -472,53 +367,53 @@ const columns = [
<DropdownMenu <DropdownMenu
buttonContent={<MoreVertical size={20} className="text-gray-400 hover:text-gray-600" />} buttonContent={<MoreVertical size={20} className="text-gray-400 hover:text-gray-600" />}
items={[ items={[
...(row.etat === 1 ? [{ ...(row.status === 1 ? [{
label: ( label: (
<> <>
<Send size={16} className="mr-2" /> Envoyer <Send size={16} className="mr-2" /> Envoyer
</> </>
), ),
onClick: () => sendConfirmFicheInscription(row.eleve.id, row.eleve.nom, row.eleve.prenom), onClick: () => sendConfirmRegisterForm(row.student.id, row.student.last_name, row.student.first_name),
}] : []), }] : []),
...(row.etat === 1 ? [{ ...(row.status === 1 ? [{
label: ( label: (
<> <>
<Edit size={16} className="mr-2" /> Modifier <Edit size={16} className="mr-2" /> Modifier
</> </>
), ),
onClick: () => window.location.href = `${FR_ADMIN_SUBSCRIPTIONS_EDIT_URL}?idEleve=${row.eleve.id}&id=1`, onClick: () => window.location.href = `${FE_ADMIN_SUBSCRIPTIONS_EDIT_URL}?studentId=${row.student.id}&id=1`,
}] : []), }] : []),
...(row.etat === 2 ? [{ ...(row.status === 2 ? [{
label: ( label: (
<> <>
<Edit size={16} className="mr-2" /> Modifier <Edit size={16} className="mr-2" /> Modifier
</> </>
), ),
onClick: () => window.location.href = `${FR_ADMIN_SUBSCRIPTIONS_EDIT_URL}?idEleve=${row.eleve.id}&id=1`, onClick: () => window.location.href = `${FE_ADMIN_SUBSCRIPTIONS_EDIT_URL}?studentId=${row.student.id}&id=1`,
}] : []), }] : []),
...(row.etat === 3 ? [{ ...(row.status === 3 ? [{
label: ( label: (
<> <>
<CheckCircle size={16} className="mr-2" /> Valider <CheckCircle size={16} className="mr-2" /> Valider
</> </>
), ),
onClick: () => openModalAssociationEleve(row.eleve), onClick: () => openModalAssociationEleve(row.student),
}] : []), }] : []),
...(row.etat === 5 ? [{ ...(row.status === 5 ? [{
label: ( label: (
<> <>
<CheckCircle size={16} className="mr-2" /> Rattacher <CheckCircle size={16} className="mr-2" /> Rattacher
</> </>
), ),
onClick: () => openModalAssociationEleve(row.eleve), onClick: () => openModalAssociationEleve(row.student),
}] : []), }] : []),
...(row.etat !== 6 ? [{ ...(row.status !== 6 ? [{
label: ( label: (
<> <>
<Trash2 size={16} className="mr-2 text-red-700" /> Archiver <Trash2 size={16} className="mr-2 text-red-700" /> Archiver
</> </>
), ),
onClick: () => archiveFicheInscription(row.eleve.id, row.eleve.nom, row.eleve.prenom), onClick: () => archiveFicheInscription(row.student.id, row.student.last_name, row.student.first_name),
}] : []), }] : []),
]} ]}
buttonClassName="text-gray-400 hover:text-gray-600" buttonClassName="text-gray-400 hover:text-gray-600"
@ -529,22 +424,23 @@ const columns = [
]; ];
const columnsSubscribed = [ const columnsSubscribed = [
{ name: t('studentName'), transform: (row) => row.eleve.nom }, { name: t('studentName'), transform: (row) => row.student.last_name },
{ name: t('studentFistName'), transform: (row) => row.eleve.prenom }, { name: t('studentFistName'), transform: (row) => row.student.first_name },
{ name: t('lastUpdateDate'), transform: (row) => row.dateMAJ_formattee}, { name: t('lastUpdateDate'), transform: (row) => row.updated_date_formated},
{ name: t('class'), transform: (row) => row.eleve.classeAssocieeName}, { name: t('class'), transform: (row) => row.student.first_name},
{ name: t('registrationFileStatus'), transform: (row) => ( { name: t('registrationFileStatus'), transform: (row) =>
<div className="flex justify-center items-center h-full"> (
<StatusLabel etat={row.etat} onChange={(newStatus) => updateStatusAction(row.eleve.id, newStatus)} showDropdown={false} /> <div className="flex justify-center items-center h-full">
</div> <StatusLabel etat={row.status} onChange={(newStatus) => updateStatusAction(row.student.id, newStatus)} showDropdown={false} />
) </div>
)
}, },
{ name: t('files'), transform: (row) => { name: t('files'), transform: (row) =>
( (row.registerForm != null) &&(
<ul> <ul>
<li className="flex items-center gap-2"> <li className="flex items-center gap-2">
<FileText size={16} /> <FileText size={16} />
<a href={ `${BASE_URL}${row.fichierInscription}`} target='_blank'>{row.fichierInscription.split('/').pop()}</a> <a href={ `${BASE_URL}${row.registerForm}`} target='_blank'>{row.registerForm?.split('/').pop()}</a>
</li> </li>
</ul> </ul>
) }, ) },
@ -557,14 +453,14 @@ const columnsSubscribed = [
<CheckCircle size={16} className="mr-2" /> Rattacher <CheckCircle size={16} className="mr-2" /> Rattacher
</> </>
), ),
onClick: () => openModalAssociationEleve(row.eleve) onClick: () => openModalAssociationEleve(row.student)
}, },
{ label: ( { label: (
<> <>
<Trash2 size={16} className="mr-2 text-red-700" /> Archiver <Trash2 size={16} className="mr-2 text-red-700" /> Archiver
</> </>
), ),
onClick: () => archiveFicheInscription(row.eleve.id, row.eleve.nom, row.eleve.prenom), onClick: () => archiveFicheInscription(row.student.id, row.student.last_name, row.student.first_name),
} }
]} ]}
buttonClassName="text-gray-400 hover:text-gray-600" buttonClassName="text-gray-400 hover:text-gray-600"
@ -575,13 +471,7 @@ const columnsSubscribed = [
]; ];
const handleFileDelete = (fileId) => { const handleFileDelete = (fileId) => {
fetch(`${BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL}/${fileId}`, { deleteRegisterFormFileTemplate(fileId,csrfToken)
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
.then(response => { .then(response => {
if (response.ok) { if (response.ok) {
setFichiers(fichiers.filter(fichier => fichier.id !== fileId)); setFichiers(fichiers.filter(fichier => fichier.id !== fileId));
@ -598,12 +488,15 @@ const handleFileDelete = (fileId) => {
const columnsFiles = [ const columnsFiles = [
{ name: 'Nom du fichier', transform: (row) => row.name }, { name: 'Nom du fichier', transform: (row) => row.name },
{ name: 'Date de création', transform: (row) => row.date_ajout }, { name: 'Date de création', transform: (row) => row.last_update },
{ name: 'Actions', transform: (row) => ( { name: 'Actions', transform: (row) => (
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
{
row.file && (
<a href={`${BASE_URL}${row.file}`} target='_blank' className="text-blue-500 hover:text-blue-700"> <a href={`${BASE_URL}${row.file}`} target='_blank' className="text-blue-500 hover:text-blue-700">
<Download size={16} /> <Download size={16} />
</a> </a>)
}
<button onClick={() => handleFileDelete(row.id)} className="text-red-500 hover:text-red-700"> <button onClick={() => handleFileDelete(row.id)} className="text-red-500 hover:text-red-700">
<Trash2 size={16} /> <Trash2 size={16} />
</button> </button>
@ -611,51 +504,19 @@ const columnsFiles = [
) }, ) },
]; ];
const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);
const [uploadFile, setUploadFile] = useState(null);
const [uploadFileName, setUploadFileName] = useState('');
const [fileName, setFileName] = useState('');
const openUploadModal = () => {
setIsUploadModalOpen(true);
};
const closeUploadModal = () => {
setIsUploadModalOpen(false);
setUploadFile(null);
setUploadFileName('');
setFileName('');
};
const handleFileChange = (event) => {
const file = event.target.files[0];
setUploadFile(file);
setUploadFileName(file ? file.name : '');
};
const handleFileNameChange = (event) => {
setFileName(event.target.value);
};
const handleFileUpload = (file, fileName) => { const handleFileUpload = (file, fileName) => {
if (!file || !fileName) { if ( !fileName) {
alert('Veuillez sélectionner un fichier et entrer un nom de fichier.'); alert('Veuillez entrer un nom de fichier.');
return; return;
} }
const formData = new FormData();
formData.append('file', file);
formData.append('name', fileName);
fetch(`${BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL}`, { const formData = new FormData();
method: 'POST', if(file){
body: formData, formData.append('fichier', file);
headers: { }
'X-CSRFToken': csrfToken, formData.append('nom', fileName);
}, createRegisterFormFileTemplate(formData,csrfToken)
credentials: 'include',
})
.then(response => response.json())
.then(data => { .then(data => {
console.log('Success:', data); console.log('Success:', data);
setFichiers([...fichiers, data]); setFichiers([...fichiers, data]);
@ -808,8 +669,8 @@ const handleFileUpload = (file, fileName) => {
title={"Création d'un nouveau dossier d'inscription"} title={"Création d'un nouveau dossier d'inscription"}
size='sm:w-1/4' size='sm:w-1/4'
ContentComponent={() => ( ContentComponent={() => (
<InscriptionForm eleves={eleves} <InscriptionForm students={students}
onSubmit={createDI} onSubmit={createRF}
/> />
)} )}
/> />
@ -821,24 +682,13 @@ const handleFileUpload = (file, fileName) => {
title="Affectation à une classe" title="Affectation à une classe"
ContentComponent={() => ( ContentComponent={() => (
<AffectationClasseForm <AffectationClasseForm
eleve={eleve} student={student}
onSubmit={validateAndAssociate} onSubmit={affectationClassFormSubmitHandler}
classes={classes} classes={classes}
/> />
)} )}
/> />
)} )}
{isUploadModalOpen && (
<Modal
isOpen={isUploadModalOpen}
setIsOpen={setIsUploadModalOpen}
title="Uploader un nouveau fichier"
size='sm:w-1/4'
ContentComponent={() => (
<FileUpload onFileUpload={handleFileUpload} />
)}
/>
)}
</div> </div>
); );
} }

View File

@ -3,10 +3,10 @@ import React, { useState, useEffect } from 'react';
import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared'; import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared';
import { useSearchParams, redirect, useRouter } from 'next/navigation'; import { useSearchParams, redirect, useRouter } from 'next/navigation';
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
import { FR_PARENTS_HOME_URL, import { FE_PARENTS_HOME_URL,
BK_GESTIONINSCRIPTION_ELEVE_URL, BE_SUBSCRIPTION_STUDENT_URL,
BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL, BE_SUBSCRIPTION_REGISTERFORM_URL,
BK_GESTIONINSCRIPTION_RECUPEREDERNIER_RESPONSABLE_URL } from '@/utils/Url'; BE_SUBSCRIPTION_LAST_GUARDIAN_URL } from '@/utils/Url';
import { mockStudent } from '@/data/mockStudent'; import { mockStudent } from '@/data/mockStudent';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true'; const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
@ -14,7 +14,7 @@ const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
export default function Page() { export default function Page() {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const idProfil = searchParams.get('id'); const idProfil = searchParams.get('id');
const idEleve = searchParams.get('idEleve'); const studentId = searchParams.get('studentId');
const router = useRouter(); const router = useRouter();
const [initialData, setInitialData] = useState(null); const [initialData, setInitialData] = useState(null);
@ -24,8 +24,8 @@ export default function Page() {
const [lastIdResponsable, setLastIdResponsable] = useState(1); const [lastIdResponsable, setLastIdResponsable] = useState(1);
useEffect(() => { useEffect(() => {
if (!idEleve || !idProfil) { if (!studentId || !idProfil) {
console.error('Missing idEleve or idProfil'); console.error('Missing studentId or idProfil');
return; return;
} }
@ -36,9 +36,9 @@ export default function Page() {
} else { } else {
Promise.all([ Promise.all([
// Fetch eleve data // Fetch eleve data
fetch(`${BK_GESTIONINSCRIPTION_ELEVE_URL}/${idEleve}`), fetch(`${BE_SUBSCRIPTION_STUDENT_URL}/${studentId}`),
// Fetch last responsable ID // Fetch last responsable ID
fetch(BK_GESTIONINSCRIPTION_RECUPEREDERNIER_RESPONSABLE_URL) fetch(BE_SUBSCRIPTION_LAST_GUARDIAN_URL)
]) ])
.then(async ([eleveResponse, responsableResponse]) => { .then(async ([eleveResponse, responsableResponse]) => {
const eleveData = await eleveResponse.json(); const eleveData = await eleveResponse.json();
@ -74,7 +74,7 @@ export default function Page() {
setIsLoading(false); setIsLoading(false);
}); });
} }
}, [idEleve, idProfil]); }, [studentId, idProfil]);
const handleSubmit = async (data) => { const handleSubmit = async (data) => {
if (useFakeData) { if (useFakeData) {
@ -83,7 +83,7 @@ export default function Page() {
} }
try { try {
const response = await fetch(`${BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL}/${idEleve}`, { const response = await fetch(`${BE_SUBSCRIPTION_REGISTERFORM_URL}/${studentId}`, {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -95,7 +95,7 @@ export default function Page() {
const result = await response.json(); const result = await response.json();
console.log('Success:', result); console.log('Success:', result);
router.push(FR_PARENTS_HOME_URL); router.push(FE_PARENTS_HOME_URL);
} catch (error) { } catch (error) {
console.error('Error:', error); console.error('Error:', error);
} }
@ -106,7 +106,7 @@ export default function Page() {
initialData={initialData} initialData={initialData}
csrfToken={csrfToken} csrfToken={csrfToken}
onSubmit={handleSubmit} onSubmit={handleSubmit}
cancelUrl={FR_PARENTS_HOME_URL} cancelUrl={FE_PARENTS_HOME_URL}
isLoading={isLoading} isLoading={isLoading}
/> />
); );

View File

@ -5,7 +5,7 @@ import DropdownMenu from '@/components/DropdownMenu';
import { useRouter } from 'next/navigation'; // Ajout de l'importation import { useRouter } from 'next/navigation'; // Ajout de l'importation
import { Bell, User, MessageSquare, LogOut, Settings, Home } from 'lucide-react'; // Ajout de l'importation de l'icône Home import { Bell, User, MessageSquare, LogOut, Settings, Home } from 'lucide-react'; // Ajout de l'importation de l'icône Home
import Logo from '@/components/Logo'; // Ajout de l'importation du composant Logo import Logo from '@/components/Logo'; // Ajout de l'importation du composant Logo
import { FR_PARENTS_HOME_URL,FR_PARENTS_MESSAGERIE_URL,FR_PARENTS_SETTINGS_URL, BK_GESTIONINSCRIPTION_MESSAGES_URL } from '@/utils/Url'; // Ajout de l'importation de l'URL de la page d'accueil parent import { FE_PARENTS_HOME_URL,FE_PARENTS_MESSAGERIE_URL,FE_PARENTS_SETTINGS_URL, BE_GESTIONINSCRIPTION_MESSAGES_URL } from '@/utils/Url'; // Ajout de l'importation de l'URL de la page d'accueil parent
import useLocalStorage from '@/hooks/useLocalStorage'; import useLocalStorage from '@/hooks/useLocalStorage';
export default function Layout({ export default function Layout({
@ -19,7 +19,7 @@ export default function Layout({
useEffect(() => { useEffect(() => {
setUserId(userId); setUserId(userId);
fetch(`${BK_GESTIONINSCRIPTION_MESSAGES_URL}/${userId}`, { fetch(`${BE_GESTIONINSCRIPTION_MESSAGES_URL}/${userId}`, {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
@ -33,7 +33,7 @@ export default function Layout({
.catch(error => { .catch(error => {
console.error('Error fetching data:', error); console.error('Error fetching data:', error);
}); });
}, []); }, []);
return ( return (
@ -49,7 +49,7 @@ export default function Layout({
<div className="flex items-center space-x-4"> <div className="flex items-center space-x-4">
<button <button
className="p-2 rounded-full hover:bg-gray-200" className="p-2 rounded-full hover:bg-gray-200"
onClick={() => { router.push(FR_PARENTS_HOME_URL); }} // Utilisation de router pour revenir à l'accueil parent onClick={() => { router.push(FE_PARENTS_HOME_URL); }} // Utilisation de router pour revenir à l'accueil parent
> >
<Home /> <Home />
</button> </button>
@ -58,7 +58,7 @@ export default function Layout({
<div className="relative"> <div className="relative">
<button <button
className="p-2 rounded-full hover:bg-gray-200" className="p-2 rounded-full hover:bg-gray-200"
onClick={() => { router.push(FR_PARENTS_MESSAGERIE_URL); }} // Utilisation de router onClick={() => { router.push(FE_PARENTS_MESSAGERIE_URL); }} // Utilisation de router
> >
<MessageSquare /> <MessageSquare />
@ -71,7 +71,7 @@ export default function Layout({
buttonContent={<User />} buttonContent={<User />}
items={[ items={[
{ label: 'Se déconnecter', icon: LogOut, onClick: () => {} }, { label: 'Se déconnecter', icon: LogOut, onClick: () => {} },
{ label: 'Settings', icon: Settings , onClick: () => { router.push(FR_PARENTS_SETTINGS_URL); } } { label: 'Settings', icon: Settings , onClick: () => { router.push(FE_PARENTS_SETTINGS_URL); } }
]} ]}
buttonClassName="p-2 rounded-full hover:bg-gray-200" buttonClassName="p-2 rounded-full hover:bg-gray-200"
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded-md shadow-lg" menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded-md shadow-lg"

View File

@ -5,7 +5,7 @@ import Table from '@/components/Table';
import { Edit } from 'lucide-react'; import { Edit } from 'lucide-react';
import StatusLabel from '@/components/StatusLabel'; import StatusLabel from '@/components/StatusLabel';
import useLocalStorage from '@/hooks/useLocalStorage'; import useLocalStorage from '@/hooks/useLocalStorage';
import { BK_GESTIONINSCRIPTION_ENFANTS_URL , FR_PARENTS_EDIT_INSCRIPTION_URL } from '@/utils/Url'; import { BE_SUBSCRIPTION_CHILDRENS_URL , FE_PARENTS_EDIT_INSCRIPTION_URL } from '@/utils/Url';
export default function ParentHomePage() { export default function ParentHomePage() {
const [actions, setActions] = useState([]); const [actions, setActions] = useState([]);
@ -24,7 +24,7 @@ export default function ParentHomePage() {
}; };
const fetchEleves = async () => { const fetchEleves = async () => {
const response = await fetch(`${BK_GESTIONINSCRIPTION_ENFANTS_URL}/${userId}`); const response = await fetch(`${BE_SUBSCRIPTION_CHILDRENS_URL}/${userId}`);
const data = await response.json(); const data = await response.json();
console.log(data); console.log(data);
@ -37,7 +37,7 @@ export default function ParentHomePage() {
function handleEdit(eleveId) { function handleEdit(eleveId) {
// Logique pour éditer le dossier de l'élève // Logique pour éditer le dossier de l'élève
console.log(`Edit dossier for eleve id: ${eleveId}`); console.log(`Edit dossier for eleve id: ${eleveId}`);
router.push(`${FR_PARENTS_EDIT_INSCRIPTION_URL}?id=${userId}&idEleve=${eleveId}`); router.push(`${FE_PARENTS_EDIT_INSCRIPTION_URL}?id=${userId}&studentId=${eleveId}`);
} }
const actionColumns = [ const actionColumns = [
{ name: 'Action', transform: (row) => row.action }, { name: 'Action', transform: (row) => row.action },

View File

@ -8,7 +8,7 @@ import InputTextIcon from '@/components/InputTextIcon';
import Loader from '@/components/Loader'; // Importez le composant Loader import Loader from '@/components/Loader'; // Importez le composant Loader
import Button from '@/components/Button'; // Importez le composant Button import Button from '@/components/Button'; // Importez le composant Button
import { User, KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires import { User, KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires
import { BK_LOGIN_URL, FR_ADMIN_SUBSCRIPTIONS_EDIT_URL, FR_ADMIN_SUBSCRIPTIONS_URL, FR_PARENTS_HOME_URL, FR_USERS_NEW_PASSWORD_URL, FR_USERS_SUBSCRIBE_URL } from '@/utils/Url'; import { BE_AUTH_LOGIN_URL, FE_ADMIN_SUBSCRIPTIONS_EDIT_URL, FE_ADMIN_SUBSCRIPTIONS_URL, FE_PARENTS_HOME_URL, FE_USERS_NEW_PASSWORD_URL, FE_USERS_SUBSCRIBE_URL } from '@/utils/Url';
import useLocalStorage from '@/hooks/useLocalStorage'; import useLocalStorage from '@/hooks/useLocalStorage';
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true'; const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
@ -44,7 +44,7 @@ export default function Page() {
setErrorMessage("") setErrorMessage("")
if(isOK(data)){ if(isOK(data)){
localStorage.setItem('userId', data.profil); // Stocker l'identifiant de l'utilisateur localStorage.setItem('userId', data.profil); // Stocker l'identifiant de l'utilisateur
router.push(`${FR_ADMIN_SUBSCRIPTIONS_EDIT_URL}?id=${data.profil}`); router.push(`${FE_ADMIN_SUBSCRIPTIONS_EDIT_URL}?id=${data.profil}`);
} else { } else {
if(data.errorFields){ if(data.errorFields){
setUserFieldError(data.errorFields.email) setUserFieldError(data.errorFields.email)
@ -56,7 +56,7 @@ export default function Page() {
} }
} else { } else {
const request = new Request( const request = new Request(
`${BK_LOGIN_URL}`, `${BE_AUTH_LOGIN_URL}`,
{ {
method:'POST', method:'POST',
headers: { headers: {
@ -82,14 +82,14 @@ export default function Page() {
// Vue ECOLE // Vue ECOLE
} else if (data.droit == 1) { } else if (data.droit == 1) {
// Vue ADMIN // Vue ADMIN
router.push(`${FR_ADMIN_SUBSCRIPTIONS_URL}`); router.push(`${FE_ADMIN_SUBSCRIPTIONS_URL}`);
} else if (data.droit == 2) { } else if (data.droit == 2) {
// Vue PARENT // Vue PARENT
router.push(`${FR_PARENTS_HOME_URL}`); router.push(`${FE_PARENTS_HOME_URL}`);
} else { } else {
// Cas anormal // Cas anormal
} }
} else { } else {
if(data.errorFields){ if(data.errorFields){
setUserFieldError(data.errorFields.email) setUserFieldError(data.errorFields.email)
@ -124,7 +124,7 @@ export default function Page() {
<div className="input-group mb-4"> <div className="input-group mb-4">
</div> </div>
<label className="text-red-500">{errorMessage}</label> <label className="text-red-500">{errorMessage}</label>
<label><a className="float-right text-emerald-900" href={`${FR_USERS_NEW_PASSWORD_URL}`}>Mot de passe oublié ?</a></label> <label><a className="float-right text-emerald-900" href={`${FE_USERS_NEW_PASSWORD_URL}`}>Mot de passe oublié ?</a></label>
<div className="form-group-submit mt-4"> <div className="form-group-submit mt-4">
<Button text="Se Connecter" className="w-full" primary type="submit" name="connect" /> <Button text="Se Connecter" className="w-full" primary type="submit" name="connect" />
</div> </div>

View File

@ -9,7 +9,7 @@ import Loader from '@/components/Loader'; // Importez le composant Loader
import Button from '@/components/Button'; // Importez le composant Button import Button from '@/components/Button'; // Importez le composant Button
import Popup from '@/components/Popup'; // Importez le composant Popup import Popup from '@/components/Popup'; // Importez le composant Popup
import { User } from 'lucide-react'; // Importez directement les icônes nécessaires import { User } from 'lucide-react'; // Importez directement les icônes nécessaires
import { BK_NEW_PASSWORD_URL,FR_USERS_LOGIN_URL } from '@/utils/Url'; import { BE_AUTH_NEW_PASSWORD_URL,FE_USERS_LOGIN_URL } from '@/utils/Url';
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true'; const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
@ -35,7 +35,7 @@ export default function Page() {
}, 1000); // Simule un délai de traitement }, 1000); // Simule un délai de traitement
} else { } else {
const request = new Request( const request = new Request(
`${BK_NEW_PASSWORD_URL}`, `${BE_AUTH_NEW_PASSWORD_URL}`,
{ {
method: 'POST', method: 'POST',
headers: { headers: {
@ -93,7 +93,7 @@ export default function Page() {
</form> </form>
<br /> <br />
<div className='flex justify-center mt-2 max-w-md mx-auto'> <div className='flex justify-center mt-2 max-w-md mx-auto'>
<Button text="Annuler" className="w-full" href={ `${FR_USERS_LOGIN_URL}`} /> <Button text="Annuler" className="w-full" href={ `${FE_USERS_LOGIN_URL}`} />
</div> </div>
</div> </div>
<Popup <Popup

View File

@ -9,7 +9,7 @@ import InputTextIcon from '@/components/InputTextIcon';
import Loader from '@/components/Loader'; // Importez le composant Loader import Loader from '@/components/Loader'; // Importez le composant Loader
import Button from '@/components/Button'; // Importez le composant Button import Button from '@/components/Button'; // Importez le composant Button
import Popup from '@/components/Popup'; import Popup from '@/components/Popup';
import { BK_RESET_PASSWORD_URL, FR_USERS_LOGIN_URL } from '@/utils/Url'; import { BE_AUTH_RESET_PASSWORD_URL, FE_USERS_LOGIN_URL } from '@/utils/Url';
import { KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires import { KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
@ -34,7 +34,7 @@ export default function Page() {
setIsLoading(false); setIsLoading(false);
}, 1000); }, 1000);
} else { } else {
const url= `${BK_RESET_PASSWORD_URL}/${uuid}`; const url= `${BE_AUTH_RESET_PASSWORD_URL}/${uuid}`;
fetch(url, { fetch(url, {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -66,11 +66,11 @@ export default function Page() {
}, 1000); }, 1000);
} else { } else {
const request = new Request( const request = new Request(
`${BK_RESET_PASSWORD_URL}/${uuid}`, `${BE_AUTH_RESET_PASSWORD_URL}/${uuid}`,
{ {
method:'POST', method:'POST',
headers: { headers: {
'Content-Type':'application/json', 'Content-Type':'application/json',
'X-CSRFToken': csrfToken 'X-CSRFToken': csrfToken
}, },
credentials: 'include', credentials: 'include',
@ -116,7 +116,7 @@ export default function Page() {
message={popupMessage} message={popupMessage}
onConfirm={() => { onConfirm={() => {
setPopupVisible(false); setPopupVisible(false);
router.push(`${FR_USERS_LOGIN_URL}`); router.push(`${FE_USERS_LOGIN_URL}`);
}} }}
onCancel={() => setPopupVisible(false)} onCancel={() => setPopupVisible(false)}
/> />
@ -136,7 +136,7 @@ export default function Page() {
</form> </form>
<br/> <br/>
<div className="flex justify-center mt-2 max-w-md mx-auto"> <div className="flex justify-center mt-2 max-w-md mx-auto">
<Button text="Annuler" className="w-full" href={`${FR_USERS_LOGIN_URL}`} /> <Button text="Annuler" className="w-full" href={`${FE_USERS_LOGIN_URL}`} />
</div> </div>
</div> </div>
</> </>

View File

@ -10,7 +10,7 @@ import Loader from '@/components/Loader'; // Importez le composant Loader
import Button from '@/components/Button'; // Importez le composant Button import Button from '@/components/Button'; // Importez le composant Button
import Popup from '@/components/Popup'; // Importez le composant Popup import Popup from '@/components/Popup'; // Importez le composant Popup
import { User, KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires import { User, KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires
import { BK_REGISTER_URL, FR_USERS_LOGIN_URL } from '@/utils/Url'; import { BE_AUTH_REGISTER_URL, FE_USERS_LOGIN_URL } from '@/utils/Url';
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true'; const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
@ -41,7 +41,7 @@ export default function Page() {
setErrorMessage("") setErrorMessage("")
setIsLoading(false); setIsLoading(false);
} else { } else {
const url= `${BK_REGISTER_URL}`; const url= `${BE_AUTH_REGISTER_URL}`;
fetch(url, { fetch(url, {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -100,11 +100,11 @@ export default function Page() {
} }
} else { } else {
const request = new Request( const request = new Request(
`${BK_REGISTER_URL}`, `${BE_AUTH_REGISTER_URL}`,
{ {
method:'POST', method:'POST',
headers: { headers: {
'Content-Type':'application/json', 'Content-Type':'application/json',
'X-CSRFToken': csrfToken 'X-CSRFToken': csrfToken
}, },
credentials: 'include', credentials: 'include',
@ -164,14 +164,14 @@ export default function Page() {
</div> </div>
</form> </form>
<br/> <br/>
<div className='flex justify-center mt-2 max-w-md mx-auto'><Button text="Annuler" className="w-full" onClick={()=>{router.push(`${FR_USERS_LOGIN_URL}`)}} /></div> <div className='flex justify-center mt-2 max-w-md mx-auto'><Button text="Annuler" className="w-full" onClick={()=>{router.push(`${FE_USERS_LOGIN_URL}`)}} /></div>
</div> </div>
<Popup <Popup
visible={popupVisible} visible={popupVisible}
message={popupMessage} message={popupMessage}
onConfirm={() => { onConfirm={() => {
setPopupVisible(false); setPopupVisible(false);
router.push(`${FR_USERS_LOGIN_URL}`); router.push(`${FE_USERS_LOGIN_URL}`);
}} }}
onCancel={() => setPopupVisible(false)} onCancel={() => setPopupVisible(false)}
/> />

View File

@ -1,39 +0,0 @@
import {
BK_LOGIN_URL,
FR_USERS_LOGIN_URL ,
FR_ADMIN_HOME_URL,
FR_ADMIN_SUBSCRIPTIONS_URL,
FR_ADMIN_CLASSES_URL,
FR_ADMIN_GRADES_URL,
FR_ADMIN_PLANNING_URL,
FR_ADMIN_TEACHERS_URL,
FR_ADMIN_SETTINGS_URL
} from '@/utils/Url';
import {mockUser} from "@/data/mockUsersData";
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
/**
* Disconnects the user after confirming the action.
* If `NEXT_PUBLIC_USE_FAKE_DATA` environment variable is set to 'true', it will log a fake disconnect and redirect to the login URL.
* Otherwise, it will send a PUT request to the backend to update the user profile and then redirect to the login URL.
*
* @function
* @name disconnect
* @returns {void}
*/
export function disconnect () {
if (confirm("\nÊtes-vous sûr(e) de vouloir vous déconnecter ?")) {
if (useFakeData) {
console.log('Fake disconnect:', mockUser);
router.push(`${FR_USERS_LOGIN_URL}`);
} else {
console.log('Fake disconnect:', mockUser);
router.push(`${FR_USERS_LOGIN_URL}`);
}
}
};

View File

@ -0,0 +1,67 @@
import {
BE_AUTH_LOGIN_URL,
BE_AUTH_PROFILE_URL,
FE_USERS_LOGIN_URL ,
} from '@/utils/Url';
import {mockUser} from "@/data/mockUsersData";
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
/**
* Disconnects the user after confirming the action.
* If `NEXT_PUBLIC_USE_FAKE_DATA` environment variable is set to 'true', it will log a fake disconnect and redirect to the login URL.
* Otherwise, it will send a PUT request to the backend to update the user profile and then redirect to the login URL.
*
* @function
* @name disconnect
* @returns {void}
*/
export const disconnect = () => {
if (confirm("\nÊtes-vous sûr(e) de vouloir vous déconnecter ?")) {
if (useFakeData) {
console.log('Fake disconnect:', mockUser);
router.push(`${FE_USERS_LOGIN_URL}`);
} else {
console.log('Fake disconnect:', mockUser);
router.push(`${FE_USERS_LOGIN_URL}`);
}
}
};
export const createProfile = (data,csrfToken) => {
const request = new Request(
`${BE_AUTH_PROFILE_URL}`,
{
method:'POST',
headers: {
'Content-Type':'application/json',
'X-CSRFToken': csrfToken
},
credentials: 'include',
body: JSON.stringify(data),
}
);
return fetch(request).then(response => response.json())
}
export const updateProfile = (id, data, csrfToken) => {
const request = new Request(
`${BE_AUTH_PROFILE_URL}/${id}`,
{
method:'PUT',
headers: {
'Content-Type':'application/json',
'X-CSRFToken': csrfToken
},
credentials: 'include',
body: JSON.stringify(data),
}
);
return fetch(request).then(response => response.json())
}

View File

@ -0,0 +1,9 @@
import {
BE_SCHOOL_SCHOOLCLASSES_URL
} from '@/utils/Url';
export const fetchClasses = () => {
return fetch(`${BE_SCHOOL_SCHOOLCLASSES_URL}`)
.then(response => response.json())
};

View File

@ -0,0 +1,123 @@
import {
BE_SUBSCRIPTION_STUDENTS_URL,
BE_SUBSCRIPTION_ARCHIVE_URL,
BE_SUBSCRIPTION_SEND_URL,
BE_SUBSCRIPTION_REGISTERFORM_URL,
BE_SUBSCRIPTION_REGISTERFORMS_URL,
BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL
} from '@/utils/Url';
export const PENDING = 'pending';
export const SUBSCRIBED = 'subscribed';
export const ARCHIVED = 'archived';
export const fetchRegisterForm = (type=PENDING, page='', pageSize='', search = '') => {
let url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${type}`;
if (page !== '' && pageSize !== '') {
url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${type}?page=${page}&search=${search}`;
}
return fetch(url, {
headers: {
'Content-Type': 'application/json',
},
}).then(response => response.json())
};
export const editRegisterForm=(id, data, csrfToken)=>{
return fetch(`${BE_SUBSCRIPTION_REGISTERFORM_URL}/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify(data),
credentials: 'include'
})
.then(response => response.json())
};
export const createRegisterForm=(data, csrfToken)=>{
const url = `${BE_SUBSCRIPTION_REGISTERFORM_URL}`;
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify(data),
credentials: 'include'
})
.then(response => response.json())
}
export const archiveRegisterForm = (id) => {
const url = `${BE_SUBSCRIPTION_ARCHIVE_URL}/${id}`;
return fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
}).then(response => response.json())
}
export const sendRegisterForm = (id) => {
const url = `${BE_SUBSCRIPTION_SEND_URL}/${id}`;
return fetch(url, {
headers: {
'Content-Type': 'application/json',
},
}).then(response => response.json())
}
export const fetchRegisterFormFileTemplate = () => {
const request = new Request(
`${BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL}`,
{
method:'GET',
headers: {
'Content-Type':'application/json'
},
}
);
return fetch(request).then(response => response.json())
};
export const createRegisterFormFileTemplate = (data,csrfToken) => {
fetch(`${BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL}`, {
method: 'POST',
body: data,
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
.then(response => response.json())
}
export const deleteRegisterFormFileTemplate = (fileId,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL}/${fileId}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
}
export const fetchStudents = () => {
const request = new Request(
`${BE_SUBSCRIPTION_STUDENTS_URL}`,
{
method:'GET',
headers: {
'Content-Type':'application/json'
},
}
);
return fetch(request).then(response => response.json())
};

View File

@ -4,20 +4,20 @@ import InputTextIcon from '@/components/InputTextIcon';
import ToggleSwitch from '@/components/ToggleSwitch'; import ToggleSwitch from '@/components/ToggleSwitch';
import Button from '@/components/Button'; import Button from '@/components/Button';
const InscriptionForm = ( { eleves, onSubmit }) => { const InscriptionForm = ( { students, onSubmit }) => {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
eleveNom: '', studentLastName: '',
elevePrenom: '', studentFirstName: '',
responsableEmail: '', guardianEmail: '',
responsableTel: '', guardianPhone: '',
selectedResponsables: [], selectedGuardians: [],
responsableType: 'new', responsableType: 'new',
autoMail: false autoMail: false
}); });
const [step, setStep] = useState(1); const [step, setStep] = useState(1);
const [selectedEleve, setSelectedEleve] = useState(''); const [selectedStudent, setSelectedEleve] = useState('');
const [existingResponsables, setExistingResponsables] = useState([]); const [existingGuardians, setExistingGuardians] = useState([]);
const maxStep = 4 const maxStep = 4
const handleToggleChange = () => { const handleToggleChange = () => {
@ -44,21 +44,21 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
} }
}; };
const handleEleveSelection = (eleve) => { const handleEleveSelection = (student) => {
setSelectedEleve(eleve); setSelectedEleve(student);
setFormData((prevData) => ({ setFormData((prevData) => ({
...prevData, ...prevData,
selectedResponsables: [] selectedGuardians: []
})); }));
setExistingResponsables(eleve.responsables); setExistingGuardians(student.guardians);
}; };
const handleResponsableSelection = (responsableId) => { const handleResponsableSelection = (guardianId) => {
setFormData((prevData) => { setFormData((prevData) => {
const selectedResponsables = prevData.selectedResponsables.includes(responsableId) const selectedGuardians = prevData.selectedGuardians.includes(guardianId)
? prevData.selectedResponsables.filter(id => id !== responsableId) ? prevData.selectedGuardians.filter(id => id !== guardianId)
: [...prevData.selectedResponsables, responsableId]; : [...prevData.selectedGuardians, guardianId];
return { ...prevData, selectedResponsables }; return { ...prevData, selectedGuardians };
}); });
}; };
@ -72,20 +72,20 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
<div> <div>
<h2 className="text-l font-bold mb-4">Nouvel élève</h2> <h2 className="text-l font-bold mb-4">Nouvel élève</h2>
<InputTextIcon <InputTextIcon
name="eleveNom" name="studentLastName"
type="text" type="text"
IconItem={User} IconItem={User}
placeholder="Nom de l'élève" placeholder="Nom de l'élève"
value={formData.eleveNom} value={formData.studentLastName}
onChange={handleChange} onChange={handleChange}
className="w-full" className="w-full"
/> />
<InputTextIcon <InputTextIcon
name="elevePrenom" name="studentFirstName"
type="text" type="text"
IconItem={User} IconItem={User}
placeholder="Prénom de l'élève" placeholder="Prénom de l'élève"
value={formData.elevePrenom} value={formData.studentFirstName}
onChange={handleChange} onChange={handleChange}
className="w-full" className="w-full"
/> />
@ -121,11 +121,11 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
</div> </div>
{formData.responsableType === 'new' && ( {formData.responsableType === 'new' && (
<InputTextIcon <InputTextIcon
name="responsableEmail" name="guardianEmail"
type="email" type="email"
IconItem={Mail} IconItem={Mail}
placeholder="Email du responsable" placeholder="Email du responsable"
value={formData.responsableEmail} value={formData.guardianEmail}
onChange={handleChange} onChange={handleChange}
className="w-full mt-4" className="w-full mt-4"
/> />
@ -142,33 +142,33 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{eleves.map((eleve, index) => ( {students.map((student, index) => (
<tr <tr
key={eleve.id} key={student.id}
className={`cursor-pointer ${selectedEleve && selectedEleve.id === eleve.id ? 'bg-emerald-600 text-white' : index % 2 === 0 ? 'bg-emerald-100' : ''}`} className={`cursor-pointer ${selectedStudent && selectedStudent.id === student.id ? 'bg-emerald-600 text-white' : index % 2 === 0 ? 'bg-emerald-100' : ''}`}
onClick={() => handleEleveSelection(eleve)} onClick={() => handleEleveSelection(student)}
> >
<td className="px-4 py-2 border">{eleve.nom}</td> <td className="px-4 py-2 border">{student.last_name}</td>
<td className="px-4 py-2 border">{eleve.prenom}</td> <td className="px-4 py-2 border">{student.first_name}</td>
</tr> </tr>
))} ))}
</tbody> </tbody>
</table> </table>
</div> </div>
{selectedEleve && ( {selectedStudent && (
<div className="mt-4"> <div className="mt-4">
<h3 className="font-bold">Responsables associés à {selectedEleve.nom} {selectedEleve.prenom} :</h3> <h3 className="font-bold">Responsables associés à {selectedStudent.last_name} {selectedStudent.first_name} :</h3>
{existingResponsables.map((responsable) => ( {existingGuardians.map((guardian) => (
<div key={responsable.id}> <div key={guardian.id}>
<label className="flex items-center space-x-3 mt-2"> <label className="flex items-center space-x-3 mt-2">
<input <input
type="checkbox" type="checkbox"
checked={formData.selectedResponsables.includes(responsable.id)} checked={formData.selectedGuardians.includes(guardian.id)}
className="form-checkbox h-5 w-5 text-emerald-600" className="form-checkbox h-5 w-5 text-emerald-600"
onChange={() => handleResponsableSelection(responsable.id)} onChange={() => handleResponsableSelection(guardian.id)}
/> />
<span className="text-gray-900"> <span className="text-gray-900">
{responsable.nom && responsable.prenom ? `${responsable.nom} ${responsable.prenom}` : `${responsable.mail}`} {guardian.last_name && guardian.first_name ? `${guardian.last_name} ${guardian.first_name}` : `${guardian.email}`}
</span> </span>
</label> </label>
</div> </div>
@ -184,11 +184,11 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
<div className="mt-6"> <div className="mt-6">
<h2 className="text-l font-bold mb-4">Téléphone (optionnel)</h2> <h2 className="text-l font-bold mb-4">Téléphone (optionnel)</h2>
<InputTextIcon <InputTextIcon
name="responsableTel" name="guardianPhone"
type="tel" type="tel"
IconItem={Phone} IconItem={Phone}
placeholder="Numéro de téléphone" placeholder="Numéro de téléphone"
value={formData.responsableTel} value={formData.guardianPhone}
onChange={handleChange} onChange={handleChange}
className="w-full mt-4" className="w-full mt-4"
/> />
@ -210,8 +210,8 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td className="px-4 py-2 border">{formData.eleveNom}</td> <td className="px-4 py-2 border">{formData.studentLastName}</td>
<td className="px-4 py-2 border">{formData.elevePrenom}</td> <td className="px-4 py-2 border">{formData.studentFirstName}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -228,15 +228,15 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td className="px-4 py-2 border">{formData.responsableEmail}</td> <td className="px-4 py-2 border">{formData.guardianEmail}</td>
<td className="px-4 py-2 border">{formData.responsableTel}</td> <td className="px-4 py-2 border">{formData.guardianPhone}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
)} )}
{formData.responsableType === 'existing' && selectedEleve && ( {formData.responsableType === 'existing' && selectedStudent && (
<div> <div>
<p>Associé(s) à : {selectedEleve.nom} {selectedEleve.prenom}</p> <p>Associé(s) à : {selectedStudent.nom} {selectedStudent.prenom}</p>
<table className="min-w-full bg-white border"> <table className="min-w-full bg-white border">
<thead> <thead>
<tr> <tr>
@ -246,11 +246,11 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{existingResponsables.filter(responsable => formData.selectedResponsables.includes(responsable.id)).map((responsable) => ( {existingGuardians.filter(guardian => formData.selectedGuardians.includes(guardian.id)).map((guardian) => (
<tr key={responsable.id}> <tr key={guardian.id}>
<td className="px-4 py-2 border">{responsable.nom}</td> <td className="px-4 py-2 border">{guardian.last_name}</td>
<td className="px-4 py-2 border">{responsable.prenom}</td> <td className="px-4 py-2 border">{guardian.first_name}</td>
<td className="px-4 py-2 border">{responsable.mail}</td> <td className="px-4 py-2 border">{guardian.email}</td>
</tr> </tr>
))} ))}
</tbody> </tbody>
@ -281,15 +281,15 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
<Button text="Suivant" <Button text="Suivant"
onClick={nextStep} onClick={nextStep}
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${ className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
(step === 1 && (!formData.eleveNom || !formData.elevePrenom)) || (step === 1 && (!formData.studentLastName || !formData.studentFirstName)) ||
(step === 2 && formData.responsableType === "new" && !formData.responsableEmail) || (step === 2 && formData.responsableType === "new" && !formData.guardianEmail) ||
(step === 2 && formData.responsableType === "existing" && formData.selectedResponsables.length === 0) (step === 2 && formData.responsableType === "existing" && formData.selectedGuardians.length === 0)
? "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"
}`} }`}
disabled={(step === 1 && (!formData.eleveNom || !formData.elevePrenom)) || disabled={(step === 1 && (!formData.studentLastName || !formData.studentFirstName)) ||
(step === 2 && formData.responsableType === "new" && !formData.responsableEmail) || (step === 2 && formData.responsableType === "new" && !formData.guardianEmail) ||
(step === 2 && formData.responsableType === "existing" && formData.selectedResponsables.length === 0) (step === 2 && formData.responsableType === "existing" && formData.selectedGuardians.length === 0)
} }
primary primary
name="Next" /> name="Next" />

View File

@ -5,7 +5,8 @@ import ResponsableInputFields from '@/components/Inscription/ResponsableInputFie
import Loader from '@/components/Loader'; import Loader from '@/components/Loader';
import Button from '@/components/Button'; import Button from '@/components/Button';
import DjangoCSRFToken from '@/components/DjangoCSRFToken'; import DjangoCSRFToken from '@/components/DjangoCSRFToken';
import FileUpload from '@/app/[locale]/admin/subscriptions/components/FileUpload';
import Table from '@/components/Table';
const niveaux = [ const niveaux = [
{ value:'1', label: 'TPS - Très Petite Section'}, { value:'1', label: 'TPS - Très Petite Section'},
@ -39,6 +40,8 @@ export default function InscriptionFormShared({
initialData?.responsables || [] initialData?.responsables || []
); );
const [uploadedFiles, setUploadedFiles] = useState([]);
// Mettre à jour les données quand initialData change // Mettre à jour les données quand initialData change
useEffect(() => { useEffect(() => {
if (initialData) { if (initialData) {
@ -62,6 +65,10 @@ export default function InscriptionFormShared({
setFormData(prev => ({...prev, [field]: value})); setFormData(prev => ({...prev, [field]: value}));
}; };
const handleFileUpload = (file, fileName) => {
setUploadedFiles([...uploadedFiles, { file, fileName }]);
};
const handleSubmit = (e) => { const handleSubmit = (e) => {
e.preventDefault(); e.preventDefault();
onSubmit({ onSubmit({
@ -72,6 +79,15 @@ export default function InscriptionFormShared({
}); });
}; };
const columns = [
{ name: 'Nom du fichier', transform: (row) => row.nom },
{ name: 'Actions', transform: (row) => (
<a href={URL.createObjectURL(row.fichier)} target='_blank' className="text-blue-500 hover:text-blue-700">
Télécharger
</a>
) },
];
if (isLoading) return <Loader />; if (isLoading) return <Loader />;
return ( return (
@ -170,6 +186,20 @@ export default function InscriptionFormShared({
/> />
</div> </div>
{/* Section Fichiers d'inscription */}
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
<h2 className="text-xl font-bold mb-4 text-gray-800">Fichiers à remplir</h2>
<Table
data={uploadedFiles}
columns={columns}
itemsPerPage={5}
currentPage={1}
totalPages={1}
onPageChange={() => {}}
/>
<FileUpload onFileUpload={handleFileUpload} />
</div>
{/* Boutons de contrôle */} {/* Boutons de contrôle */}
<div className="flex justify-end space-x-4"> <div className="flex justify-end space-x-4">
<Button href={cancelUrl} text="Annuler" /> <Button href={cancelUrl} text="Annuler" />

View File

@ -4,41 +4,41 @@ import TeachersSection from '@/components/Structure/Configuration/TeachersSectio
import ClassesSection from '@/components/Structure/Configuration/ClassesSection'; import ClassesSection from '@/components/Structure/Configuration/ClassesSection';
import { ClassesProvider } from '@/context/ClassesContext'; import { ClassesProvider } from '@/context/ClassesContext';
import { BK_GESTIONENSEIGNANTS_SPECIALITE_URL, import { BE_SCHOOL_SPECIALITY_URL,
BK_GESTIONENSEIGNANTS_TEACHER_URL, BE_SCHOOL_TEACHER_URL,
BK_GESTIONENSEIGNANTS_CLASSE_URL } from '@/utils/Url'; BE_SCHOOL_SCHOOLCLASS_URL } from '@/utils/Url';
const StructureManagement = ({ specialities, setSpecialities, teachers, setTeachers, classes, setClasses, handleCreate, handleEdit, handleDelete }) => { const StructureManagement = ({ specialities, setSpecialities, teachers, setTeachers, classes, setClasses, handleCreate, handleEdit, handleDelete }) => {
return ( return (
<div className='p-8'> <div className='p-8'>
<ClassesProvider> <ClassesProvider>
<SpecialitiesSection <SpecialitiesSection
specialities={specialities} specialities={specialities}
setSpecialities={setSpecialities} setSpecialities={setSpecialities}
handleCreate={(newData) => handleCreate(`${BK_GESTIONENSEIGNANTS_SPECIALITE_URL}`, newData, setSpecialities)} handleCreate={(newData) => handleCreate(`${BE_SCHOOL_SPECIALITY_URL}`, newData, setSpecialities)}
handleEdit={(id, updatedData) => handleEdit(`${BK_GESTIONENSEIGNANTS_SPECIALITE_URL}`, id, updatedData, setSpecialities)} handleEdit={(id, updatedData) => handleEdit(`${BE_SCHOOL_SPECIALITY_URL}`, id, updatedData, setSpecialities)}
handleDelete={(id) => handleDelete(`${BK_GESTIONENSEIGNANTS_SPECIALITE_URL}`, id, setSpecialities)} handleDelete={(id) => handleDelete(`${BE_SCHOOL_SPECIALITY_URL}`, id, setSpecialities)}
/> />
<TeachersSection <TeachersSection
teachers={teachers} teachers={teachers}
specialities={specialities} specialities={specialities}
handleCreate={(newData) => handleCreate(`${BK_GESTIONENSEIGNANTS_TEACHER_URL}`, newData, setTeachers)} handleCreate={(newData) => handleCreate(`${BE_SCHOOL_TEACHER_URL}`, newData, setTeachers)}
handleEdit={(id, updatedData) => handleEdit(`${BK_GESTIONENSEIGNANTS_TEACHER_URL}`, id, updatedData, setTeachers)} handleEdit={(id, updatedData) => handleEdit(`${BE_SCHOOL_TEACHER_URL}`, id, updatedData, setTeachers)}
handleDelete={(id) => handleDelete(`${BK_GESTIONENSEIGNANTS_TEACHER_URL}`, id, setTeachers)} handleDelete={(id) => handleDelete(`${BE_SCHOOL_TEACHER_URL}`, id, setTeachers)}
/> />
<ClassesSection <ClassesSection
classes={classes} classes={classes}
specialities={specialities} specialities={specialities}
teachers={teachers} teachers={teachers}
handleCreate={(newData) => handleCreate(`${BK_GESTIONENSEIGNANTS_CLASSE_URL}`, newData, setClasses)} handleCreate={(newData) => handleCreate(`${BE_SCHOOL_SCHOOLCLASS_URL}`, newData, setClasses)}
handleEdit={(id, updatedData) => handleEdit(`${BK_GESTIONENSEIGNANTS_CLASSE_URL}`, id, updatedData, setClasses)} handleEdit={(id, updatedData) => handleEdit(`${BE_SCHOOL_SCHOOLCLASS_URL}`, id, updatedData, setClasses)}
handleDelete={(id) => handleDelete(`${BK_GESTIONENSEIGNANTS_CLASSE_URL}`, id, setClasses)} handleDelete={(id) => handleDelete(`${BE_SCHOOL_SCHOOLCLASS_URL}`, id, setClasses)}
/> />
</ClassesProvider> </ClassesProvider>
</div> </div>
); );
}; };

View File

@ -4,9 +4,10 @@ import Table from '@/components/Table';
import DropdownMenu from '@/components/DropdownMenu'; import DropdownMenu from '@/components/DropdownMenu';
import Modal from '@/components/Modal'; import Modal from '@/components/Modal';
import TeacherForm from '@/components/Structure/Configuration/TeacherForm'; import TeacherForm from '@/components/Structure/Configuration/TeacherForm';
import {BK_PROFILE_URL} from '@/utils/Url';
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
import { TeacherFormProvider } from '@/context/TeacherFormContext'; import { TeacherFormProvider } from '@/context/TeacherFormContext';
import { createProfile, updateProfile } from '@/app/lib/authAction';
const TeachersSection = ({ teachers, handleCreate, handleEdit, handleDelete, specialities }) => { const TeachersSection = ({ teachers, handleCreate, handleEdit, handleDelete, specialities }) => {
@ -20,31 +21,21 @@ const TeachersSection = ({ teachers, handleCreate, handleEdit, handleDelete, spe
setEditingTeacher(teacher); setEditingTeacher(teacher);
} }
const closeEditModal = () => { const closeEditModal = () => {
setIsOpen(false); setIsOpen(false);
setEditingTeacher(null); setEditingTeacher(null);
}; };
const handleModalSubmit = (updatedData) => { const handleModalSubmit = (updatedData) => {
if (editingTeacher) { if (editingTeacher) {
// Modification du profil // Modification du profil
const request = new Request( const data = {
`${BK_PROFILE_URL}/${updatedData.profilAssocie_id}`, email: updatedData.mail,
{ username: updatedData.mail,
method:'PUT', droit:updatedData.droit
headers: { }
'Content-Type':'application/json',
'X-CSRFToken': csrfToken updateProfile(updatedData.profilAssocie_id,data,csrfToken)
},
credentials: 'include',
body: JSON.stringify( {
email: updatedData.mail,
username: updatedData.mail,
droit:updatedData.droit
}),
}
);
fetch(request).then(response => response.json())
.then(response => { .then(response => {
console.log('Success:', response); console.log('Success:', response);
console.log('UpdateData:', updatedData); console.log('UpdateData:', updatedData);
@ -58,25 +49,14 @@ const TeachersSection = ({ teachers, handleCreate, handleEdit, handleDelete, spe
} else { } else {
// Création d'un profil associé à l'adresse mail du responsable saisie // Création d'un profil associé à l'adresse mail du responsable saisie
// Le profil est inactif // Le profil est inactif
const request = new Request( const data = {
`${BK_PROFILE_URL}`, email: updatedData.mail,
{ password: 'Provisoire01!',
method:'POST', username: updatedData.mail,
headers: { is_active: 1, // On rend le profil actif : on considère qu'au moment de la configuration de l'école un abonnement a été souscrit
'Content-Type':'application/json', droit:updatedData.droit
'X-CSRFToken': csrfToken }
}, createProfile(data,csrfToken)
credentials: 'include',
body: JSON.stringify( {
email: updatedData.mail,
password: 'Provisoire01!',
username: updatedData.mail,
is_active: 1, // On rend le profil actif : on considère qu'au moment de la configuration de l'école un abonnement a été souscrit
droit:updatedData.droit
}),
}
);
fetch(request).then(response => response.json())
.then(response => { .then(response => {
console.log('Success:', response); console.log('Success:', response);
console.log('UpdateData:', updatedData); console.log('UpdateData:', updatedData);
@ -133,7 +113,7 @@ const TeachersSection = ({ teachers, handleCreate, handleEdit, handleDelete, spe
) )
}, },
{ {
name: 'TYPE PROFIL', name: 'TYPE PROFIL',
transform: (row) => { transform: (row) => {
if (row.profilAssocie) { if (row.profilAssocie) {
const badgeClass = row.DroitLabel === 'ECOLE' ? 'bg-blue-100 text-blue-600' : 'bg-red-100 text-red-600'; const badgeClass = row.DroitLabel === 'ECOLE' ? 'bg-blue-100 text-blue-600' : 'bg-red-100 text-red-600';
@ -168,9 +148,9 @@ const TeachersSection = ({ teachers, handleCreate, handleEdit, handleDelete, spe
</div> </div>
{isOpen && ( {isOpen && (
<TeacherFormProvider initialTeacher={editingTeacher || {}}> <TeacherFormProvider initialTeacher={editingTeacher || {}}>
<Modal <Modal
isOpen={isOpen} isOpen={isOpen}
setIsOpen={setIsOpen} setIsOpen={setIsOpen}
title={editingTeacher ? "Modification de l'enseignant" : "Création d'un nouvel enseignant"} title={editingTeacher ? "Modification de l'enseignant" : "Création d'un nouvel enseignant"}
size='sm:w-1/4' size='sm:w-1/4'
ContentComponent={() => ( ContentComponent={() => (

View File

@ -6,7 +6,7 @@ import { DndProvider } from 'react-dnd';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
import PlanningClassView from '@/components/Structure/Planning/PlanningClassView'; import PlanningClassView from '@/components/Structure/Planning/PlanningClassView';
import SpecialitiesList from '@/components/Structure/Planning/SpecialitiesList'; import SpecialitiesList from '@/components/Structure/Planning/SpecialitiesList';
import { BK_GESTIONENSEIGNANTS_PLANNING_URL } from '@/utils/Url'; import { BE_SCHOOL_PLANNING_URL } from '@/utils/Url';
import { useClasses } from '@/context/ClassesContext'; import { useClasses } from '@/context/ClassesContext';
import { ClasseFormProvider } from '@/context/ClasseFormContext'; import { ClasseFormProvider } from '@/context/ClasseFormContext';
import TabsStructure from '@/components/Structure/Configuration/TabsStructure'; import TabsStructure from '@/components/Structure/Configuration/TabsStructure';
@ -60,14 +60,14 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => {
const onDrop = (item, hour, day) => { const onDrop = (item, hour, day) => {
const { id, name, color, teachers } = item; const { id, name, color, teachers } = item;
const newSchedule = { ...schedule, emploiDuTemps: schedule.emploiDuTemps || {} }; const newSchedule = { ...schedule, emploiDuTemps: schedule.emploiDuTemps || {} };
if (!newSchedule.emploiDuTemps[day]) { if (!newSchedule.emploiDuTemps[day]) {
newSchedule.emploiDuTemps[day] = []; newSchedule.emploiDuTemps[day] = [];
} }
const courseTime = `${hour.toString().padStart(2, '0')}:00`; const courseTime = `${hour.toString().padStart(2, '0')}:00`;
const existingCourseIndex = newSchedule.emploiDuTemps[day].findIndex(course => course.heure === courseTime); const existingCourseIndex = newSchedule.emploiDuTemps[day].findIndex(course => course.heure === courseTime);
const newCourse = { const newCourse = {
duree: '1', duree: '1',
heure: courseTime, heure: courseTime,
@ -75,21 +75,21 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => {
teachers: teachers, teachers: teachers,
color: color, color: color,
}; };
if (existingCourseIndex !== -1) { if (existingCourseIndex !== -1) {
newSchedule.emploiDuTemps[day][existingCourseIndex] = newCourse; newSchedule.emploiDuTemps[day][existingCourseIndex] = newCourse;
} else { } else {
newSchedule.emploiDuTemps[day].push(newCourse); newSchedule.emploiDuTemps[day].push(newCourse);
} }
// Mettre à jour scheduleRef // Mettre à jour scheduleRef
setSchedule(newSchedule) setSchedule(newSchedule)
// Utiliser `handleUpdatePlanning` pour mettre à jour le planning du niveau de la classe // Utiliser `handleUpdatePlanning` pour mettre à jour le planning du niveau de la classe
const planningId = selectedClass.plannings_read.find(planning => planning.niveau === selectedLevel)?.planning.id; const planningId = selectedClass.plannings_read.find(planning => planning.niveau === selectedLevel)?.planning.id;
if (planningId) { if (planningId) {
console.log('newSchedule : ', newSchedule) console.log('newSchedule : ', newSchedule)
handleUpdatePlanning(BK_GESTIONENSEIGNANTS_PLANNING_URL, planningId, newSchedule); handleUpdatePlanning(BE_SCHOOL_PLANNING_URL, planningId, newSchedule);
} }
}; };
@ -110,7 +110,7 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => {
<DndProvider backend={HTML5Backend}> <DndProvider backend={HTML5Backend}>
<div className="p-4 bg-gray-100 border-b"> <div className="p-4 bg-gray-100 border-b">
<div className="grid grid-cols-3 gap-4"> <div className="grid grid-cols-3 gap-4">
{/* Colonne Classes */} {/* Colonne Classes */}
<div className="p-4 bg-gray-50 rounded-lg shadow-inner"> <div className="p-4 bg-gray-50 rounded-lg shadow-inner">
<div className="flex justify-between items-center mb-4"> <div className="flex justify-between items-center mb-4">
@ -131,7 +131,7 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => {
/> />
} }
</div> </div>
{/* Colonne Niveaux */} {/* Colonne Niveaux */}
<div className="p-4 bg-gray-50 rounded-lg shadow-inner"> <div className="p-4 bg-gray-50 rounded-lg shadow-inner">
<div className="flex justify-between items-center mb-4"> <div className="flex justify-between items-center mb-4">
@ -144,7 +144,7 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => {
<TabsStructure activeTab={selectedLevel} setActiveTab={handleLevelSelect} tabs={niveauxLabels} /> <TabsStructure activeTab={selectedLevel} setActiveTab={handleLevelSelect} tabs={niveauxLabels} />
} }
</div> </div>
{/* Colonne Spécialités */} {/* Colonne Spécialités */}
<div className="p-4 bg-gray-50 rounded-lg shadow-inner"> <div className="p-4 bg-gray-50 rounded-lg shadow-inner">
<div className="flex justify-between items-center mb-4"> <div className="flex justify-between items-center mb-4">
@ -155,10 +155,10 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => {
</div> </div>
<SpecialitiesList teachers={selectedClass ? selectedClass.enseignants : []} /> <SpecialitiesList teachers={selectedClass ? selectedClass.enseignants : []} />
</div> </div>
</div> </div>
</div> </div>
<div className="flex-1 p-4 overflow-y-auto"> <div className="flex-1 p-4 overflow-y-auto">
<AnimatePresence mode="wait"> <AnimatePresence mode="wait">
<motion.div <motion.div
@ -178,7 +178,7 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => {
</DndProvider> </DndProvider>
</div> </div>
); );
}; };
export default ScheduleManagement; export default ScheduleManagement;

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import SelectChoice from '@/components/SelectChoice'; import SelectChoice from '@/components/SelectChoice';
import { useClasses } from '@/context/ClassesContext'; import { useClasses } from '@/context/ClassesContext';
import { useClasseForm } from '@/context/ClasseFormContext'; import { useClasseForm } from '@/context/ClasseFormContext';
import { BK_GESTIONENSEIGNANTS_PLANNING_URL } from '@/utils/Url'; import { BE_SCHOOL_PLANNING_URL } from '@/utils/Url';
import { BookOpen, Users } from 'lucide-react'; import { BookOpen, Users } from 'lucide-react';
const SpecialityEventModal = ({ isOpen, onClose, selectedCell, existingEvent, handleUpdatePlanning, classe }) => { const SpecialityEventModal = ({ isOpen, onClose, selectedCell, existingEvent, handleUpdatePlanning, classe }) => {
@ -56,17 +56,17 @@ const SpecialityEventModal = ({ isOpen, onClose, selectedCell, existingEvent, ha
const handleSubmit = (e) => { const handleSubmit = (e) => {
e.preventDefault(); e.preventDefault();
if (!eventData.specialiteId) { if (!eventData.specialiteId) {
alert('Veuillez sélectionner une spécialité'); alert('Veuillez sélectionner une spécialité');
return; return;
} }
if (!eventData.teacherId) { if (!eventData.teacherId) {
alert('Veuillez sélectionner un enseignant'); alert('Veuillez sélectionner un enseignant');
return; return;
} }
// Transformer eventData pour correspondre au format du planning // Transformer eventData pour correspondre au format du planning
const selectedTeacherData = formData.enseignants.find(teacher => teacher.id === parseInt(eventData.teacherId, 10)); const selectedTeacherData = formData.enseignants.find(teacher => teacher.id === parseInt(eventData.teacherId, 10));
const newCourse = { const newCourse = {
@ -114,14 +114,14 @@ const SpecialityEventModal = ({ isOpen, onClose, selectedCell, existingEvent, ha
const planningId = updatedPlanning ? updatedPlanning.planning.id : null; const planningId = updatedPlanning ? updatedPlanning.planning.id : null;
console.log("id : ", planningId) console.log("id : ", planningId)
if (planningId) { if (planningId) {
handleUpdatePlanning(BK_GESTIONENSEIGNANTS_PLANNING_URL, planningId, updatedPlanning.emploiDuTemps); handleUpdatePlanning(BE_SCHOOL_PLANNING_URL, planningId, updatedPlanning.emploiDuTemps);
} }
onClose(); onClose();
}; };
const filteredTeachers = selectedSpeciality const filteredTeachers = selectedSpeciality
? formData.enseignants.filter(teacher => ? formData.enseignants.filter(teacher =>
teacher.specialites_ids.includes(parseInt(selectedSpeciality, 10)) teacher.specialites_ids.includes(parseInt(selectedSpeciality, 10))
) )
: formData.enseignants; : formData.enseignants;

View File

@ -1,11 +1,11 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { BK_GET_CSRF } from '@/utils/Url'; import { BE_AUTH_CSRF_URL } from '@/utils/Url';
const useCsrfToken = () => { const useCsrfToken = () => {
const [token, setToken] = useState(''); const [token, setToken] = useState('');
useEffect(() => { useEffect(() => {
fetch(`${BK_GET_CSRF}`, { fetch(`${BE_AUTH_CSRF_URL}`, {
method: 'GET', method: 'GET',
credentials: 'include' // Inclut les cookies dans la requête credentials: 'include' // Inclut les cookies dans la requête
}) })

View File

@ -6,76 +6,75 @@ export const BASE_URL = process.env.NEXT_PUBLIC_API_URL;
// GESTION LOGIN // GESTION LOGIN
export const BK_NEW_PASSWORD_URL = `${BASE_URL}/GestionLogin/newPassword` export const BE_AUTH_NEW_PASSWORD_URL = `${BASE_URL}/Auth/newPassword`
export const BK_REGISTER_URL = `${BASE_URL}/GestionLogin/subscribe` export const BE_AUTH_REGISTER_URL = `${BASE_URL}/Auth/subscribe`
export const BK_RESET_PASSWORD_URL = `${BASE_URL}/GestionLogin/resetPassword` export const BE_AUTH_RESET_PASSWORD_URL = `${BASE_URL}/Auth/resetPassword`
export const BK_LOGIN_URL = `${BASE_URL}/GestionLogin/login` export const BE_AUTH_LOGIN_URL = `${BASE_URL}/Auth/login`
export const BK_LOGOUT_URL = `${BASE_URL}/GestionLogin/logout` export const BE_AUTH_LOGOUT_URL = `${BASE_URL}/Auth/logout`
export const BK_PROFILE_URL = `${BASE_URL}/GestionLogin/profil` export const BE_AUTH_PROFILE_URL = `${BASE_URL}/Auth/profile`
export const BK_GET_CSRF = `${BASE_URL}/GestionLogin/csrf` export const BE_AUTH_CSRF_URL = `${BASE_URL}/Auth/csrf`
// GESTION INSCRIPTION // GESTION INSCRIPTION
export const BK_GESTIONINSCRIPTION_ELEVE_URL = `${BASE_URL}/GestionInscriptions/eleve` export const BE_SUBSCRIPTION_STUDENT_URL = `${BASE_URL}/Subscriptions/student`
export const BK_GESTIONINSCRIPTION_ENFANTS_URL = `${BASE_URL}/GestionInscriptions/enfants` // Récupère la liste des élèves d'un profil export const BE_SUBSCRIPTION_STUDENTS_URL = `${BASE_URL}/Subscriptions/students` // Récupère la liste des élèves inscrits ou en cours d'inscriptions
export const BK_GESTIONINSCRIPTION_ELEVES_URL = `${BASE_URL}/GestionInscriptions/eleves` // Récupère la liste des élèves inscrits ou en cours d'inscriptions export const BE_SUBSCRIPTION_CHILDRENS_URL = `${BASE_URL}/Subscriptions/childrens` // Récupère la liste des élèves d'un profil
export const BK_GESTIONINSCRIPTION_SEND_URL = `${BASE_URL}/GestionInscriptions/send` export const BE_SUBSCRIPTION_SEND_URL = `${BASE_URL}/Subscriptions/send`
export const BK_GESTIONINSCRIPTION_ARCHIVE_URL = `${BASE_URL}/GestionInscriptions/archive` export const BE_SUBSCRIPTION_ARCHIVE_URL = `${BASE_URL}/Subscriptions/archive`
export const BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/fichesInscription` export const BE_SUBSCRIPTION_REGISTERFORM_URL = `${BASE_URL}/Subscriptions/registerForm`
export const BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/ficheInscription` export const BE_SUBSCRIPTION_REGISTERFORMS_URL = `${BASE_URL}/Subscriptions/registerForms`
export const BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/fichiersInscription` export const BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL = `${BASE_URL}/Subscriptions/registerFormFileTemplate`
export const BK_GESTIONINSCRIPTION_RECUPEREDERNIER_RESPONSABLE_URL = `${BASE_URL}/GestionInscriptions/recupereDernierResponsable` export const BE_SUBSCRIPTION_LAST_GUARDIAN_URL = `${BASE_URL}/Subscriptions/lastGuardian`
export const BK_GESTIONINSCRIPTION_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messagerie`
//GESTION ENSEIGNANT //GESTION ENSEIGNANT
export const BK_GESTIONENSEIGNANTS_SPECIALITES_URL = `${BASE_URL}/GestionEnseignants/specialites` export const BE_SCHOOL_SPECIALITY_URL = `${BASE_URL}/School/speciality`
export const BK_GESTIONENSEIGNANTS_SPECIALITE_URL = `${BASE_URL}//GestionEnseignants/specialite` export const BE_SCHOOL_SPECIALITIES_URL = `${BASE_URL}/School/specialities`
export const BK_GESTIONENSEIGNANTS_CLASSES_URL = `${BASE_URL}/GestionEnseignants/classes` export const BE_SCHOOL_SCHOOLCLASS_URL = `${BASE_URL}/School/schoolClass`
export const BK_GESTIONENSEIGNANTS_CLASSE_URL = `${BASE_URL}/GestionEnseignants/classe` export const BE_SCHOOL_SCHOOLCLASSES_URL = `${BASE_URL}/School/schoolClasses`
export const BK_GESTIONENSEIGNANTS_TEACHERS_URL = `${BASE_URL}/GestionEnseignants/enseignants` export const BE_SCHOOL_TEACHER_URL = `${BASE_URL}/School/teacher`
export const BK_GESTIONENSEIGNANTS_TEACHER_URL = `${BASE_URL}/GestionEnseignants/enseignant` export const BE_SCHOOL_TEACHERS_URL = `${BASE_URL}/School/teachers`
export const BK_GESTIONENSEIGNANTS_PLANNINGS_URL = `${BASE_URL}/GestionEnseignants/plannings` export const BE_SCHOOL_PLANNING_URL = `${BASE_URL}/School/planning`
export const BK_GESTIONENSEIGNANTS_PLANNING_URL = `${BASE_URL}/GestionEnseignants/planning` export const BE_SCHOOL_PLANNINGS_URL = `${BASE_URL}/School/plannings`
// GESTION MESSAGERIE
export const BE_GESTIONINSCRIPTION_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messagerie`
// URL FRONT-END // URL FRONT-END
export const FE_HOME_URL = `/`
export const FR_HOME_URL = `/`
// USERS // USERS
export const FR_USERS_LOGIN_URL = `/users/login` export const FE_USERS_LOGIN_URL = `/users/login`
export const FR_USERS_SUBSCRIBE_URL = `/users/subscribe` export const FE_USERS_SUBSCRIBE_URL = `/users/subscribe`
export const FR_USERS_RESET_PASSWORD_URL = `/users/password/reset` export const FE_USERS_RESET_PASSWORD_URL = `/users/password/reset`
export const FR_USERS_NEW_PASSWORD_URL = `/users/password/new` export const FE_USERS_NEW_PASSWORD_URL = `/users/password/new`
//ADMIN //ADMIN
export const FR_ADMIN_HOME_URL = `/admin` export const FE_ADMIN_HOME_URL = `/admin`
// ADMIN/SUBSCRIPTIONS URL // ADMIN/SUBSCRIPTIONS URL
export const FR_ADMIN_SUBSCRIPTIONS_URL = `/admin/subscriptions` export const FE_ADMIN_SUBSCRIPTIONS_URL = `/admin/subscriptions`
export const FR_ADMIN_SUBSCRIPTIONS_EDIT_URL = `/admin/subscriptions/editInscription` export const FE_ADMIN_SUBSCRIPTIONS_EDIT_URL = `/admin/subscriptions/editInscription`
//ADMIN/CLASSES URL //ADMIN/CLASSES URL
export const FR_ADMIN_CLASSES_URL = `/admin/classes` export const FE_ADMIN_CLASSES_URL = `/admin/classes`
//ADMIN/STRUCTURE URL //ADMIN/STRUCTURE URL
export const FR_ADMIN_STRUCTURE_URL = `/admin/structure` export const FE_ADMIN_STRUCTURE_URL = `/admin/structure`
//ADMIN/GRADES URL //ADMIN/GRADES URL
export const FR_ADMIN_GRADES_URL = `/admin/grades` export const FE_ADMIN_GRADES_URL = `/admin/grades`
//ADMIN/TEACHERS URL //ADMIN/TEACHERS URL
export const FR_ADMIN_TEACHERS_URL = `/admin/teachers` export const FE_ADMIN_TEACHERS_URL = `/admin/teachers`
//ADMIN/PLANNING URL //ADMIN/PLANNING URL
export const FR_ADMIN_PLANNING_URL = `/admin/planning` export const FE_ADMIN_PLANNING_URL = `/admin/planning`
//ADMIN/SETTINGS URL //ADMIN/SETTINGS URL
export const FR_ADMIN_SETTINGS_URL = `/admin/settings` export const FE_ADMIN_SETTINGS_URL = `/admin/settings`
// PARENT HOME // PARENT HOME
export const FR_PARENTS_HOME_URL = `/parents` export const FE_PARENTS_HOME_URL = `/parents`
export const FR_PARENTS_MESSAGERIE_URL = `/parents/messagerie` export const FE_PARENTS_MESSAGERIE_URL = `/parents/messagerie`
export const FR_PARENTS_SETTINGS_URL = `/parents/settings` export const FE_PARENTS_SETTINGS_URL = `/parents/settings`
export const FR_PARENTS_EDIT_INSCRIPTION_URL = `/parents/editInscription` export const FE_PARENTS_EDIT_INSCRIPTION_URL = `/parents/editInscription`