mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
feat: Création d'un profile selector [#37,#38]
This commit is contained in:
@ -1,29 +1,65 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { useEstablishment } from '@/context/EstablishmentContext';
|
||||
import DropdownMenu from '@/components/DropdownMenu';
|
||||
import { getRightStr } from '@/utils/rights';
|
||||
import { ChevronDown } from 'lucide-react'; // Import de l'icône
|
||||
|
||||
const ProfileSelector = ({ onEstablishmentChange, className = '' }) => {
|
||||
const { establishments, selectedEstablishmentId, setSelectedEstablishmentId, setProfileRole } = useEstablishment();
|
||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
||||
|
||||
const handleEstablishmentChange = (establishmentId) => {
|
||||
setSelectedEstablishmentId(establishmentId);
|
||||
const role = establishments.find(est => est.id === establishmentId)?.role_type;
|
||||
setProfileRole(role);
|
||||
|
||||
if (onEstablishmentChange) {
|
||||
onEstablishmentChange(establishmentId);
|
||||
}
|
||||
setDropdownOpen(false); // Fermer le menu après sélection
|
||||
};
|
||||
|
||||
// Si on a pas de rôle ou un seul rôle, on n'affiche pas le sélecteur
|
||||
if (!establishments || establishments.length === 0 || establishments.length === 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const selectedEstablishment = establishments.find(est => est.id === selectedEstablishmentId);
|
||||
|
||||
const ProfileSelector = ({ selectedProfile, setSelectedProfile }) => {
|
||||
return (
|
||||
<div className="flex space-x-4">
|
||||
<button
|
||||
type="button"
|
||||
className={`px-4 py-2 rounded-lg shadow-md focus:outline-none focus:ring-2 focus:ring-blue-300 ${selectedProfile === 1 ? 'bg-blue-500 text-white ring-2 ring-blue-500' : 'bg-gray-200'}`}
|
||||
onClick={() => setSelectedProfile(1)}
|
||||
>
|
||||
ADMINISTRATEUR
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`px-4 py-2 rounded-lg shadow-md focus:outline-none focus:ring-2 focus:ring-blue-300 ${selectedProfile === 0 ? 'bg-blue-500 text-white ring-2 ring-blue-500' : 'bg-gray-200'}`}
|
||||
onClick={() => setSelectedProfile(0)}
|
||||
>
|
||||
PROFESSEUR
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`px-4 py-2 rounded-lg shadow-md focus:outline-none focus:ring-2 focus:ring-blue-300 ${selectedProfile === 2 ? 'bg-blue-500 text-white ring-2 ring-blue-500' : 'bg-gray-200'}`}
|
||||
onClick={() => setSelectedProfile(2)}
|
||||
>
|
||||
PARENT
|
||||
</button>
|
||||
<div className={`relative ${className}`}>
|
||||
<DropdownMenu
|
||||
buttonContent={
|
||||
<div className="h-16 flex items-center gap-2 cursor-pointer px-4 bg-white">
|
||||
<div className="flex-1">
|
||||
<div className="font-bold text-left">{getRightStr(selectedEstablishment?.role_type) || ''}</div>
|
||||
<div className="text-sm text-gray-500 text-left">
|
||||
{selectedEstablishment?.name || 'Sélectionnez un établissement'}
|
||||
</div>
|
||||
</div>
|
||||
{/* Icône ChevronDown avec rotation conditionnelle */}
|
||||
<ChevronDown
|
||||
className={`w-5 h-5 transition-transform duration-200 ${
|
||||
dropdownOpen ? 'rotate-180' : 'rotate-0'
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
items={establishments.map(establishment => ({
|
||||
type: 'item',
|
||||
label: (
|
||||
<div className="text-left">
|
||||
<div className="font-bold">{getRightStr(establishment.role_type)}</div>
|
||||
<div className="text-sm text-gray-500">{establishment.name}</div>
|
||||
</div>
|
||||
),
|
||||
onClick: () => handleEstablishmentChange(establishment.id),
|
||||
}))}
|
||||
buttonClassName="w-full"
|
||||
menuClassName="absolute mt-2 w-full bg-white border border-gray-200 rounded shadow-lg z-10"
|
||||
dropdownOpen={dropdownOpen}
|
||||
setDropdownOpen={setDropdownOpen}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,33 +1,33 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import Loader from '@/components/Loader'; // Importez le composant Loader
|
||||
import { FE_USERS_LOGIN_URL } from '@/utils/Url';
|
||||
import { useEstablishment } from '@/context/EstablishmentContext';
|
||||
import { FE_USERS_LOGIN_URL,getRedirectUrlFromRole } from '@/utils/Url';
|
||||
|
||||
const ProtectedRoute = ({ children, requiredRight }) => {
|
||||
const { data: session, status } = useSession({
|
||||
required: true,
|
||||
onUnauthenticated() {
|
||||
router.push(`${FE_USERS_LOGIN_URL}`);
|
||||
}
|
||||
});
|
||||
const router = useRouter();
|
||||
|
||||
// Ne vérifier que si le statut est définitif
|
||||
if (status === 'loading') {
|
||||
return <Loader />;
|
||||
}
|
||||
const { user, profileRole } = useEstablishment();
|
||||
const router = useRouter();
|
||||
const hasRequiredRight = (profileRole === requiredRight);
|
||||
|
||||
// Vérifier si l'utilisateur a au moins un rôle correspondant au requiredRight
|
||||
const hasRequiredRight = session?.user?.roles?.some(role => role.role_type === requiredRight);
|
||||
useEffect(() => {
|
||||
if(user){
|
||||
// Vérifier si l'utilisateur a le droit requis mais pas le bon role on le redirige la page d'accueil associé au role
|
||||
if (!hasRequiredRight) {
|
||||
const redirectUrl = getRedirectUrlFromRole(profileRole);
|
||||
router.push(`${redirectUrl}`);
|
||||
}
|
||||
|
||||
}else{
|
||||
// User non authentifié
|
||||
router.push(`${FE_USERS_LOGIN_URL}`);
|
||||
}
|
||||
}, [profileRole]);
|
||||
|
||||
|
||||
if (session && requiredRight && !hasRequiredRight) {
|
||||
router.push(`${FE_USERS_LOGIN_URL}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Autoriser l'affichage si authentifié et rôle correct
|
||||
return session ? children : null;
|
||||
return hasRequiredRight ? children : null;
|
||||
};
|
||||
|
||||
export default ProtectedRoute;
|
||||
@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEstablishment } from '@/context/EstablishmentContext';
|
||||
import ProfileSelector from '@/components/ProfileSelector';
|
||||
|
||||
const SidebarItem = ({ icon: Icon, text, active, url, onClick }) => (
|
||||
<div
|
||||
@ -15,9 +15,9 @@ const SidebarItem = ({ icon: Icon, text, active, url, onClick }) => (
|
||||
</div>
|
||||
);
|
||||
|
||||
function Sidebar({ establishments, currentPage, items, onCloseMobile, onEstablishmentChange }) {
|
||||
function Sidebar({ currentPage, items, onCloseMobile, onEstablishmentChange }) {
|
||||
const router = useRouter();
|
||||
const { selectedEstablishmentId, setSelectedEstablishmentId, setProfileRole } = useEstablishment();
|
||||
|
||||
const [selectedItem, setSelectedItem] = useState(currentPage);
|
||||
|
||||
useEffect(() => {
|
||||
@ -32,31 +32,15 @@ function Sidebar({ establishments, currentPage, items, onCloseMobile, onEstablis
|
||||
}
|
||||
};
|
||||
|
||||
const handleEstablishmentChange = (e) => {
|
||||
const establishmentId = parseInt(e.target.value, 10);
|
||||
setSelectedEstablishmentId(establishmentId);
|
||||
const role = establishments.find(est => est.id === establishmentId)?.role_type;
|
||||
setProfileRole(role);
|
||||
onEstablishmentChange(establishmentId);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-64 bg-white border-r h-full border-gray-200 py-6 px-4">
|
||||
<div className="flex items-center mb-8 px-2">
|
||||
<select
|
||||
value={selectedEstablishmentId || ''}
|
||||
onChange={handleEstablishmentChange}
|
||||
className="form-select block w-full mt-1"
|
||||
>
|
||||
{establishments.map(establishment => (
|
||||
<option key={establishment.id} value={establishment.id}>
|
||||
{establishment.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<div className="w-64 bg-white border-r h-full border-gray-200">
|
||||
<div className="border-b border-gray-200 ">
|
||||
<ProfileSelector
|
||||
onEstablishmentChange={onEstablishmentChange}
|
||||
className="border-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<nav className="space-y-1">
|
||||
<nav className="space-y-1 px-4 py-6">
|
||||
{items.map((item) => (
|
||||
<SidebarItem
|
||||
key={item.id}
|
||||
|
||||
Reference in New Issue
Block a user