chore: application prettier

This commit is contained in:
Luc SORIGNET
2025-04-15 19:37:47 +02:00
parent dd0884bbce
commit f7666c894b
174 changed files with 10609 additions and 8760 deletions

View File

@ -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 (
<div className='flex items-center justify-center min-h-screen bg-emerald-500'>
<div className='text-center p-6 '>
<div className="flex items-center justify-center min-h-screen bg-emerald-500">
<div className="text-center p-6 ">
<Logo className="w-32 h-32 mx-auto mb-4" />
<h2 className='text-2xl font-bold text-emerald-900 mb-4'>500 | Erreur interne</h2>
<p className='text-emerald-900 mb-4'>Une erreur interne est survenue.</p>
<Link className="text-gray-900 hover:underline" href="/">Retour Accueil</Link>
<h2 className="text-2xl font-bold text-emerald-900 mb-4">
500 | Erreur interne
</h2>
<p className="text-emerald-900 mb-4">
Une erreur interne est survenue.
</p>
<Link className="text-gray-900 hover:underline" href="/">
Retour Accueil
</Link>
</div>
</div>
)
}
);
}

View File

@ -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 (
<div className='p-8'>
<div className="p-8">
<DjangoCSRFToken csrfToken={csrfToken} />
<div className="w-full p-4">
<ProfileDirectory profileRoles={profileRoles} handleActivateProfile={handleEdit} handleDeleteProfile={handleDelete} handleDissociateGuardian={handleDissociate} />
<ProfileDirectory
profileRoles={profileRoles}
handleActivateProfile={handleEdit}
handleDeleteProfile={handleDelete}
handleDissociateGuardian={handleDissociate}
/>
</div>
</div>
);

View File

@ -1,10 +1,10 @@
'use client'
'use client';
import React, { useState, useEffect } from 'react';
export default function Page() {
return (
<div className='p-8'>
<h1 className='heading-section'>Statistiques</h1>
</div>
);
}
return (
<div className="p-8">
<h1 className="heading-section">Statistiques</h1>
</div>
);
}

View File

@ -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: (
<div className="px-4 py-2">
<div className="font-medium">{user?.email || 'Utilisateur'}</div>
<div className="text-xs text-gray-400">{getRightStr(profileRole) || ''}</div>
<div className="text-xs text-gray-400">
{getRightStr(profileRole) || ''}
</div>
</div>
)
),
},
{
type: 'separator',
content: <hr className="my-2 border-gray-200" />
content: <hr className="my-2 border-gray-200" />,
},
{
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 ? <X size={24} /> : <Menu size={24} />}
</button>
<div className="text-lg md:text-xl font-semibold">{headerTitle}</div>
<div className="text-lg md:text-xl font-semibold">
{headerTitle}
</div>
</div>
<DropdownMenu
buttonContent={
@ -175,11 +219,12 @@ export default function Layout({
{/* Main Content */}
<div className="flex-1 flex flex-col">
{/* Content avec scroll si nécessaire */}
<div className="flex-1 overflow-auto p-4 md:p-6">
{children}
</div>
<div className="flex-1 overflow-auto p-4 md:p-6">{children}</div>
{/* Footer responsive */}
<Footer softwareName={softwareName} softwareVersion={softwareVersion} />
<Footer
softwareName={softwareName}
softwareVersion={softwareVersion}
/>
</div>
</div>
</div>
@ -192,5 +237,3 @@ export default function Layout({
</ProtectedRoute>
);
}

View File

@ -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 }) => (
<div className="bg-white p-4 rounded-lg shadow-sm border border-gray-100 mb-4">
@ -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={<School className="text-green-500" size={24} />}
color="emerald"
/>
<StatCard
<StatCard
title={t('capacityRate')}
value={`${(totalStudents/structureCapacity * 100).toFixed(1)}%`}
value={`${((totalStudents / structureCapacity) * 100).toFixed(1)}%`}
icon={<School className="text-orange-500" size={24} />}
color="orange"
/>
@ -122,7 +126,9 @@ export default function DashboardPage() {
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6">
{/* Graphique des inscriptions */}
<div className="lg:col-span-2 bg-white p-6 rounded-lg shadow-sm border border-gray-100">
<h2 className="text-lg font-semibold mb-4">{t('inscriptionTrends')}</h2>
<h2 className="text-lg font-semibold mb-4">
{t('inscriptionTrends')}
</h2>
{/* Insérer ici un composant de graphique */}
<div className="h-64 bg-gray-50 rounded flex items-center justify-center">
<TrendingUp size={48} className="text-gray-300" />
@ -140,11 +146,14 @@ export default function DashboardPage() {
<div className="flex flex-wrap">
{classes.map((classe) => (
<div key={classe.id} className="lg:col-span-2 bg-white p-6 rounded-lg shadow-sm border border-gray-100 mr-4">
<ClasseDetails classe={classe} />
<div
key={classe.id}
className="lg:col-span-2 bg-white p-6 rounded-lg shadow-sm border border-gray-100 mr-4"
>
<ClasseDetails classe={classe} />
</div>
))}
</div>
</div>
);
}
}

View File

@ -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() {
</div>
</PlanningProvider>
);
}
}

View File

@ -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() {
<div className="mt-4">
<TabContent isActive={activeTab === 'structure'}>
<form onSubmit={handleSubmit}>
<InputText label="Email" value={email} onChange={handleEmailChange} />
<InputText label="Mot de passe" type="password" value={password} onChange={handlePasswordChange} />
<InputText label="Confirmer le mot de passe" type="password" value={confirmPassword} onChange={handleConfirmPasswordChange} />
<InputText
label="Email"
value={email}
onChange={handleEmailChange}
/>
<InputText
label="Mot de passe"
type="password"
value={password}
onChange={handlePasswordChange}
/>
<InputText
label="Confirmer le mot de passe"
type="password"
value={confirmPassword}
onChange={handleConfirmPasswordChange}
/>
<Button type="submit" primary text="Mettre à jour"></Button>
</form>
</TabContent>
<TabContent isActive={activeTab === 'smtp'}>
<form onSubmit={handleSmtpSubmit}>
<InputText label="Serveur SMTP" value={smtpServer} onChange={handleSmtpServerChange} />
<InputText label="Port SMTP" value={smtpPort} onChange={handleSmtpPortChange} />
<InputText label="Utilisateur SMTP" value={smtpUser} onChange={handleSmtpUserChange} />
<InputText label="Mot de passe SMTP" type="password" value={smtpPassword} onChange={handleSmtpPasswordChange} />
<InputText
label="Serveur SMTP"
value={smtpServer}
onChange={handleSmtpServerChange}
/>
<InputText
label="Port SMTP"
value={smtpPort}
onChange={handleSmtpPortChange}
/>
<InputText
label="Utilisateur SMTP"
value={smtpUser}
onChange={handleSmtpUserChange}
/>
<InputText
label="Mot de passe SMTP"
type="password"
value={smtpPassword}
onChange={handleSmtpPasswordChange}
/>
<Button type="submit" primary text="Mettre à jour"></Button>
</form>
</TabContent>

View File

@ -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}
/>
</ClassesProvider>
)
),
},
{
id: 'Fees',
@ -311,23 +328,27 @@ export default function Page() {
handleEdit={handleEdit}
handleDelete={handleDelete}
/>
)
),
},
{
id: 'Files',
label: 'Documents d\'inscription',
content: <FilesGroupsManagement csrfToken={csrfToken} selectedEstablishmentId={selectedEstablishmentId} />
}
label: "Documents d'inscription",
content: (
<FilesGroupsManagement
csrfToken={csrfToken}
selectedEstablishmentId={selectedEstablishmentId}
/>
),
},
];
return (
<div className='p-8'>
<div className="p-8">
<DjangoCSRFToken csrfToken={csrfToken} />
<div className="w-full p-4">
<SidebarTabs tabs={tabs} />
</div>
</div>
);
}

View File

@ -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 (
<InscriptionFormShared
studentId={studentId}
csrfToken={csrfToken}
selectedEstablishmentId={selectedEstablishmentId}
onSubmit={handleSubmit}
cancelUrl={FE_ADMIN_SUBSCRIPTIONS_URL}
errors={formErrors}
/>
);
}
return (
<InscriptionFormShared
studentId={studentId}
csrfToken={csrfToken}
selectedEstablishmentId={selectedEstablishmentId}
onSubmit={handleSubmit}
cancelUrl={FE_ADMIN_SUBSCRIPTIONS_URL}
errors={formErrors}
/>
);
}

File diff suppressed because it is too large Load Diff

View File

@ -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 (
<ValidateSubscription
studentId={studentId}
@ -50,4 +50,4 @@ export default function Page() {
onAccept={handleAcceptRF}
/>
);
}
}

View File

@ -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

View File

@ -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 (
<InscriptionFormShared
studentId={studentId}
csrfToken={csrfToken}
selectedEstablishmentId={selectedEstablishmentId}
onSubmit={handleSubmit}
cancelUrl={FE_PARENTS_HOME_URL}
/>
);
}
return (
<InscriptionFormShared
studentId={studentId}
csrfToken={csrfToken}
selectedEstablishmentId={selectedEstablishmentId}
onSubmit={handleSubmit}
cancelUrl={FE_PARENTS_HOME_URL}
/>
);
}

View File

@ -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: (
<div className="px-4 py-2">
<div className="font-medium">{user?.email || 'Utilisateur'}</div>
<div className="text-xs text-gray-400">{getRightStr(profileRole) || ''}</div>
<div className="text-xs text-gray-400">
{getRightStr(profileRole) || ''}
</div>
</div>
)
),
},
{
type: 'separator',
content: <hr className="my-2 border-gray-200" />
content: <hr className="my-2 border-gray-200" />,
},
{
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 (
<ProtectedRoute requiredRight={RIGHTS.PARENT}>
<ProtectedRoute requiredRight={RIGHTS.PARENT}>
<div className="flex flex-col min-h-screen bg-gray-50">
{/* Entête */}
<header className="h-16 bg-white border-b border-gray-200 px-4 md:px-8 py-4 flex items-center justify-between fixed top-0 left-0 right-0 z-10">
<div className="flex items-center space-x-2">
<div className="border-b border-gray-200 ">
<ProfileSelector
className="w-64 border-r"
/>
</div>
<div className="text-lg md:text-xl p-2 font-semibold">Accueil</div>
<div className="flex items-center space-x-2">
<div className="border-b border-gray-200 ">
<ProfileSelector className="w-64 border-r" />
</div>
<div className="flex items-center space-x-2 md:space-x-4">
<button
className="p-1 md:p-2 rounded-full hover:bg-gray-200"
onClick={() => { router.push(FE_PARENTS_HOME_URL); }} // Utilisation de router pour revenir à l'accueil parent
>
<Home className="h-5 w-5 md:h-6 md:w-6" />
</button>
<div className="text-lg md:text-xl p-2 font-semibold">Accueil</div>
</div>
<div className="flex items-center space-x-2 md:space-x-4">
<button
className="p-1 md:p-2 rounded-full hover:bg-gray-200"
onClick={() => {
router.push(FE_PARENTS_HOME_URL);
}} // Utilisation de router pour revenir à l'accueil parent
>
<Home className="h-5 w-5 md:h-6 md:w-6" />
</button>
<div className="relative">
<div className="relative">
<button
className="p-1 md:p-2 rounded-full hover:bg-gray-200"
onClick={() => { router.push(FE_PARENTS_MESSAGERIE_URL); }} // Utilisation de router
onClick={() => {
router.push(FE_PARENTS_MESSAGERIE_URL);
}} // Utilisation de router
>
<MessageSquare className="h-5 w-5 md:h-6 md:w-6" />
</button>
{messages.length > 0 && (
<span className="absolute top-0 right-0 block h-2 w-2 rounded-full bg-emerald-600"></span>
)}
</div>
<DropdownMenu
buttonContent={<Image
src={getGravatarUrl(user?.email)}
alt="Profile"
className="w-8 h-8 rounded-full cursor-pointer"
width={32}
height={32}
/>}
items={dropdownItems}
buttonClassName=""
menuClassName="absolute right-0 mt-2 w-64 bg-white border border-gray-200 rounded shadow-lg"
/>
{messages.length > 0 && (
<span className="absolute top-0 right-0 block h-2 w-2 rounded-full bg-emerald-600"></span>
)}
</div>
<DropdownMenu
buttonContent={
<Image
src={getGravatarUrl(user?.email)}
alt="Profile"
className="w-8 h-8 rounded-full cursor-pointer"
width={32}
height={32}
/>
}
items={dropdownItems}
buttonClassName=""
menuClassName="absolute right-0 mt-2 w-64 bg-white border border-gray-200 rounded shadow-lg"
/>
</div>
</header>
{/* Content */}
<div className="pt-16 md:pt-20 p-4 md:p-8 flex-1"> {/* Ajout de flex-1 pour utiliser toute la hauteur disponible */}
<div className="pt-16 md:pt-20 p-4 md:p-8 flex-1">
{' '}
{/* Ajout de flex-1 pour utiliser toute la hauteur disponible */}
{children}
</div>
{/* Footer responsive */}
<Footer softwareName={softwareName} softwareVersion={softwareVersion} />
</div>
<Popup
visible={isPopupVisible}
message="Êtes-vous sûr(e) de vouloir vous déconnecter ?"
onConfirm={confirmDisconnect}
onCancel={() => setIsPopupVisible(false)}
/>
</ProtectedRoute>
visible={isPopupVisible}
message="Êtes-vous sûr(e) de vouloir vous déconnecter ?"
onConfirm={confirmDisconnect}
onCancel={() => setIsPopupVisible(false)}
/>
</ProtectedRoute>
);
}

View File

@ -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 (
<div className="flex" style={{ height: 'calc(100vh - 128px )' }}> {/* Utilisation de calc pour soustraire la hauteur de l'entête */}
<div className="flex" style={{ height: 'calc(100vh - 128px )' }}>
{' '}
{/* Utilisation de calc pour soustraire la hauteur de l'entête */}
<div className="w-1/4 border-r border-gray-200 p-4 overflow-y-auto h-full ">
{contacts.map((contact) => (
<div
@ -63,27 +92,49 @@ export default function MessageriePage() {
className={`p-2 cursor-pointer ${selectedContact?.id === contact.id ? 'bg-gray-200' : ''}`}
onClick={() => setSelectedContact(contact)}
>
<Image src={contact.profilePic} alt={`${contact.name}'s profile`} className="w-8 h-8 rounded-full inline-block mr-2" width={150} height={150}/>
<Image
src={contact.profilePic}
alt={`${contact.name}'s profile`}
className="w-8 h-8 rounded-full inline-block mr-2"
width={150}
height={150}
/>
{contact.name}
</div>
))}
</div>
<div className="flex-1 flex flex-col h-full">
<div className="flex-1 overflow-y-auto p-4 h-full">
{selectedContact && (messages[selectedContact.id] || []).map((message) => (
<div
key={message.id}
className={`mb-2 p-2 rounded max-w-xs ${message.isResponse ? 'bg-gray-200 justify-self-end' : 'bg-emerald-200 justify-self-start'}`}
style={{ borderRadius: message.isResponse ? '20px 20px 0 20px' : '20px 20px 20px 0', minWidth: '25%' }}
>
<div className="flex items-center mb-1">
<img src={selectedContact.profilePic} alt={`${selectedContact.name}'s profile`} className="w-8 h-8 rounded-full inline-block mr-2" width={150} height={150} />
<span className="text-xs text-gray-600">{selectedContact.name}</span>
<span className="text-xs text-gray-400 ml-2">{new Date(message.date).toLocaleTimeString()}</span>
{selectedContact &&
(messages[selectedContact.id] || []).map((message) => (
<div
key={message.id}
className={`mb-2 p-2 rounded max-w-xs ${message.isResponse ? 'bg-gray-200 justify-self-end' : 'bg-emerald-200 justify-self-start'}`}
style={{
borderRadius: message.isResponse
? '20px 20px 0 20px'
: '20px 20px 20px 0',
minWidth: '25%',
}}
>
<div className="flex items-center mb-1">
<img
src={selectedContact.profilePic}
alt={`${selectedContact.name}'s profile`}
className="w-8 h-8 rounded-full inline-block mr-2"
width={150}
height={150}
/>
<span className="text-xs text-gray-600">
{selectedContact.name}
</span>
<span className="text-xs text-gray-400 ml-2">
{new Date(message.date).toLocaleTimeString()}
</span>
</div>
{message.text}
</div>
{message.text}
</div>
))}
))}
<div ref={messagesEndRef} />
</div>
<div className="p-4 border-t border-gray-200 flex">

View File

@ -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) => (
<div className="flex justify-center items-center">
<StatusLabel status={row.status} showDropdown={false} parent/>
<StatusLabel status={row.status} showDropdown={false} parent />
</div>
)
),
},
{
name: 'Actions',
@ -71,8 +78,8 @@ export default function ParentHomePage() {
<Edit className="h-5 w-5" />
</button>
</div>
)
}
),
},
];
const itemsPerPage = 5;

View File

@ -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
/>
<div className="flex items-center justify-between">
<Button
type="submit"
primary
text={" Mettre à jour"}
/>
<Button type="submit" primary text={' Mettre à jour'} />
</div>
</form>
</div>

View File

@ -1,7 +1,5 @@
"use client";
'use client';
function ErrorBoundary({
error
}) {
function ErrorBoundary({ error }) {
return <>{error.message}</>;
}
}

View File

@ -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 <Loader /> // Affichez le composant Loader
} else {
return <>
<div className="container max mx-auto p-4">
<div className="flex justify-center mb-4">
<Logo className="h-150 w-150" />
</div>
<h1 className="text-2xl font-bold text-center mb-4">Authentification</h1>
<form className="max-w-md mx-auto" onSubmit={(e) => { e.preventDefault(); handleFormLogin(new FormData(e.target)); }}>
<DjangoCSRFToken csrfToken={csrfToken} />
<InputTextIcon name="login" type="text" IconItem={User} label="Identifiant" placeholder="Identifiant" errorMsg={userFieldError} className="w-full mb-5" />
<InputTextIcon name="password" type="password" IconItem={KeySquare} label="Mot de passe" placeholder="Mot de passe" errorMsg={passwordFieldError} className="w-full mb-5" />
<div className="input-group mb-4">
</div>
<label className="text-red-500">{errorMessage}</label>
<label><a className="float-right mb-4" href={`${FE_USERS_NEW_PASSWORD_URL}`}>Mot de passe oublié ?</a></label>
<div className="form-group-submit mt-4">
<Button text="Se Connecter" className="w-full" primary type="submit" name="connect" />
</div>
</form>
if (isLoading === true) {
return <Loader />; // Affichez le composant Loader
} else {
return (
<>
<div className="container max mx-auto p-4">
<div className="flex justify-center mb-4">
<Logo className="h-150 w-150" />
</div>
<h1 className="text-2xl font-bold text-center mb-4">
Authentification
</h1>
<form
className="max-w-md mx-auto"
onSubmit={(e) => {
e.preventDefault();
handleFormLogin(new FormData(e.target));
}}
>
<DjangoCSRFToken csrfToken={csrfToken} />
<InputTextIcon
name="login"
type="text"
IconItem={User}
label="Identifiant"
placeholder="Identifiant"
errorMsg={userFieldError}
className="w-full mb-5"
/>
<InputTextIcon
name="password"
type="password"
IconItem={KeySquare}
label="Mot de passe"
placeholder="Mot de passe"
errorMsg={passwordFieldError}
className="w-full mb-5"
/>
<div className="input-group mb-4"></div>
<label className="text-red-500">{errorMessage}</label>
<label>
<a
className="float-right mb-4"
href={`${FE_USERS_NEW_PASSWORD_URL}`}
>
Mot de passe oublié ?
</a>
</label>
<div className="form-group-submit mt-4">
<Button
text="Se Connecter"
className="w-full"
primary
type="submit"
name="connect"
/>
</div>
</>
}
};
</form>
</div>
</>
);
}
}

View File

@ -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 <Loader /> // 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 <>
<div className="container max mx-auto p-4">
<div className="flex justify-center mb-4">
<Logo className="h-150 w-150" />
</div>
<h1 className="text-2xl font-bold text-center mb-4">Nouveau Mot de passe</h1>
<form className="max-w-md mx-auto" onSubmit={(e) => { e.preventDefault(); validate(new FormData(e.target)); }}>
<DjangoCSRFToken csrfToken={csrfToken} />
<InputTextIcon name="email" type="text" IconItem={User} label="Identifiant" placeholder="Identifiant" errorMsg={userFieldError} className="w-full" />
<p className="text-red-500">{errorMessage}</p>
<div className="form-group-submit mt-4">
<Button text="Réinitialiser" className="w-full" primary type="submit" name="validate" />
</div>
</form>
<br />
<div className='flex justify-center mt-2 max-w-md mx-auto'>
<Button text="Annuler" className="w-full" href={ `${FE_USERS_LOGIN_URL}`} />
</div>
</div>
<Popup
visible={popupVisible}
message={popupMessage}
onConfirm={popupConfirmAction}
onCancel={() => 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);
});
}
}
}
if (isLoading === true) {
return <Loader />; // Affichez le composant Loader
} else {
return (
<>
<div className="container max mx-auto p-4">
<div className="flex justify-center mb-4">
<Logo className="h-150 w-150" />
</div>
<h1 className="text-2xl font-bold text-center mb-4">
Nouveau Mot de passe
</h1>
<form
className="max-w-md mx-auto"
onSubmit={(e) => {
e.preventDefault();
validate(new FormData(e.target));
}}
>
<DjangoCSRFToken csrfToken={csrfToken} />
<InputTextIcon
name="email"
type="text"
IconItem={User}
label="Identifiant"
placeholder="Identifiant"
errorMsg={userFieldError}
className="w-full"
/>
<p className="text-red-500">{errorMessage}</p>
<div className="form-group-submit mt-4">
<Button
text="Réinitialiser"
className="w-full"
primary
type="submit"
name="validate"
/>
</div>
</form>
<br />
<div className="flex justify-center mt-2 max-w-md mx-auto">
<Button
text="Annuler"
className="w-full"
href={`${FE_USERS_LOGIN_URL}`}
/>
</div>
</div>
<Popup
visible={popupVisible}
message={popupMessage}
onConfirm={popupConfirmAction}
onCancel={() => setPopupVisible(false)}
/>
</>
);
}
}

View File

@ -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 <Loader /> // Affichez le composant Loader
useEffect(() => {
if (useFakeData) {
setTimeout(() => {
setIsLoading(false);
}, 1000);
} else {
return <>
<Popup
visible={popupVisible}
message={popupMessage}
onConfirm={() => {
setPopupVisible(false);
router.push(`${FE_USERS_LOGIN_URL}`);
}}
onCancel={() => setPopupVisible(false)}
/>
<div className="container max mx-auto p-4">
<div className="flex justify-center mb-4">
<Logo className="h-150 w-150" />
</div>
<h1 className="text-2xl font-bold text-center mb-4">Réinitialisation du mot de passe</h1>
<form className="max-w-md mx-auto" onSubmit={(e) => { e.preventDefault(); validate(new FormData(e.target)); }}>
<DjangoCSRFToken csrfToken={csrfToken} />
<InputTextIcon name="password1" type="password" IconItem={KeySquare} label="Mot de passe" placeholder="Mot de passe" errorMsg={password1FieldError} className="w-full mb-5" />
<InputTextIcon name="password2" type="password" IconItem={KeySquare} label="Confirmation mot de passe" placeholder="Confirmation mot de passe" errorMsg={password2FieldError} className="w-full" />
<label className="text-red-500">{errorMessage}</label>
<div className="form-group-submit mt-4">
<Button text="Enregistrer" className="w-full" primary type="submit" name="validate" />
</div>
</form>
<br/>
<div className="flex justify-center mt-2 max-w-md mx-auto">
<Button text="Annuler" className="w-full" href={`${FE_USERS_LOGIN_URL}`} />
</div>
</div>
</>
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 <Loader />; // Affichez le composant Loader
} else {
return (
<>
<Popup
visible={popupVisible}
message={popupMessage}
onConfirm={() => {
setPopupVisible(false);
router.push(`${FE_USERS_LOGIN_URL}`);
}}
onCancel={() => setPopupVisible(false)}
/>
<div className="container max mx-auto p-4">
<div className="flex justify-center mb-4">
<Logo className="h-150 w-150" />
</div>
<h1 className="text-2xl font-bold text-center mb-4">
Réinitialisation du mot de passe
</h1>
<form
className="max-w-md mx-auto"
onSubmit={(e) => {
e.preventDefault();
validate(new FormData(e.target));
}}
>
<DjangoCSRFToken csrfToken={csrfToken} />
<InputTextIcon
name="password1"
type="password"
IconItem={KeySquare}
label="Mot de passe"
placeholder="Mot de passe"
errorMsg={password1FieldError}
className="w-full mb-5"
/>
<InputTextIcon
name="password2"
type="password"
IconItem={KeySquare}
label="Confirmation mot de passe"
placeholder="Confirmation mot de passe"
errorMsg={password2FieldError}
className="w-full"
/>
<label className="text-red-500">{errorMessage}</label>
<div className="form-group-submit mt-4">
<Button
text="Enregistrer"
className="w-full"
primary
type="submit"
name="validate"
/>
</div>
</form>
<br />
<div className="flex justify-center mt-2 max-w-md mx-auto">
<Button
text="Annuler"
className="w-full"
href={`${FE_USERS_LOGIN_URL}`}
/>
</div>
</div>
</>
);
}
}

View File

@ -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 <Loader /> // Affichez le composant Loader
} else {
return <>
<div className="container max mx-auto p-4">
<div className="flex justify-center mb-4">
<Logo className="h-150 w-150" />
</div>
<h1 className="text-2xl font-bold text-center mb-4">Nouveau profil</h1>
<form className="max-w-md mx-auto" onSubmit={(e) => { e.preventDefault(); subscribeFormSubmit(new FormData(e.target)); }}>
<DjangoCSRFToken csrfToken={csrfToken} />
<InputTextIcon name="login" type="text" IconItem={User} label="Identifiant" placeholder="Identifiant" errorMsg={userFieldError} className="w-full mb-5" />
<InputTextIcon name="password1" type="password" IconItem={KeySquare} label="Mot de passe" placeholder="Mot de passe" errorMsg={password1FieldError} className="w-full mb-5" />
<InputTextIcon name="password2" type="password" IconItem={KeySquare} label="Confirmation mot de passe" placeholder="Confirmation mot de passe" errorMsg={password2FieldError} className="w-full" />
<p className="text-red-500">{errorMessage}</p>
<div className="form-group-submit mt-4">
<Button text="Enregistrer" className="w-full" primary type="submit" name="validate" />
</div>
</form>
<br/>
<div className='flex justify-center mt-2 max-w-md mx-auto'><Button text="Annuler" className="w-full" onClick={()=>{router.push(`${FE_USERS_LOGIN_URL}`)}} /></div>
</div>
<Popup
visible={popupVisible}
message={popupMessage}
onConfirm={() => {
setPopupVisible(false);
router.push(`${FE_USERS_LOGIN_URL}`);
}}
onCancel={() => setPopupVisible(false)}
if (isLoading === true) {
return <Loader />; // Affichez le composant Loader
} else {
return (
<>
<div className="container max mx-auto p-4">
<div className="flex justify-center mb-4">
<Logo className="h-150 w-150" />
</div>
<h1 className="text-2xl font-bold text-center mb-4">
Nouveau profil
</h1>
<form
className="max-w-md mx-auto"
onSubmit={(e) => {
e.preventDefault();
subscribeFormSubmit(new FormData(e.target));
}}
>
<DjangoCSRFToken csrfToken={csrfToken} />
<InputTextIcon
name="login"
type="text"
IconItem={User}
label="Identifiant"
placeholder="Identifiant"
errorMsg={userFieldError}
className="w-full mb-5"
/>
</>
}
}
<InputTextIcon
name="password1"
type="password"
IconItem={KeySquare}
label="Mot de passe"
placeholder="Mot de passe"
errorMsg={password1FieldError}
className="w-full mb-5"
/>
<InputTextIcon
name="password2"
type="password"
IconItem={KeySquare}
label="Confirmation mot de passe"
placeholder="Confirmation mot de passe"
errorMsg={password2FieldError}
className="w-full"
/>
<p className="text-red-500">{errorMessage}</p>
<div className="form-group-submit mt-4">
<Button
text="Enregistrer"
className="w-full"
primary
type="submit"
name="validate"
/>
</div>
</form>
<br />
<div className="flex justify-center mt-2 max-w-md mx-auto">
<Button
text="Annuler"
className="w-full"
onClick={() => {
router.push(`${FE_USERS_LOGIN_URL}`);
}}
/>
</div>
</div>
<Popup
visible={popupVisible}
message={popupMessage}
onConfirm={() => {
setPopupVisible(false);
router.push(`${FE_USERS_LOGIN_URL}`);
}}
onCancel={() => setPopupVisible(false)}
/>
</>
);
}
}

View File

@ -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);
};

View File

@ -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)
}
export const fetchMessages = (id) => {
return fetch(`${BE_GESTIONMESSAGERIE_MESSAGES_URL}/${id}`, {
headers: {
'Content-Type': 'application/json',
},
}).then(requestResponseHandler);
};

View File

@ -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`);
};

View File

@ -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);
};
};

View File

@ -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)
};
return fetch(`${url}/${id}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
credentials: 'include',
}).then(requestResponseHandler);
};

View File

@ -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();
};
};

View File

@ -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',
},
],

View File

@ -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 (
<div className='flex items-center justify-center min-h-screen bg-emerald-500'>
<div className='text-center p-6 '>
<div className="flex items-center justify-center min-h-screen bg-emerald-500">
<div className="text-center p-6 ">
<Logo className="w-32 h-32 mx-auto mb-4" />
<h2 className='text-2xl font-bold text-emerald-900 mb-4'>404 | Page non trouvée</h2>
<p className='text-emerald-900 mb-4'>La ressource que vous souhaitez consulter n&apos;existe pas ou plus.</p>
<Link className="text-gray-900 hover:underline" href="/">Retour Accueil</Link>
<h2 className="text-2xl font-bold text-emerald-900 mb-4">
404 | Page non trouvée
</h2>
<p className="text-emerald-900 mb-4">
La ressource que vous souhaitez consulter n&apos;existe pas ou plus.
</p>
<Link className="text-gray-900 hover:underline" href="/">
Retour Accueil
</Link>
</div>
</div>
)
}
);
}