"use client"; import { Search, Menu } from "lucide-react"; import * as React from "react"; import { Command } from "cmdk"; import StatusEditModal from "./StatusEditModal"; type ClientInfo = { id: string; name: string; api_name?: string; user?: { id: string; email: string; display_name?: string | null; first_name?: string | null; } | null; } | null; interface StatusData { status_top_text: string; status_bottom_text: string; status_top_color: string; status_bottom_color: string; } export default function Header({ clientInfo, isStaff }: { clientInfo?: ClientInfo; isStaff?: boolean; }) { const paletteRef = React.useRef(null); const [paletteH, setPaletteH] = React.useState(null); const [expandSection, setExpandSection] = React.useState(null); const topMsgRef = React.useRef(null); const botMsgRef = React.useRef(null); const [topTrunc, setTopTrunc] = React.useState(false); const [botTrunc, setBotTrunc] = React.useState(false); // État pour le modal et les données de statut const [statusData, setStatusData] = React.useState({ status_top_text: 'Aucun incident à signaler.', status_bottom_text: 'Nous serons exceptionnellement fermés le 3 novembre 2025.', status_top_color: 'emerald', status_bottom_color: 'sky' }); const [isModalOpen, setIsModalOpen] = React.useState(false); const [isLoading, setIsLoading] = React.useState(false); // Fonction pour charger les données de statut const loadStatusData = React.useCallback(async () => { try { const response = await fetch('/api/maintenance/status'); if (response.ok) { const data = await response.json(); setStatusData(data); } } catch (error) { console.error('Erreur lors du chargement des données de statut:', error); } }, []); // Fonction pour sauvegarder les modifications const handleSaveStatus = React.useCallback(async (newData: StatusData) => { setIsLoading(true); try { const response = await fetch('/api/maintenance/status', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newData) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || 'Erreur lors de la sauvegarde'); } const updatedData = await response.json(); setStatusData(updatedData); } catch (error) { throw error; // Re-lancer l'erreur pour que le modal la gère } finally { setIsLoading(false); } }, []); // Fonction pour gérer le clic sur la card const handleCardClick = React.useCallback(() => { if (isStaff) { setIsModalOpen(true); } }, [isStaff]); // Fonction pour obtenir les classes CSS des couleurs const getColorClasses = React.useCallback((color: string) => { const colorMap: Record = { emerald: 'bg-emerald-500 ring-emerald-200/70', red: 'bg-red-500 ring-red-200/70', yellow: 'bg-yellow-500 ring-yellow-200/70', orange: 'bg-orange-500 ring-orange-200/70', sky: 'bg-sky-500 ring-sky-200/70', blue: 'bg-blue-500 ring-blue-200/70', purple: 'bg-purple-500 ring-purple-200/70', pink: 'bg-pink-500 ring-pink-200/70', gray: 'bg-gray-500 ring-gray-200/70' }; return colorMap[color] || 'bg-gray-500 ring-gray-200/70'; }, []); const getTextColorClasses = React.useCallback((color: string) => { const textColorMap: Record = { emerald: 'text-emerald-700', red: 'text-red-700', yellow: 'text-yellow-700', orange: 'text-orange-700', sky: 'text-sky-700', blue: 'text-blue-700', purple: 'text-purple-700', pink: 'text-pink-700', gray: 'text-gray-700' }; return textColorMap[color] || 'text-gray-700'; }, []); const recomputeTrunc = React.useCallback(() => { const isTrunc = (el: HTMLSpanElement | null) => !!el && el.scrollWidth > el.clientWidth + 1; setTopTrunc(isTrunc(topMsgRef.current)); setBotTrunc(isTrunc(botMsgRef.current)); }, []); // Charger les données de statut au montage React.useEffect(() => { loadStatusData(); }, [loadStatusData]); React.useEffect(() => { recomputeTrunc(); const onResize = () => recomputeTrunc(); window.addEventListener('resize', onResize); const id = window.setInterval(recomputeTrunc, 1500); return () => { window.removeEventListener('resize', onResize); window.clearInterval(id); }; }, [recomputeTrunc]); React.useEffect(() => { const update = () => { if (paletteRef.current) setPaletteH(paletteRef.current.offsetHeight); }; update(); window.addEventListener('resize', update); return () => window.removeEventListener('resize', update); }, []); return (
{/* Bouton hamburger mobile */} Odentas
Espace Paie Odentas
{/* Centre: card d'état (dynamique) */}
topTrunc && setExpandSection('top')} onMouseLeave={() => setExpandSection(null)} title={statusData.status_top_text} > {statusData.status_top_text} {expandSection==='top' && topTrunc && (
{statusData.status_top_text}
)}
botTrunc && setExpandSection('bottom')} onMouseLeave={() => setExpandSection(null)} title={statusData.status_bottom_text} > {statusData.status_bottom_text} {expandSection==='bottom' && botTrunc && (
{statusData.status_bottom_text}
)}
{/* Modal de modification des statuts (staff uniquement) */} {isStaff && ( setIsModalOpen(false)} onSave={handleSaveStatus} initialData={statusData} /> )}
); }