feat: Création d'un profile selector [#37,#38]

This commit is contained in:
Luc SORIGNET
2025-04-12 16:07:30 +02:00
parent 4c2e2f8756
commit 89b01b79db
16 changed files with 237 additions and 286 deletions

View File

@ -131,7 +131,6 @@ export default function Layout({
if (roleIndex === -1) {
roleIndex = 0;
}
setCurrentRoleIndex(roleIndex);
const role = session.user.roles[roleIndex].role_type;
setProfileRole(role);
}}

View File

@ -10,7 +10,7 @@ import logger from '@/utils/logger';
import { fetchRegisterForms } from '@/app/actions/subscriptionAction';
import { fetchUpcomingEvents } from '@/app/actions/planningAction';
import { getSession } from 'next-auth/react';
import { getCurrentRoleIndex } from '@/store/Store';
import { useEstablishment } from '@/context/EstablishmentContext';
// Composant EventCard pour afficher les événements
@ -42,14 +42,11 @@ export default function DashboardPage() {
const [classes, setClasses] = useState([]);
const [establishmentId, setEstablishmentId] = useState(null);
const { selectedEstablishmentId } = useEstablishment();
useEffect(() => {
getSession()
.then(session => {
if (session && session.user) {
const establishmentId = session.user.roles[getCurrentRoleIndex()].establishment__id;
setEstablishmentId(establishmentId);
}
setEstablishmentId(selectedEstablishmentId);
})
.catch(err => {
logger.error('Error fetching session:', err);

View File

@ -2,6 +2,7 @@
// src/components/Layout.js
import React, { useState, useEffect } from 'react';
import DropdownMenu from '@/components/DropdownMenu';
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
@ -11,11 +12,11 @@ import ProtectedRoute from '@/components/ProtectedRoute';
import { disconnect } from '@/app/actions/authAction';
import Popup from '@/components/Popup';
import logger from '@/utils/logger';
import { useSession } from 'next-auth/react';
import { FE_USERS_LOGIN_URL } from '@/utils/Url';
import { getRightStr, RIGHTS } from '@/utils/rights';
import { getGravatarUrl } from '@/utils/gravatar';
import { useEstablishment } from '@/context/EstablishmentContext';
import Image from 'next/image';
import Footer from '@/components/Footer';
export default function Layout({
children,
@ -23,11 +24,12 @@ export default function Layout({
const router = useRouter(); // Définition de router
const [messages, setMessages] = useState([]);
const { data: session, status } = useSession();
const [userId, setUserId] = useState(null);
const [user, setUser] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [isPopupVisible, setIsPopupVisible] = useState(false);
const { profileRole, user } = useEstablishment();
const softwareName = "N3WT School";
const softwareVersion = `${process.env.NEXT_PUBLIC_APP_VERSION}`;
const handleDisconnect = () => {
setIsPopupVisible(true);
@ -36,42 +38,15 @@ export default function Layout({
const confirmDisconnect = () => {
setIsPopupVisible(false);
disconnect();
};
};
// useEffect(() => {
// if (status === 'loading') return;
// if (!session) {
// router.push(`${FE_USERS_LOGIN_URL}`);
// }
// const userIdFromSession = session.user.id;
// setUserId(userIdFromSession);
// setIsLoading(true);
// fetchMessages(userId)
// .then(data => {
// if (data) {
// setMessages(data);
// }
// logger.debug('Success :', data);
// })
// .catch(error => {
// logger.error('Error fetching data:', error);
// })
// .finally(() => {
// setIsLoading(false);
// });
// }, [userId]);
// if (isLoading) {
// return <div>Loading...</div>;
// }
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(user?.roles[0]?.role_type) || ''}</div>
<div className="text-xs text-gray-400">{getRightStr(profileRole) || ''}</div>
</div>
)
},
@ -91,11 +66,14 @@ const dropdownItems = [
<ProtectedRoute requiredRight={RIGHTS.PARENT}>
<div className="flex flex-col min-h-screen bg-gray-50">
{/* Entête */}
<header className="bg-white border-b border-gray-200 px-4 py-2 md:px-8 md:py-4 flex items-center justify-between fixed top-0 left-0 right-0 z-10">
<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">
<Logo className="h-6 w-6 md:h-8 md:w-8" /> {/* Utilisation du composant Logo */}
<div className="text-lg md:text-xl font-semibold">Accueil</div>
<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>
<div className="flex items-center space-x-2 md:space-x-4">
<button
@ -116,6 +94,7 @@ const dropdownItems = [
<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)}
@ -135,6 +114,8 @@ const dropdownItems = [
<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}

View File

@ -7,51 +7,33 @@ import StatusLabel from '@/components/StatusLabel';
import { FE_PARENTS_EDIT_INSCRIPTION_URL } from '@/utils/Url';
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';
import ProfileSelector from '@/components/ProfileSelector';
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 { user, setProfileRole, selectedEstablishmentId, setSelectedEstablishmentId, establishments } = useEstablishment();
const router = useRouter();
useEffect(() => {
if (status === 'loading') return;
if (!session || !session.user) {
router.push(`${FE_USERS_LOGIN_URL}`);
} else {
const userIdFromSession = session.user.user_id;
const userIdFromSession = user.user_id;
setUserId(userIdFromSession);
const userEstablishments = session.user.roles.map(role => ({
id: role.establishment__id,
name: role.establishment__name,
role_type: role.role_type
}));
setEstablishments(userEstablishments);
if (!selectedEstablishmentId && userEstablishments.length > 0) {
setSelectedEstablishmentId(userEstablishments[0].id);
}
console.log(selectedEstablishmentId)
fetchChildren(userIdFromSession, selectedEstablishmentId).then(data => {
setChildren(data);
});
}
}, [status, session, selectedEstablishmentId]);
}, [ selectedEstablishmentId]);
const handleEstablishmentChange = (e) => {
const establishmentId = parseInt(e.target.value, 10);
setSelectedEstablishmentId(establishmentId);
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}`);
@ -107,22 +89,6 @@ 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, index) => (
<option key={`${establishment.id}-${index}`} value={establishment.id}>
{establishment.name}
</option>
))}
</select>
</div>
)}
<div className="overflow-x-auto">
<Table
data={children}

View File

@ -9,16 +9,16 @@ 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,
FE_ADMIN_SUBSCRIPTIONS_URL,
FE_PARENTS_HOME_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 ProfileSelector from '@/components/ProfileSelector'; // Importez le composant ProfileSelector
import { RIGHTS } from '@/utils/rights';
import { setCurrentRoleIndex } from '@/store/Store';
import { useEstablishment } from '@/context/EstablishmentContext';
export default function Page() {
@ -26,8 +26,7 @@ export default function Page() {
const [errorMessage, setErrorMessage] = useState("");
const [userFieldError, setUserFieldError] = useState("")
const [passwordFieldError, setPasswordFieldError] = useState("")
const [selectedProfile, setSelectedProfile] = useState(1); // Par défaut, sélectionnez ADMIN
const { setUser } = useEstablishment();
const [isLoading, setIsLoading] = useState(false);
const router = useRouter();
@ -37,14 +36,15 @@ export default function Page() {
return data.errorMessage === ""
}
function handleFormLogin(formData) {
setIsLoading(true);
setErrorMessage("");
login({
email: formData.get('login'),
password: formData.get('password'),
role_type: selectedProfile
password: formData.get('password')
}).then(result => {
logger.debug('Sign In Result', result);
@ -58,18 +58,16 @@ export default function Page() {
}
const user = session.user;
logger.debug('User Session:', user);
const roles = user.roles.filter(role => role.role_type === selectedProfile);
if (roles.length > 0) {
// Redirection en fonction du rôle
// Ne pas désactiver le loader avant la redirection
const currentRoleIndex = 0;
setCurrentRoleIndex(currentRoleIndex);
const role = roles[currentRoleIndex].role_type;
if (role === RIGHTS.ADMIN || role === RIGHTS.TEACHER) {
router.push(FE_ADMIN_SUBSCRIPTIONS_URL);
} else if (role === RIGHTS.PARENT) {
router.push(FE_PARENTS_HOME_URL);
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é');
@ -104,7 +102,6 @@ export default function Page() {
<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" />
<ProfileSelector selectedProfile={selectedProfile} setSelectedProfile={setSelectedProfile} />
<div className="input-group mb-4">
</div>
<label className="text-red-500">{errorMessage}</label>