feat: Gestion multi-profil multi-école

This commit is contained in:
N3WT DE COMPET
2025-03-09 16:22:28 +01:00
parent 95c154a4a2
commit 16178296ec
51 changed files with 1621 additions and 802 deletions

View File

@ -3,7 +3,7 @@
import React, { useState, useEffect } from 'react';
import Sidebar from '@/components/Sidebar';
import { usePathname } from 'next/navigation';
import {useTranslations} from 'next-intl';
import { useTranslations } from 'next-intl';
import Image from 'next/image';
import {
Users,
@ -35,6 +35,9 @@ import ProtectedRoute from '@/components/ProtectedRoute';
import { getGravatarUrl } from '@/utils/gravatar';
import Footer from '@/components/Footer';
import { getRightStr, RIGHTS } from '@/utils/rights';
import { getSession } from 'next-auth/react';
import logger from '@/utils/logger';
import { useEstablishment } from '@/context/EstablishmentContext';
export default function Layout({
children,
@ -51,11 +54,12 @@ export default function Layout({
"settings": { "id": "settings", "name": t('settings'), "url": FE_ADMIN_SETTINGS_URL, "icon": Settings }
};
const [establishment, setEstablishment] = useState(null);
const [establishments, setEstablishments] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [isPopupVisible, setIsPopupVisible] = useState(false);
const [user, setUser] = useState(null);
const { data: session } = useSession();
const { selectedEstablishmentId, setSelectedEstablishmentId, profileRole, setProfileRole } = useEstablishment();
const pathname = usePathname();
const currentPage = pathname.split('/').pop();
@ -80,7 +84,7 @@ 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(user?.role) || ''}</div>
<div className="text-xs text-gray-400">{getRightStr(profileRole) || ''}</div>
</div>
)
},
@ -106,17 +110,34 @@ export default function Layout({
}, [pathname]);
useEffect(() => {
setIsLoading(true);
fetchEstablishment()
.then(data => {
setEstablishment(data);
getSession()
.then(session => {
if (session && session.user) {
setUser(session.user);
setEstablishments(session.user.roles.map(role => ({
id: role.establishment__id,
name: role.establishment__name,
role_type: role.role_type
})));
// Sélectionner l'établissement depuis le localStorage ou le premier établissement par défaut
const storedEstablishmentId = localStorage.getItem('selectedEstablishmentId');
if (storedEstablishmentId) {
setSelectedEstablishmentId(storedEstablishmentId);
const storedProfileRole = session.user.roles.find(role => role.establishment__id === parseInt(storedEstablishmentId))?.role_type;
setProfileRole(storedProfileRole);
} else if (session.user.roles.length > 0) {
setSelectedEstablishmentId(session.user.roles[0].establishment__id);
setProfileRole(session.user.roles[0].role_type);
}
}
})
.catch(error => console.error('Error fetching establishment : ', error))
.finally(() => setIsLoading(false));
.catch(err => {
logger.error('Error fetching session:', err);
});
}, []);
useEffect(() => {
const fetchUser = async () => {
const fetchUser = async () => {
if (session) { // Vérifier que la session existe
const userData = await getUser();
setUser(userData);
@ -126,8 +147,6 @@ export default function Layout({
fetchUser();
}, [session]);
return (
<ProtectedRoute requiredRight={RIGHTS.ADMIN}>
{!isLoading && (
@ -138,12 +157,16 @@ export default function Layout({
style={{ height: '100vh' }} // Force la hauteur à 100% de la hauteur de la vue
>
<Sidebar
establishment={establishment}
establishments={establishments}
currentPage={currentPage}
items={Object.values(sidebarItems)}
onCloseMobile={toggleSidebar}
onEstablishmentChange={(establishmentId) => {
const parsedEstablishmentId = parseInt(establishmentId, 10);
setSelectedEstablishmentId(parsedEstablishmentId);
const role = session.user.roles.find(role => role.establishment__id === parsedEstablishmentId)?.role_type;
setProfileRole(role);
}}
/>
</div>

View File

@ -39,47 +39,61 @@ export default function DashboardPage() {
const [classes, setClasses] = useState([]);
const [establishmentId, setEstablishmentId] = useState(null);
useEffect(() => {
// Fetch data for classes
fetchClasses().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);
setStructureCapacity(nbMaxStudents);
setTotalStudents(nbStudents);
getSession()
.then(session => {
if (session && session.user) {
setEstablishmentId(session.user.establishment);
}
})
.catch(error => {
logger.error('Error fetching classes:', error);
.catch(err => {
logger.error('Error fetching session:', err);
});
}, []);
fetchRegisterForms().then(data => {
logger.info('Pending registrations fetched:', data);
setPendingRegistration(data.count);
})
.catch(error => {
logger.error('Error fetching pending registrations:', error);
});
useEffect(() => {
if (establishmentId) {
// Fetch data for classes
fetchClasses(establishmentId).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);
setStructureCapacity(nbMaxStudents);
setTotalStudents(nbStudents);
fetchUpcomingEvents().then(data => {
setUpcomingEvents(data);
}).catch(error => {
logger.error('Error fetching upcoming events:', error);
});
})
.catch(error => {
logger.error('Error fetching classes:', error);
});
// Simulation de chargement des données
setTimeout(() => {
setMonthlyStats({
inscriptions: [150, 180, 210, 245],
completionRate: 78
});
setIsLoading(false);
}, 1000);
}
, []);
fetchRegisterForms().then(data => {
logger.info('Pending registrations fetched:', data);
setPendingRegistration(data.count);
})
.catch(error => {
logger.error('Error fetching pending registrations:', error);
});
fetchUpcomingEvents().then(data => {
setUpcomingEvents(data);
}).catch(error => {
logger.error('Error fetching upcoming events:', error);
});
// Simulation de chargement des données
setTimeout(() => {
setMonthlyStats({
inscriptions: [150, 180, 210, 245],
completionRate: 78
});
setIsLoading(false);
}, 1000);
}
}
, [establishmentId]);
if (isLoading) return <Loader />;

View File

@ -27,13 +27,13 @@ import {
fetchRegistrationTemplateMaster
} from "@/app/actions/registerFileGroupAction";
import logger from '@/utils/logger';
import { useEstablishment } from '@/context/EstablishmentContext';
export default function Page() {
const [specialities, setSpecialities] = useState([]);
const [classes, setClasses] = useState([]);
const [teachers, setTeachers] = useState([]);
const [schedules, setSchedules] = useState([]); // Add this line
const [schedules, setSchedules] = useState([]);
const [registrationDiscounts, setRegistrationDiscounts] = useState([]);
const [tuitionDiscounts, setTuitionDiscounts] = useState([]);
const [registrationFees, setRegistrationFees] = useState([]);
@ -45,54 +45,57 @@ export default function Page() {
const [tuitionPaymentModes, setTuitionPaymentModes] = useState([]);
const csrfToken = useCsrfToken();
const { selectedEstablishmentId } = useEstablishment();
useEffect(() => {
// Fetch data for specialities
handleSpecialities();
if (selectedEstablishmentId) {
// Fetch data for specialities
handleSpecialities();
// Fetch data for teachers
handleTeachers();
// Fetch data for teachers
handleTeachers();
// Fetch data for classes
handleClasses();
// Fetch data for classes
handleClasses();
// Fetch data for schedules
handleSchedules();
// Fetch data for schedules
handleSchedules();
// Fetch data for registration discounts
handleRegistrationDiscounts();
// Fetch data for registration discounts
handleRegistrationDiscounts();
// Fetch data for tuition discounts
handleTuitionDiscounts();
// Fetch data for tuition discounts
handleTuitionDiscounts();
// Fetch data for registration fees
handleRegistrationFees();
// Fetch data for registration fees
handleRegistrationFees();
// Fetch data for tuition fees
handleTuitionFees();
// Fetch data for tuition fees
handleTuitionFees();
// Fetch data for registration file templates
fetchRegistrationTemplateMaster()
.then((data)=> {
setFichiers(data)
})
.catch(error => logger.error('Error fetching files:', error));
// Fetch data for registration file templates
fetchRegistrationTemplateMaster()
.then((data)=> {
setFichiers(data)
})
.catch(error => logger.error('Error fetching files:', error));
// Fetch data for registration payment plans
handleRegistrationPaymentPlans();
// Fetch data for registration payment plans
handleRegistrationPaymentPlans();
// Fetch data for tuition payment plans
handleTuitionPaymentPlans();
// Fetch data for tuition payment plans
handleTuitionPaymentPlans();
// Fetch data for registration payment modes
handleRegistrationPaymentModes();
// Fetch data for registration payment modes
handleRegistrationPaymentModes();
// Fetch data for tuition payment modes
handleTuitionPaymentModes();
}, []);
// Fetch data for tuition payment modes
handleTuitionPaymentModes();
}
}, [selectedEstablishmentId]);
const handleSpecialities = () => {
fetchSpecialities()
fetchSpecialities(selectedEstablishmentId)
.then(data => {
setSpecialities(data);
})
@ -100,7 +103,7 @@ export default function Page() {
};
const handleTeachers = () => {
fetchTeachers()
fetchTeachers(selectedEstablishmentId)
.then(data => {
setTeachers(data);
})
@ -108,7 +111,7 @@ export default function Page() {
};
const handleClasses = () => {
fetchClasses()
fetchClasses(selectedEstablishmentId)
.then(data => {
setClasses(data);
})
@ -124,7 +127,7 @@ export default function Page() {
};
const handleRegistrationDiscounts = () => {
fetchRegistrationDiscounts()
fetchRegistrationDiscounts(selectedEstablishmentId)
.then(data => {
setRegistrationDiscounts(data);
})
@ -132,7 +135,7 @@ export default function Page() {
};
const handleTuitionDiscounts = () => {
fetchTuitionDiscounts()
fetchTuitionDiscounts(selectedEstablishmentId)
.then(data => {
setTuitionDiscounts(data);
})
@ -140,7 +143,7 @@ export default function Page() {
};
const handleRegistrationFees = () => {
fetchRegistrationFees()
fetchRegistrationFees(selectedEstablishmentId)
.then(data => {
setRegistrationFees(data);
})
@ -148,7 +151,7 @@ export default function Page() {
};
const handleTuitionFees = () => {
fetchTuitionFees()
fetchTuitionFees(selectedEstablishmentId)
.then(data => {
setTuitionFees(data);
})
@ -156,7 +159,7 @@ export default function Page() {
};
const handleRegistrationPaymentPlans = () => {
fetchRegistrationPaymentPlans()
fetchRegistrationPaymentPlans(selectedEstablishmentId)
.then(data => {
setRegistrationPaymentPlans(data);
})
@ -164,7 +167,7 @@ export default function Page() {
};
const handleTuitionPaymentPlans = () => {
fetchTuitionPaymentPlans()
fetchTuitionPaymentPlans(selectedEstablishmentId)
.then(data => {
setTuitionPaymentPlans(data);
})
@ -172,7 +175,7 @@ export default function Page() {
};
const handleRegistrationPaymentModes = () => {
fetchRegistrationPaymentModes()
fetchRegistrationPaymentModes(selectedEstablishmentId)
.then(data => {
setRegistrationPaymentModes(data);
})
@ -180,7 +183,7 @@ export default function Page() {
};
const handleTuitionPaymentModes = () => {
fetchTuitionPaymentModes()
fetchTuitionPaymentModes(selectedEstablishmentId)
.then(data => {
setTuitionPaymentModes(data);
})

View File

@ -16,6 +16,7 @@ import Modal from '@/components/Modal';
import InscriptionForm from '@/components/Inscription/InscriptionForm'
import AffectationClasseForm from '@/components/AffectationClasseForm'
import { getSession } from 'next-auth/react';
import { useEstablishment } from '@/context/EstablishmentContext';
import {
PENDING,
@ -50,7 +51,6 @@ import {
import DjangoCSRFToken from '@/components/DjangoCSRFToken'
import { useCsrfToken } from '@/context/CsrfContext';
import { ESTABLISHMENT_ID } from '@/utils/Url';
import logger from '@/utils/logger';
export default function Page({ params: { locale } }) {
@ -87,9 +87,8 @@ export default function Page({ params: { locale } }) {
const [tuitionFees, setTuitionFees] = useState([]);
const [groups, setGroups] = useState([]);
const [establishmentId, setEstablishmentId] = useState(null);
const csrfToken = useCsrfToken();
const { selectedEstablishmentId } = useEstablishment();
const openModal = () => {
setIsOpen(true);
@ -167,23 +166,11 @@ const registerFormArchivedDataHandler = (data) => {
}
useEffect(() => {
getSession()
.then(session => {
if (session && session.user) {
setEstablishmentId(session.user.establishment);
}
})
.catch(err => {
logger.error('Error fetching session:', err);
});
}, []);
useEffect(() => {
if (establishmentId) {
if (selectedEstablishmentId) {
const fetchInitialData = () => {
Promise.all([
fetchClasses(),
fetchStudents(establishmentId) // Utiliser l'ID de l'établissement ici
fetchClasses(selectedEstablishmentId),
fetchStudents(selectedEstablishmentId) // Utiliser l'ID de l'établissement ici
])
.then(([classesData, studentsData]) => {
setClasses(classesData);
@ -198,21 +185,21 @@ useEffect(() => {
fetchInitialData();
}
}, [establishmentId]);
}, [selectedEstablishmentId]);
useEffect(() => {
if (establishmentId) {
if (selectedEstablishmentId) {
const fetchDataAndSetState = () => {
setIsLoading(true);
Promise.all([
fetchRegisterForms(establishmentId, PENDING, currentPage, itemsPerPage, searchTerm)
fetchRegisterForms(selectedEstablishmentId, PENDING, currentPage, itemsPerPage, searchTerm)
.then(registerFormPendingDataHandler)
.catch(requestErrorHandler),
fetchRegisterForms(establishmentId, SUBSCRIBED)
fetchRegisterForms(selectedEstablishmentId, SUBSCRIBED)
.then(registerFormSubscribedDataHandler)
.catch(requestErrorHandler),
fetchRegisterForms(establishmentId, ARCHIVED)
fetchRegisterForms(selectedEstablishmentId, ARCHIVED)
.then(registerFormArchivedDataHandler)
.catch(requestErrorHandler),
fetchRegistrationTemplateMaster()
@ -222,27 +209,27 @@ useEffect(() => {
.catch(err => {
logger.debug(err.message);
}),
fetchRegistrationDiscounts()
fetchRegistrationDiscounts(selectedEstablishmentId)
.then(data => {
setRegistrationDiscounts(data);
})
.catch(requestErrorHandler),
fetchTuitionDiscounts()
fetchTuitionDiscounts(selectedEstablishmentId)
.then(data => {
setTuitionDiscounts(data);
})
.catch(requestErrorHandler),
fetchRegistrationFees()
fetchRegistrationFees(selectedEstablishmentId)
.then(data => {
setRegistrationFees(data);
})
.catch(requestErrorHandler),
fetchTuitionFees()
fetchTuitionFees(selectedEstablishmentId)
.then(data => {
setTuitionFees(data);
})
.catch(requestErrorHandler),
fetchRegistrationFileGroups()
fetchRegistrationFileGroups(selectedEstablishmentId)
.then(data => {
setGroups(data);
})
@ -263,20 +250,20 @@ useEffect(() => {
fetchDataAndSetState();
}
}, [establishmentId, reloadFetch, currentPage, searchTerm]);
}, [selectedEstablishmentId, reloadFetch, currentPage, searchTerm]);
useEffect(() => {
if (establishmentId) {
if (selectedEstablishmentId) {
const fetchDataAndSetState = () => {
setIsLoading(true);
fetchRegisterForms(establishmentId, PENDING, currentPage, itemsPerPage, searchTerm)
fetchRegisterForms(selectedEstablishmentId, PENDING, currentPage, itemsPerPage, searchTerm)
.then(registerFormPendingDataHandler)
.catch(requestErrorHandler)
fetchRegisterForms(establishmentId, SUBSCRIBED)
fetchRegisterForms(selectedEstablishmentId, SUBSCRIBED)
.then(registerFormSubscribedDataHandler)
.catch(requestErrorHandler)
fetchRegisterForms(establishmentId, ARCHIVED)
fetchRegisterForms(selectedEstablishmentId, ARCHIVED)
.then(registerFormArchivedDataHandler)
.catch(requestErrorHandler)
fetchRegistrationTemplateMaster()
@ -545,7 +532,7 @@ useEffect(()=>{
const columns = [
{ name: t('studentName'), transform: (row) => row.student.last_name },
{ name: t('studentFistName'), transform: (row) => row.student.first_name },
{ name: t('mainContactMail'), transform: (row) => row.student.guardians[0].email },
{ name: t('mainContactMail'), transform: (row) => row.student.guardians[0].associated_profile_email },
{ name: t('phone'), transform: (row) => formatPhoneNumber(row.student.guardians[0].phone) },
{ name: t('lastUpdateDate'), transform: (row) => row.formatted_last_update},
{ name: t('registrationFileStatus'), transform: (row) => (

View File

@ -37,8 +37,9 @@ export default function Layout({
setIsPopupVisible(false);
disconnect();
};
useEffect(() => {
const fetchUser = async () => {
useEffect(() => {
const fetchUser = async () => {
if (session) { // Vérifier que la session existe
const userData = await getUser();
setUser(userData);
@ -47,6 +48,7 @@ export default function Layout({
fetchUser();
}, [session]);
// useEffect(() => {
// if (status === 'loading') return;
@ -81,7 +83,7 @@ const dropdownItems = [
content: (
<div className="px-4 py-2">
<div className="font-medium">{user?.email || 'Utilisateur'}</div>
<div className="text-xs text-gray-400">{getRightStr(user?.role) || ''}</div>
<div className="text-xs text-gray-400">{getRightStr(user?.roles[0]?.role_type) || ''}</div>
</div>
)
},

View File

@ -9,13 +9,15 @@ import { fetchChildren } from '@/app/actions/subscriptionAction';
import logger from '@/utils/logger';
import { useSession } from 'next-auth/react';
import { FE_USERS_LOGIN_URL } from '@/utils/Url';
import { useEstablishment } from '@/context/EstablishmentContext';
export default function ParentHomePage() {
const [children, setChildren] = useState([]);
const { data: session, status } = useSession();
const [userId, setUserId] = useState(null);
const [currentPage, setCurrentPage] = useState(1);
const [establishments, setEstablishments] = useState([]);
const { selectedEstablishmentId, setSelectedEstablishmentId } = useEstablishment();
const router = useRouter();
@ -24,21 +26,42 @@ export default function ParentHomePage() {
if (!session) {
router.push(`${FE_USERS_LOGIN_URL}`);
}
console.log(session);
const userIdFromSession = session.user.user_id;
setUserId(userIdFromSession);
} else {
const userIdFromSession = session.user.user_id;
setUserId(userIdFromSession);
fetchChildren(userIdFromSession).then(data => {
setChildren(data);
});
}, [userId]);
const userEstablishments = session.user.roles.map(role => ({
id: role.establishment__id,
name: role.establishment__name,
role_type: role.role_type
}));
setEstablishments(userEstablishments);
const storedEstablishmentId = localStorage.getItem('selectedEstablishmentId');
if (storedEstablishmentId) {
setSelectedEstablishmentId(storedEstablishmentId);
} else if (userEstablishments.length > 0) {
setSelectedEstablishmentId(userEstablishments[0].id);
}
fetchChildren(userIdFromSession, storedEstablishmentId).then(data => {
setChildren(data);
});
}
}, [status, session, selectedEstablishmentId]);
const handleEstablishmentChange = (e) => {
const establishmentId = parseInt(e.target.value, 10);
setSelectedEstablishmentId(establishmentId);
localStorage.setItem('selectedEstablishmentId', establishmentId);
};
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}`);
}
const actionColumns = [
{ name: 'Action', transform: (row) => row.action },
];
@ -106,6 +129,22 @@ export default function ParentHomePage() {
<Users className="h-6 w-6 text-emerald-600" />
Enfants
</h2>
{establishments.length > 1 && (
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2">Sélectionnez un établissement :</label>
<select
value={selectedEstablishmentId}
onChange={handleEstablishmentChange}
className="block w-full mt-1 p-2 border border-gray-300 rounded-md"
>
{establishments.map(establishment => (
<option key={establishment.id} value={establishment.id}>
{establishment.name}
</option>
))}
</select>
</div>
)}
<div className="overflow-x-auto">
<Table
data={children}

View File

@ -13,18 +13,20 @@ import {
FE_PARENTS_HOME_URL
} from '@/utils/Url';
import { login } from '@/app/actions/authAction';
import { getSession } from 'next-auth/react';
import { getSession } from 'next-auth/react';
import { useCsrfToken } from '@/context/CsrfContext'; // Importez le hook useCsrfToken
import logger from '@/utils/logger';
import { useSession } from 'next-auth/react';
import ProfileSelector from '@/components/ProfileSelector'; // Importez le composant ProfileSelector
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 [passwordFieldError,setPasswordFieldError] = useState("")
const [userFieldError, setUserFieldError] = useState("")
const [passwordFieldError, setPasswordFieldError] = useState("")
const [selectedProfile, setSelectedProfile] = useState(1); // Par défaut, sélectionnez ADMIN
const [isLoading, setIsLoading] = useState(false);
@ -35,52 +37,54 @@ export default function Page() {
return data.errorMessage === ""
}
function handleFormLogin(formData) {
setIsLoading(true);
function handleFormLogin(formData) {
setIsLoading(true);
login({
email: formData.get('login'),
password: formData.get('password'),
}).then(result => {
logger.debug('Sign In Result', result);
setIsLoading(false);
if (result.error) {
setErrorMessage(result.error);
} else {
getSession().then(session => {
if (!session || !session.user) {
throw new Error('Session not found');
}
const user = session.user;
logger.debug('User Session:', user);
login({
email: formData.get('login'),
password: formData.get('password'),
role_type: selectedProfile // Utilisez le profil sélectionné
}).then(result => {
logger.debug('Sign In Result', result);
setIsLoading(false);
if (result.error) {
setErrorMessage(result.error);
} else {
getSession().then(session => {
if (!session || !session.user) {
throw new Error('Session not found');
}
const user = session.user;
logger.debug('User Session:', user);
if (user.establishment_id) {
localStorage.setItem('establishment_id', user.establishment_id);
}
if (user.droit === 0) {
// Vue ECOLE
} else if (user.droit === 1) {
// Vue ADMIN
const roles = user.roles.filter(role => role.role_type === selectedProfile);
if (roles.length > 0) {
// const establishment = roles[0].establishment;
// localStorage.setItem('establishment_id', establishment);
// Redirection en fonction du rôle
if (roles[0].role_type === 1) {
router.push(FE_ADMIN_SUBSCRIPTIONS_URL);
} else if (user.droit === 2) {
// Vue PARENT
} else if (roles[0].role_type === 2) {
router.push(FE_PARENTS_HOME_URL);
} else {
// Cas anormal
}
}).catch(error => {
logger.error('Error during session retrieval:', error);
setIsLoading(false);
setErrorMessage('An error occurred during session retrieval.');
});
}
}).catch(error => {
logger.error('Error during sign in:', error);
setIsLoading(false);
setErrorMessage('An error occurred during sign in.');
});
}
} else {
setErrorMessage('No roles found for the specified role type.');
}
}).catch(error => {
logger.error('Error during session retrieval:', error);
setIsLoading(false);
setErrorMessage('An error occurred during session retrieval.');
});
}
}).catch(error => {
logger.error('Error during sign in:', error);
setIsLoading(false);
setErrorMessage('An error occurred during sign in.');
});
}
if (isLoading === true) {
return <Loader /> // Affichez le composant Loader
@ -94,7 +98,8 @@ export default function Page() {
<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" />
<InputTextIcon name="password" type="password" IconItem={KeySquare} label="Mot de passe" placeholder="Mot de passe" errorMsg={passwordFieldError} className="w-full mb-5" />
<ProfileSelector selectedProfile={selectedProfile} setSelectedProfile={setSelectedProfile} />
<div className="input-group mb-4">
</div>
<label className="text-red-500">{errorMessage}</label>