- Correction des erreurs TypeScript dans userService.ts et workflowTester.ts - Ajout des propriétés manquantes aux objets User mockés - Conversion des dates de string vers objets Date - Correction des appels asynchrones et des types incompatibles - Ajout de dynamic rendering pour résoudre les erreurs useSearchParams - Enveloppement de useSearchParams dans Suspense boundary - Configuration de force-dynamic au niveau du layout principal Build réussi: 126 pages générées avec succès 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
77 lines
3.0 KiB
TypeScript
77 lines
3.0 KiB
TypeScript
'use client';
|
|
|
|
import React from 'react';
|
|
import { Card } from 'primereact/card';
|
|
import { Button } from 'primereact/button';
|
|
import { useRouter } from 'next/navigation';
|
|
import { useUserRoles, PAGE_ROLES, PageRole } from '@/hooks/useUserRoles';
|
|
|
|
interface RoleProtectedPageProps {
|
|
children: React.ReactNode;
|
|
requiredPage: PageRole;
|
|
fallbackMessage?: string;
|
|
}
|
|
|
|
const RoleProtectedPage: React.FC<RoleProtectedPageProps> = ({
|
|
children,
|
|
requiredPage,
|
|
fallbackMessage
|
|
}) => {
|
|
const { canAccess, isLoading, roles } = useUserRoles();
|
|
const router = useRouter();
|
|
|
|
const requiredRoles = [...PAGE_ROLES[requiredPage]];
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="flex justify-content-center align-items-center" style={{ minHeight: '400px' }}>
|
|
<div className="text-center">
|
|
<i className="pi pi-spin pi-spinner text-4xl text-primary mb-3"></i>
|
|
<p className="text-lg text-600">Vérification des autorisations...</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!canAccess(requiredRoles)) {
|
|
return (
|
|
<div className="flex justify-content-center align-items-center" style={{ minHeight: '400px' }}>
|
|
<Card className="w-full max-w-md">
|
|
<div className="text-center">
|
|
<i className="pi pi-lock text-6xl text-orange-500 mb-4"></i>
|
|
<h2 className="text-2xl font-bold text-900 mb-3">Accès restreint</h2>
|
|
<p className="text-600 mb-4 line-height-3">
|
|
{fallbackMessage ||
|
|
`Vous n'avez pas les autorisations nécessaires pour accéder à cette page.
|
|
Les rôles requis sont : ${requiredRoles.join(', ')}.`}
|
|
</p>
|
|
<div className="mb-4">
|
|
<p className="text-sm text-500">
|
|
<strong>Vos rôles actuels :</strong> {roles.length > 0 ? roles.join(', ') : 'Aucun rôle assigné'}
|
|
</p>
|
|
</div>
|
|
<div className="flex gap-2 justify-content-center">
|
|
<Button
|
|
label="Retour au dashboard"
|
|
icon="pi pi-home"
|
|
onClick={() => router.push('/dashboard')}
|
|
className="p-button-outlined"
|
|
/>
|
|
<Button
|
|
label="Contacter l'admin"
|
|
icon="pi pi-envelope"
|
|
onClick={() => router.push('/contact')}
|
|
severity="secondary"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return <>{children}</>;
|
|
};
|
|
|
|
export default RoleProtectedPage;
|