diff --git a/Front-End/.prettierignore b/Front-End/.prettierignore new file mode 100644 index 0000000..7ee78a6 --- /dev/null +++ b/Front-End/.prettierignore @@ -0,0 +1,3 @@ +node_modules/ +build/ +dist/ \ No newline at end of file diff --git a/Front-End/.prettierrc b/Front-End/.prettierrc new file mode 100644 index 0000000..92f97e7 --- /dev/null +++ b/Front-End/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5" +} diff --git a/Front-End/messages/en/ResponsableInputFields.json b/Front-End/messages/en/ResponsableInputFields.json index 36105a6..c2bf0d9 100644 --- a/Front-End/messages/en/ResponsableInputFields.json +++ b/Front-End/messages/en/ResponsableInputFields.json @@ -1,4 +1,3 @@ - { "responsable": "Guardian", "delete": "Delete", @@ -10,4 +9,4 @@ "profession": "Profession", "address": "Address", "add_responsible": "Add guardian" -} \ No newline at end of file +} diff --git a/Front-End/messages/en/dashboard.json b/Front-End/messages/en/dashboard.json index 60bee0d..339d16e 100644 --- a/Front-End/messages/en/dashboard.json +++ b/Front-End/messages/en/dashboard.json @@ -1,10 +1,10 @@ { - "dashboard": "Dashboard", - "totalStudents": "Total Students", - "pendingRegistrations": "Pending Registration", - "reInscriptionRate": "Re-enrollment Rate", - "structureCapacity": "Structure Capacity", - "capacityRate": "Capacity Rate", - "inscriptionTrends": "Enrollment Trends", - "upcomingEvents": "Upcoming Events" -} \ No newline at end of file + "dashboard": "Dashboard", + "totalStudents": "Total Students", + "pendingRegistrations": "Pending Registration", + "reInscriptionRate": "Re-enrollment Rate", + "structureCapacity": "Structure Capacity", + "capacityRate": "Capacity Rate", + "inscriptionTrends": "Enrollment Trends", + "upcomingEvents": "Upcoming Events" +} diff --git a/Front-End/messages/en/homePage.json b/Front-End/messages/en/homePage.json index c3d3d78..f6c601a 100644 --- a/Front-End/messages/en/homePage.json +++ b/Front-End/messages/en/homePage.json @@ -1,5 +1,5 @@ { - "welcomeParents": "Welcome Parents", - "pleaseLogin": "Please login to access your account", - "loginButton": "Go to login page" -} \ No newline at end of file + "welcomeParents": "Welcome Parents", + "pleaseLogin": "Please login to access your account", + "loginButton": "Go to login page" +} diff --git a/Front-End/messages/en/pagination.json b/Front-End/messages/en/pagination.json index 7b8cb98..3467b18 100644 --- a/Front-End/messages/en/pagination.json +++ b/Front-End/messages/en/pagination.json @@ -1,6 +1,6 @@ { - "page": "Page", - "of": "of", - "previous": "Previous", - "next": "Next" -} \ No newline at end of file + "page": "Page", + "of": "of", + "previous": "Previous", + "next": "Next" +} diff --git a/Front-End/messages/en/sidebar.json b/Front-End/messages/en/sidebar.json index 2fce791..41e44f9 100644 --- a/Front-End/messages/en/sidebar.json +++ b/Front-End/messages/en/sidebar.json @@ -1,10 +1,10 @@ { - "dashboard": "Dashboard", - "subscriptions": "Subscriptions", - "structure": "Structure", - "directory": "Directory", - "events": "Events", - "grades": "Grades", - "settings": "Settings", - "schoolAdmin": "School Administration" -} \ No newline at end of file + "dashboard": "Dashboard", + "subscriptions": "Subscriptions", + "structure": "Structure", + "directory": "Directory", + "events": "Events", + "grades": "Grades", + "settings": "Settings", + "schoolAdmin": "School Administration" +} diff --git a/Front-End/messages/en/subscriptions.json b/Front-End/messages/en/subscriptions.json index ffde89a..0f6b4b1 100644 --- a/Front-End/messages/en/subscriptions.json +++ b/Front-End/messages/en/subscriptions.json @@ -1,33 +1,33 @@ { - "headerBarTitle": "Administration", - "addStudent": "New", - "allStudents": "All Students", - "pending": "Pending Registrations", - "subscribed": "Subscribed", - "archived": "Archived", - "name": "Name", - "class": "Class", - "status": "Status", - "attendance": "Attendance", - "lastEvaluation": "Last Evaluation", - "active": "Active", - "pendingStatus": "Pending", - "goodAttendance": "Good", - "averageAttendance": "Average", - "lowAttendance": "Poor", - "searchStudent": "Search for a student...", - "title": "Registration", - "information": "Information", - "no_records": "There are currently no registration records.", - "add_button": "Add", - "create_first_record": "Please click the ADD button to create your first registration record.", - "studentName":"Student name", - "studentFistName":"Student first name", - "mainContactMail":"Main contact email", - "phone":"Phone", - "lastUpdateDate":"Last update", - "classe":"Class", - "registrationFileStatus":"Registration file status", - "files":"Files", - "subscribeFiles":"Subscribe files" -} \ No newline at end of file + "headerBarTitle": "Administration", + "addStudent": "New", + "allStudents": "All Students", + "pending": "Pending Registrations", + "subscribed": "Subscribed", + "archived": "Archived", + "name": "Name", + "class": "Class", + "status": "Status", + "attendance": "Attendance", + "lastEvaluation": "Last Evaluation", + "active": "Active", + "pendingStatus": "Pending", + "goodAttendance": "Good", + "averageAttendance": "Average", + "lowAttendance": "Poor", + "searchStudent": "Search for a student...", + "title": "Registration", + "information": "Information", + "no_records": "There are currently no registration records.", + "add_button": "Add", + "create_first_record": "Please click the ADD button to create your first registration record.", + "studentName": "Student name", + "studentFistName": "Student first name", + "mainContactMail": "Main contact email", + "phone": "Phone", + "lastUpdateDate": "Last update", + "classe": "Class", + "registrationFileStatus": "Registration file status", + "files": "Files", + "subscribeFiles": "Subscribe files" +} diff --git a/Front-End/messages/fr/ResponsableInputFields.json b/Front-End/messages/fr/ResponsableInputFields.json index 86ab314..951a3dc 100644 --- a/Front-End/messages/fr/ResponsableInputFields.json +++ b/Front-End/messages/fr/ResponsableInputFields.json @@ -1,4 +1,3 @@ - { "responsable": "Responsable", "delete": "Supprimer", diff --git a/Front-End/messages/fr/dashboard.json b/Front-End/messages/fr/dashboard.json index 2bee5a0..b85a89a 100644 --- a/Front-End/messages/fr/dashboard.json +++ b/Front-End/messages/fr/dashboard.json @@ -1,10 +1,10 @@ { - "dashboard": "Tableau de bord", - "totalStudents": "Total des étudiants", - "pendingRegistrations": "Inscriptions en attente", - "reInscriptionRate": "Taux de réinscription", - "structureCapacity": "Capacité de la structure", - "capacityRate": "Remplissage de la structure", - "inscriptionTrends": "Tendances d'inscription", - "upcomingEvents": "Événements à venir" -} \ No newline at end of file + "dashboard": "Tableau de bord", + "totalStudents": "Total des étudiants", + "pendingRegistrations": "Inscriptions en attente", + "reInscriptionRate": "Taux de réinscription", + "structureCapacity": "Capacité de la structure", + "capacityRate": "Remplissage de la structure", + "inscriptionTrends": "Tendances d'inscription", + "upcomingEvents": "Événements à venir" +} diff --git a/Front-End/messages/fr/homePage.json b/Front-End/messages/fr/homePage.json index 21561d1..e2e582f 100644 --- a/Front-End/messages/fr/homePage.json +++ b/Front-End/messages/fr/homePage.json @@ -1,5 +1,5 @@ { - "welcomeParents": "Bienvenue aux parents", - "pleaseLogin": "Veuillez vous connecter pour accéder à votre compte", - "loginButton": "Accéder à la page de login" -} \ No newline at end of file + "welcomeParents": "Bienvenue aux parents", + "pleaseLogin": "Veuillez vous connecter pour accéder à votre compte", + "loginButton": "Accéder à la page de login" +} diff --git a/Front-End/messages/fr/pagination.json b/Front-End/messages/fr/pagination.json index 60f6f77..6bb5772 100644 --- a/Front-End/messages/fr/pagination.json +++ b/Front-End/messages/fr/pagination.json @@ -1,6 +1,6 @@ { - "page": "Page", - "of": "sur", - "previous": "Précédent", - "next": "Suivant" -} \ No newline at end of file + "page": "Page", + "of": "sur", + "previous": "Précédent", + "next": "Suivant" +} diff --git a/Front-End/messages/fr/sidebar.json b/Front-End/messages/fr/sidebar.json index 5be92eb..f5ebffe 100644 --- a/Front-End/messages/fr/sidebar.json +++ b/Front-End/messages/fr/sidebar.json @@ -1,10 +1,10 @@ - { - "dashboard": "Tableau de bord", - "subscriptions": "Inscriptions", - "structure": "Structure", - "directory": "Annuaire", - "events": "Evenements", - "grades": "Notes", - "settings": "Paramètres", - "schoolAdmin": "Administration Scolaire" - } \ No newline at end of file +{ + "dashboard": "Tableau de bord", + "subscriptions": "Inscriptions", + "structure": "Structure", + "directory": "Annuaire", + "events": "Evenements", + "grades": "Notes", + "settings": "Paramètres", + "schoolAdmin": "Administration Scolaire" +} diff --git a/Front-End/messages/fr/subscriptions.json b/Front-End/messages/fr/subscriptions.json index eb1f509..d4670ea 100644 --- a/Front-End/messages/fr/subscriptions.json +++ b/Front-End/messages/fr/subscriptions.json @@ -1,33 +1,33 @@ { - "headerBarTitle":"Administration", - "addStudent": "Nouveau", - "allStudents": "Tous les élèves", - "pending": "Inscriptions en attente", - "subscribed": "Inscrits", - "archived": "Archivés", - "name": "Nom", - "class": "Classe", - "status": "Statut", - "attendance": "Assiduité", - "lastEvaluation": "Dernière évaluation", - "active": "Actif", - "pendingStatus": "En attente", - "goodAttendance": "Bonne", - "averageAttendance": "Moyenne", - "lowAttendance": "Faible", - "searchStudent": "Rechercher un élève...", - "title": "Inscription", - "information": "Information", - "no_records": "Il n'y a actuellement aucun dossier d'inscription.", - "add_button": "Ajouter", - "create_first_record": "Veuillez cliquer sur le bouton AJOUTER pour créer votre premier dossier d'inscription.", - "studentName":"Nom de l'élève", - "studentFistName":"Prénom de l'élève", - "mainContactMail":"Email de contact principal", - "phone":"Téléphone", - "lastUpdateDate":"Dernière mise à jour", - "classe":"Classe", - "registrationFileStatus":"État du dossier d'inscription", - "files":"Fichiers", - "subscribeFiles":"Fichiers d'inscription" -} \ No newline at end of file + "headerBarTitle": "Administration", + "addStudent": "Nouveau", + "allStudents": "Tous les élèves", + "pending": "Inscriptions en attente", + "subscribed": "Inscrits", + "archived": "Archivés", + "name": "Nom", + "class": "Classe", + "status": "Statut", + "attendance": "Assiduité", + "lastEvaluation": "Dernière évaluation", + "active": "Actif", + "pendingStatus": "En attente", + "goodAttendance": "Bonne", + "averageAttendance": "Moyenne", + "lowAttendance": "Faible", + "searchStudent": "Rechercher un élève...", + "title": "Inscription", + "information": "Information", + "no_records": "Il n'y a actuellement aucun dossier d'inscription.", + "add_button": "Ajouter", + "create_first_record": "Veuillez cliquer sur le bouton AJOUTER pour créer votre premier dossier d'inscription.", + "studentName": "Nom de l'élève", + "studentFistName": "Prénom de l'élève", + "mainContactMail": "Email de contact principal", + "phone": "Téléphone", + "lastUpdateDate": "Dernière mise à jour", + "classe": "Classe", + "registrationFileStatus": "État du dossier d'inscription", + "files": "Fichiers", + "subscribeFiles": "Fichiers d'inscription" +} diff --git a/Front-End/next.config.mjs b/Front-End/next.config.mjs index 45f3941..caa5fc6 100644 --- a/Front-End/next.config.mjs +++ b/Front-End/next.config.mjs @@ -1,14 +1,13 @@ import createNextIntlPlugin from 'next-intl/plugin'; -import { createRequire } from "module"; +import { createRequire } from 'module'; const require = createRequire(import.meta.url); -const pkg = require("./package.json") - +const pkg = require('./package.json'); const withNextIntl = createNextIntlPlugin(); /** @type {import('next').NextConfig} */ const nextConfig = { - output: "standalone", + output: 'standalone', reactStrictMode: true, experimental: { instrumentationHook: true, @@ -16,17 +15,18 @@ const nextConfig = { images: { remotePatterns: [ { - protocol: "https", - hostname: "www.gravatar.com", + protocol: 'https', + hostname: 'www.gravatar.com', }, ], }, env: { NEXT_PUBLIC_APP_VERSION: pkg.version, - NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080", + NEXT_PUBLIC_API_URL: + process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080', NEXT_PUBLIC_USE_FAKE_DATA: process.env.NEXT_PUBLIC_USE_FAKE_DATA || 'false', AUTH_SECRET: process.env.AUTH_SECRET || 'false', - NEXTAUTH_URL: process.env.NEXTAUTH_URL || "http://localhost:3000", + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'http://localhost:3000', DOCUSEAL_API_KEY: process.env.DOCUSEAL_API_KEY, }, async rewrites() { @@ -40,7 +40,7 @@ const nextConfig = { destination: '/api/auth/:path*', // Exclure les routes NextAuth des réécritures de proxy }, ]; - } + }, }; -export default withNextIntl(nextConfig); \ No newline at end of file +export default withNextIntl(nextConfig); diff --git a/Front-End/postcss.config.js b/Front-End/postcss.config.js index 33ad091..12a703d 100644 --- a/Front-End/postcss.config.js +++ b/Front-End/postcss.config.js @@ -3,4 +3,4 @@ module.exports = { tailwindcss: {}, autoprefixer: {}, }, -} +}; diff --git a/Front-End/scripts/check-hardcoded-strings.js b/Front-End/scripts/check-hardcoded-strings.js index db1a771..1eab648 100644 --- a/Front-End/scripts/check-hardcoded-strings.js +++ b/Front-End/scripts/check-hardcoded-strings.js @@ -29,7 +29,7 @@ const TAILWIND_PATTERNS = [ // États /^(hover|focus|active|disabled|group|dark):/, // Couleurs - /-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-[0-9]+$/ + /-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-[0-9]+$/, ]; // Nouveaux patterns pour ignorer les logs et imports @@ -58,7 +58,7 @@ function isHardcodedString(str) { // Vérifier si la chaîne fait partie d'un console.log ou d'un import const context = str.trim(); - if (CODE_PATTERNS.some(pattern => pattern.test(context))) { + if (CODE_PATTERNS.some((pattern) => pattern.test(context))) { return false; } @@ -68,19 +68,20 @@ function isHardcodedString(str) { } // Vérifier si c'est une chaîne dans un import - if (context.includes('from \'') || context.includes('from "')) { + if (context.includes("from '") || context.includes('from "')) { return false; } // Vérifier si c'est une classe Tailwind const classes = str.split(' '); - if (classes.some(cls => - TAILWIND_PATTERNS.some(pattern => pattern.test(cls)) - )) { + if ( + classes.some((cls) => + TAILWIND_PATTERNS.some((pattern) => pattern.test(cls)) + ) + ) { return false; } - // Autres patterns à ignorer const IGNORE_PATTERNS = [ /^[A-Z][A-Za-z]+$/, // Noms de composants @@ -95,7 +96,7 @@ function isHardcodedString(str) { /^className=/, // className attributes ]; - return !IGNORE_PATTERNS.some(pattern => pattern.test(str)); + return !IGNORE_PATTERNS.some((pattern) => pattern.test(str)); } async function scanFile(filePath) { @@ -106,7 +107,7 @@ async function scanFile(filePath) { const ast = babel.parse(content, { sourceType: 'module', plugins: ['jsx', 'typescript'], - locations: true // Active le tracking des positions + locations: true, // Active le tracking des positions }); traverse(ast, { @@ -140,7 +141,11 @@ async function scanDirectory(dir) { const filePath = path.join(dir, file); const stat = fs.statSync(filePath); - if (stat.isDirectory() && !file.startsWith('.') && file !== 'node_modules') { + if ( + stat.isDirectory() && + !file.startsWith('.') && + file !== 'node_modules' + ) { Object.assign(results, await scanDirectory(filePath)); } else if ( stat.isFile() && @@ -189,4 +194,4 @@ async function main() { await logStringsToFile(results); } -main().catch(console.error); \ No newline at end of file +main().catch(console.error); diff --git a/Front-End/src/app/500.js b/Front-End/src/app/500.js index e2a6f48..17758f0 100644 --- a/Front-End/src/app/500.js +++ b/Front-End/src/app/500.js @@ -1,15 +1,21 @@ -import Link from 'next/link' -import Logo from '../components/Logo' +import Link from 'next/link'; +import Logo from '../components/Logo'; export default function Custom500() { return ( -
-
+
+
-

500 | Erreur interne

-

Une erreur interne est survenue.

- Retour Accueil +

+ 500 | Erreur interne +

+

+ Une erreur interne est survenue. +

+ + Retour Accueil +
- ) -} \ No newline at end of file + ); +} diff --git a/Front-End/src/app/[locale]/admin/directory/page.js b/Front-End/src/app/[locale]/admin/directory/page.js index 38090a3..acd8732 100644 --- a/Front-End/src/app/[locale]/admin/directory/page.js +++ b/Front-End/src/app/[locale]/admin/directory/page.js @@ -1,6 +1,10 @@ -'use client' +'use client'; import React, { useState, useEffect } from 'react'; -import { fetchProfileRoles, updateProfileRoles, deleteProfileRoles } from '@/app/actions/authAction'; +import { + fetchProfileRoles, + updateProfileRoles, + deleteProfileRoles, +} from '@/app/actions/authAction'; import { dissociateGuardian } from '@/app/actions/subscriptionAction'; import logger from '@/utils/logger'; import { useEstablishment } from '@/context/EstablishmentContext'; @@ -24,21 +28,23 @@ export default function Page() { const handleProfiles = () => { fetchProfileRoles(selectedEstablishmentId) - .then(data => { + .then((data) => { setProfileRoles(data); }) - .catch(error => logger.error('Error fetching profileRoles:', error)); - setReloadFetch(false); + .catch((error) => logger.error('Error fetching profileRoles:', error)); + setReloadFetch(false); }; const handleEdit = (profileRole) => { const updatedData = { ...profileRole, is_active: !profileRole.is_active }; return updateProfileRoles(profileRole.id, updatedData, csrfToken) - .then(data => { - setProfileRoles(prevState => prevState.map(item => item.id === profileRole.id ? data : item)); + .then((data) => { + setProfileRoles((prevState) => + prevState.map((item) => (item.id === profileRole.id ? data : item)) + ); return data; }) - .catch(error => { + .catch((error) => { logger.error('Error editing data:', error); throw error; }); @@ -47,10 +53,12 @@ export default function Page() { const handleDelete = (id) => { return deleteProfileRoles(id, csrfToken) .then(() => { - setProfileRoles(prevState => prevState.filter(item => item.id !== id)); - logger.debug("Profile deleted successfully:", id); + setProfileRoles((prevState) => + prevState.filter((item) => item.id !== id) + ); + logger.debug('Profile deleted successfully:', id); }) - .catch(error => { + .catch((error) => { logger.error('Error deleting profile:', error); throw error; }); @@ -59,49 +67,58 @@ export default function Page() { const handleDissociate = (studentId, guardianId) => { return dissociateGuardian(studentId, guardianId) .then((response) => { - logger.debug("Guardian dissociated successfully:", guardianId); - + logger.debug('Guardian dissociated successfully:', guardianId); + // Vérifier si le Guardian a été supprimé const isGuardianDeleted = response?.isGuardianDeleted; - + // Mettre à jour le modèle profileRoles - setProfileRoles(prevState => - prevState.map(profileRole => { - if (profileRole.associated_person?.id === guardianId) { - if (isGuardianDeleted) { - // Si le Guardian est supprimé, retirer le profileRole - return null; - } else { - // Si le Guardian n'est pas supprimé, mettre à jour les élèves associés - const updatedStudents = profileRole.associated_person.students.filter( - student => student.id !== studentId - ); - return { - ...profileRole, - associated_person: { - ...profileRole.associated_person, - students: updatedStudents, // Mettre à jour les élèves associés - }, - }; - } - } - setReloadFetch(true); - return profileRole; // Conserver les autres profileRoles - }).filter(Boolean) // Supprimer les entrées nulles + setProfileRoles( + (prevState) => + prevState + .map((profileRole) => { + if (profileRole.associated_person?.id === guardianId) { + if (isGuardianDeleted) { + // Si le Guardian est supprimé, retirer le profileRole + return null; + } else { + // Si le Guardian n'est pas supprimé, mettre à jour les élèves associés + const updatedStudents = + profileRole.associated_person.students.filter( + (student) => student.id !== studentId + ); + return { + ...profileRole, + associated_person: { + ...profileRole.associated_person, + students: updatedStudents, // Mettre à jour les élèves associés + }, + }; + } + } + setReloadFetch(true); + return profileRole; // Conserver les autres profileRoles + }) + .filter(Boolean) // Supprimer les entrées nulles ); }) - .catch(error => { + .catch((error) => { logger.error('Error dissociating guardian:', error); throw error; }); }; return ( -
+
- +
); diff --git a/Front-End/src/app/[locale]/admin/grades/page.js b/Front-End/src/app/[locale]/admin/grades/page.js index a7804eb..2c00327 100644 --- a/Front-End/src/app/[locale]/admin/grades/page.js +++ b/Front-End/src/app/[locale]/admin/grades/page.js @@ -1,10 +1,10 @@ -'use client' +'use client'; import React, { useState, useEffect } from 'react'; export default function Page() { -return ( -
-

Statistiques

-
-); -} \ No newline at end of file + return ( +
+

Statistiques

+
+ ); +} diff --git a/Front-End/src/app/[locale]/admin/layout.js b/Front-End/src/app/[locale]/admin/layout.js index d3315a4..d936ff8 100644 --- a/Front-End/src/app/[locale]/admin/layout.js +++ b/Front-End/src/app/[locale]/admin/layout.js @@ -1,4 +1,4 @@ -'use client' +'use client'; import React, { useState, useEffect } from 'react'; import Sidebar from '@/components/Sidebar'; import { usePathname } from 'next/navigation'; @@ -14,7 +14,7 @@ import { Settings, LogOut, Menu, - X + X, } from 'lucide-react'; import DropdownMenu from '@/components/DropdownMenu'; @@ -26,7 +26,7 @@ import { FE_ADMIN_DIRECTORY_URL, FE_ADMIN_GRADES_URL, FE_ADMIN_PLANNING_URL, - FE_ADMIN_SETTINGS_URL + FE_ADMIN_SETTINGS_URL, } from '@/utils/Url'; import { disconnect } from '@/app/actions/authAction'; @@ -38,25 +38,63 @@ import { getRightStr, RIGHTS } from '@/utils/rights'; import logger from '@/utils/logger'; import { useEstablishment } from '@/context/EstablishmentContext'; -export default function Layout({ - children, -}) { +export default function Layout({ children }) { const t = useTranslations('sidebar'); const [isSidebarOpen, setIsSidebarOpen] = useState(false); const { data: session } = useSession(); - const { selectedEstablishmentId, setSelectedEstablishmentId, profileRole, setProfileRole, establishments, user } = useEstablishment(); - - + const { + selectedEstablishmentId, + setSelectedEstablishmentId, + profileRole, + setProfileRole, + establishments, + user, + } = useEstablishment(); // Déplacer le reste du code ici... const sidebarItems = { - "admin": { "id": "admin", "name": t('dashboard'), "url": FE_ADMIN_HOME_URL, "icon": LayoutDashboard }, - "subscriptions": { "id": "subscriptions", "name": t('subscriptions'), "url": FE_ADMIN_SUBSCRIPTIONS_URL, "icon": FileText }, - "structure": { "id": "structure", "name": t('structure'), "url": FE_ADMIN_STRUCTURE_URL, "icon": School }, - "directory": { "id": "directory", "name": t('directory'), "url": FE_ADMIN_DIRECTORY_URL, "icon": Users }, - "grades": { "id": "grades", "name": t('grades'), "url": FE_ADMIN_GRADES_URL, "icon": Award }, - "planning": { "id": "planning", "name": t('events'), "url": FE_ADMIN_PLANNING_URL, "icon": Calendar }, - "settings": { "id": "settings", "name": t('settings'), "url": FE_ADMIN_SETTINGS_URL, "icon": Settings } + admin: { + id: 'admin', + name: t('dashboard'), + url: FE_ADMIN_HOME_URL, + icon: LayoutDashboard, + }, + subscriptions: { + id: 'subscriptions', + name: t('subscriptions'), + url: FE_ADMIN_SUBSCRIPTIONS_URL, + icon: FileText, + }, + structure: { + id: 'structure', + name: t('structure'), + url: FE_ADMIN_STRUCTURE_URL, + icon: School, + }, + directory: { + id: 'directory', + name: t('directory'), + url: FE_ADMIN_DIRECTORY_URL, + icon: Users, + }, + grades: { + id: 'grades', + name: t('grades'), + url: FE_ADMIN_GRADES_URL, + icon: Award, + }, + planning: { + id: 'planning', + name: t('events'), + url: FE_ADMIN_PLANNING_URL, + icon: Calendar, + }, + settings: { + id: 'settings', + name: t('settings'), + url: FE_ADMIN_SETTINGS_URL, + icon: Settings, + }, }; const [isPopupVisible, setIsPopupVisible] = useState(false); @@ -66,7 +104,7 @@ export default function Layout({ const headerTitle = sidebarItems[currentPage]?.name || t('dashboard'); - const softwareName = "N3WT School"; + const softwareName = 'N3WT School'; const softwareVersion = `${process.env.NEXT_PUBLIC_APP_VERSION}`; const handleDisconnect = () => { @@ -84,13 +122,15 @@ export default function Layout({ content: (
{user?.email || 'Utilisateur'}
-
{getRightStr(profileRole) || ''}
+
+ {getRightStr(profileRole) || ''} +
- ) + ), }, { type: 'separator', - content:
+ content:
, }, { type: 'item', @@ -126,7 +166,9 @@ export default function Layout({ onEstablishmentChange={(establishmentId) => { const parsedEstablishmentId = parseInt(establishmentId, 10); setSelectedEstablishmentId(parsedEstablishmentId); - let roleIndex = session.user.roles.findIndex(role => role.establishment__id === parsedEstablishmentId) + let roleIndex = session.user.roles.findIndex( + (role) => role.establishment__id === parsedEstablishmentId + ); if (roleIndex === -1) { roleIndex = 0; } @@ -155,7 +197,9 @@ export default function Layout({ > {isSidebarOpen ? : } -
{headerTitle}
+
+ {headerTitle} +
{/* Content avec scroll si nécessaire */} -
- {children} -
+
{children}
{/* Footer responsive */} -
@@ -192,5 +237,3 @@ export default function Layout({ ); } - - diff --git a/Front-End/src/app/[locale]/admin/page.js b/Front-End/src/app/[locale]/admin/page.js index fd45b4b..889c203 100644 --- a/Front-End/src/app/[locale]/admin/page.js +++ b/Front-End/src/app/[locale]/admin/page.js @@ -1,7 +1,7 @@ -'use client' +'use client'; import React, { useState, useEffect } from 'react'; import { useTranslations } from 'next-intl'; -import { Users, Clock, CalendarCheck, School, TrendingUp, UserCheck } from 'lucide-react'; +import { Users, Clock, CalendarCheck, School, TrendingUp } from 'lucide-react'; import Loader from '@/components/Loader'; import ClasseDetails from '@/components/ClasseDetails'; import { fetchClasses } from '@/app/actions/schoolAction'; @@ -11,7 +11,6 @@ import { fetchRegisterForms } from '@/app/actions/subscriptionAction'; import { fetchUpcomingEvents } from '@/app/actions/planningAction'; import { useEstablishment } from '@/context/EstablishmentContext'; - // Composant EventCard pour afficher les événements const EventCard = ({ title, date, description, type }) => (
@@ -35,10 +34,9 @@ export default function DashboardPage() { const [upcomingEvents, setUpcomingEvents] = useState([]); const [monthlyStats, setMonthlyStats] = useState({ inscriptions: [], - completionRate: 0 + completionRate: 0, }); - const [classes, setClasses] = useState([]); const { selectedEstablishmentId } = useEstablishment(); @@ -49,35 +47,41 @@ export default function DashboardPage() { // Fetch des classes fetchClasses(selectedEstablishmentId) - .then(data => { + .then((data) => { setClasses(data); logger.info('Classes fetched:', data); - const nbMaxStudents = data.reduce((acc, classe) => acc + classe.number_of_students, 0); - const nbStudents = data.reduce((acc, classe) => acc + classe.students.length, 0); + const nbMaxStudents = data.reduce( + (acc, classe) => acc + classe.number_of_students, + 0 + ); + const nbStudents = data.reduce( + (acc, classe) => acc + classe.students.length, + 0 + ); setStructureCapacity(nbMaxStudents); setTotalStudents(nbStudents); }) - .catch(error => { + .catch((error) => { logger.error('Error fetching classes:', error); }); // Fetch des formulaires d'inscription fetchRegisterForms() - .then(data => { + .then((data) => { logger.info('Pending registrations fetched:', data); setPendingRegistration(data.count); }) - .catch(error => { + .catch((error) => { logger.error('Error fetching pending registrations:', error); }); // Fetch des événements à venir fetchUpcomingEvents() - .then(data => { + .then((data) => { setUpcomingEvents(data); }) - .catch(error => { + .catch((error) => { logger.error('Error fetching upcoming events:', error); }) .finally(() => { @@ -110,9 +114,9 @@ export default function DashboardPage() { icon={} color="emerald" /> - } color="orange" /> @@ -122,7 +126,9 @@ export default function DashboardPage() {
{/* Graphique des inscriptions */}
-

{t('inscriptionTrends')}

+

+ {t('inscriptionTrends')} +

{/* Insérer ici un composant de graphique */}
@@ -140,11 +146,14 @@ export default function DashboardPage() {
{classes.map((classe) => ( -
- +
+
))}
); -} \ No newline at end of file +} diff --git a/Front-End/src/app/[locale]/admin/planning/page.js b/Front-End/src/app/[locale]/admin/planning/page.js index a09e2a8..8085ffd 100644 --- a/Front-End/src/app/[locale]/admin/planning/page.js +++ b/Front-End/src/app/[locale]/admin/planning/page.js @@ -1,4 +1,4 @@ -'use client' +'use client'; import { PlanningProvider } from '@/context/PlanningContext'; import Calendar from '@/components/Calendar'; import EventModal from '@/components/EventModal'; @@ -19,7 +19,7 @@ export default function Page() { recurrenceEnd: '', customInterval: 1, customUnit: 'days', - viewType: 'week' // Ajouter la vue semaine par défaut + viewType: 'week', // Ajouter la vue semaine par défaut }); const initializeNewEvent = (date = new Date()) => { @@ -37,7 +37,7 @@ export default function Page() { selectedDays: [], recurrenceEnd: '', customInterval: 1, - customUnit: 'days' + customUnit: 'days', }); setIsModalOpen(true); }; @@ -62,4 +62,4 @@ export default function Page() {
); -} \ No newline at end of file +} diff --git a/Front-End/src/app/[locale]/admin/settings/page.js b/Front-End/src/app/[locale]/admin/settings/page.js index 3b8aaa2..f9bcd12 100644 --- a/Front-End/src/app/[locale]/admin/settings/page.js +++ b/Front-End/src/app/[locale]/admin/settings/page.js @@ -1,4 +1,4 @@ -'use client' +'use client'; import React, { useState } from 'react'; import Tab from '@/components/Tab'; import TabContent from '@/components/TabContent'; @@ -85,18 +85,49 @@ export default function SettingsPage() {
- - - + + +
- - - - + + + +
diff --git a/Front-End/src/app/[locale]/admin/structure/page.js b/Front-End/src/app/[locale]/admin/structure/page.js index 4943f6b..f095821 100644 --- a/Front-End/src/app/[locale]/admin/structure/page.js +++ b/Front-End/src/app/[locale]/admin/structure/page.js @@ -1,4 +1,4 @@ -'use client' +'use client'; import React, { useState, useEffect } from 'react'; import StructureManagement from '@/components/Structure/Configuration/StructureManagement'; import ScheduleManagement from '@/components/Structure/Planning/ScheduleManagement'; @@ -6,26 +6,27 @@ import FeesManagement from '@/components/Structure/Tarification/FeesManagement'; import DjangoCSRFToken from '@/components/DjangoCSRFToken'; import { useCsrfToken } from '@/context/CsrfContext'; import { ClassesProvider } from '@/context/ClassesContext'; -import { - createDatas, - updateDatas, - removeDatas, - fetchSpecialities, - fetchTeachers, - fetchClasses, - fetchSchedules, - fetchRegistrationDiscounts, - fetchTuitionDiscounts, - fetchRegistrationFees, - fetchTuitionFees, - fetchRegistrationPaymentPlans, - fetchTuitionPaymentPlans, - fetchRegistrationPaymentModes, - fetchTuitionPaymentModes } from '@/app/actions/schoolAction'; +import { + createDatas, + updateDatas, + removeDatas, + fetchSpecialities, + fetchTeachers, + fetchClasses, + fetchSchedules, + fetchRegistrationDiscounts, + fetchTuitionDiscounts, + fetchRegistrationFees, + fetchTuitionFees, + fetchRegistrationPaymentPlans, + fetchTuitionPaymentPlans, + fetchRegistrationPaymentModes, + fetchTuitionPaymentModes, +} from '@/app/actions/schoolAction'; import { fetchProfileRoles, fetchProfiles } from '@/app/actions/authAction'; import SidebarTabs from '@/components/SidebarTabs'; import FilesGroupsManagement from '@/components/Structure/Files/FilesGroupsManagement'; -import { fetchRegistrationTemplateMaster } from "@/app/actions/registerFileGroupAction"; +import { fetchRegistrationTemplateMaster } from '@/app/actions/registerFileGroupAction'; import logger from '@/utils/logger'; import { useEstablishment } from '@/context/EstablishmentContext'; @@ -76,10 +77,10 @@ export default function Page() { // Fetch data for registration file templates fetchRegistrationTemplateMaster() - .then((data)=> { - setFichiers(data) + .then((data) => { + setFichiers(data); }) - .catch(error => logger.error('Error fetching files:', error)); + .catch((error) => logger.error('Error fetching files:', error)); // Fetch data for registration payment plans handleRegistrationPaymentPlans(); @@ -94,145 +95,161 @@ export default function Page() { handleTuitionPaymentModes(); fetchProfiles() - .then(data => { - setProfiles(data); - }) - .catch(error => { - logger.error('Error fetching profileRoles:', error); - }) + .then((data) => { + setProfiles(data); + }) + .catch((error) => { + logger.error('Error fetching profileRoles:', error); + }); } }, [selectedEstablishmentId]); const handleSpecialities = () => { fetchSpecialities(selectedEstablishmentId) - .then(data => { + .then((data) => { setSpecialities(data); }) - .catch(error => logger.error('Error fetching specialities:', error)); + .catch((error) => logger.error('Error fetching specialities:', error)); }; const handleTeachers = () => { fetchTeachers(selectedEstablishmentId) - .then(data => { + .then((data) => { setTeachers(data); }) - .catch(error => logger.error('Error fetching teachers:', error)); + .catch((error) => logger.error('Error fetching teachers:', error)); }; const handleClasses = () => { fetchClasses(selectedEstablishmentId) - .then(data => { + .then((data) => { setClasses(data); }) - .catch(error => logger.error('Error fetching classes:', error)); + .catch((error) => logger.error('Error fetching classes:', error)); }; const handleSchedules = () => { fetchSchedules() - .then(data => { + .then((data) => { setSchedules(data); }) - .catch(error => logger.error('Error fetching schedules:', error)); + .catch((error) => logger.error('Error fetching schedules:', error)); }; const handleRegistrationDiscounts = () => { fetchRegistrationDiscounts(selectedEstablishmentId) - .then(data => { + .then((data) => { setRegistrationDiscounts(data); }) - .catch(error => logger.error('Error fetching registration discounts:', error)); + .catch((error) => + logger.error('Error fetching registration discounts:', error) + ); }; const handleTuitionDiscounts = () => { fetchTuitionDiscounts(selectedEstablishmentId) - .then(data => { + .then((data) => { setTuitionDiscounts(data); }) - .catch(error => logger.error('Error fetching tuition discounts:', error)); + .catch((error) => + logger.error('Error fetching tuition discounts:', error) + ); }; const handleRegistrationFees = () => { fetchRegistrationFees(selectedEstablishmentId) - .then(data => { + .then((data) => { setRegistrationFees(data); }) - .catch(error => logger.error('Error fetching registration fees:', error)); + .catch((error) => + logger.error('Error fetching registration fees:', error) + ); }; const handleTuitionFees = () => { fetchTuitionFees(selectedEstablishmentId) - .then(data => { + .then((data) => { setTuitionFees(data); }) - .catch(error => logger.error('Error fetching tuition fees', error)); + .catch((error) => logger.error('Error fetching tuition fees', error)); }; const handleRegistrationPaymentPlans = () => { fetchRegistrationPaymentPlans(selectedEstablishmentId) - .then(data => { + .then((data) => { setRegistrationPaymentPlans(data); }) - .catch(error => logger.error('Error fetching registration payment plans:', error)); + .catch((error) => + logger.error('Error fetching registration payment plans:', error) + ); }; const handleTuitionPaymentPlans = () => { fetchTuitionPaymentPlans(selectedEstablishmentId) - .then(data => { + .then((data) => { setTuitionPaymentPlans(data); }) - .catch(error => logger.error('Error fetching tuition payment plans:', error)); + .catch((error) => + logger.error('Error fetching tuition payment plans:', error) + ); }; const handleRegistrationPaymentModes = () => { fetchRegistrationPaymentModes(selectedEstablishmentId) - .then(data => { + .then((data) => { setRegistrationPaymentModes(data); }) - .catch(error => logger.error('Error fetching registration payment modes:', error)); + .catch((error) => + logger.error('Error fetching registration payment modes:', error) + ); }; const handleTuitionPaymentModes = () => { fetchTuitionPaymentModes(selectedEstablishmentId) - .then(data => { + .then((data) => { setTuitionPaymentModes(data); }) - .catch(error => logger.error('Error fetching tuition payment modes:', error)); + .catch((error) => + logger.error('Error fetching tuition payment modes:', error) + ); }; const handleCreate = (url, newData, setDatas) => { return createDatas(url, newData, csrfToken) - .then(data => { - setDatas(prevState => [...prevState, data]); - return data; - }) - .catch(error => { - logger.error('Error creating data:', error); - throw error; - }); + .then((data) => { + setDatas((prevState) => [...prevState, data]); + return data; + }) + .catch((error) => { + logger.error('Error creating data:', error); + throw error; + }); }; const handleEdit = (url, id, updatedData, setDatas) => { return updateDatas(url, id, updatedData, csrfToken) - .then(data => { - setDatas(prevState => prevState.map(item => item.id === id ? data : item)); - return data; - }) - .catch(error => { - logger.error('Error editing data:', error); - throw error; - }); + .then((data) => { + setDatas((prevState) => + prevState.map((item) => (item.id === id ? data : item)) + ); + return data; + }) + .catch((error) => { + logger.error('Error editing data:', error); + throw error; + }); }; const handleDelete = (url, id, setDatas) => { return removeDatas(url, id, csrfToken) - .then(data => { - setDatas(prevState => prevState.filter(item => item.id !== id)); - return data; - }) - .catch(error => { - logger.error('Error deleting data:', error); - throw error; - }); + .then((data) => { + setDatas((prevState) => prevState.filter((item) => item.id !== id)); + return data; + }) + .catch((error) => { + logger.error('Error deleting data:', error); + throw error; + }); }; const handleUpdatePlanning = (url, planningId, updatedData) => { @@ -240,19 +257,19 @@ export default function Page() { method: 'PUT', headers: { 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken + 'X-CSRFToken': csrfToken, }, body: JSON.stringify(updatedData), - credentials: 'include' + credentials: 'include', }) - .then(response => response.json()) - .then(data => { - logger.debug('Planning mis à jour avec succès :', data); - //setDatas(data); - }) - .catch(error => { - logger.error('Erreur :', error); - }); + .then((response) => response.json()) + .then((data) => { + logger.debug('Planning mis à jour avec succès :', data); + //setDatas(data); + }) + .catch((error) => { + logger.error('Erreur :', error); + }); }; const tabs = [ @@ -272,7 +289,7 @@ export default function Page() { handleEdit={handleEdit} handleDelete={handleDelete} /> - ) + ), }, { id: 'Schedule', @@ -284,7 +301,7 @@ export default function Page() { classes={classes} /> - ) + ), }, { id: 'Fees', @@ -311,23 +328,27 @@ export default function Page() { handleEdit={handleEdit} handleDelete={handleDelete} /> - ) + ), }, { id: 'Files', - label: 'Documents d\'inscription', - content: - } + label: "Documents d'inscription", + content: ( + + ), + }, ]; return ( -
+
-
); } diff --git a/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js b/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js index 4f7ecd7..b4eb1d0 100644 --- a/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js +++ b/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js @@ -1,4 +1,4 @@ -'use client' +'use client'; import React, { useState } from 'react'; import { useSearchParams, useRouter } from 'next/navigation'; import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared'; @@ -9,41 +9,37 @@ import { editRegisterForm } from '@/app/actions/subscriptionAction'; import logger from '@/utils/logger'; export default function Page() { - const router = useRouter(); - const searchParams = useSearchParams(); - const studentId = searchParams.get('studentId'); // Changé de codeDI à studentId + const router = useRouter(); + const searchParams = useSearchParams(); + const studentId = searchParams.get('studentId'); // Changé de codeDI à studentId - const [formErrors, setFormErrors] = useState({}); - const csrfToken = useCsrfToken(); - const { selectedEstablishmentId } = useEstablishment(); + const [formErrors, setFormErrors] = useState({}); + const csrfToken = useCsrfToken(); + const { selectedEstablishmentId } = useEstablishment(); + const handleSubmit = (data) => { + editRegisterForm(studentId, data, csrfToken) + .then((result) => { + logger.debug('Success:', result); + router.push(FE_ADMIN_SUBSCRIPTIONS_URL); + }) + .catch((error) => { + logger.error('Error:', error.message); + if (error.details) { + logger.error('Form errors:', error.details); + setFormErrors(error.details); + } + }); + }; - const handleSubmit = (data) => { - - editRegisterForm(studentId, data, csrfToken) - - .then((result) => { - logger.debug('Success:', result); - router.push(FE_ADMIN_SUBSCRIPTIONS_URL); - }) - .catch((error) => { - logger.error('Error:', error.message); - if (error.details) { - logger.error('Form errors:', error.details); - setFormErrors(error.details); - } - }); - - }; - - return ( - - ); -} \ No newline at end of file + return ( + + ); +} diff --git a/Front-End/src/app/[locale]/admin/subscriptions/page.js b/Front-End/src/app/[locale]/admin/subscriptions/page.js index 680c723..0d208e5 100644 --- a/Front-End/src/app/[locale]/admin/subscriptions/page.js +++ b/Front-End/src/app/[locale]/admin/subscriptions/page.js @@ -1,18 +1,27 @@ -'use client' +'use client'; import React, { useState, useEffect } from 'react'; import Table from '@/components/Table'; import Tab from '@/components/Tab'; import { useTranslations } from 'next-intl'; -import StatusLabel from '@/components/StatusLabel'; +import StatusLabel from '@/components/StatusLabel'; import { Search } from 'lucide-react'; import Popup from '@/components/Popup'; import Loader from '@/components/Loader'; import AlertWithModal from '@/components/AlertWithModal'; -import DropdownMenu from "@/components/DropdownMenu"; -import { MoreVertical, Send, Edit, Archive, FileText, CircleCheck, Plus, XCircle } from 'lucide-react'; +import DropdownMenu from '@/components/DropdownMenu'; +import { + MoreVertical, + Send, + Edit, + Archive, + FileText, + CircleCheck, + Plus, + XCircle, +} from 'lucide-react'; import Modal from '@/components/Modal'; -import InscriptionForm from '@/components/Inscription/InscriptionForm' -import AffectationClasseForm from '@/components/AffectationClasseForm' +import InscriptionForm from '@/components/Inscription/InscriptionForm'; +import AffectationClasseForm from '@/components/AffectationClasseForm'; import { useEstablishment } from '@/context/EstablishmentContext'; import ValidateSubscription from '@/components/Inscription/ValidateSubscription'; @@ -25,30 +34,37 @@ import { sendRegisterForm, archiveRegisterForm, fetchStudents, - editRegisterForm } from "@/app/actions/subscriptionAction" + editRegisterForm, +} from '@/app/actions/subscriptionAction'; - import { - fetchRegistrationTemplateMaster, - createRegistrationTemplates, - fetchRegistrationFileGroups, - cloneTemplate - } from "@/app/actions/registerFileGroupAction"; +import { + fetchRegistrationTemplateMaster, + createRegistrationTemplates, + fetchRegistrationFileGroups, + cloneTemplate, +} from '@/app/actions/registerFileGroupAction'; import { fetchClasses, fetchRegistrationDiscounts, fetchTuitionDiscounts, fetchRegistrationFees, - fetchTuitionFees } from '@/app/actions/schoolAction'; + fetchTuitionFees, +} from '@/app/actions/schoolAction'; -import { createProfile, deleteProfile, fetchProfiles } from '@/app/actions/authAction'; +import { + createProfile, + deleteProfile, + fetchProfiles, +} from '@/app/actions/authAction'; import { BASE_URL, FE_ADMIN_SUBSCRIPTIONS_EDIT_URL, - FE_ADMIN_SUBSCRIPTIONS_VALIDATE_URL } from '@/utils/Url'; + FE_ADMIN_SUBSCRIPTIONS_VALIDATE_URL, +} from '@/utils/Url'; -import DjangoCSRFToken from '@/components/DjangoCSRFToken' +import DjangoCSRFToken from '@/components/DjangoCSRFToken'; import { useCsrfToken } from '@/context/CsrfContext'; import logger from '@/utils/logger'; import { PhoneLabel } from '@/components/PhoneLabel'; @@ -56,14 +72,21 @@ import { PhoneLabel } from '@/components/PhoneLabel'; export default function Page({ params: { locale } }) { const t = useTranslations('subscriptions'); const [registrationForms, setRegistrationForms] = useState([]); - const [registrationFormsDataPending, setRegistrationFormsDataPending] = useState([]); - const [registrationFormsDataSubscribed, setRegistrationFormsDataSubscribed] = useState([]); - const [registrationFormsDataArchived, setRegistrationFormsDataArchived] = useState([]); + const [registrationFormsDataPending, setRegistrationFormsDataPending] = + useState([]); + const [registrationFormsDataSubscribed, setRegistrationFormsDataSubscribed] = + useState([]); + const [registrationFormsDataArchived, setRegistrationFormsDataArchived] = + useState([]); // const [filter, setFilter] = useState('*'); const [searchTerm, setSearchTerm] = useState(''); const [alertPage, setAlertPage] = useState(false); const [isLoading, setIsLoading] = useState(false); - const [popup, setPopup] = useState({ visible: false, message: '', onConfirm: null }); + const [popup, setPopup] = useState({ + visible: false, + message: '', + onConfirm: null, + }); const [activeTab, setActiveTab] = useState('pending'); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); @@ -80,7 +103,6 @@ export default function Page({ params: { locale } }) { const [students, setEleves] = useState([]); const [reloadFetch, setReloadFetch] = useState(false); - const [registrationDiscounts, setRegistrationDiscounts] = useState([]); const [tuitionDiscounts, setTuitionDiscounts] = useState([]); const [registrationFees, setRegistrationFees] = useState([]); @@ -94,12 +116,11 @@ export default function Page({ params: { locale } }) { const openModal = () => { setIsOpen(true); - } + }; const closeModal = () => { setIsOpen(false); - - } + }; const handleOpenAddGuardian = (eleveSelected) => { setIsOpenAddGuardian(true); @@ -113,11 +134,11 @@ export default function Page({ params: { locale } }) { const openModalAssociationEleve = (eleveSelected) => { setIsOpenAffectationClasse(true); setStudent(eleveSelected); - } + }; - const requestErrorHandler = (err)=>{ + const requestErrorHandler = (err) => { logger.error('Error fetching data:', err); - } + }; /** * Handles the pending data for the registration form. @@ -132,13 +153,12 @@ export default function Page({ params: { locale } }) { if (registerForms) { setRegistrationFormsDataPending(registerForms); } - const calculatedTotalPages = count === 0 ? 1 : Math.ceil(count / page_size); + const calculatedTotalPages = + count === 0 ? 1 : Math.ceil(count / page_size); setTotalPending(count); setTotalPages(calculatedTotalPages); } - } - - + }; /** * Handles the data received from the subscription registration form. @@ -155,162 +175,176 @@ export default function Page({ params: { locale } }) { setRegistrationFormsDataSubscribed(registerForms); } } - } + }; + /** + * Handles the archived data for the register form. + * + * @param {Object} data - The data object containing archived register forms and count. + * @param {Array} data.registerForms - The array of archived register forms. + * @param {number} data.count - The total count of archived register forms. + */ + const registerFormArchivedDataHandler = (data) => { + if (data) { + const { registerForms, count, page_size } = data; -/** - * Handles the archived data for the register form. - * - * @param {Object} data - The data object containing archived register forms and count. - * @param {Array} data.registerForms - The array of archived register forms. - * @param {number} data.count - The total count of archived register forms. - */ -const registerFormArchivedDataHandler = (data) => { - if (data) { - const { registerForms, count, page_size } = data; - - setTotalArchives(count); - if (registerForms) { - setRegistrationFormsDataArchived(registerForms); + setTotalArchives(count); + if (registerForms) { + setRegistrationFormsDataArchived(registerForms); + } } - } -} + }; -useEffect(() => { - if (selectedEstablishmentId) { - const fetchInitialData = () => { - Promise.all([ - fetchClasses(selectedEstablishmentId), - fetchStudents(selectedEstablishmentId) - ]) - .then(([classesData, studentsData]) => { - setClasses(classesData); - setEleves(studentsData); - logger.debug('Success - Classes:', classesData); - logger.debug('Success - Students:', studentsData); - }) - .catch(error => { - logger.error('Error fetching initial data:', error); - }); - }; + useEffect(() => { + if (selectedEstablishmentId) { + const fetchInitialData = () => { + Promise.all([ + fetchClasses(selectedEstablishmentId), + fetchStudents(selectedEstablishmentId), + ]) + .then(([classesData, studentsData]) => { + setClasses(classesData); + setEleves(studentsData); + logger.debug('Success - Classes:', classesData); + logger.debug('Success - Students:', studentsData); + }) + .catch((error) => { + logger.error('Error fetching initial data:', error); + }); + }; - fetchInitialData(); - } -}, [selectedEstablishmentId]); + fetchInitialData(); + } + }, [selectedEstablishmentId]); + useEffect(() => { + if (selectedEstablishmentId) { + const fetchDataAndSetState = () => { + setIsLoading(true); + Promise.all([ + fetchRegisterForms( + selectedEstablishmentId, + PENDING, + currentPage, + itemsPerPage, + searchTerm + ) + .then(registerFormPendingDataHandler) + .catch(requestErrorHandler), + fetchRegisterForms(selectedEstablishmentId, SUBSCRIBED) + .then(registerFormSubscribedDataHandler) + .catch(requestErrorHandler), + fetchRegisterForms(selectedEstablishmentId, ARCHIVED) + .then(registerFormArchivedDataHandler) + .catch(requestErrorHandler), + fetchRegistrationTemplateMaster() + .then((data) => { + setTemplateMasters(data); + }) + .catch((err) => { + logger.debug(err.message); + }), + fetchRegistrationDiscounts(selectedEstablishmentId) + .then((data) => { + setRegistrationDiscounts(data); + }) + .catch(requestErrorHandler), + fetchTuitionDiscounts(selectedEstablishmentId) + .then((data) => { + setTuitionDiscounts(data); + }) + .catch(requestErrorHandler), + fetchRegistrationFees(selectedEstablishmentId) + .then((data) => { + setRegistrationFees(data); + }) + .catch(requestErrorHandler), + fetchTuitionFees(selectedEstablishmentId) + .then((data) => { + setTuitionFees(data); + }) + .catch(requestErrorHandler), + fetchRegistrationFileGroups(selectedEstablishmentId) + .then((data) => { + setGroups(data); + }) + .catch((error) => { + logger.error('Error fetching file groups:', error); + }), + fetchProfiles() + .then((data) => { + setProfiles(data); + }) + .catch((error) => { + logger.error('Error fetching profileRoles:', error); + }), + ]) + .then(() => { + setIsLoading(false); + setReloadFetch(false); + }) + .catch((err) => { + logger.error(err); + setIsLoading(false); + setReloadFetch(false); + }); + }; -useEffect(() => { - if (selectedEstablishmentId) { - const fetchDataAndSetState = () => { - setIsLoading(true); - Promise.all([ - fetchRegisterForms(selectedEstablishmentId, PENDING, currentPage, itemsPerPage, searchTerm) + fetchDataAndSetState(); + } + }, [selectedEstablishmentId, reloadFetch, currentPage, searchTerm]); + + useEffect(() => { + if (selectedEstablishmentId) { + const fetchDataAndSetState = () => { + setIsLoading(true); + fetchRegisterForms( + selectedEstablishmentId, + PENDING, + currentPage, + itemsPerPage, + searchTerm + ) .then(registerFormPendingDataHandler) - .catch(requestErrorHandler), + .catch(requestErrorHandler); fetchRegisterForms(selectedEstablishmentId, SUBSCRIBED) .then(registerFormSubscribedDataHandler) - .catch(requestErrorHandler), + .catch(requestErrorHandler); fetchRegisterForms(selectedEstablishmentId, ARCHIVED) .then(registerFormArchivedDataHandler) - .catch(requestErrorHandler), + .catch(requestErrorHandler); fetchRegistrationTemplateMaster() - .then(data => { + .then((data) => { setTemplateMasters(data); }) - .catch(err => { - logger.debug(err.message); - }), - fetchRegistrationDiscounts(selectedEstablishmentId) - .then(data => { - setRegistrationDiscounts(data); - }) - .catch(requestErrorHandler), - fetchTuitionDiscounts(selectedEstablishmentId) - .then(data => { - setTuitionDiscounts(data); - }) - .catch(requestErrorHandler), - fetchRegistrationFees(selectedEstablishmentId) - .then(data => { - setRegistrationFees(data); - }) - .catch(requestErrorHandler), - fetchTuitionFees(selectedEstablishmentId) - .then(data => { - setTuitionFees(data); - }) - .catch(requestErrorHandler), - fetchRegistrationFileGroups(selectedEstablishmentId) - .then(data => { - setGroups(data); - }) - .catch(error => { - logger.error('Error fetching file groups:', error); - }), - fetchProfiles() - .then(data => { - setProfiles(data); - }) - .catch(error => { - logger.error('Error fetching profileRoles:', error); - }), - ]) - .then(() => { - setIsLoading(false); - setReloadFetch(false); - }) - .catch(err => { - logger.error(err); - setIsLoading(false); - setReloadFetch(false); - }); - }; + .catch((err) => { + err = err.message; + logger.debug(err); + }); - fetchDataAndSetState(); - } -}, [selectedEstablishmentId, reloadFetch, currentPage, searchTerm]); + setIsLoading(false); + setReloadFetch(false); + }; -useEffect(() => { - if (selectedEstablishmentId) { - const fetchDataAndSetState = () => { - - setIsLoading(true); - fetchRegisterForms(selectedEstablishmentId, PENDING, currentPage, itemsPerPage, searchTerm) - .then(registerFormPendingDataHandler) - .catch(requestErrorHandler) - fetchRegisterForms(selectedEstablishmentId, SUBSCRIBED) - .then(registerFormSubscribedDataHandler) - .catch(requestErrorHandler) - fetchRegisterForms(selectedEstablishmentId, ARCHIVED) - .then(registerFormArchivedDataHandler) - .catch(requestErrorHandler) - fetchRegistrationTemplateMaster() - .then((data)=> {setTemplateMasters(data)}) - .catch((err)=>{ err = err.message; logger.debug(err);}); - - setIsLoading(false); - setReloadFetch(false); - } - - const timeoutId = setTimeout(() => { - fetchDataAndSetState(); + const timeoutId = setTimeout(() => { + fetchDataAndSetState(); }, 500); // Debounce la recherche return () => clearTimeout(timeoutId); - } -}, [searchTerm]); + } + }, [searchTerm]); -/** - * UseEffect to update page count of tab - */ -useEffect(()=>{ - if (activeTab === 'pending') { - setTotalPages(Math.ceil(totalPending / itemsPerPage)); - } else if (activeTab === 'subscribed') { - setTotalPages(Math.ceil(totalSubscribed / itemsPerPage)); - } else if (activeTab === 'archived') { - setTotalPages(Math.ceil(totalArchives / itemsPerPage)); - } -},[currentPage]); + /** + * UseEffect to update page count of tab + */ + useEffect(() => { + if (activeTab === 'pending') { + setTotalPages(Math.ceil(totalPending / itemsPerPage)); + } else if (activeTab === 'subscribed') { + setTotalPages(Math.ceil(totalSubscribed / itemsPerPage)); + } else if (activeTab === 'archived') { + setTotalPages(Math.ceil(totalArchives / itemsPerPage)); + } + }, [currentPage]); /** * Archives a registration form after user confirmation. * @@ -323,18 +357,22 @@ useEffect(()=>{ 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 ?`, onConfirm: () => { - archiveRegisterForm(id) - .then(data => { + archiveRegisterForm(id) + .then((data) => { logger.debug('Success:', data); - setRegistrationForms(registrationForms.filter(fiche => fiche.id !== id)); + setRegistrationForms( + registrationForms.filter((fiche) => fiche.id !== id) + ); setReloadFetch(true); alert("Le dossier d'inscription a été correctement archivé"); }) - .catch(error => { + .catch((error) => { logger.error('Error archiving data:', error); - alert("Erreur lors de l'archivage du dossier d'inscription.\nContactez l'administrateur."); + alert( + "Erreur lors de l'archivage du dossier d'inscription.\nContactez l'administrateur." + ); }); - } + }, }); }; @@ -343,27 +381,28 @@ useEffect(()=>{ 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 ?`, onConfirm: () => { - sendRegisterForm(id).then(data => { + sendRegisterForm(id) + .then((data) => { logger.debug('Success:', data); setReloadFetch(true); }) - .catch(error => { + .catch((error) => { logger.error('Error fetching data:', error); }); - } + }, }); }; - const affectationClassFormSubmitHandler = (formdata)=> { - editRegisterForm(student.id,formData, csrfToken) - .then(data => { + const affectationClassFormSubmitHandler = (formdata) => { + editRegisterForm(student.id, formData, csrfToken) + .then((data) => { logger.debug('Success:', data); setReloadFetch(true); }) - .catch(error => { + .catch((error) => { logger.error('Error :', error); }); - } + }; const refuseRegistrationForm = (id, lastname, firstname, guardianEmail) => { const data = { status: 2, establishment: selectedEstablishmentId }; @@ -373,19 +412,21 @@ useEffect(()=>{ message: `Avertissement ! \nVous êtes sur le point de refuser le dossier d'inscription de ${lastname} ${firstname}\nUne notification va être envoyée à l'adresse ${guardianEmail}\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?`, onConfirm: () => { editRegisterForm(id, data, csrfToken) - .then(data => { + .then((data) => { logger.debug('Success:', data); setReloadFetch(true); }) - .catch(error => { + .catch((error) => { logger.error('Error refusing RF:', error); }); - } + }, }); }; const updateStatusAction = (id, newStatus) => { - logger.debug(`Mise à jour du statut du dossier d'inscription avec l'ID : ${id} vers le statut : ${newStatus}`); + logger.debug( + `Mise à jour du statut du dossier d'inscription avec l'ID : ${id} vers le statut : ${newStatus}` + ); }; const handleSearchChange = (event) => { @@ -398,234 +439,306 @@ useEffect(()=>{ const createRF = (updatedData) => { logger.debug('createRF updatedData:', updatedData); - const selectedRegistrationFeesIds = updatedData.selectedRegistrationFees.map(feeId => feeId) - const selectedRegistrationDiscountsIds = updatedData.selectedRegistrationDiscounts.map(discountId => discountId) - const selectedTuitionFeesIds = updatedData.selectedTuitionFees.map(feeId => feeId) - const selectedTuitionDiscountsIds = updatedData.selectedTuitionDiscounts.map(discountId => discountId) - const selectedFileGroup = updatedData.selectedFileGroup - const allFeesIds = [...selectedRegistrationFeesIds, ...selectedTuitionFeesIds]; - const allDiscountsds = [...selectedRegistrationDiscountsIds, ...selectedTuitionDiscountsIds]; + const selectedRegistrationFeesIds = + updatedData.selectedRegistrationFees.map((feeId) => feeId); + const selectedRegistrationDiscountsIds = + updatedData.selectedRegistrationDiscounts.map((discountId) => discountId); + const selectedTuitionFeesIds = updatedData.selectedTuitionFees.map( + (feeId) => feeId + ); + const selectedTuitionDiscountsIds = + updatedData.selectedTuitionDiscounts.map((discountId) => discountId); + const selectedFileGroup = updatedData.selectedFileGroup; + const allFeesIds = [ + ...selectedRegistrationFeesIds, + ...selectedTuitionFeesIds, + ]; + const allDiscountsds = [ + ...selectedRegistrationDiscountsIds, + ...selectedTuitionDiscountsIds, + ]; const data = { student: { last_name: updatedData.studentLastName, first_name: updatedData.studentFirstName, - guardians: updatedData.selectedGuardians.length !== 0 - ? updatedData.selectedGuardians.map(guardianId => ({ id: guardianId })) - : (() => { - if (updatedData.isExistingParentProfile) { - return [{ - profile_role_data: { - establishment: selectedEstablishmentId, - role_type: 2, - is_active: false, - profile: updatedData.existingProfileId, // Associer au profil existant - }, - last_name: updatedData.guardianLastName, - first_name: updatedData.guardianFirstName, - birth_date: updatedData.guardianBirthDate, - address: updatedData.guardianAddress, - phone: updatedData.guardianPhone, - profession: updatedData.guardianProfession - }]; - } + guardians: + updatedData.selectedGuardians.length !== 0 + ? updatedData.selectedGuardians.map((guardianId) => ({ + id: guardianId, + })) + : (() => { + if (updatedData.isExistingParentProfile) { + return [ + { + profile_role_data: { + establishment: selectedEstablishmentId, + role_type: 2, + is_active: false, + profile: updatedData.existingProfileId, // Associer au profil existant + }, + last_name: updatedData.guardianLastName, + first_name: updatedData.guardianFirstName, + birth_date: updatedData.guardianBirthDate, + address: updatedData.guardianAddress, + phone: updatedData.guardianPhone, + profession: updatedData.guardianProfession, + }, + ]; + } - // Si aucun profil existant n'est trouvé, créer un nouveau profil - return [{ - profile_role_data: { - establishment: selectedEstablishmentId, - role_type: 2, - is_active: false, - profile_data: { - email: updatedData.guardianEmail, - password: 'Provisoire01!', - username: updatedData.guardianEmail, - } - }, - last_name: updatedData.guardianLastName, - first_name: updatedData.guardianFirstName, - birth_date: updatedData.guardianBirthDate, - address: updatedData.guardianAddress, - phone: updatedData.guardianPhone, - profession: updatedData.guardianProfession - }]; - })(), - sibling: [] + // Si aucun profil existant n'est trouvé, créer un nouveau profil + return [ + { + profile_role_data: { + establishment: selectedEstablishmentId, + role_type: 2, + is_active: false, + profile_data: { + email: updatedData.guardianEmail, + password: 'Provisoire01!', + username: updatedData.guardianEmail, + }, + }, + last_name: updatedData.guardianLastName, + first_name: updatedData.guardianFirstName, + birth_date: updatedData.guardianBirthDate, + address: updatedData.guardianAddress, + phone: updatedData.guardianPhone, + profession: updatedData.guardianProfession, + }, + ]; + })(), + sibling: [], }, fees: allFeesIds, discounts: allDiscountsds, fileGroup: selectedFileGroup, - establishment: selectedEstablishmentId + establishment: selectedEstablishmentId, }; createRegisterForm(data, csrfToken) - .then(data => { - // Cloner les templates pour chaque templateMaster du fileGroup - const masters = templateMasters.filter(file => file.groups.includes(selectedFileGroup)); - const clonePromises = masters.map((templateMaster, index) => { - return cloneTemplate(templateMaster.id, updatedData.guardianEmail, templateMaster.is_required) - .then(clonedDocument => { - // Sauvegarde des templates clonés dans la base de données - const cloneData = { - name: `${templateMaster.name}_${updatedData.guardianFirstName}_${updatedData.guardianLastName}`, - slug: clonedDocument.slug, - id: clonedDocument.id, - master: templateMaster.id, - registration_form: data.student.id - }; + .then((data) => { + // Cloner les templates pour chaque templateMaster du fileGroup + const masters = templateMasters.filter((file) => + file.groups.includes(selectedFileGroup) + ); + const clonePromises = masters.map((templateMaster, index) => { + return cloneTemplate( + templateMaster.id, + updatedData.guardianEmail, + templateMaster.is_required + ) + .then((clonedDocument) => { + // Sauvegarde des templates clonés dans la base de données + const cloneData = { + name: `${templateMaster.name}_${updatedData.guardianFirstName}_${updatedData.guardianLastName}`, + slug: clonedDocument.slug, + id: clonedDocument.id, + master: templateMaster.id, + registration_form: data.student.id, + }; - return createRegistrationTemplates(cloneData, csrfToken) - .then(response => { - logger.debug('Template enregistré avec succès:', response); - }) - .catch(error => { - logger.error('Erreur lors de l\'enregistrement du template:', error); - }); + return createRegistrationTemplates(cloneData, csrfToken) + .then((response) => { + logger.debug('Template enregistré avec succès:', response); + }) + .catch((error) => { + logger.error( + "Erreur lors de l'enregistrement du template:", + error + ); + }); + }) + .catch((error) => { + logger.error('Error during cloning or sending:', error); + }); + }); + + // Attendre que tous les clones soient créés + Promise.all(clonePromises) + .then(() => { + // Mise à jour immédiate des données + setRegistrationFormsDataPending((prevState) => [ + ...(prevState || []), + data, + ]); + setTotalPending((prev) => prev + 1); + if (updatedData.autoMail) { + sendConfirmRegisterForm( + data.student.id, + updatedData.studentLastName, + updatedData.studentFirstName + ); + } + closeModal(); + // Forcer le rechargement complet des données + setReloadFetch(true); }) - .catch(error => { + .catch((error) => { logger.error('Error during cloning or sending:', error); }); + }) + .catch((error) => { + logger.error('Error:', error); }); - - // Attendre que tous les clones soient créés - Promise.all(clonePromises) - .then(() => { - // Mise à jour immédiate des données - setRegistrationFormsDataPending(prevState => [...(prevState || []), data]); - setTotalPending(prev => prev + 1); - if (updatedData.autoMail) { - sendConfirmRegisterForm(data.student.id, updatedData.studentLastName, updatedData.studentFirstName); - } - closeModal(); - // Forcer le rechargement complet des données - setReloadFetch(true); - }) - .catch(error => { - logger.error('Error during cloning or sending:', error); - }); - }) - .catch((error) => { - logger.error('Error:', error); - }); - } + }; const updateRF = (updatedData) => { logger.debug('updateRF updatedData:', updatedData); const data = { student: { - guardians: updatedData.selectedGuardians.length !== 0 - ? updatedData.selectedGuardians.map(guardianId => ({ id: guardianId })) - : (() => { - if (updatedData.isExistingParentProfile) { - return [{ - profile_role_data: { - establishment: selectedEstablishmentId, - role_type: 2, - is_active: false, - profile: updatedData.existingProfileId, // Associer au profil existant - }, - last_name: updatedData.guardianLastName, - first_name: updatedData.guardianFirstName, - birth_date: updatedData.guardianBirthDate, - address: updatedData.guardianAddress, - phone: updatedData.guardianPhone, - profession: updatedData.guardianProfession - }]; - } + guardians: + updatedData.selectedGuardians.length !== 0 + ? updatedData.selectedGuardians.map((guardianId) => ({ + id: guardianId, + })) + : (() => { + if (updatedData.isExistingParentProfile) { + return [ + { + profile_role_data: { + establishment: selectedEstablishmentId, + role_type: 2, + is_active: false, + profile: updatedData.existingProfileId, // Associer au profil existant + }, + last_name: updatedData.guardianLastName, + first_name: updatedData.guardianFirstName, + birth_date: updatedData.guardianBirthDate, + address: updatedData.guardianAddress, + phone: updatedData.guardianPhone, + profession: updatedData.guardianProfession, + }, + ]; + } - // Si aucun profil existant n'est trouvé, créer un nouveau profil - return [{ - profile_role_data: { - establishment: selectedEstablishmentId, - role_type: 2, - is_active: false, - profile_data: { - email: updatedData.guardianEmail, - password: 'Provisoire01!', - username: updatedData.guardianEmail, - } - }, - last_name: updatedData.guardianLastName, - first_name: updatedData.guardianFirstName, - birth_date: updatedData.guardianBirthDate, - address: updatedData.guardianAddress, - phone: updatedData.guardianPhone, - profession: updatedData.guardianProfession - }]; - })(), + // Si aucun profil existant n'est trouvé, créer un nouveau profil + return [ + { + profile_role_data: { + establishment: selectedEstablishmentId, + role_type: 2, + is_active: false, + profile_data: { + email: updatedData.guardianEmail, + password: 'Provisoire01!', + username: updatedData.guardianEmail, + }, + }, + last_name: updatedData.guardianLastName, + first_name: updatedData.guardianFirstName, + birth_date: updatedData.guardianBirthDate, + address: updatedData.guardianAddress, + phone: updatedData.guardianPhone, + profession: updatedData.guardianProfession, + }, + ]; + })(), }, - establishment: selectedEstablishmentId + establishment: selectedEstablishmentId, }; editRegisterForm(student.id, data, csrfToken) - .then(data => { - // Mise à jour immédiate des données - setRegistrationFormsDataPending(prevState => [...(prevState || []), data]); - setTotalPending(prev => prev + 1); - if (updatedData.autoMail) { - sendConfirmRegisterForm(data.student.id, updatedData.studentLastName, updatedData.studentFirstName); - } - handleCloseAddGuardian(); - // Forcer le rechargement complet des données - setReloadFetch(true); - }) - .catch(error => { - logger.error('Error during updating registration form:', error); - }); - } + .then((data) => { + // Mise à jour immédiate des données + setRegistrationFormsDataPending((prevState) => [ + ...(prevState || []), + data, + ]); + setTotalPending((prev) => prev + 1); + if (updatedData.autoMail) { + sendConfirmRegisterForm( + data.student.id, + updatedData.studentLastName, + updatedData.studentFirstName + ); + } + handleCloseAddGuardian(); + // Forcer le rechargement complet des données + setReloadFetch(true); + }) + .catch((error) => { + logger.error('Error during updating registration form:', error); + }); + }; const getActionsByStatus = (row) => { const actions = { 1: [ { icon: , - onClick: () => window.location.href = `${FE_ADMIN_SUBSCRIPTIONS_EDIT_URL}?studentId=${row.student.id}&id=1`, + onClick: () => + (window.location.href = `${FE_ADMIN_SUBSCRIPTIONS_EDIT_URL}?studentId=${row.student.id}&id=1`), }, { - icon: , - onClick: () => sendConfirmRegisterForm(row.student.id, row.student.last_name, row.student.first_name), + icon: ( + + ), + onClick: () => + sendConfirmRegisterForm( + row.student.id, + row.student.last_name, + row.student.first_name + ), }, ], 2: [ { icon: , - onClick: () => window.location.href = `${FE_ADMIN_SUBSCRIPTIONS_EDIT_URL}?studentId=${row.student.id}&id=1`, + onClick: () => + (window.location.href = `${FE_ADMIN_SUBSCRIPTIONS_EDIT_URL}?studentId=${row.student.id}&id=1`), }, ], 3: [ { - icon: , - onClick: () => window.location.href = `${FE_ADMIN_SUBSCRIPTIONS_VALIDATE_URL}?studentId=${row.student.id}&firstName=${row.student.first_name}&lastName=${row.student.last_name}&paymentMode=${row.registration_payment}&file=${row.registration_file}`, + icon: ( + + ), + onClick: () => + (window.location.href = `${FE_ADMIN_SUBSCRIPTIONS_VALIDATE_URL}?studentId=${row.student.id}&firstName=${row.student.first_name}&lastName=${row.student.last_name}&paymentMode=${row.registration_payment}&file=${row.registration_file}`), }, ], 5: [ { - icon: , + icon: ( + + ), onClick: () => openModalAssociationEleve(row.student), }, ], default: [ { - icon: , - onClick: () => archiveFicheInscription(row.student.id, row.student.last_name, row.student.first_name), + icon: ( + + ), + onClick: () => + archiveFicheInscription( + row.student.id, + row.student.last_name, + row.student.first_name + ), }, ], }; // Combine actions for the specific status and default actions - return [...(actions[row.status] || []), ...(row.status !== 6 ? actions.default : [])]; + return [ + ...(actions[row.status] || []), + ...(row.status !== 6 ? actions.default : []), + ]; }; -const columns = [ - { name: t('studentName'), transform: (row) => row.student.last_name }, - { name: t('studentFistName'), transform: (row) => row.student.first_name }, - { - name: t('mainContactMail'), - transform: (row) => ( - row.student.guardians && row.student.guardians.length > 0 - ? row.student.guardians[0].associated_profile_email - : ( + const columns = [ + { name: t('studentName'), transform: (row) => row.student.last_name }, + { name: t('studentFistName'), transform: (row) => row.student.first_name }, + { + name: t('mainContactMail'), + transform: (row) => + row.student.guardians && row.student.guardians.length > 0 ? ( + row.student.guardians[0].associated_profile_email + ) : (
- ) - ) - }, - { name: t('phone'), transform: (row) => }, - { name: t('lastUpdateDate'), transform: (row) => row.formatted_last_update}, - { name: t('registrationFileStatus'), transform: (row) => ( -
- updateStatusAction(row.student.id, newStatus)} showDropdown={false} /> -
- ) - }, - { name: t('files'), transform: (row) => - (row.registration_file != null) &&( - - ) }, - { name: 'Actions', - transform: (row) => ( -
- {getActionsByStatus(row).map((action, index) => ( - - ))} -
- ), - }, - -]; - -const columnsSubscribed = [ - { name: t('studentName'), transform: (row) => row.student.last_name }, - { name: t('studentFistName'), transform: (row) => row.student.first_name }, - { name: t('lastUpdateDate'), transform: (row) => row.updated_date_formated}, - { name: t('class'), transform: (row) => row.student.first_name}, - { name: t('registrationFileStatus'), transform: (row) => - ( -
- updateStatusAction(row.student.id, newStatus)} showDropdown={false} /> -
- ) - }, - { name: t('files'), transform: (row) => - (row.registration_file != null) &&( - - ) }, - { name: 'Actions', transform: (row) => ( - } - items={[ - { label: ( - <> - Rattacher - - ), - onClick: () => openModalAssociationEleve(row.student) - }, - { label: ( - <> - Archiver - - ), - onClick: () => archiveFicheInscription(row.student.id, row.student.last_name, row.student.first_name), - } - ]} - buttonClassName="text-gray-400 hover:text-gray-600" - menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded-md shadow-lg z-10 flex flex-col items-center" - /> - ) }, - -]; + ), + }, + { + name: t('phone'), + transform: (row) => ( + + ), + }, + { + name: t('lastUpdateDate'), + transform: (row) => row.formatted_last_update, + }, + { + name: t('registrationFileStatus'), + transform: (row) => ( +
+ + updateStatusAction(row.student.id, newStatus) + } + showDropdown={false} + /> +
+ ), + }, + { + name: t('files'), + transform: (row) => + row.registration_file != null && ( + + ), + }, + { + name: 'Actions', + transform: (row) => ( +
+ {getActionsByStatus(row).map((action, index) => ( + + ))} +
+ ), + }, + ]; + const columnsSubscribed = [ + { name: t('studentName'), transform: (row) => row.student.last_name }, + { name: t('studentFistName'), transform: (row) => row.student.first_name }, + { + name: t('lastUpdateDate'), + transform: (row) => row.updated_date_formated, + }, + { name: t('class'), transform: (row) => row.student.first_name }, + { + name: t('registrationFileStatus'), + transform: (row) => ( +
+ + updateStatusAction(row.student.id, newStatus) + } + showDropdown={false} + /> +
+ ), + }, + { + name: t('files'), + transform: (row) => + row.registration_file != null && ( + + ), + }, + { + name: 'Actions', + transform: (row) => ( + + } + items={[ + { + label: ( + <> + Rattacher + + ), + onClick: () => openModalAssociationEleve(row.student), + }, + { + label: ( + <> + Archiver + + ), + onClick: () => + archiveFicheInscription( + row.student.id, + row.student.last_name, + row.student.first_name + ), + }, + ]} + buttonClassName="text-gray-400 hover:text-gray-600" + menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded-md shadow-lg z-10 flex flex-col items-center" + /> + ), + }, + ]; if (isLoading) { return ; } else { - if (registrationForms.length === 0 && registrationFormsDataArchived.length === 0 && alertPage) { + if ( + registrationForms.length === 0 && + registrationFormsDataArchived.length === 0 && + alertPage + ) { return ( -
+
); } else { return ( -
+
{t('pending')} - ({totalPending}) + + ({totalPending}) + - )} + } active={activeTab === 'pending'} onClick={() => setActiveTab('pending')} /> {t('subscribed')} - ({totalSubscribed}) + + ({totalSubscribed}) + - )} + } active={activeTab === 'subscribed'} onClick={() => setActiveTab('subscribed')} /> {t('archived')} - ({totalArchives}) + + ({totalArchives}) + - )} + } active={activeTab === 'archived'} onClick={() => setActiveTab('archived')} />
- {/*SI STATE == pending || subscribe || archived */} - {activeTab === 'pending' || activeTab === 'subscribed' || activeTab === 'archived' ? ( - -
-
- - -
- -
+ {/*SI STATE == pending || subscribe || archived */} + {activeTab === 'pending' || + activeTab === 'subscribed' || + activeTab === 'archived' ? ( + +
+
+ + +
+ +
-
- - - - +
+ +
+ + ) : null} ( - fee.is_active)} - tuitionFees={tuitionFees.filter(fee => fee.is_active)} - groups={groups} - profiles={profiles} - onSubmit={createRF} - /> - )} - /> + isOpen={isOpen} + setIsOpen={setIsOpen} + title={"Nouveau dossier d'inscription"} + ContentComponent={() => ( + fee.is_active + )} + tuitionFees={tuitionFees.filter((fee) => fee.is_active)} + groups={groups} + profiles={profiles} + onSubmit={createRF} + /> + )} + /> )} {isOpenAffectationClasse && ( )} {isOpenAddGuardian && ( - ( - - )} - /> - )} + ( + + )} + /> + )} ); } } -} \ No newline at end of file +} diff --git a/Front-End/src/app/[locale]/admin/subscriptions/validateSubscription/page.js b/Front-End/src/app/[locale]/admin/subscriptions/validateSubscription/page.js index fe5c8e1..63cf2f8 100644 --- a/Front-End/src/app/[locale]/admin/subscriptions/validateSubscription/page.js +++ b/Front-End/src/app/[locale]/admin/subscriptions/validateSubscription/page.js @@ -1,11 +1,11 @@ -'use client' +'use client'; import React from 'react'; import { useSearchParams, useRouter } from 'next/navigation'; import ValidateSubscription from '@/components/Inscription/ValidateSubscription'; -import { sendSEPARegisterForm } from "@/app/actions/subscriptionAction" +import { sendSEPARegisterForm } from '@/app/actions/subscriptionAction'; import { useCsrfToken } from '@/context/CsrfContext'; import logger from '@/utils/logger'; -import { FE_ADMIN_SUBSCRIPTIONS_URL} from '@/utils/Url'; +import { FE_ADMIN_SUBSCRIPTIONS_URL } from '@/utils/Url'; export default function Page() { const searchParams = useSearchParams(); @@ -23,11 +23,11 @@ export default function Page() { const handleAcceptRF = (data) => { logger.debug('Mise à jour du RF avec les données:', data); - const {status, sepa_file} = data + const { status, sepa_file } = data; const formData = new FormData(); formData.append('status', status); // Ajoute le statut formData.append('sepa_file', sepa_file); // Ajoute le fichier SEPA - + // Appeler l'API pour mettre à jour le RF sendSEPARegisterForm(studentId, formData, csrfToken) .then((response) => { @@ -39,7 +39,7 @@ export default function Page() { logger.error('Erreur lors de la mise à jour du RF:', error); }); }; - + return ( ); -} \ No newline at end of file +} diff --git a/Front-End/src/app/[locale]/page.js b/Front-End/src/app/[locale]/page.js index e2f8f00..cadbff1 100644 --- a/Front-End/src/app/[locale]/page.js +++ b/Front-End/src/app/[locale]/page.js @@ -1,5 +1,5 @@ -'use client' -import {useTranslations} from 'next-intl'; +'use client'; +import { useTranslations } from 'next-intl'; import React from 'react'; import Button from '@/components/Button'; import Logo from '@/components/Logo'; // Import du composant Logo diff --git a/Front-End/src/app/[locale]/parents/editInscription/page.js b/Front-End/src/app/[locale]/parents/editInscription/page.js index 490fc46..80dca19 100644 --- a/Front-End/src/app/[locale]/parents/editInscription/page.js +++ b/Front-End/src/app/[locale]/parents/editInscription/page.js @@ -1,38 +1,38 @@ -'use client' -import React, { useState } from 'react'; +'use client'; +import React, { useState } from 'react'; import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared'; import { useSearchParams, useRouter } from 'next/navigation'; import { useCsrfToken } from '@/context/CsrfContext'; import { useEstablishment } from '@/context/EstablishmentContext'; -import { FE_PARENTS_HOME_URL} from '@/utils/Url'; -import { editRegisterForm} from '@/app/actions/subscriptionAction'; +import { FE_PARENTS_HOME_URL } from '@/utils/Url'; +import { editRegisterForm } from '@/app/actions/subscriptionAction'; import logger from '@/utils/logger'; export default function Page() { - const searchParams = useSearchParams(); - const idProfil = searchParams.get('id'); - const studentId = searchParams.get('studentId'); - const router = useRouter(); - const csrfToken = useCsrfToken(); - const { selectedEstablishmentId } = useEstablishment(); + const searchParams = useSearchParams(); + const idProfil = searchParams.get('id'); + const studentId = searchParams.get('studentId'); + const router = useRouter(); + const csrfToken = useCsrfToken(); + const { selectedEstablishmentId } = useEstablishment(); - const handleSubmit = async (data) => { - try { - const result = await editRegisterForm(studentId, data, csrfToken); - logger.debug('Success:', result); - router.push(FE_PARENTS_HOME_URL); - } catch (error) { - logger.error('Error:', error); - } - }; + const handleSubmit = async (data) => { + try { + const result = await editRegisterForm(studentId, data, csrfToken); + logger.debug('Success:', result); + router.push(FE_PARENTS_HOME_URL); + } catch (error) { + logger.error('Error:', error); + } + }; - return ( - - ); -} \ No newline at end of file + return ( + + ); +} diff --git a/Front-End/src/app/[locale]/parents/layout.js b/Front-End/src/app/[locale]/parents/layout.js index 3076328..a814c33 100644 --- a/Front-End/src/app/[locale]/parents/layout.js +++ b/Front-End/src/app/[locale]/parents/layout.js @@ -1,4 +1,4 @@ -'use client' +'use client'; // src/components/Layout.js import React, { useState, useEffect } from 'react'; import DropdownMenu from '@/components/DropdownMenu'; @@ -6,7 +6,11 @@ import ProfileSelector from '@/components/ProfileSelector'; import { useRouter } from 'next/navigation'; // Ajout de l'importation import { 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 { FE_PARENTS_HOME_URL,FE_PARENTS_MESSAGERIE_URL,FE_PARENTS_SETTINGS_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, +} from '@/utils/Url'; // Ajout de l'importation de l'URL de la page d'accueil parent import { fetchMessages } from '@/app/actions/messagerieAction'; import ProtectedRoute from '@/components/ProtectedRoute'; import { disconnect } from '@/app/actions/authAction'; @@ -18,19 +22,15 @@ import { useEstablishment } from '@/context/EstablishmentContext'; import Image from 'next/image'; import Footer from '@/components/Footer'; -export default function Layout({ - children, -}) { - +export default function Layout({ children }) { const router = useRouter(); // Définition de router const [messages, setMessages] = useState([]); const [isLoading, setIsLoading] = useState(true); const [isPopupVisible, setIsPopupVisible] = useState(false); const { profileRole, user } = useEstablishment(); - const softwareName = "N3WT School"; + const softwareName = 'N3WT School'; const softwareVersion = `${process.env.NEXT_PUBLIC_APP_VERSION}`; - const handleDisconnect = () => { setIsPopupVisible(true); }; @@ -40,21 +40,29 @@ export default function Layout({ disconnect(); }; -const dropdownItems = [ + const dropdownItems = [ { type: 'info', content: (
{user?.email || 'Utilisateur'}
-
{getRightStr(profileRole) || ''}
+
+ {getRightStr(profileRole) || ''} +
- ) + ), }, { type: 'separator', - content:
+ content:
, + }, + { + label: 'Settings', + icon: Settings, + onClick: () => { + router.push(FE_PARENTS_SETTINGS_URL); + }, }, - { label: 'Settings', icon: Settings , onClick: () => { router.push(FE_PARENTS_SETTINGS_URL); } }, { type: 'item', label: 'Déconnexion', @@ -63,68 +71,72 @@ const dropdownItems = [ }, ]; return ( - +
{/* Entête */}
-
-
- -
-
Accueil
+
+
+
-
- +
Accueil
+
+
+ -
+
- {messages.length > 0 && ( - - )} -
- - } - items={dropdownItems} - buttonClassName="" - menuClassName="absolute right-0 mt-2 w-64 bg-white border border-gray-200 rounded shadow-lg" - /> + {messages.length > 0 && ( + + )}
+ + + } + items={dropdownItems} + buttonClassName="" + menuClassName="absolute right-0 mt-2 w-64 bg-white border border-gray-200 rounded shadow-lg" + /> +
{/* Content */} -
{/* Ajout de flex-1 pour utiliser toute la hauteur disponible */} +
+ {' '} + {/* Ajout de flex-1 pour utiliser toute la hauteur disponible */} {children}
{/* Footer responsive */}
setIsPopupVisible(false)} - /> - + visible={isPopupVisible} + message="Êtes-vous sûr(e) de vouloir vous déconnecter ?" + onConfirm={confirmDisconnect} + onCancel={() => setIsPopupVisible(false)} + /> + ); } - - diff --git a/Front-End/src/app/[locale]/parents/messagerie/page.js b/Front-End/src/app/[locale]/parents/messagerie/page.js index 1d40809..1cd7627 100644 --- a/Front-End/src/app/[locale]/parents/messagerie/page.js +++ b/Front-End/src/app/[locale]/parents/messagerie/page.js @@ -1,13 +1,25 @@ -'use client' +'use client'; import React, { useState, useRef, useEffect } from 'react'; import { SendHorizontal } from 'lucide-react'; import Image from 'next/image'; import { getGravatarUrl } from '@/utils/gravatar'; const contacts = [ - { id: 1, name: 'Facturation', profilePic: getGravatarUrl('facturation@n3wtschool.com') }, - { id: 2, name: 'Enseignant 1', profilePic: getGravatarUrl('enseignant@n3wtschool.com') }, - { id: 3, name: 'Contact', profilePic: getGravatarUrl('contact@n3wtschool.com') }, + { + id: 1, + name: 'Facturation', + profilePic: getGravatarUrl('facturation@n3wtschool.com'), + }, + { + id: 2, + name: 'Enseignant 1', + profilePic: getGravatarUrl('enseignant@n3wtschool.com'), + }, + { + id: 3, + name: 'Contact', + profilePic: getGravatarUrl('contact@n3wtschool.com'), + }, ]; export default function MessageriePage() { @@ -29,7 +41,14 @@ export default function MessageriePage() { const contactMessages = messages[selectedContact.id] || []; setMessages({ ...messages, - [selectedContact.id]: [...contactMessages, { id: contactMessages.length + 1, text: newMessage, date: new Date() }], + [selectedContact.id]: [ + ...contactMessages, + { + id: contactMessages.length + 1, + text: newMessage, + date: new Date(), + }, + ], }); setNewMessage(''); simulateContactResponse(selectedContact.id); @@ -48,14 +67,24 @@ export default function MessageriePage() { const contactMessages = prevMessages[contactId] || []; return { ...prevMessages, - [contactId]: [...contactMessages, { id: contactMessages.length + 2, text: 'Réponse automatique', isResponse: true, date: new Date() }], + [contactId]: [ + ...contactMessages, + { + id: contactMessages.length + 2, + text: 'Réponse automatique', + isResponse: true, + date: new Date(), + }, + ], }; }); }, 2000); }; return ( -
{/* Utilisation de calc pour soustraire la hauteur de l'entête */} +
+ {' '} + {/* Utilisation de calc pour soustraire la hauteur de l'entête */}
{contacts.map((contact) => (
setSelectedContact(contact)} > - + {contact.name}
))}
- {selectedContact && (messages[selectedContact.id] || []).map((message) => ( -
-
- {`${selectedContact.name}'s - {selectedContact.name} - {new Date(message.date).toLocaleTimeString()} + {selectedContact && + (messages[selectedContact.id] || []).map((message) => ( +
+
+ {`${selectedContact.name}'s + + {selectedContact.name} + + + {new Date(message.date).toLocaleTimeString()} + +
+ {message.text}
- {message.text} -
- ))} + ))}
diff --git a/Front-End/src/app/[locale]/parents/page.js b/Front-End/src/app/[locale]/parents/page.js index d82d520..b31b80a 100644 --- a/Front-End/src/app/[locale]/parents/page.js +++ b/Front-End/src/app/[locale]/parents/page.js @@ -1,4 +1,4 @@ -'use client' +'use client'; import React, { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import Table from '@/components/Table'; @@ -14,35 +14,42 @@ export default function ParentHomePage() { const [children, setChildren] = useState([]); const [userId, setUserId] = useState(null); const [currentPage, setCurrentPage] = useState(1); - const { user, setProfileRole, selectedEstablishmentId, setSelectedEstablishmentId, establishments } = useEstablishment(); + const { + user, + setProfileRole, + selectedEstablishmentId, + setSelectedEstablishmentId, + establishments, + } = useEstablishment(); const router = useRouter(); useEffect(() => { - const userIdFromSession = user.user_id; - setUserId(userIdFromSession); - console.log(selectedEstablishmentId) - fetchChildren(userIdFromSession, selectedEstablishmentId).then(data => { - setChildren(data); - }); - - }, [ selectedEstablishmentId]); + const userIdFromSession = user.user_id; + setUserId(userIdFromSession); + console.log(selectedEstablishmentId); + fetchChildren(userIdFromSession, selectedEstablishmentId).then((data) => { + setChildren(data); + }); + }, [selectedEstablishmentId]); const handleEstablishmentChange = (e) => { const establishmentId = parseInt(e.target.value, 10); setSelectedEstablishmentId(establishmentId); - const role = establishments.find(est => est.id === establishmentId)?.role_type; + const role = establishments.find( + (est) => est.id === establishmentId + )?.role_type; setProfileRole(role); }; function handleEdit(eleveId) { // Logique pour éditer le dossier de l'élève logger.debug(`Edit dossier for student id: ${eleveId}`); - router.push(`${FE_PARENTS_EDIT_INSCRIPTION_URL}?id=${userId}&studentId=${eleveId}`); + router.push( + `${FE_PARENTS_EDIT_INSCRIPTION_URL}?id=${userId}&studentId=${eleveId}` + ); } - const actionColumns = [ - { name: 'Action', transform: (row) => row.action }, - ]; + const actionColumns = [{ name: 'Action', transform: (row) => row.action }]; // Définir les colonnes du tableau const childrenColumns = [ @@ -52,9 +59,9 @@ export default function ParentHomePage() { name: 'Statut', transform: (row) => (
- +
- ) + ), }, { name: 'Actions', @@ -71,8 +78,8 @@ export default function ParentHomePage() {
- ) - } + ), + }, ]; const itemsPerPage = 5; diff --git a/Front-End/src/app/[locale]/parents/settings/page.js b/Front-End/src/app/[locale]/parents/settings/page.js index 9694e0e..a6211e4 100644 --- a/Front-End/src/app/[locale]/parents/settings/page.js +++ b/Front-End/src/app/[locale]/parents/settings/page.js @@ -1,4 +1,4 @@ -'use client' +'use client'; import React, { useState } from 'react'; import Button from '@/components/Button'; import InputText from '@/components/InputText'; @@ -61,13 +61,7 @@ export default function SettingsPage() { required />
-
diff --git a/Front-End/src/app/[locale]/users/login/error.js b/Front-End/src/app/[locale]/users/login/error.js index 5f75634..b08f8aa 100644 --- a/Front-End/src/app/[locale]/users/login/error.js +++ b/Front-End/src/app/[locale]/users/login/error.js @@ -1,7 +1,5 @@ -"use client"; +'use client'; -function ErrorBoundary({ - error -}) { +function ErrorBoundary({ error }) { return <>{error.message}; -} \ No newline at end of file +} diff --git a/Front-End/src/app/[locale]/users/login/page.js b/Front-End/src/app/[locale]/users/login/page.js index 2a68cce..2e6be43 100644 --- a/Front-End/src/app/[locale]/users/login/page.js +++ b/Front-End/src/app/[locale]/users/login/page.js @@ -1,116 +1,159 @@ -'use client' -import React, { useState } from 'react' -import DjangoCSRFToken from '@/components/DjangoCSRFToken' +'use client'; +import React, { useState } from 'react'; +import DjangoCSRFToken from '@/components/DjangoCSRFToken'; import Logo from '@/components/Logo'; -import { useSearchParams, useRouter } from 'next/navigation' +import { useSearchParams, useRouter } from 'next/navigation'; import InputTextIcon from '@/components/InputTextIcon'; import Loader from '@/components/Loader'; // Importez le composant Loader import Button from '@/components/Button'; // Importez le composant Button import { User, KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires -import { - FE_USERS_NEW_PASSWORD_URL, - getRedirectUrlFromRole -} from '@/utils/Url'; +import { FE_USERS_NEW_PASSWORD_URL, getRedirectUrlFromRole } from '@/utils/Url'; import { login } from '@/app/actions/authAction'; import { getSession } from 'next-auth/react'; import { useCsrfToken } from '@/context/CsrfContext'; // Importez le hook useCsrfToken import logger from '@/utils/logger'; - import { useEstablishment } from '@/context/EstablishmentContext'; - - export default function Page() { - const searchParams = useSearchParams(); - const [errorMessage, setErrorMessage] = useState(""); - const [userFieldError, setUserFieldError] = useState("") - const [passwordFieldError, setPasswordFieldError] = useState("") - const { setUser } = useEstablishment(); - const [isLoading, setIsLoading] = useState(false); + const searchParams = useSearchParams(); + const [errorMessage, setErrorMessage] = useState(''); + const [userFieldError, setUserFieldError] = useState(''); + const [passwordFieldError, setPasswordFieldError] = useState(''); + const { setUser } = useEstablishment(); + const [isLoading, setIsLoading] = useState(false); - const router = useRouter(); - const csrfToken = useCsrfToken(); // Utilisez le hook useCsrfToken + const router = useRouter(); + const csrfToken = useCsrfToken(); // Utilisez le hook useCsrfToken - function isOK(data) { - return data.errorMessage === "" - } + function isOK(data) { + return data.errorMessage === ''; + } + function handleFormLogin(formData) { + setIsLoading(true); + setErrorMessage(''); + login({ + email: formData.get('login'), + password: formData.get('password'), + }) + .then((result) => { + logger.debug('Sign In Result', result); - function handleFormLogin(formData) { - setIsLoading(true); - setErrorMessage(""); - - login({ - email: formData.get('login'), - password: formData.get('password') - }).then(result => { - logger.debug('Sign In Result', result); - - if (result.error) { - setErrorMessage(result.error); + if (result.error) { + setErrorMessage(result.error); + setIsLoading(false); + } else { + getSession() + .then((session) => { + if (!session || !session.user) { + throw new Error('Session not found'); + } + const user = session.user; + logger.debug('User Session:', user); + setUser(session.user); + if (session.user.roles && session.user.roles.length > 0) { + let roleIndex = 0; + if ( + session.user.roles.length > session.user.roleIndexLoginDefault + ) { + roleIndex = session.user.roleIndexLoginDefault; + } + const role = session.user.roles[roleIndex].role_type; + const url = getRedirectUrlFromRole(role); + if (url) { + router.push(url); + } else { + setIsLoading(false); + setErrorMessage('Type de rôle non géré'); + } + } else { setIsLoading(false); - } else { - getSession().then(session => { - if (!session || !session.user) { - throw new Error('Session not found'); - } - const user = session.user; - logger.debug('User Session:', user); - setUser(session.user); - if (session.user.roles && session.user.roles.length > 0) { - let roleIndex = 0; - if( session.user.roles.length > session.user.roleIndexLoginDefault){ - roleIndex = session.user.roleIndexLoginDefault; - } - const role = session.user.roles[roleIndex].role_type; - const url = getRedirectUrlFromRole(role); - if (url) { - router.push(url); - } else { - setIsLoading(false); - setErrorMessage('Type de rôle non géré'); - } - } else { - setIsLoading(false); - setErrorMessage('Aucun rôle trouvé pour le profil sélectionné.'); - } - }).catch(error => { - logger.error('Erreur lors de la récupération de la session:', error); - setIsLoading(false); - setErrorMessage('Une erreur est survenue lors de la récupération de la session.'); - }); - } - }).catch(error => { - logger.error('Erreur lors de la connexion:', error); - setIsLoading(false); - setErrorMessage('Une erreur est survenue lors de la connexion.'); - }); - } + setErrorMessage( + 'Aucun rôle trouvé pour le profil sélectionné.' + ); + } + }) + .catch((error) => { + logger.error( + 'Erreur lors de la récupération de la session:', + error + ); + setIsLoading(false); + setErrorMessage( + 'Une erreur est survenue lors de la récupération de la session.' + ); + }); + } + }) + .catch((error) => { + logger.error('Erreur lors de la connexion:', error); + setIsLoading(false); + setErrorMessage('Une erreur est survenue lors de la connexion.'); + }); + } - if (isLoading === true) { - return // Affichez le composant Loader - } else { - return <> -
-
- -
-

Authentification

-
{ e.preventDefault(); handleFormLogin(new FormData(e.target)); }}> - - - -
-
- - -
-
- + if (isLoading === true) { + return ; // Affichez le composant Loader + } else { + return ( + <> +
+
+ +
+

+ Authentification +

+
{ + e.preventDefault(); + handleFormLogin(new FormData(e.target)); + }} + > + + + +
+ + +
+
- - } -}; + +
+ + ); + } +} diff --git a/Front-End/src/app/[locale]/users/password/new/page.js b/Front-End/src/app/[locale]/users/password/new/page.js index 495bbe8..5e46f3c 100644 --- a/Front-End/src/app/[locale]/users/password/new/page.js +++ b/Front-End/src/app/[locale]/users/password/new/page.js @@ -1,7 +1,7 @@ -'use client' +'use client'; import React, { useState } from 'react'; -import DjangoCSRFToken from '@/components/DjangoCSRFToken' +import DjangoCSRFToken from '@/components/DjangoCSRFToken'; import Logo from '@/components/Logo'; import { useSearchParams } from 'next/navigation'; import InputTextIcon from '@/components/InputTextIcon'; @@ -17,80 +17,108 @@ import logger from '@/utils/logger'; const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true'; export default function Page() { - const searchParams = useSearchParams(); - const [errorMessage, setErrorMessage] = useState(""); - const [userFieldError, setUserFieldError] = useState(""); - const [isLoading, setIsLoading] = useState(false); - const [popupVisible, setPopupVisible] = useState(false); - const [popupMessage, setPopupMessage] = useState(""); - const [popupConfirmAction, setPopupConfirmAction] = useState(null); - const csrfToken = useCsrfToken(); + const searchParams = useSearchParams(); + const [errorMessage, setErrorMessage] = useState(''); + const [userFieldError, setUserFieldError] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const [popupVisible, setPopupVisible] = useState(false); + const [popupMessage, setPopupMessage] = useState(''); + const [popupConfirmAction, setPopupConfirmAction] = useState(null); + const csrfToken = useCsrfToken(); - function validate(formData) { - if (useFakeData) { - setTimeout(() => { - setUserFieldError(""); - setErrorMessage(""); - setPopupMessage("Mot de passe réinitialisé avec succès !"); - setPopupConfirmAction(() => () => setPopupVisible(false)); - setPopupVisible(true); - }, 1000); // Simule un délai de traitement - } else { - const data = {email: formData.get('email')} - sendNewPassword(data, csrfToken) - .then(data => { - logger.debug('Success:', data); - setUserFieldError(""); - setErrorMessage(""); - if (data.errorMessage === "") { - setPopupMessage(data.message); - setPopupConfirmAction(() => () => setPopupVisible(false)); - setPopupVisible(true); - } else { - if (data.errorFields) { - setUserFieldError(data.errorFields.email); - } - if (data.errorMessage) { - setErrorMessage(data.errorMessage); - } - } - }) - .catch(error => { - logger.error('Error fetching data:', error); - error = error.errorMessage; - logger.debug(error); - }); - } - } - - if (isLoading === true) { - return // Affichez le composant Loader + function validate(formData) { + if (useFakeData) { + setTimeout(() => { + setUserFieldError(''); + setErrorMessage(''); + setPopupMessage('Mot de passe réinitialisé avec succès !'); + setPopupConfirmAction(() => () => setPopupVisible(false)); + setPopupVisible(true); + }, 1000); // Simule un délai de traitement } else { - return <> -
-
- -
-

Nouveau Mot de passe

-
{ e.preventDefault(); validate(new FormData(e.target)); }}> - - -

{errorMessage}

-
-
- -
-
-
-
- setPopupVisible(false)} - /> - + const data = { email: formData.get('email') }; + sendNewPassword(data, csrfToken) + .then((data) => { + logger.debug('Success:', data); + setUserFieldError(''); + setErrorMessage(''); + if (data.errorMessage === '') { + setPopupMessage(data.message); + setPopupConfirmAction(() => () => setPopupVisible(false)); + setPopupVisible(true); + } else { + if (data.errorFields) { + setUserFieldError(data.errorFields.email); + } + if (data.errorMessage) { + setErrorMessage(data.errorMessage); + } + } + }) + .catch((error) => { + logger.error('Error fetching data:', error); + error = error.errorMessage; + logger.debug(error); + }); } -} \ No newline at end of file + } + + if (isLoading === true) { + return ; // Affichez le composant Loader + } else { + return ( + <> +
+
+ +
+

+ Nouveau Mot de passe +

+
{ + e.preventDefault(); + validate(new FormData(e.target)); + }} + > + + +

{errorMessage}

+
+
+ +
+
+
+
+ setPopupVisible(false)} + /> + + ); + } +} diff --git a/Front-End/src/app/[locale]/users/password/reset/page.js b/Front-End/src/app/[locale]/users/password/reset/page.js index 6ac49f1..ae0f355 100644 --- a/Front-End/src/app/[locale]/users/password/reset/page.js +++ b/Front-End/src/app/[locale]/users/password/reset/page.js @@ -1,10 +1,10 @@ -'use client' +'use client'; // src/app/pages/subscribe.js import React, { useState, useEffect } from 'react'; -import DjangoCSRFToken from '@/components/DjangoCSRFToken' +import DjangoCSRFToken from '@/components/DjangoCSRFToken'; import Logo from '@/components/Logo'; -import { useSearchParams, useRouter } from 'next/navigation' +import { useSearchParams, useRouter } from 'next/navigation'; import InputTextIcon from '@/components/InputTextIcon'; import Loader from '@/components/Loader'; // Importez le composant Loader import Button from '@/components/Button'; // Importez le composant Button @@ -18,113 +18,149 @@ import logger from '@/utils/logger'; const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true'; export default function Page() { - const searchParams = useSearchParams(); - const uuid = searchParams.get('uuid'); - const [errorMessage, setErrorMessage] = useState(""); - const [password1FieldError,setPassword1FieldError] = useState("") - const [password2FieldError,setPassword2FieldError] = useState("") - const [isLoading, setIsLoading] = useState(false); - const [popupVisible, setPopupVisible] = useState(false); - const [popupMessage, setPopupMessage] = useState(""); + const searchParams = useSearchParams(); + const uuid = searchParams.get('uuid'); + const [errorMessage, setErrorMessage] = useState(''); + const [password1FieldError, setPassword1FieldError] = useState(''); + const [password2FieldError, setPassword2FieldError] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const [popupVisible, setPopupVisible] = useState(false); + const [popupMessage, setPopupMessage] = useState(''); - const router = useRouter(); - const csrfToken = useCsrfToken(); + const router = useRouter(); + const csrfToken = useCsrfToken(); - useEffect(() => { - if (useFakeData) { - setTimeout(() => { - setIsLoading(false); - }, 1000); - } else { - getResetPassword(uuid) - .then(data => { - logger.debug('Success:', data); - setIsLoading(true); - if(data.errorFields){ - setPassword1FieldError(data.errorFields.password1) - setPassword2FieldError(data.errorFields.password2) - } - if(data.errorMessage){ - setErrorMessage(data.errorMessage) - } - setIsLoading(false); - }) - .catch(error => { - logger.error('Error fetching data:', error); - }); - } - }, []); - - function validate(formData) { - if (useFakeData) { - setTimeout(() => { - setPopupMessage("Mot de passe réinitialisé avec succès"); - setPopupVisible(true); - }, 1000); - } else { - const data = { - password1: formData.get('password1'), - password2: formData.get('password2'), - } - resetPassword(uuid,data,csrfToken) - .then(data => { - logger.debug('Success:', data); - setPassword1FieldError("") - setPassword2FieldError("") - setErrorMessage("") - if(data.errorMessage === ""){ - setPopupMessage(data.message); - setPopupVisible(true); - } else { - if(data.errorMessage){ - setErrorMessage(data.errorMessage); - } - if(data.errorFields){ - setPassword1FieldError(data.errorFields.password1) - setPassword2FieldError(data.errorFields.password2) - } - } - }) - .catch(error => { - logger.error('Error fetching data:', error); - error = error.errorMessage; - logger.debug(error); - }); - } - } - - if (isLoading === true) { - return // Affichez le composant Loader + useEffect(() => { + if (useFakeData) { + setTimeout(() => { + setIsLoading(false); + }, 1000); } else { - return <> - { - setPopupVisible(false); - router.push(`${FE_USERS_LOGIN_URL}`); - }} - onCancel={() => setPopupVisible(false)} - /> -
-
- -
-

Réinitialisation du mot de passe

-
{ e.preventDefault(); validate(new FormData(e.target)); }}> - - - - -
-
- -
-
-
-
- + getResetPassword(uuid) + .then((data) => { + logger.debug('Success:', data); + setIsLoading(true); + if (data.errorFields) { + setPassword1FieldError(data.errorFields.password1); + setPassword2FieldError(data.errorFields.password2); + } + if (data.errorMessage) { + setErrorMessage(data.errorMessage); + } + setIsLoading(false); + }) + .catch((error) => { + logger.error('Error fetching data:', error); + }); } -} \ No newline at end of file + }, []); + + function validate(formData) { + if (useFakeData) { + setTimeout(() => { + setPopupMessage('Mot de passe réinitialisé avec succès'); + setPopupVisible(true); + }, 1000); + } else { + const data = { + password1: formData.get('password1'), + password2: formData.get('password2'), + }; + resetPassword(uuid, data, csrfToken) + .then((data) => { + logger.debug('Success:', data); + setPassword1FieldError(''); + setPassword2FieldError(''); + setErrorMessage(''); + if (data.errorMessage === '') { + setPopupMessage(data.message); + setPopupVisible(true); + } else { + if (data.errorMessage) { + setErrorMessage(data.errorMessage); + } + if (data.errorFields) { + setPassword1FieldError(data.errorFields.password1); + setPassword2FieldError(data.errorFields.password2); + } + } + }) + .catch((error) => { + logger.error('Error fetching data:', error); + error = error.errorMessage; + logger.debug(error); + }); + } + } + + if (isLoading === true) { + return ; // Affichez le composant Loader + } else { + return ( + <> + { + setPopupVisible(false); + router.push(`${FE_USERS_LOGIN_URL}`); + }} + onCancel={() => setPopupVisible(false)} + /> +
+
+ +
+

+ Réinitialisation du mot de passe +

+
{ + e.preventDefault(); + validate(new FormData(e.target)); + }} + > + + + + +
+
+ +
+
+
+
+ + ); + } +} diff --git a/Front-End/src/app/[locale]/users/subscribe/page.js b/Front-End/src/app/[locale]/users/subscribe/page.js index db7e37e..b1f3c38 100644 --- a/Front-End/src/app/[locale]/users/subscribe/page.js +++ b/Front-End/src/app/[locale]/users/subscribe/page.js @@ -1,106 +1,155 @@ -'use client' +'use client'; // src/app/pages/subscribe.js import React, { useState, useEffect } from 'react'; -import DjangoCSRFToken from '@/components/DjangoCSRFToken' +import DjangoCSRFToken from '@/components/DjangoCSRFToken'; import Logo from '@/components/Logo'; -import { useSearchParams, useRouter } from 'next/navigation' +import { useSearchParams, useRouter } from 'next/navigation'; import InputTextIcon from '@/components/InputTextIcon'; import Loader from '@/components/Loader'; // Importez le composant Loader import Button from '@/components/Button'; // Importez le composant Button import Popup from '@/components/Popup'; // Importez le composant Popup import { User, KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires -import { FE_USERS_LOGIN_URL } from '@/utils/Url'; +import { FE_USERS_LOGIN_URL } from '@/utils/Url'; import { useCsrfToken } from '@/context/CsrfContext'; import { subscribe } from '@/app/actions/authAction'; import logger from '@/utils/logger'; import { useEstablishment } from '@/context/EstablishmentContext'; export default function Page() { - const searchParams = useSearchParams(); + const searchParams = useSearchParams(); - const [errorMessage, setErrorMessage] = useState(""); - const [userFieldError,setUserFieldError] = useState("") - const [password1FieldError,setPassword1FieldError] = useState("") - const [password2FieldError,setPassword2FieldError] = useState("") - const [isLoading, setIsLoading] = useState(false); - const [popupVisible, setPopupVisible] = useState(false); - const [popupMessage, setPopupMessage] = useState(""); + const [errorMessage, setErrorMessage] = useState(''); + const [userFieldError, setUserFieldError] = useState(''); + const [password1FieldError, setPassword1FieldError] = useState(''); + const [password2FieldError, setPassword2FieldError] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const [popupVisible, setPopupVisible] = useState(false); + const [popupMessage, setPopupMessage] = useState(''); - const router = useRouter(); - const csrfToken = useCsrfToken(); - - const establishment_id = searchParams.get('establishment_id'); + const router = useRouter(); + const csrfToken = useCsrfToken(); - function isOK(data) { - return data.errorMessage === "" - } + const establishment_id = searchParams.get('establishment_id'); - function subscribeFormSubmit(formData) { - const data ={ - email: formData.get('login'), - password1: formData.get('password1'), - password2: formData.get('password2'), - establishment_id: establishment_id + function isOK(data) { + return data.errorMessage === ''; + } + + function subscribeFormSubmit(formData) { + const data = { + email: formData.get('login'), + password1: formData.get('password1'), + password2: formData.get('password2'), + establishment_id: establishment_id, + }; + subscribe(data, csrfToken) + .then((data) => { + logger.debug('Success:', data); + setUserFieldError(''); + setPassword1FieldError(''); + setPassword2FieldError(''); + setErrorMessage(''); + if (isOK(data)) { + setPopupMessage(data.message); + setPopupVisible(true); + } else { + if (data.errorMessage) { + setErrorMessage(data.errorMessage); + } + if (data.errorFields) { + setUserFieldError(data.errorFields.email); + setPassword1FieldError(data.errorFields.password1); + setPassword2FieldError(data.errorFields.password2); + } } - subscribe(data,csrfToken).then(data => { - logger.debug('Success:', data); - setUserFieldError("") - setPassword1FieldError("") - setPassword2FieldError("") - setErrorMessage("") - if(isOK(data)){ - setPopupMessage(data.message); - setPopupVisible(true); - } else { - if(data.errorMessage){ - setErrorMessage(data.errorMessage); - } - if(data.errorFields){ - setUserFieldError(data.errorFields.email) - setPassword1FieldError(data.errorFields.password1) - setPassword2FieldError(data.errorFields.password2) - } - } - }) - .catch(error => { - logger.error('Error fetching data:', error); - error = error.errorMessage; - logger.debug(error); - }); - } + }) + .catch((error) => { + logger.error('Error fetching data:', error); + error = error.errorMessage; + logger.debug(error); + }); + } - if (isLoading === true) { - return // Affichez le composant Loader - } else { - return <> -
-
- -
-

Nouveau profil

-
{ e.preventDefault(); subscribeFormSubmit(new FormData(e.target)); }}> - - - - -

{errorMessage}

-
-
- -
-
-
- { - setPopupVisible(false); - router.push(`${FE_USERS_LOGIN_URL}`); - }} - onCancel={() => setPopupVisible(false)} + if (isLoading === true) { + return ; // Affichez le composant Loader + } else { + return ( + <> +
+
+ +
+

+ Nouveau profil +

+
{ + e.preventDefault(); + subscribeFormSubmit(new FormData(e.target)); + }} + > + + - - } -} \ No newline at end of file + + +

{errorMessage}

+
+
+ +
+
+
+
+ { + setPopupVisible(false); + router.push(`${FE_USERS_LOGIN_URL}`); + }} + onCancel={() => setPopupVisible(false)} + /> + + ); + } +} diff --git a/Front-End/src/app/actions/authAction.js b/Front-End/src/app/actions/authAction.js index 377917f..875f790 100644 --- a/Front-End/src/app/actions/authAction.js +++ b/Front-End/src/app/actions/authAction.js @@ -11,14 +11,13 @@ import { } from '@/utils/Url'; import logger from '@/utils/logger'; - const requestResponseHandler = async (response) => { const body = await response.json(); if (response.ok) { return body; } - const error = new Error(body?.errorMessage || "Une erreur est survenue"); + const error = new Error(body?.errorMessage || 'Une erreur est survenue'); error.details = body; throw error; }; @@ -27,43 +26,39 @@ const requestResponseHandler = async (response) => { * Login action */ export const login = (data) => { - return signIn('credentials', { - redirect: false, - email: data.email, - password: data.password, - role_type: data.role_type, - }) + return signIn('credentials', { + redirect: false, + email: data.email, + password: data.password, + role_type: data.role_type, + }); }; /** * Login user with API */ -export const getJWT = (data) =>{ - const request = new Request( - `${BE_AUTH_LOGIN_URL}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - credentials: 'include' - } - ); - return fetch(request).then(requestResponseHandler) -} -export const refreshJWT = (data) =>{ - const request = new Request( - `${BE_AUTH_REFRESH_JWT_URL}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - credentials: 'include' - } - ); - return fetch(request).then(requestResponseHandler) -} +export const getJWT = (data) => { + const request = new Request(`${BE_AUTH_LOGIN_URL}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + credentials: 'include', + }); + return fetch(request).then(requestResponseHandler); +}; +export const refreshJWT = (data) => { + const request = new Request(`${BE_AUTH_REFRESH_JWT_URL}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + credentials: 'include', + }); + return fetch(request).then(requestResponseHandler); +}; /** * Disconnects the user after confirming the action. @@ -75,140 +70,116 @@ export const refreshJWT = (data) =>{ * @returns {void} */ export const disconnect = () => { - signOut({ callbackUrl: FE_USERS_LOGIN_URL }); + signOut({ callbackUrl: FE_USERS_LOGIN_URL }); }; export const fetchProfileRoles = (establishment) => { - return fetch(`${BE_AUTH_PROFILES_ROLES_URL}?establishment_id=${establishment}`) - .then(requestResponseHandler) + return fetch( + `${BE_AUTH_PROFILES_ROLES_URL}?establishment_id=${establishment}` + ).then(requestResponseHandler); }; export const updateProfileRoles = (id, data, csrfToken) => { - const request = new Request( - `${BE_AUTH_PROFILES_ROLES_URL}/${id}`, - { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - credentials: 'include', - body: JSON.stringify(data), - } - ); + const request = new Request(`${BE_AUTH_PROFILES_ROLES_URL}/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + body: JSON.stringify(data), + }); return fetch(request).then(requestResponseHandler); }; export const deleteProfileRoles = (id, csrfToken) => { - const request = new Request( - `${BE_AUTH_PROFILES_ROLES_URL}/${id}`, - { - method: 'DELETE', - headers: { - 'X-CSRFToken': csrfToken - }, - credentials: 'include' - } - ); + const request = new Request(`${BE_AUTH_PROFILES_ROLES_URL}/${id}`, { + method: 'DELETE', + headers: { + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + }); return fetch(request).then(requestResponseHandler); }; export const fetchProfiles = () => { - return fetch(`${BE_AUTH_PROFILES_URL}`) - .then(requestResponseHandler) + return fetch(`${BE_AUTH_PROFILES_URL}`).then(requestResponseHandler); }; export const createProfile = (data, csrfToken) => { - const request = new Request( - `${BE_AUTH_PROFILES_URL}`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - credentials: 'include', - body: JSON.stringify(data), - } - ); + const request = new Request(`${BE_AUTH_PROFILES_URL}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + body: JSON.stringify(data), + }); return fetch(request).then(requestResponseHandler); }; export const deleteProfile = (id, csrfToken) => { - const request = new Request( - `${BE_AUTH_PROFILES_URL}/${id}`, - { - method: 'DELETE', - headers: { - 'X-CSRFToken': csrfToken - }, - credentials: 'include' - } - ); + const request = new Request(`${BE_AUTH_PROFILES_URL}/${id}`, { + method: 'DELETE', + headers: { + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + }); return fetch(request).then(requestResponseHandler); }; export const updateProfile = (id, data, csrfToken) => { - const request = new Request( - `${BE_AUTH_PROFILES_URL}/${id}`, - { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - credentials: 'include', - body: JSON.stringify(data), - } - ); + const request = new Request(`${BE_AUTH_PROFILES_URL}/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + body: JSON.stringify(data), + }); return fetch(request).then(requestResponseHandler); }; export const sendNewPassword = (data, csrfToken) => { - const request = new Request( - `${BE_AUTH_NEW_PASSWORD_URL}`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - credentials: 'include', - body: JSON.stringify(data), - } - ); + const request = new Request(`${BE_AUTH_NEW_PASSWORD_URL}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + body: JSON.stringify(data), + }); return fetch(request).then(requestResponseHandler); }; export const subscribe = (data, csrfToken) => { - const request = new Request( - `${BE_AUTH_REGISTER_URL}`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - credentials: 'include', - body: JSON.stringify(data), - } - ); + const request = new Request(`${BE_AUTH_REGISTER_URL}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + body: JSON.stringify(data), + }); return fetch(request).then(requestResponseHandler); }; export const resetPassword = (uuid, data, csrfToken) => { - const request = new Request( - `${BE_AUTH_RESET_PASSWORD_URL}/${uuid}`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - credentials: 'include', - body: JSON.stringify(data), - } - ); + const request = new Request(`${BE_AUTH_RESET_PASSWORD_URL}/${uuid}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + body: JSON.stringify(data), + }); return fetch(request).then(requestResponseHandler); }; diff --git a/Front-End/src/app/actions/messagerieAction.js b/Front-End/src/app/actions/messagerieAction.js index c62bdad..5b06962 100644 --- a/Front-End/src/app/actions/messagerieAction.js +++ b/Front-End/src/app/actions/messagerieAction.js @@ -1,24 +1,20 @@ -import { -BE_GESTIONMESSAGERIE_MESSAGES_URL -} from '@/utils/Url'; +import { BE_GESTIONMESSAGERIE_MESSAGES_URL } from '@/utils/Url'; const requestResponseHandler = async (response) => { - const body = await response.json(); if (response.ok) { return body; } - // Throw an error with the JSON body containing the form errors - const error = new Error(body?.errorMessage || "Une erreur est survenue"); + // Throw an error with the JSON body containing the form errors + const error = new Error(body?.errorMessage || 'Une erreur est survenue'); error.details = body; throw error; -} +}; - -export const fetchMessages = (id) =>{ - return fetch(`${BE_GESTIONMESSAGERIE_MESSAGES_URL}/${id}`, { - headers: { - 'Content-Type': 'application/json', - }, - }).then(requestResponseHandler) -} \ No newline at end of file +export const fetchMessages = (id) => { + return fetch(`${BE_GESTIONMESSAGERIE_MESSAGES_URL}/${id}`, { + headers: { + 'Content-Type': 'application/json', + }, + }).then(requestResponseHandler); +}; diff --git a/Front-End/src/app/actions/planningAction.js b/Front-End/src/app/actions/planningAction.js index cba39fe..a5a18f0 100644 --- a/Front-End/src/app/actions/planningAction.js +++ b/Front-End/src/app/actions/planningAction.js @@ -1,112 +1,96 @@ -import { BE_PLANNING_PLANNINGS_URL, - BE_PLANNING_EVENTS_URL -} from '@/utils/Url'; - - +import { BE_PLANNING_PLANNINGS_URL, BE_PLANNING_EVENTS_URL } from '@/utils/Url'; const requestResponseHandler = async (response) => { const body = response.status !== 204 ? await response?.json() : {}; - console.log(response) + console.log(response); if (response.ok) { return body; } - // Throw an error with the JSON body containing the form errors - const error = new Error(body?.errorMessage || "Une erreur est survenue"); + // Throw an error with the JSON body containing the form errors + const error = new Error(body?.errorMessage || 'Une erreur est survenue'); error.details = body; throw error; -} +}; -const getData = (url) => { +const getData = (url) => { return fetch(`${url}`).then(requestResponseHandler); -} +}; const createDatas = (url, newData, csrfToken) => { return fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken + 'X-CSRFToken': csrfToken, }, body: JSON.stringify(newData), - credentials: 'include' - }) - .then(requestResponseHandler) + credentials: 'include', + }).then(requestResponseHandler); }; const updateDatas = (url, updatedData, csrfToken) => { - return fetch(`${url}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - body: JSON.stringify(updatedData), - credentials: 'include' - }) - .then(requestResponseHandler) - }; - -const removeDatas = (url, csrfToken) => { - return fetch(`${url}`, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - credentials: 'include' - }) - .then(requestResponseHandler) + return fetch(`${url}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + body: JSON.stringify(updatedData), + credentials: 'include', + }).then(requestResponseHandler); }; - - +const removeDatas = (url, csrfToken) => { + return fetch(`${url}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + }).then(requestResponseHandler); +}; export const fetchPlannings = () => { - return getData(`${BE_PLANNING_PLANNINGS_URL}`) + return getData(`${BE_PLANNING_PLANNINGS_URL}`); }; - export const getPlanning = (id) => { - return getData(`${BE_PLANNING_PLANNINGS_URL}/${id}`) + return getData(`${BE_PLANNING_PLANNINGS_URL}/${id}`); }; export const createPlanning = (newData, csrfToken) => { - return createDatas(`${BE_PLANNING_PLANNINGS_URL}`, newData, csrfToken) -} - -export const updatePlanning = (id,newData, csrfToken) => { - return updateDatas(`${BE_PLANNING_PLANNINGS_URL}/${id}`, newData, csrfToken) -} - -export const deletePlanning = (id, csrfToken) => { - return removeDatas(`${BE_PLANNING_PLANNINGS_URL}/${id}`, csrfToken) -} - - -export const fetchEvents = () => { - return getData(`${BE_PLANNING_EVENTS_URL}`) + return createDatas(`${BE_PLANNING_PLANNINGS_URL}`, newData, csrfToken); }; +export const updatePlanning = (id, newData, csrfToken) => { + return updateDatas(`${BE_PLANNING_PLANNINGS_URL}/${id}`, newData, csrfToken); +}; + +export const deletePlanning = (id, csrfToken) => { + return removeDatas(`${BE_PLANNING_PLANNINGS_URL}/${id}`, csrfToken); +}; + +export const fetchEvents = () => { + return getData(`${BE_PLANNING_EVENTS_URL}`); +}; export const getEvent = (id) => { - return getData(`${BE_PLANNING_EVENTS_URL}/${id}`) + return getData(`${BE_PLANNING_EVENTS_URL}/${id}`); }; export const createEvent = (newData, csrfToken) => { - return createDatas(`${BE_PLANNING_EVENTS_URL}`, newData, csrfToken) -} + return createDatas(`${BE_PLANNING_EVENTS_URL}`, newData, csrfToken); +}; -export const updateEvent = (id,newData, csrfToken) => { - return updateDatas(`${BE_PLANNING_EVENTS_URL}/${id}`, newData, csrfToken) -} +export const updateEvent = (id, newData, csrfToken) => { + return updateDatas(`${BE_PLANNING_EVENTS_URL}/${id}`, newData, csrfToken); +}; export const deleteEvent = (id, csrfToken) => { - return removeDatas(`${BE_PLANNING_EVENTS_URL}/${id}`, csrfToken) -} + return removeDatas(`${BE_PLANNING_EVENTS_URL}/${id}`, csrfToken); +}; export const fetchUpcomingEvents = () => { return getData(`${BE_PLANNING_EVENTS_URL}/upcoming`); }; - - - diff --git a/Front-End/src/app/actions/registerFileGroupAction.js b/Front-End/src/app/actions/registerFileGroupAction.js index 604ca7b..ad1d077 100644 --- a/Front-End/src/app/actions/registerFileGroupAction.js +++ b/Front-End/src/app/actions/registerFileGroupAction.js @@ -1,30 +1,33 @@ -import { BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL, - BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL, - BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL, - FE_API_DOCUSEAL_CLONE_URL, - FE_API_DOCUSEAL_DOWNLOAD_URL, - FE_API_DOCUSEAL_GENERATE_TOKEN +import { + BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL, + BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL, + BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL, + FE_API_DOCUSEAL_CLONE_URL, + FE_API_DOCUSEAL_DOWNLOAD_URL, + FE_API_DOCUSEAL_GENERATE_TOKEN, } from '@/utils/Url'; const requestResponseHandler = async (response) => { - const body = await response.json(); if (response.ok) { return body; } - // Throw an error with the JSON body containing the form errors - const error = new Error(body?.errorMessage || "Une erreur est survenue"); + // Throw an error with the JSON body containing the form errors + const error = new Error(body?.errorMessage || 'Une erreur est survenue'); error.details = body; throw error; -} +}; export async function fetchRegistrationFileGroups(establishment) { - const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}?establishment_id=${establishment}`, { - credentials: 'include', - headers: { - 'Accept': 'application/json', + const response = await fetch( + `${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}?establishment_id=${establishment}`, + { + credentials: 'include', + headers: { + Accept: 'application/json', + }, } - }); + ); if (!response.ok) { throw new Error('Failed to fetch file groups'); } @@ -32,15 +35,18 @@ export async function fetchRegistrationFileGroups(establishment) { } export async function createRegistrationFileGroup(groupData, csrfToken) { - const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken, - }, - body: JSON.stringify(groupData), - credentials: 'include' - }); + const response = await fetch( + `${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + body: JSON.stringify(groupData), + credentials: 'include', + } + ); if (!response.ok) { throw new Error('Failed to create file group'); @@ -50,26 +56,36 @@ export async function createRegistrationFileGroup(groupData, csrfToken) { } export async function deleteRegistrationFileGroup(groupId, csrfToken) { - const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}`, { - method: 'DELETE', - headers: { - 'X-CSRFToken': csrfToken, - }, - credentials: 'include' - }); + const response = await fetch( + `${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}`, + { + method: 'DELETE', + headers: { + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + } + ); return response; } -export const editRegistrationFileGroup = async (groupId, groupData, csrfToken) => { - const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken, - }, - body: JSON.stringify(groupData), - }); +export const editRegistrationFileGroup = async ( + groupId, + groupData, + csrfToken +) => { + const response = await fetch( + `${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}`, + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + body: JSON.stringify(groupData), + } + ); if (!response.ok) { throw new Error('Erreur lors de la modification du groupe'); @@ -79,33 +95,35 @@ export const editRegistrationFileGroup = async (groupId, groupData, csrfToken) = }; export const fetchRegistrationFileFromGroup = async (groupId) => { - const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}/templates`, { - credentials: 'include', - headers: { - 'Accept': 'application/json', + const response = await fetch( + `${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}/templates`, + { + credentials: 'include', + headers: { + Accept: 'application/json', + }, } - }); + ); if (!response.ok) { - throw new Error('Erreur lors de la récupération des fichiers associés au groupe'); + throw new Error( + 'Erreur lors de la récupération des fichiers associés au groupe' + ); } return response.json(); -} +}; -export const fetchRegistrationTemplates = (id = null) => { - let url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}` +export const fetchRegistrationTemplates = (id = null) => { + let url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}`; if (id) { url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}/${id}`; } - const request = new Request( - `${url}`, - { - method:'GET', - headers: { - 'Content-Type':'application/json' - }, - } - ); - return fetch(request).then(requestResponseHandler) + const request = new Request(`${url}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + return fetch(request).then(requestResponseHandler); }; export const editRegistrationTemplates = (fileId, data, csrfToken) => { @@ -116,12 +134,10 @@ export const editRegistrationTemplates = (fileId, data, csrfToken) => { 'X-CSRFToken': csrfToken, }, credentials: 'include', - }) - .then(requestResponseHandler) -} - -export const createRegistrationTemplates = (data,csrfToken) => { + }).then(requestResponseHandler); +}; +export const createRegistrationTemplates = (data, csrfToken) => { return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}`, { method: 'POST', body: JSON.stringify(data), @@ -130,73 +146,72 @@ export const createRegistrationTemplates = (data,csrfToken) => { 'Content-Type': 'application/json', }, credentials: 'include', - }) - .then(requestResponseHandler) -} + }).then(requestResponseHandler); +}; -export const deleteRegistrationTemplates = (fileId,csrfToken) => { +export const deleteRegistrationTemplates = (fileId, csrfToken) => { return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}/${fileId}`, { method: 'DELETE', headers: { 'X-CSRFToken': csrfToken, }, credentials: 'include', - }) -} + }); +}; export const fetchRegistrationTemplateMaster = (id = null) => { let url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}`; - if(id){ + if (id) { url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${id}`; } - const request = new Request( - `${url}`, - { - method:'GET', - headers: { - 'Content-Type':'application/json' - }, - } - ); - return fetch(request).then(requestResponseHandler) + const request = new Request(`${url}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + return fetch(request).then(requestResponseHandler); }; -export const createRegistrationTemplateMaster = (data,csrfToken) => { - +export const createRegistrationTemplateMaster = (data, csrfToken) => { return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}`, { method: 'POST', body: JSON.stringify(data), headers: { 'X-CSRFToken': csrfToken, - 'Content-Type':'application/json' + 'Content-Type': 'application/json', }, credentials: 'include', - }) - .then(requestResponseHandler) -} + }).then(requestResponseHandler); +}; -export const deleteRegistrationTemplateMaster = (fileId,csrfToken) => { - return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${fileId}`, { - method: 'DELETE', - headers: { - 'X-CSRFToken': csrfToken, - }, - credentials: 'include', - }) -} +export const deleteRegistrationTemplateMaster = (fileId, csrfToken) => { + return fetch( + `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${fileId}`, + { + method: 'DELETE', + headers: { + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + } + ); +}; export const editRegistrationTemplateMaster = (fileId, data, csrfToken) => { - return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${fileId}`, { - method: 'PUT', - body: JSON.stringify(data), - headers: { - 'X-CSRFToken': csrfToken, - 'Content-Type':'application/json' - }, - credentials: 'include', - }) - .then(requestResponseHandler) -} + return fetch( + `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${fileId}`, + { + method: 'PUT', + body: JSON.stringify(data), + headers: { + 'X-CSRFToken': csrfToken, + 'Content-Type': 'application/json', + }, + credentials: 'include', + } + ).then(requestResponseHandler); +}; export const cloneTemplate = (templateId, email, is_required) => { return fetch(`${FE_API_DOCUSEAL_CLONE_URL}`, { @@ -207,21 +222,19 @@ export const cloneTemplate = (templateId, email, is_required) => { body: JSON.stringify({ templateId, email, - is_required - }) - }) - .then(requestResponseHandler) -} + is_required, + }), + }).then(requestResponseHandler); +}; export const downloadTemplate = (slug) => { return fetch(`${FE_API_DOCUSEAL_DOWNLOAD_URL}/${slug}`, { method: 'GET', headers: { 'Content-Type': 'application/json', - } - }) - .then(requestResponseHandler) -} + }, + }).then(requestResponseHandler); +}; export const generateToken = (email, id = null) => { return fetch(`${FE_API_DOCUSEAL_GENERATE_TOKEN}`, { @@ -231,4 +244,4 @@ export const generateToken = (email, id = null) => { }, body: JSON.stringify({ user_email: email, id }), }).then(requestResponseHandler); -}; \ No newline at end of file +}; diff --git a/Front-End/src/app/actions/schoolAction.js b/Front-End/src/app/actions/schoolAction.js index a890ba1..fd1fa2d 100644 --- a/Front-End/src/app/actions/schoolAction.js +++ b/Front-End/src/app/actions/schoolAction.js @@ -1,127 +1,133 @@ import { - BE_SCHOOL_SPECIALITIES_URL, - BE_SCHOOL_TEACHERS_URL, - BE_SCHOOL_SCHOOLCLASSES_URL, - BE_SCHOOL_PLANNINGS_URL, - BE_SCHOOL_FEES_URL, - BE_SCHOOL_DISCOUNTS_URL, - BE_SCHOOL_PAYMENT_PLANS_URL, - BE_SCHOOL_PAYMENT_MODES_URL, - BE_SCHOOL_ESTABLISHMENT_URL + BE_SCHOOL_SPECIALITIES_URL, + BE_SCHOOL_TEACHERS_URL, + BE_SCHOOL_SCHOOLCLASSES_URL, + BE_SCHOOL_PLANNINGS_URL, + BE_SCHOOL_FEES_URL, + BE_SCHOOL_DISCOUNTS_URL, + BE_SCHOOL_PAYMENT_PLANS_URL, + BE_SCHOOL_PAYMENT_MODES_URL, + BE_SCHOOL_ESTABLISHMENT_URL, } from '@/utils/Url'; const requestResponseHandler = async (response) => { - const body = await response.json(); if (response.ok) { return body; } - // Throw an error with the JSON body containing the form errors - const error = new Error(body?.errorMessage || "Une erreur est survenue"); + // Throw an error with the JSON body containing the form errors + const error = new Error(body?.errorMessage || 'Une erreur est survenue'); error.details = body; throw error; -} - +}; export const fetchSpecialities = (establishment) => { - return fetch(`${BE_SCHOOL_SPECIALITIES_URL}?establishment_id=${establishment}`) - .then(requestResponseHandler) + return fetch( + `${BE_SCHOOL_SPECIALITIES_URL}?establishment_id=${establishment}` + ).then(requestResponseHandler); }; export const fetchTeachers = (establishment) => { - return fetch(`${BE_SCHOOL_TEACHERS_URL}?establishment_id=${establishment}`) - .then(requestResponseHandler) + return fetch( + `${BE_SCHOOL_TEACHERS_URL}?establishment_id=${establishment}` + ).then(requestResponseHandler); }; export const fetchClasses = (establishment) => { - return fetch(`${BE_SCHOOL_SCHOOLCLASSES_URL}?establishment_id=${establishment}`) - .then(requestResponseHandler) + return fetch( + `${BE_SCHOOL_SCHOOLCLASSES_URL}?establishment_id=${establishment}` + ).then(requestResponseHandler); }; export const fetchSchedules = () => { - return fetch(`${BE_SCHOOL_PLANNINGS_URL}`) - .then(requestResponseHandler) + return fetch(`${BE_SCHOOL_PLANNINGS_URL}`).then(requestResponseHandler); }; export const fetchRegistrationDiscounts = (establishment) => { - return fetch(`${BE_SCHOOL_DISCOUNTS_URL}?filter=registration&establishment_id=${establishment}`) - .then(requestResponseHandler) + return fetch( + `${BE_SCHOOL_DISCOUNTS_URL}?filter=registration&establishment_id=${establishment}` + ).then(requestResponseHandler); }; export const fetchTuitionDiscounts = (establishment) => { - return fetch(`${BE_SCHOOL_DISCOUNTS_URL}?filter=tuition&establishment_id=${establishment}`) - .then(requestResponseHandler) + return fetch( + `${BE_SCHOOL_DISCOUNTS_URL}?filter=tuition&establishment_id=${establishment}` + ).then(requestResponseHandler); }; export const fetchRegistrationFees = (establishment) => { - return fetch(`${BE_SCHOOL_FEES_URL}?filter=registration&establishment_id=${establishment}`) - .then(requestResponseHandler) + return fetch( + `${BE_SCHOOL_FEES_URL}?filter=registration&establishment_id=${establishment}` + ).then(requestResponseHandler); }; export const fetchTuitionFees = (establishment) => { - return fetch(`${BE_SCHOOL_FEES_URL}?filter=tuition&establishment_id=${establishment}`) - .then(requestResponseHandler) + return fetch( + `${BE_SCHOOL_FEES_URL}?filter=tuition&establishment_id=${establishment}` + ).then(requestResponseHandler); }; export const fetchRegistrationPaymentPlans = (establishment) => { - return fetch(`${BE_SCHOOL_PAYMENT_PLANS_URL}?filter=registration&establishment_id=${establishment}`) - .then(requestResponseHandler) -} + return fetch( + `${BE_SCHOOL_PAYMENT_PLANS_URL}?filter=registration&establishment_id=${establishment}` + ).then(requestResponseHandler); +}; export const fetchTuitionPaymentPlans = (establishment) => { - return fetch(`${BE_SCHOOL_PAYMENT_PLANS_URL}?filter=tuition&establishment_id=${establishment}`) - .then(requestResponseHandler) -} + return fetch( + `${BE_SCHOOL_PAYMENT_PLANS_URL}?filter=tuition&establishment_id=${establishment}` + ).then(requestResponseHandler); +}; export const fetchRegistrationPaymentModes = (establishment) => { - return fetch(`${BE_SCHOOL_PAYMENT_MODES_URL}?filter=registration&establishment_id=${establishment}`) - .then(requestResponseHandler) -} + return fetch( + `${BE_SCHOOL_PAYMENT_MODES_URL}?filter=registration&establishment_id=${establishment}` + ).then(requestResponseHandler); +}; export const fetchTuitionPaymentModes = (establishment) => { - return fetch(`${BE_SCHOOL_PAYMENT_MODES_URL}?filter=tuition&establishment_id=${establishment}`) - .then(requestResponseHandler) -} + return fetch( + `${BE_SCHOOL_PAYMENT_MODES_URL}?filter=tuition&establishment_id=${establishment}` + ).then(requestResponseHandler); +}; export const fetchEstablishment = (establishment) => { - return fetch(`${BE_SCHOOL_ESTABLISHMENT_URL}/${establishment}`) - .then(requestResponseHandler) -} + return fetch(`${BE_SCHOOL_ESTABLISHMENT_URL}/${establishment}`).then( + requestResponseHandler + ); +}; export const createDatas = (url, newData, csrfToken) => { return fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken + 'X-CSRFToken': csrfToken, }, body: JSON.stringify(newData), - credentials: 'include' - }) - .then(requestResponseHandler) + credentials: 'include', + }).then(requestResponseHandler); }; export const updateDatas = (url, id, updatedData, csrfToken) => { - return fetch(`${url}/${id}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - body: JSON.stringify(updatedData), - credentials: 'include' - }) - .then(requestResponseHandler) - }; + return fetch(`${url}/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + body: JSON.stringify(updatedData), + credentials: 'include', + }).then(requestResponseHandler); +}; export const removeDatas = (url, id, csrfToken) => { - return fetch(`${url}/${id}`, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - credentials: 'include' - }) - .then(requestResponseHandler) -}; \ No newline at end of file + return fetch(`${url}/${id}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + credentials: 'include', + }).then(requestResponseHandler); +}; diff --git a/Front-End/src/app/actions/subscriptionAction.js b/Front-End/src/app/actions/subscriptionAction.js index 7309b38..6788be7 100644 --- a/Front-End/src/app/actions/subscriptionAction.js +++ b/Front-End/src/app/actions/subscriptionAction.js @@ -1,150 +1,152 @@ import { - BE_SUBSCRIPTION_STUDENTS_URL, - BE_SUBSCRIPTION_CHILDRENS_URL, - BE_SUBSCRIPTION_REGISTERFORMS_URL, - BE_SUBSCRIPTION_LAST_GUARDIAN_ID_URL + BE_SUBSCRIPTION_STUDENTS_URL, + BE_SUBSCRIPTION_CHILDRENS_URL, + BE_SUBSCRIPTION_REGISTERFORMS_URL, + BE_SUBSCRIPTION_LAST_GUARDIAN_ID_URL, } from '@/utils/Url'; export const PENDING = 'pending'; export const SUBSCRIBED = 'subscribed'; export const ARCHIVED = 'archived'; - const requestResponseHandler = async (response) => { - const body = await response.json(); if (response.ok) { return body; } - // Throw an error with the JSON body containing the form errors - const error = new Error(body?.errorMessage || "Une erreur est survenue"); + // Throw an error with the JSON body containing the form errors + const error = new Error(body?.errorMessage || 'Une erreur est survenue'); error.details = body; throw error; -} - -export const fetchRegisterForms = (establishment, filter=PENDING, page='', pageSize='', search = '') => { - let url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}?filter=${filter}&establishment_id=${establishment}`; - if (page !== '' && pageSize !== '') { - url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}?filter=${filter}&establishment_id=${establishment}&page=${page}&search=${search}`; - } - return fetch(url, { - headers: { - 'Content-Type': 'application/json', - }, - }).then(requestResponseHandler) - }; - -export const fetchRegisterForm = (id) =>{ - return fetch(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`) // Utilisation de studentId au lieu de codeDI - .then(requestResponseHandler) -} -export const fetchLastGuardian = () =>{ - return fetch(`${BE_SUBSCRIPTION_LAST_GUARDIAN_ID_URL}`) - .then(requestResponseHandler) -} - -export const editRegisterForm=(id, data, csrfToken)=>{ - return fetch(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - body: JSON.stringify(data), - credentials: 'include' - }) - .then(requestResponseHandler) }; -export const sendSEPARegisterForm=(id, data, csrfToken)=>{ +export const fetchRegisterForms = ( + establishment, + filter = PENDING, + page = '', + pageSize = '', + search = '' +) => { + let url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}?filter=${filter}&establishment_id=${establishment}`; + if (page !== '' && pageSize !== '') { + url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}?filter=${filter}&establishment_id=${establishment}&page=${page}&search=${search}`; + } + return fetch(url, { + headers: { + 'Content-Type': 'application/json', + }, + }).then(requestResponseHandler); +}; + +export const fetchRegisterForm = (id) => { + return fetch(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`) // Utilisation de studentId au lieu de codeDI + .then(requestResponseHandler); +}; +export const fetchLastGuardian = () => { + return fetch(`${BE_SUBSCRIPTION_LAST_GUARDIAN_ID_URL}`).then( + requestResponseHandler + ); +}; + +export const editRegisterForm = (id, data, csrfToken) => { return fetch(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`, { method: 'PUT', headers: { - 'X-CSRFToken': csrfToken + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + body: JSON.stringify(data), + credentials: 'include', + }).then(requestResponseHandler); +}; + +export const sendSEPARegisterForm = (id, data, csrfToken) => { + return fetch(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`, { + method: 'PUT', + headers: { + 'X-CSRFToken': csrfToken, }, body: data, - credentials: 'include' - }) - .then(requestResponseHandler) + credentials: 'include', + }).then(requestResponseHandler); }; -export const createRegisterForm=(data, csrfToken)=>{ - const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}`; - return fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken - }, - body: JSON.stringify(data), - credentials: 'include' - }) - .then(requestResponseHandler) -} +export const createRegisterForm = (data, csrfToken) => { + const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}`; + return fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + body: JSON.stringify(data), + credentials: 'include', + }).then(requestResponseHandler); +}; export const sendRegisterForm = (id) => { - const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/send`; - return fetch(url, { - headers: { - 'Content-Type': 'application/json', - }, - }).then(requestResponseHandler) -} - -export const resendRegisterForm = (id) => { - const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/resend`; - return fetch(url, { - headers: { - 'Content-Type': 'application/json', - }, - }).then(requestResponseHandler) - -} -export const archiveRegisterForm = (id) => { - const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/archive`; - return fetch(url, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }).then(requestResponseHandler) -} - -export const fetchStudents = (establishment, id=null) => { - const url = (id)?`${BE_SUBSCRIPTION_STUDENTS_URL}/${id}`:`${BE_SUBSCRIPTION_STUDENTS_URL}?establishment_id=${establishment}`; - const request = new Request( - url, - { - method:'GET', - headers: { - 'Content-Type':'application/json' - }, - } - ); - return fetch(request).then(requestResponseHandler) - + const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/send`; + return fetch(url, { + headers: { + 'Content-Type': 'application/json', + }, + }).then(requestResponseHandler); }; -export const fetchChildren = (id, establishment) =>{ - const request = new Request( - `${BE_SUBSCRIPTION_CHILDRENS_URL}/${id}?establishment_id=${establishment}`, - { - method:'GET', - headers: { - 'Content-Type':'application/json' - }, - } - ); - return fetch(request).then(requestResponseHandler) -} +export const resendRegisterForm = (id) => { + const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/resend`; + return fetch(url, { + headers: { + 'Content-Type': 'application/json', + }, + }).then(requestResponseHandler); +}; +export const archiveRegisterForm = (id) => { + const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/archive`; + return fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }).then(requestResponseHandler); +}; + +export const fetchStudents = (establishment, id = null) => { + const url = id + ? `${BE_SUBSCRIPTION_STUDENTS_URL}/${id}` + : `${BE_SUBSCRIPTION_STUDENTS_URL}?establishment_id=${establishment}`; + const request = new Request(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + return fetch(request).then(requestResponseHandler); +}; + +export const fetchChildren = (id, establishment) => { + const request = new Request( + `${BE_SUBSCRIPTION_CHILDRENS_URL}/${id}?establishment_id=${establishment}`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + } + ); + return fetch(request).then(requestResponseHandler); +}; export async function getRegisterFormFileTemplate(fileId) { - const response = await fetch(`${BE_SUBSCRIPTION_REGISTERFORM_FILE_TEMPLATE_URL}/${fileId}`, { - credentials: 'include', - headers: { - 'Accept': 'application/json', + const response = await fetch( + `${BE_SUBSCRIPTION_REGISTERFORM_FILE_TEMPLATE_URL}/${fileId}`, + { + credentials: 'include', + headers: { + Accept: 'application/json', + }, } - }); + ); if (!response.ok) { throw new Error('Failed to fetch file template'); } @@ -152,28 +154,36 @@ export async function getRegisterFormFileTemplate(fileId) { } export const fetchTemplatesFromRegistrationFiles = async (id) => { - const response = await fetch(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/templates`, { - credentials: 'include', - headers: { - 'Accept': 'application/json', + const response = await fetch( + `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/templates`, + { + credentials: 'include', + headers: { + Accept: 'application/json', + }, } - }); + ); if (!response.ok) { - throw new Error('Erreur lors de la récupération des fichiers associés au groupe'); + throw new Error( + 'Erreur lors de la récupération des fichiers associés au groupe' + ); } return response.json(); -} +}; export const dissociateGuardian = async (studentId, guardianId) => { - const response = await fetch(`${BE_SUBSCRIPTION_STUDENTS_URL}/${studentId}/guardians/${guardianId}/dissociate`, { + const response = await fetch( + `${BE_SUBSCRIPTION_STUDENTS_URL}/${studentId}/guardians/${guardianId}/dissociate`, + { credentials: 'include', method: 'PUT', headers: { - 'Accept': 'application/json', + Accept: 'application/json', }, - }); + } + ); if (!response.ok) { - throw new Error('Erreur lors de la dissociation.'); + throw new Error('Erreur lors de la dissociation.'); } return response.json(); -}; \ No newline at end of file +}; diff --git a/Front-End/src/app/layout.js b/Front-End/src/app/layout.js index 21ac084..cf8feea 100644 --- a/Front-End/src/app/layout.js +++ b/Front-End/src/app/layout.js @@ -1,11 +1,11 @@ import React from 'react'; import { getMessages } from 'next-intl/server'; -import Providers from '@/components/Providers' -import "@/css/tailwind.css"; +import Providers from '@/components/Providers'; +import '@/css/tailwind.css'; import { headers } from 'next/headers'; export const metadata = { - title: "N3WT-SCHOOL", + title: 'N3WT-SCHOOL', description: "Gestion de l'école", icons: { icon: [ @@ -14,7 +14,7 @@ export const metadata = { type: 'image/svg+xml', }, { - url: '/favicon.ico', // Fallback pour les anciens navigateurs + url: '/favicon.ico', // Fallback pour les anciens navigateurs sizes: 'any', }, ], diff --git a/Front-End/src/app/not-found.js b/Front-End/src/app/not-found.js index 1ffc731..d1a1c58 100644 --- a/Front-End/src/app/not-found.js +++ b/Front-End/src/app/not-found.js @@ -1,15 +1,21 @@ -import Link from 'next/link' -import Logo from '../components/Logo' +import Link from 'next/link'; +import Logo from '../components/Logo'; export default function NotFound() { return ( -
-
+
+
-

404 | Page non trouvée

-

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

- Retour Accueil +

+ 404 | Page non trouvée +

+

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

+ + Retour Accueil +
- ) -} \ No newline at end of file + ); +} diff --git a/Front-End/src/components/AffectationClasseForm.js b/Front-End/src/components/AffectationClasseForm.js index b96db19..6bd5278 100644 --- a/Front-End/src/components/AffectationClasseForm.js +++ b/Front-End/src/components/AffectationClasseForm.js @@ -1,7 +1,6 @@ import React, { useState } from 'react'; const AffectationClasseForm = ({ eleve = {}, onSubmit, classes }) => { - const [formData, setFormData] = useState({ classeAssocie_id: eleve?.classeAssocie_id || null, }); @@ -17,10 +16,10 @@ const AffectationClasseForm = ({ eleve = {}, onSubmit, classes }) => { const handleSubmit = () => { onSubmit({ eleve: { - ...formData + ...formData, }, - etat:5 - }); + etat: 5, + }); }; return ( @@ -30,18 +29,21 @@ const AffectationClasseForm = ({ eleve = {}, onSubmit, classes }) => { Classes
- {classes.map(classe => ( + {classes.map((classe) => (
-
@@ -50,15 +52,15 @@ const AffectationClasseForm = ({ eleve = {}, onSubmit, classes }) => {
diff --git a/Front-End/src/components/AlertMessage.js b/Front-End/src/components/AlertMessage.js index bebee7d..38c1f5e 100644 --- a/Front-End/src/components/AlertMessage.js +++ b/Front-End/src/components/AlertMessage.js @@ -2,11 +2,17 @@ import React from 'react'; const AlertMessage = ({ title, message, buttonText, buttonLink }) => { return ( -
+

{title}

{message}

diff --git a/Front-End/src/components/AlertWithModal.js b/Front-End/src/components/AlertWithModal.js index 76b02bb..347227a 100644 --- a/Front-End/src/components/AlertWithModal.js +++ b/Front-End/src/components/AlertWithModal.js @@ -2,28 +2,31 @@ import React, { useState } from 'react'; import Modal from '@/components/Modal'; import { UserPlus } from 'lucide-react'; -const AlertWithModal = ({ title, message, buttonText}) => { - const [isOpen, setIsOpen] = useState(false); +const AlertWithModal = ({ title, message, buttonText }) => { + const [isOpen, setIsOpen] = useState(false); - const openModal = () => { - setIsOpen(true); - }; + const openModal = () => { + setIsOpen(true); + }; - return ( -
-

{title}

-

{message}

-
- -
- -
- ); + return ( +
+

{title}

+

{message}

+
+ +
+ +
+ ); }; -export default AlertWithModal; \ No newline at end of file +export default AlertWithModal; diff --git a/Front-End/src/components/AlphabetLinks.js b/Front-End/src/components/AlphabetLinks.js index 79fd4b9..4f68f34 100644 --- a/Front-End/src/components/AlphabetLinks.js +++ b/Front-End/src/components/AlphabetLinks.js @@ -1,37 +1,39 @@ - import React, { useState } from 'react'; - -const AlphabetPaginationNumber = ({ letter, active , onClick}) => ( - ); - -const AlphabetLinks = ({filter, onLetterClick }) => { +const AlphabetLinks = ({ filter, onLetterClick }) => { const [currentLetter, setCurrentLetter] = useState(filter); - const alphabet = "*ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(''); - + const alphabet = '*ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''); return (
- {alphabet.map((letter) => ( - {setCurrentLetter(letter);onLetterClick(letter)}} - /> - - - ))} + {alphabet.map((letter) => ( + { + setCurrentLetter(letter); + onLetterClick(letter); + }} + /> + ))}
); }; -export default AlphabetLinks; \ No newline at end of file +export default AlphabetLinks; diff --git a/Front-End/src/components/Button.js b/Front-End/src/components/Button.js index 7a634fa..df209fa 100644 --- a/Front-End/src/components/Button.js +++ b/Front-End/src/components/Button.js @@ -1,9 +1,18 @@ import React from 'react'; import { useRouter } from 'next/navigation'; -const Button = ({ text, onClick, href, className, primary, icon, disabled}) => { +const Button = ({ + text, + onClick, + href, + className, + primary, + icon, + disabled, +}) => { const router = useRouter(); - const baseClass = 'px-4 py-2 rounded-md text-white h-8 flex items-center justify-center'; + const baseClass = + 'px-4 py-2 rounded-md text-white h-8 flex items-center justify-center'; const primaryClass = 'bg-emerald-500 hover:bg-emerald-600'; const secondaryClass = 'bg-gray-300 hover:bg-gray-400 text-black'; const buttonClass = `${baseClass} ${primary && !disabled ? primaryClass : secondaryClass} ${className}`; diff --git a/Front-End/src/components/Calendar.js b/Front-End/src/components/Calendar.js index 4ffdb1c..13ed929 100644 --- a/Front-End/src/components/Calendar.js +++ b/Front-End/src/components/Calendar.js @@ -6,25 +6,43 @@ import YearView from '@/components/Calendar/YearView'; import PlanningView from '@/components/Calendar/PlanningView'; import ToggleView from '@/components/ToggleView'; import { ChevronLeft, ChevronRight, Plus, ChevronDown } from 'lucide-react'; -import { format, addWeeks, addMonths, addYears, subWeeks, subMonths, subYears, getWeek, setMonth, setYear } from 'date-fns'; +import { + format, + addWeeks, + addMonths, + addYears, + subWeeks, + subMonths, + subYears, + getWeek, + setMonth, + setYear, +} from 'date-fns'; import { fr } from 'date-fns/locale'; import { AnimatePresence, motion } from 'framer-motion'; // Ajouter cet import import logger from '@/utils/logger'; const Calendar = ({ onDateClick, onEventClick }) => { - const { currentDate, setCurrentDate, viewType, setViewType, events, hiddenSchedules } = usePlanning(); + const { + currentDate, + setCurrentDate, + viewType, + setViewType, + events, + hiddenSchedules, + } = usePlanning(); const [visibleEvents, setVisibleEvents] = useState([]); const [showDatePicker, setShowDatePicker] = useState(false); // Ajouter ces fonctions pour la gestion des mois et années const months = Array.from({ length: 12 }, (_, i) => ({ value: i, - label: format(new Date(2024, i, 1), 'MMMM', { locale: fr }) + label: format(new Date(2024, i, 1), 'MMMM', { locale: fr }), })); const years = Array.from({ length: 10 }, (_, i) => ({ value: new Date().getFullYear() - 5 + i, - label: new Date().getFullYear() - 5 + i + label: new Date().getFullYear() - 5 + i, })); const handleMonthSelect = (monthIndex) => { @@ -39,7 +57,9 @@ const Calendar = ({ onDateClick, onEventClick }) => { useEffect(() => { // S'assurer que le filtrage est fait au niveau parent - const filtered = events?.filter(event => !hiddenSchedules.includes(event.planning)); + const filtered = events?.filter( + (event) => !hiddenSchedules.includes(event.planning) + ); setVisibleEvents(filtered); logger.debug('Events filtrés:', filtered); // Debug }, [events, hiddenSchedules]); @@ -78,7 +98,10 @@ const Calendar = ({ onDateClick, onEventClick }) => { > Aujourd'hui - @@ -89,7 +112,11 @@ const Calendar = ({ onDateClick, onEventClick }) => { className="flex items-center gap-1 px-2 py-1 hover:bg-gray-100 rounded-md" >

- {format(currentDate, viewType === 'year' ? 'yyyy' : 'MMMM yyyy', { locale: fr })} + {format( + currentDate, + viewType === 'year' ? 'yyyy' : 'MMMM yyyy', + { locale: fr } + )}

@@ -129,7 +156,10 @@ const Calendar = ({ onDateClick, onEventClick }) => { )}
-
@@ -168,7 +198,11 @@ const Calendar = ({ onDateClick, onEventClick }) => { transition={{ duration: 0.2 }} className="h-full flex flex-col" > - + )} {viewType === 'month' && ( @@ -179,7 +213,11 @@ const Calendar = ({ onDateClick, onEventClick }) => { exit={{ opacity: 0, y: -20 }} transition={{ duration: 0.2 }} > - + )} {viewType === 'year' && ( @@ -201,7 +239,10 @@ const Calendar = ({ onDateClick, onEventClick }) => { exit={{ opacity: 0, y: -20 }} transition={{ duration: 0.2 }} > - + )} @@ -210,4 +251,4 @@ const Calendar = ({ onDateClick, onEventClick }) => { ); }; -export default Calendar; \ No newline at end of file +export default Calendar; diff --git a/Front-End/src/components/Calendar/MonthView.js b/Front-End/src/components/Calendar/MonthView.js index 3f99d1a..b8f3ed7 100644 --- a/Front-End/src/components/Calendar/MonthView.js +++ b/Front-End/src/components/Calendar/MonthView.js @@ -1,6 +1,15 @@ import React from 'react'; import { usePlanning } from '@/context/PlanningContext'; -import { format, startOfWeek, endOfWeek, eachDayOfInterval, startOfMonth, endOfMonth, isSameMonth, isToday } from 'date-fns'; +import { + format, + startOfWeek, + endOfWeek, + eachDayOfInterval, + startOfMonth, + endOfMonth, + isSameMonth, + isToday, +} from 'date-fns'; import { fr } from 'date-fns/locale'; import { getEventsForDate } from '@/utils/events'; @@ -35,7 +44,8 @@ const MonthView = ({ onDateClick, onEventClick }) => { onClick={() => handleDayClick(day)} >
- @@ -50,7 +60,7 @@ const MonthView = ({ onDateClick, onEventClick }) => { style={{ backgroundColor: `${event.color}15`, color: event.color, - borderLeft: `2px solid ${event.color}` + borderLeft: `2px solid ${event.color}`, }} onClick={(e) => { e.stopPropagation(); @@ -69,8 +79,11 @@ const MonthView = ({ onDateClick, onEventClick }) => {
{/* En-tête des jours de la semaine */}
- {['Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim'].map(day => ( -
+ {['Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim'].map((day) => ( +
{day}
))} @@ -83,4 +96,4 @@ const MonthView = ({ onDateClick, onEventClick }) => { ); }; -export default MonthView; \ No newline at end of file +export default MonthView; diff --git a/Front-End/src/components/Calendar/PlanningView.js b/Front-End/src/components/Calendar/PlanningView.js index a3e71a9..ee0fb30 100644 --- a/Front-End/src/components/Calendar/PlanningView.js +++ b/Front-End/src/components/Calendar/PlanningView.js @@ -15,17 +15,20 @@ const PlanningView = ({ events, onEventClick }) => { // Sinon, créer une entrée pour chaque jour const days = eachDayOfInterval({ start, end }); - return days.map(day => ({ + return days.map((day) => ({ ...event, displayDate: day, - isMultiDay: true + isMultiDay: true, })); }; // Aplatir tous les événements en incluant les événements sur plusieurs jours const flattenedEvents = events .flatMap(splitEventByDays) - .sort((a, b) => new Date(a.displayDate || a.start) - new Date(b.displayDate || b.start)); + .sort( + (a, b) => + new Date(a.displayDate || a.start) - new Date(b.displayDate || b.start) + ); return (
@@ -58,26 +61,29 @@ const PlanningView = ({ events, onEventClick }) => {
{format(start, 'd')} - {format(start, 'MMM', { locale: fr }).toLowerCase()} - {format(start, 'EEE', { locale: fr })} + + {format(start, 'MMM', { locale: fr }).toLowerCase()} + + + {format(start, 'EEE', { locale: fr })} +
-
-
+
- {isMultiDay - ? (isSameDay(start, new Date(event.start)) - ? "À partir de " - : isSameDay(start, end) - ? "Jusqu'à " - : "Toute la journée") - : "" - } - {format(new Date(event.start), 'HH:mm')} - {!isMultiDay && ` - ${format(end, 'HH:mm')}`} + {isMultiDay + ? isSameDay(start, new Date(event.start)) + ? 'À partir de ' + : isSameDay(start, end) + ? "Jusqu'à " + : 'Toute la journée' + : ''} + {format(new Date(event.start), 'HH:mm')} + {!isMultiDay && ` - ${format(end, 'HH:mm')}`}
@@ -108,4 +114,4 @@ const PlanningView = ({ events, onEventClick }) => { ); }; -export default PlanningView; \ No newline at end of file +export default PlanningView; diff --git a/Front-End/src/components/Calendar/WeekView.js b/Front-End/src/components/Calendar/WeekView.js index 2804368..446a835 100644 --- a/Front-End/src/components/Calendar/WeekView.js +++ b/Front-End/src/components/Calendar/WeekView.js @@ -1,6 +1,12 @@ import React, { useEffect, useState, useRef } from 'react'; import { usePlanning } from '@/context/PlanningContext'; -import { format, startOfWeek, addDays, differenceInMinutes, isSameDay } from 'date-fns'; +import { + format, + startOfWeek, + addDays, + differenceInMinutes, + isSameDay, +} from 'date-fns'; import { fr } from 'date-fns/locale'; import { getWeekEvents } from '@/utils/events'; import { isToday } from 'date-fns'; @@ -16,7 +22,7 @@ const WeekView = ({ onDateClick, onEventClick, events }) => { const weekDays = Array.from({ length: 7 }, (_, i) => addDays(weekStart, i)); // Maintenant on peut utiliser weekDays - const isCurrentWeek = weekDays.some(day => isSameDay(day, new Date())); + const isCurrentWeek = weekDays.some((day) => isSameDay(day, new Date())); // Mettre à jour la position de la ligne toutes les minutes useEffect(() => { @@ -61,7 +67,7 @@ const WeekView = ({ onDateClick, onEventClick, events }) => { const eventStart = new Date(event.start); const eventEnd = new Date(event.end); - return dayEvents.filter(otherEvent => { + return dayEvents.filter((otherEvent) => { if (otherEvent.id === event.id) return false; const otherStart = new Date(otherEvent.start); const otherEnd = new Date(otherEvent.end); @@ -77,7 +83,7 @@ const WeekView = ({ onDateClick, onEventClick, events }) => { // Trouver les événements qui se chevauchent const overlappingEvents = findOverlappingEvents(event, dayEvents); - const eventIndex = overlappingEvents.findIndex(e => e.id > event.id) + 1; + const eventIndex = overlappingEvents.findIndex((e) => e.id > event.id) + 1; const totalOverlapping = overlappingEvents.length + 1; // Calculer la largeur et la position horizontale @@ -93,7 +99,7 @@ const WeekView = ({ onDateClick, onEventClick, events }) => { borderLeft: `3px solid ${event.color}`, borderRadius: '0.25rem', zIndex: 1, - transform: `translateY(${startMinutes}rem)` + transform: `translateY(${startMinutes}rem)`, }; }; @@ -111,14 +117,24 @@ const WeekView = ({ onDateClick, onEventClick, events }) => { }} >
-
+
{event.title}
-
- {format(new Date(event.start), 'HH:mm')} - {format(new Date(event.end), 'HH:mm')} +
+ {format(new Date(event.start), 'HH:mm')} -{' '} + {format(new Date(event.end), 'HH:mm')}
{event.location && ( -
+
{event.location}
)} @@ -130,7 +146,10 @@ const WeekView = ({ onDateClick, onEventClick, events }) => { return (
{/* En-tête des jours */} -
+
{weekDays.map((day) => (
{
{format(day, 'EEEE', { locale: fr })}
-
+
{format(day, 'd', { locale: fr })}
@@ -158,17 +179,17 @@ const WeekView = ({ onDateClick, onEventClick, events }) => { className="absolute left-0 right-0 z-10 border-emerald-500 border pointer-events-none" style={{ top: getCurrentTimePosition(), - }} > -
+
)} -
- {timeSlots.map(hour => ( +
+ {timeSlots.map((hour) => (
{`${hour.toString().padStart(2, '0')}:00`} @@ -188,11 +209,15 @@ const WeekView = ({ onDateClick, onEventClick, events }) => { onDateClick(date); }} > -
{/* Ajout de gap-1 */} - {dayEvents.filter(event => { - const eventStart = new Date(event.start); - return eventStart.getHours() === hour; - }).map(event => renderEventInCell(event, dayEvents))} +
+ {' '} + {/* Ajout de gap-1 */} + {dayEvents + .filter((event) => { + const eventStart = new Date(event.start); + return eventStart.getHours() === hour; + }) + .map((event) => renderEventInCell(event, dayEvents))}
); @@ -205,4 +230,4 @@ const WeekView = ({ onDateClick, onEventClick, events }) => { ); }; -export default WeekView; \ No newline at end of file +export default WeekView; diff --git a/Front-End/src/components/Calendar/YearView.js b/Front-End/src/components/Calendar/YearView.js index 0f31967..e6261ed 100644 --- a/Front-End/src/components/Calendar/YearView.js +++ b/Front-End/src/components/Calendar/YearView.js @@ -37,7 +37,7 @@ const YearView = ({ onDateClick }) => { return (
- {months.map(month => ( + {months.map((month) => ( { ); }; -export default YearView; \ No newline at end of file +export default YearView; diff --git a/Front-End/src/components/CheckBox.js b/Front-End/src/components/CheckBox.js index 02f8fd5..7fb6e70 100644 --- a/Front-End/src/components/CheckBox.js +++ b/Front-End/src/components/CheckBox.js @@ -1,13 +1,24 @@ import React from 'react'; -const CheckBox = ({ item, formData, handleChange, fieldName, itemLabelFunc = () => null, labelAttenuated = () => false, horizontal }) => { +const CheckBox = ({ + item, + formData, + handleChange, + fieldName, + itemLabelFunc = () => null, + labelAttenuated = () => false, + horizontal, +}) => { const isChecked = formData[fieldName].includes(parseInt(item.id)); const isAttenuated = labelAttenuated(item) && !isChecked; return ( -
+
{horizontal && ( -