mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +00:00
feat: Ajout d'une fonction de logout
This commit is contained in:
@ -15,6 +15,7 @@ import {
|
||||
} from 'lucide-react';
|
||||
import DropdownMenu from '@/components/DropdownMenu';
|
||||
import Logo from '@/components/Logo';
|
||||
import Popup from '@/components/Popup';
|
||||
import {
|
||||
FE_ADMIN_HOME_URL,
|
||||
FE_ADMIN_SUBSCRIPTIONS_URL,
|
||||
@ -45,6 +46,7 @@ export default function Layout({
|
||||
|
||||
const [establishment, setEstablishment] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isPopupVisible, setIsPopupVisible] = useState(false);
|
||||
|
||||
const pathname = usePathname();
|
||||
const currentPage = pathname.split('/').pop();
|
||||
@ -54,11 +56,19 @@ export default function Layout({
|
||||
const softwareName = "N3WT School";
|
||||
const softwareVersion = `v${process.env.NEXT_PUBLIC_APP_VERSION}`;
|
||||
|
||||
const handleDisconnect = () => {
|
||||
setIsPopupVisible(true);
|
||||
};
|
||||
|
||||
const confirmDisconnect = () => {
|
||||
setIsPopupVisible(false);
|
||||
disconnect();
|
||||
};
|
||||
|
||||
const dropdownItems = [
|
||||
{
|
||||
label: 'Déconnexion',
|
||||
onClick: disconnect,
|
||||
onClick: handleDisconnect,
|
||||
icon: LogOut,
|
||||
},
|
||||
];
|
||||
@ -74,46 +84,48 @@ export default function Layout({
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<SessionProvider>
|
||||
<ProtectedRoute>
|
||||
{!isLoading && (
|
||||
<div className="flex min-h-screen bg-gray-50">
|
||||
<Sidebar establishment={establishment} currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" />
|
||||
<div className="flex flex-col flex-1">
|
||||
{/* Header - h-16 = 64px */}
|
||||
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
|
||||
<div className="text-xl font-semibold">{headerTitle}</div>
|
||||
<DropdownMenu
|
||||
buttonContent={<img src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" />}
|
||||
items={dropdownItems}
|
||||
buttonClassName=""
|
||||
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
||||
/>
|
||||
</header>
|
||||
{/* Main Content */}
|
||||
<div className="flex-1 flex flex-col">
|
||||
{/* Content avec scroll si nécessaire */}
|
||||
<div className="flex-1 overflow-auto">
|
||||
{children}
|
||||
</div>
|
||||
{/* Footer - h-16 = 64px */}
|
||||
<footer className="h-16 bg-white border-t border-gray-200 px-8 py-4 flex items-center justify-between">
|
||||
<div className="text-sm font-light">
|
||||
<span>© {new Date().getFullYear()} N3WT-INNOV Tous droits réservés.</span>
|
||||
<div className="text-sm font-light">{softwareName} - {softwareVersion}</div>
|
||||
<ProtectedRoute>
|
||||
{!isLoading && (
|
||||
<div className="flex min-h-screen bg-gray-50">
|
||||
<Sidebar establishment={establishment} currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" />
|
||||
<div className="flex flex-col flex-1">
|
||||
{/* Header - h-16 = 64px */}
|
||||
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
|
||||
<div className="text-xl font-semibold">{headerTitle}</div>
|
||||
<DropdownMenu
|
||||
buttonContent={<img src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" />}
|
||||
items={dropdownItems}
|
||||
buttonClassName=""
|
||||
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
||||
/>
|
||||
</header>
|
||||
{/* Main Content */}
|
||||
<div className="flex-1 flex flex-col">
|
||||
{/* Content avec scroll si nécessaire */}
|
||||
<div className="flex-1 overflow-auto">
|
||||
{children}
|
||||
</div>
|
||||
<Logo className="w-8 h-8" />
|
||||
</footer>
|
||||
{/* Footer - h-16 = 64px */}
|
||||
<footer className="h-16 bg-white border-t border-gray-200 px-8 py-4 flex items-center justify-between">
|
||||
<div className="text-sm font-light">
|
||||
<span>© {new Date().getFullYear()} N3WT-INNOV Tous droits réservés.</span>
|
||||
<div className="text-sm font-light">{softwareName} - {softwareVersion}</div>
|
||||
</div>
|
||||
<Logo className="w-8 h-8" />
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</ProtectedRoute>
|
||||
)}
|
||||
<Popup
|
||||
visible={isPopupVisible}
|
||||
message="Êtes-vous sûr(e) de vouloir vous déconnecter ?"
|
||||
onConfirm={confirmDisconnect}
|
||||
onCancel={() => setIsPopupVisible(false)}
|
||||
/>
|
||||
</ProtectedRoute>
|
||||
</SessionProvider>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -44,6 +44,7 @@ import {
|
||||
import DjangoCSRFToken from '@/components/DjangoCSRFToken'
|
||||
import { useCsrfToken } from '@/context/CsrfContext';
|
||||
import { fetchRegistrationFileGroups } from '@/app/lib/registerFileGroupAction';
|
||||
import { ESTABLISHMENT_ID } from '@/utils/Url';
|
||||
|
||||
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
|
||||
|
||||
@ -371,7 +372,8 @@ useEffect(()=>{
|
||||
idGuardians: selectedGuardiansIds,
|
||||
fees: allFeesIds,
|
||||
discounts: allDiscountsds,
|
||||
fileGroup: selectedFileGroup
|
||||
fileGroup: selectedFileGroup,
|
||||
establishment: ESTABLISHMENT_ID
|
||||
};
|
||||
|
||||
createRegisterForm(data, csrfToken)
|
||||
@ -413,7 +415,8 @@ useEffect(()=>{
|
||||
sibling: []
|
||||
},
|
||||
fees: allFeesIds,
|
||||
discounts: allDiscountsds
|
||||
discounts: allDiscountsds,
|
||||
establishment: ESTABLISHMENT_ID
|
||||
};
|
||||
|
||||
createRegisterForm(data, csrfToken)
|
||||
|
||||
@ -9,6 +9,9 @@ import { FE_PARENTS_HOME_URL,FE_PARENTS_MESSAGERIE_URL,FE_PARENTS_SETTINGS_URL
|
||||
import useLocalStorage from '@/hooks/useLocalStorage';
|
||||
import { fetchMessages } from '@/app/lib/messagerieAction';
|
||||
import ProtectedRoute from '@/components/ProtectedRoute';
|
||||
import { SessionProvider } from 'next-auth/react';
|
||||
import { disconnect } from '@/app/lib/authAction';
|
||||
import Popup from '@/components/Popup';
|
||||
|
||||
export default function Layout({
|
||||
children,
|
||||
@ -18,6 +21,16 @@ export default function Layout({
|
||||
const [messages, setMessages] = useState([]);
|
||||
const [userId, setUserId] = useLocalStorage("userId", '') ;
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isPopupVisible, setIsPopupVisible] = useState(false);
|
||||
|
||||
const handleDisconnect = () => {
|
||||
setIsPopupVisible(true);
|
||||
};
|
||||
|
||||
const confirmDisconnect = () => {
|
||||
setIsPopupVisible(false);
|
||||
disconnect();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setIsLoading(true);
|
||||
@ -42,7 +55,8 @@ export default function Layout({
|
||||
}
|
||||
|
||||
return (
|
||||
<ProtectedRoute>
|
||||
<SessionProvider>
|
||||
<ProtectedRoute>
|
||||
<div className="flex flex-col min-h-screen bg-gray-50">
|
||||
{/* Entête */}
|
||||
<header className="bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between fixed top-0 left-0 right-0 z-10">
|
||||
@ -75,7 +89,7 @@ export default function Layout({
|
||||
<DropdownMenu
|
||||
buttonContent={<User />}
|
||||
items={[
|
||||
{ label: 'Se déconnecter', icon: LogOut, onClick: () => {} },
|
||||
{ label: 'Se déconnecter', icon: LogOut, onClick: handleDisconnect },
|
||||
{ label: 'Settings', icon: Settings , onClick: () => { router.push(FE_PARENTS_SETTINGS_URL); } }
|
||||
]}
|
||||
buttonClassName="p-2 rounded-full hover:bg-gray-200"
|
||||
@ -90,7 +104,14 @@ export default function Layout({
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</ProtectedRoute>
|
||||
<Popup
|
||||
visible={isPopupVisible}
|
||||
message="Êtes-vous sûr(e) de vouloir vous déconnecter ?"
|
||||
onConfirm={confirmDisconnect}
|
||||
onCancel={() => setIsPopupVisible(false)}
|
||||
/>
|
||||
</ProtectedRoute>
|
||||
</SessionProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ export default function Page() {
|
||||
return data.errorMessage === ""
|
||||
}
|
||||
|
||||
async function handleFormLogin(formData) {
|
||||
/*async function handleFormLogin(formData) {
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
@ -76,7 +76,52 @@ export default function Page() {
|
||||
setIsLoading(false);
|
||||
setErrorMessage('An error occurred during sign in.');
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
function handleFormLogin(formData) {
|
||||
setIsLoading(true);
|
||||
|
||||
signIn('credentials', {
|
||||
redirect: false,
|
||||
email: formData.get('login'),
|
||||
password: formData.get('password'),
|
||||
}).then(result => {
|
||||
console.log('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;
|
||||
console.log('User Session:', user);
|
||||
localStorage.setItem('userId', user.id); // Stocker l'identifiant de l'utilisateur
|
||||
if (user.droit === 0) {
|
||||
// Vue ECOLE
|
||||
} else if (user.droit === 1) {
|
||||
// Vue ADMIN
|
||||
router.push(FE_ADMIN_SUBSCRIPTIONS_URL);
|
||||
} else if (user.droit === 2) {
|
||||
// Vue PARENT
|
||||
router.push(FE_PARENTS_HOME_URL);
|
||||
} else {
|
||||
// Cas anormal
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Error during session retrieval:', error);
|
||||
setIsLoading(false);
|
||||
setErrorMessage('An error occurred during session retrieval.');
|
||||
});
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Error during sign in:', error);
|
||||
setIsLoading(false);
|
||||
setErrorMessage('An error occurred during sign in.');
|
||||
});
|
||||
}
|
||||
|
||||
if (isLoading === true) {
|
||||
return <Loader /> // Affichez le composant Loader
|
||||
|
||||
Reference in New Issue
Block a user