espace-paie-odentas/components/MobileSidebarOverlay.tsx
2025-10-15 00:40:57 +02:00

89 lines
3.3 KiB
TypeScript

"use client";
import { useEffect, useState, useCallback } from "react";
import Sidebar from "./Sidebar";
export default function MobileSidebarOverlay() {
const [open, setOpen] = useState(false);
const [closing, setClosing] = useState(false);
const [clientInfo, setClientInfo] = useState<any>(null);
const [isStaff, setIsStaff] = useState(false);
const close = useCallback(() => {
setClosing(true);
setTimeout(() => {
setOpen(false);
setClosing(false);
}, 180); // Durée de l'animation
}, []);
const openEvt = useCallback(() => setOpen(true), []);
// Récupérer les infos du client et le statut staff
useEffect(() => {
let cancelled = false;
async function fetchUserInfo() {
try {
const res = await fetch('/api/me', { credentials: 'include', cache: 'no-store' });
if (!res.ok) throw new Error(String(res.status));
const data = await res.json();
if (!cancelled) {
// Transformer la réponse API en format clientInfo attendu par Sidebar
const clientInfo = {
id: data.active_org_id || '',
name: data.active_org_name || 'Organisation',
api_name: data.active_org_api_name || null,
user: data.user || null
};
setClientInfo(clientInfo);
setIsStaff(data.is_staff || false);
}
} catch (err) {
console.error('Error fetching user info:', err);
}
}
fetchUserInfo();
return () => { cancelled = true; };
}, []);
useEffect(() => {
const onOpen = () => openEvt();
const onClose = () => close();
window.addEventListener("open-mobile-sidebar" as any, onOpen as any);
window.addEventListener("close-mobile-sidebar" as any, onClose as any);
return () => {
window.removeEventListener("open-mobile-sidebar" as any, onOpen as any);
window.removeEventListener("close-mobile-sidebar" as any, onClose as any);
};
}, [openEvt, close]);
if (!open) return null;
return (
<div className="fixed inset-0 z-[1000] md:hidden" aria-modal="true" role="dialog">
<div
className={`absolute inset-0 bg-black/40 transition-opacity duration-180 ${closing ? 'opacity-0' : 'opacity-100'}`}
onClick={close}
/>
<div
className={`absolute top-0 left-0 h-full w-[86vw] max-w-[360px] bg-white shadow-xl border-r will-change-transform transition-transform duration-180 ease-out ${
closing ? '-translate-x-full' : 'translate-x-0 animate-slideIn'
}`}
role="complementary"
>
<div className="h-[var(--header-h)] border-b flex items-center justify-between px-3">
<div className="font-semibold">Menu</div>
<button onClick={close} className="px-3 py-1.5 rounded-md text-sm border hover:bg-slate-50">Fermer</button>
</div>
<div className="overflow-y-auto h-[calc(100%-var(--header-h))] p-2">
{/* Sidebar réutilisée en mobile */}
<Sidebar clientInfo={clientInfo} isStaff={isStaff} mobile onNavigate={close} />
</div>
</div>
<style jsx>{`
@keyframes slideIn { from { transform: translateX(-100%); } to { transform: translateX(0); } }
.animate-slideIn { animation: slideIn .18s ease-out; }
.duration-180 { transition-duration: 180ms; }
`}</style>
</div>
);
}