@ramses1er/cbk-toolkit 2.0.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +17 -6
- package/dist/client.js +447 -351
- package/dist/client.js.map +1 -1
- package/package.json +1 -1
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../packages/ui/src/layouts/side-nav.tsx","../packages/ui/src/config/create-side-nav.tsx","../packages/ui/src/table/table.tsx","../packages/ui/src/feedback/error-display.tsx","../packages/ui/src/table/actions-menu.tsx","../packages/ui/src/modals/modal.tsx","../packages/ui/src/feedback/confirmation.tsx","../packages/ui/src/headers/header-content.tsx","../packages/ui/src/forms/form.tsx","../packages/ui/src/forms/field-container.tsx","../packages/ui/src/forms/label.tsx","../packages/ui/src/forms/input.tsx","../packages/ui/src/forms/select.tsx","../packages/ui/src/forms/textarea.tsx","../packages/ui/src/forms/date-picker.tsx","../packages/ui/src/loaders/loading.tsx","../packages/ui/src/loaders/loader-submit.tsx","../packages/ui/src/pages/session-expired.tsx","../packages/ui/src/pages/access-denied.tsx","../packages/ui/src/route-guard/route-guard.tsx","../packages/utils/src/fetcher.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n ReactNode,\r\n useState,\r\n useEffect,\r\n createElement,\r\n isValidElement,\r\n type ComponentType,\r\n} from \"react\";\r\n\r\ntype IconType = ReactNode | ComponentType<{ size?: number }>;\r\n\r\nexport interface NavItem {\r\n id: string;\r\n label: string;\r\n title?: string;\r\n icon?: IconType;\r\n href: string;\r\n subItems?: NavItem[];\r\n}\r\n\r\nexport interface SideNavStaticConfig {\r\n brand?: {\r\n logo?: ReactNode;\r\n name?: string;\r\n tagline?: string;\r\n };\r\n mainItems: NavItem[];\r\n title?: string;\r\n footer?: { icon?: IconType; label: string; href: string }[];\r\n toggleIcon?: ReactNode;\r\n}\r\n\r\nexport interface SideNavProps extends SideNavStaticConfig {\r\n children: ReactNode;\r\n currentPath: string;\r\n}\r\n\r\nfunction isActive(href: string, currentPath: string) {\r\n return currentPath === href || currentPath.startsWith(href + \"/\");\r\n}\r\n\r\nfunction isExactActive(href: string, currentPath: string) {\r\n return currentPath === href;\r\n}\r\n\r\nexport function SideNav({\r\n children,\r\n title,\r\n mainItems,\r\n currentPath,\r\n brand,\r\n footer,\r\n toggleIcon,\r\n}: SideNavProps) {\r\n const activeMain = mainItems.find((item) => isActive(item.href, currentPath));\r\n const headerTitle = title ?? activeMain?.title ?? activeMain?.label;\r\n const [expandedSection, setExpandedSection] = useState<string | null>(\r\n activeMain?.id ?? null,\r\n );\r\n\r\n const toggleSection = (id: string) => {\r\n setExpandedSection((prev) => (prev === id ? null : id));\r\n };\r\n\r\n const [isMobileOpen, setIsMobileOpen] = useState(false);\r\n\r\n useEffect(() => {\r\n const handleEscape = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") setIsMobileOpen(false);\r\n };\r\n document.addEventListener(\"keydown\", handleEscape);\r\n return () => document.removeEventListener(\"keydown\", handleEscape);\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (isMobileOpen) {\r\n document.body.style.overflow = \"hidden\";\r\n } else {\r\n document.body.style.overflow = \"\";\r\n }\r\n return () => {\r\n document.body.style.overflow = \"\";\r\n };\r\n }, [isMobileOpen]);\r\n\r\n const closeMobileNav = () => setIsMobileOpen(false);\r\n\r\n return (\r\n <div className=\"flex min-h-screen\">\r\n <aside\r\n className={`w-64 bg-white border-r border-gray-200 flex flex-col fixed h-full z-50 transition-transform duration-300 ease-in-out md:translate-x-0 ${\r\n isMobileOpen ? \"translate-x-0\" : \"-translate-x-full\"\r\n }`}\r\n >\r\n {brand && (\r\n <div className=\"p-[6.5px] border-b border-gray-100\">\r\n <div className=\"flex flex-row gap-2 items-center\">\r\n {brand.logo &&\r\n (typeof brand.logo === \"string\" ? (\r\n <img\r\n src={brand.logo}\r\n alt={brand.name ?? \"\"}\r\n className=\"w-12.5 h-12.5\"\r\n />\r\n ) : (\r\n brand.logo\r\n ))}\r\n {brand.name && (\r\n <p className=\"text-gray-500 text-base font-semibold\">\r\n {brand.name}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n <nav className=\"flex-1 p-4 overflow-y-auto\">\r\n <ul className=\"space-y-1\">\r\n {mainItems.map((item) => {\r\n const active = isActive(item.href, currentPath);\r\n const isExpanded = expandedSection === item.id;\r\n const hasSubItems = item.subItems && item.subItems.length > 0;\r\n\r\n return (\r\n <li key={item.id}>\r\n <div className=\"flex items-center gap-1\">\r\n <a\r\n href={item.href}\r\n onClick={closeMobileNav}\r\n className={`flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors flex-1 ${\r\n active\r\n ? \"bg-gray-200 text-black\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n >\r\n {item.icon &&\r\n (typeof item.icon === \"string\" ? (\r\n <span className=\"text-lg\">{item.icon}</span>\r\n ) : isValidElement(item.icon) ? (\r\n item.icon\r\n ) : (\r\n createElement(\r\n item.icon as ComponentType<{ size?: number }>,\r\n { size: 20 },\r\n )\r\n ))}\r\n {item.label}\r\n </a>\r\n {active && hasSubItems && (\r\n <button\r\n onClick={() => toggleSection(item.id)}\r\n className={`p-1.5 rounded-lg transition-colors ${\r\n active\r\n ? \"text-black hover:bg-gray-100\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n title={isExpanded ? \"Réduire\" : \"Développer\"}\r\n >\r\n {toggleIcon ? (\r\n <span\r\n className={`inline-block transition-transform duration-200 ${\r\n isExpanded ? \"rotate-0\" : \"-rotate-90\"\r\n }`}\r\n >\r\n {toggleIcon}\r\n </span>\r\n ) : (\r\n <span className=\"text-xs\">\r\n {isExpanded ? \"▼\" : \"▶\"}\r\n </span>\r\n )}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {active && hasSubItems && (\r\n <div\r\n className={`grid transition-all duration-300 ease-in-out ${\r\n isExpanded ? \"grid-rows-[1fr]\" : \"grid-rows-[0fr]\"\r\n }`}\r\n >\r\n <div className=\"overflow-hidden\">\r\n <ul className=\"ml-4 mt-1 space-y-1 pl-2\">\r\n {item.subItems!.map((sub) => (\r\n <li key={sub.id}>\r\n <a\r\n href={sub.href}\r\n onClick={closeMobileNav}\r\n className={`flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium transition-colors ${\r\n isExactActive(sub.href, currentPath)\r\n ? \"bg-gray-200 text-black\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n >\r\n {sub.label}\r\n </a>\r\n </li>\r\n ))}\r\n </ul>\r\n </div>\r\n </div>\r\n )}\r\n </li>\r\n );\r\n })}\r\n </ul>\r\n </nav>\r\n\r\n {footer && footer.length > 0 && (\r\n <div className=\"p-4 border-t border-gray-100 space-y-1\">\r\n {footer.map((item) => (\r\n <a\r\n key={item.label}\r\n href={item.href}\r\n onClick={closeMobileNav}\r\n className=\"flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-100 transition-colors\"\r\n >\r\n {typeof item.icon === \"string\" ? (\r\n <span className=\"text-lg\">{item.icon}</span>\r\n ) : isValidElement(item.icon) ? (\r\n item.icon\r\n ) : (\r\n createElement(item.icon as ComponentType<{ size?: number }>, {\r\n size: 20,\r\n })\r\n )}\r\n {item.label}\r\n </a>\r\n ))}\r\n </div>\r\n )}\r\n </aside>\r\n\r\n {isMobileOpen && (\r\n <div\r\n className=\"fixed inset-0 z-40 bg-black/50 md:hidden\"\r\n onClick={closeMobileNav}\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n\r\n <div className=\"flex-1 ml-64 max-md:ml-0 min-w-0\">\r\n {headerTitle && (\r\n <header className=\"h-16 bg-white border-b border-gray-200 flex items-center justify-between px-6 fixed top-0 right-0 left-64 max-md:left-0 z-20\">\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n className=\"md:hidden p-2 -ml-2 rounded-lg hover:bg-gray-100 transition-colors\"\r\n onClick={() => setIsMobileOpen(!isMobileOpen)}\r\n aria-label={isMobileOpen ? \"Fermer le menu\" : \"Menu\"}\r\n aria-expanded={isMobileOpen}\r\n >\r\n {isMobileOpen ? (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M6 18L18 6M6 6l12 12\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M4 6h16M4 12h16M4 18h16\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n <h1 className=\"text-base font-semibold text-gray-500\">\r\n {headerTitle}\r\n </h1>\r\n </div>\r\n {brand?.tagline && (\r\n <span className=\"text-sm text-gray-500 max-md:hidden\">\r\n {brand.tagline}\r\n </span>\r\n )}\r\n </header>\r\n )}\r\n {!headerTitle && (\r\n <button\r\n className=\"md:hidden fixed top-4 left-4 z-10 p-2 rounded-lg bg-white border border-gray-200 shadow-sm hover:bg-gray-100 transition-colors\"\r\n onClick={() => setIsMobileOpen(!isMobileOpen)}\r\n aria-label={isMobileOpen ? \"Fermer le menu\" : \"Menu\"}\r\n aria-expanded={isMobileOpen}\r\n >\r\n {isMobileOpen ? (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M6 18L18 6M6 6l12 12\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M4 6h16M4 12h16M4 18h16\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n )}\r\n <main\r\n className={(headerTitle ? \"p-6 pt-20\" : \"p-6\") + \" overflow-x-auto\"}\r\n >\r\n {children}\r\n </main>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { SideNav, type SideNavStaticConfig } from \"../layouts/side-nav\";\n\nexport function createSideNav(config: SideNavStaticConfig) {\n return function ConfiguredSideNav({\n children,\n currentPath,\n }: {\n children: React.ReactNode;\n currentPath: string;\n }) {\n return (\n <SideNav {...config} currentPath={currentPath}>\n {children}\n </SideNav>\n );\n };\n}\n","\"use client\";\r\n\r\nimport { Printer, ChevronLeft, ChevronRight } from \"lucide-react\";\r\nimport clsx from \"clsx\";\r\nimport { useState, useMemo, useCallback } from \"react\";\r\nimport { ErrorDisplay } from \"../feedback/error-display\";\r\nimport { ApiError } from \"../../../utils/src/fetcher\";\r\n\r\nexport type Column<T> = {\r\n header: string;\r\n accessor?: keyof T;\r\n render?: (row: T) => React.ReactNode;\r\n excludeFromPrint?: boolean;\r\n};\r\n\r\ntype TableProps<T> = {\r\n data: T[];\r\n columns: Column<T>[];\r\n loading?: boolean;\r\n error?: ApiError | null;\r\n label?: string;\r\n printable?: boolean;\r\n pageSize?: number;\r\n pageSizeOptions?: number[];\r\n showPagination?: boolean;\r\n};\r\n\r\nconst VISIBLE_PAGES = 5;\r\n\r\nexport function Table<T>({\r\n data,\r\n columns,\r\n loading,\r\n error,\r\n label,\r\n printable,\r\n pageSize = 5,\r\n pageSizeOptions = [5, 10, 20],\r\n showPagination = true,\r\n}: TableProps<T>) {\r\n const [tooltip, setTooltip] = useState<{\r\n content: string;\r\n x: number;\r\n y: number;\r\n } | null>(null);\r\n const [page, setPage] = useState(1);\r\n const [perPage, setPerPage] = useState(pageSize);\r\n\r\n const totalPages = useMemo(\r\n () => Math.max(1, Math.ceil(data.length / perPage)),\r\n [data.length, perPage],\r\n );\r\n\r\n const safePage = Math.min(page, totalPages);\r\n\r\n const displayData = useMemo(\r\n () => data.slice((safePage - 1) * perPage, safePage * perPage),\r\n [data, safePage, perPage],\r\n );\r\n\r\n const paginationRange = useMemo(() => {\r\n const half = Math.floor(VISIBLE_PAGES / 2);\r\n let start = Math.max(1, safePage - half);\r\n let end = Math.min(totalPages, start + VISIBLE_PAGES - 1);\r\n if (end - start + 1 < VISIBLE_PAGES) {\r\n start = Math.max(1, end - VISIBLE_PAGES + 1);\r\n }\r\n const range: (number | \"...\")[] = [];\r\n if (start > 1) {\r\n range.push(1);\r\n if (start > 2) range.push(\"...\");\r\n }\r\n for (let i = start; i <= end; i++) range.push(i);\r\n if (end < totalPages) {\r\n if (end < totalPages - 1) range.push(\"...\");\r\n range.push(totalPages);\r\n }\r\n return range;\r\n }, [safePage, totalPages]);\r\n\r\n const handlePageSizeChange = useCallback((value: number) => {\r\n setPerPage(value);\r\n setPage(1);\r\n }, []);\r\n\r\n const colCount = columns.length;\r\n const colWidth = colCount > 0 ? `${Math.round(100 / colCount)}%` : \"auto\";\r\n\r\n const handleMouseEnter = (\r\n e: React.MouseEvent<HTMLDivElement>,\r\n content: string,\r\n ) => {\r\n const rect = e.currentTarget.getBoundingClientRect();\r\n setTooltip({\r\n content,\r\n x: rect.left + rect.width / 2,\r\n y: rect.top,\r\n });\r\n };\r\n\r\n const handleMouseLeave = () => {\r\n setTooltip(null);\r\n };\r\n\r\n const banner = error ? (\r\n <div className=\"mb-4\">\r\n <ErrorDisplay key={error.message} error={error} />\r\n </div>\r\n ) : null;\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n {banner}\r\n <div className=\"rounded-lg shadow-md border border-gray-200\">\r\n <div className=\"flex items-center justify-center py-20 text-gray-500\">\r\n Chargement...\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!data || data.length === 0) {\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n {banner}\r\n <div className=\"rounded-lg shadow-md border border-gray-200\">\r\n <div className=\"flex items-center justify-center py-20 text-gray-500\">\r\n Aucun élément\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n {banner}\r\n <div className=\"flex items-center justify-between mb-2\">\r\n {label && (\r\n <div className=\"text-sm font-semibold text-gray-700\">\r\n {label}: {data.length}\r\n </div>\r\n )}\r\n {printable && (\r\n <button\r\n onClick={() => window.print()}\r\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-blue-500 rounded-lg hover:bg-blue-600 transition-colors print:hidden\"\r\n >\r\n <Printer className=\"w-4 h-4\" />\r\n Imprimer\r\n </button>\r\n )}\r\n </div>\r\n <div className=\"rounded-lg shadow-md border border-gray-200\">\r\n <table className=\"w-full table-fixed divide-y divide-gray-200 print:table-fixed\">\r\n <thead className=\"bg-blue-500 rounded-t-lg\">\r\n <tr>\r\n {columns.map((col, index) => (\r\n <th\r\n key={index}\r\n style={{ width: colWidth }}\r\n className={clsx(\r\n \"px-6 py-3 text-left text-xs font-bold text-white uppercase tracking-wider truncate\",\r\n col.excludeFromPrint && \"print:hidden\",\r\n )}\r\n >\r\n {col.header}\r\n </th>\r\n ))}\r\n </tr>\r\n </thead>\r\n <tbody\r\n className={clsx(\r\n \"bg-white divide-y divide-gray-200\",\r\n printable && \"print:hidden\",\r\n )}\r\n >\r\n {displayData.map((row, rowIndex) => (\r\n <tr\r\n key={rowIndex}\r\n className=\"hover:bg-gray-100 transition-colors duration-200\"\r\n >\r\n {columns.map((col, colIndex) => {\r\n const cellContent = col.render\r\n ? col.render(row)\r\n : String(row[col.accessor!]);\r\n const textContent =\r\n typeof cellContent === \"string\" ? cellContent : \"\";\r\n\r\n return (\r\n <td\r\n key={colIndex}\r\n style={{ width: colWidth }}\r\n className={clsx(\r\n \"px-6 py-4 text-sm text-gray-700\",\r\n col.excludeFromPrint && \"print:hidden\",\r\n )}\r\n >\r\n {typeof cellContent === \"string\" ? (\r\n <div\r\n className=\"truncate\"\r\n onMouseEnter={(e) => handleMouseEnter(e, textContent)}\r\n onMouseLeave={handleMouseLeave}\r\n >\r\n {cellContent}\r\n </div>\r\n ) : (\r\n cellContent\r\n )}\r\n </td>\r\n );\r\n })}\r\n </tr>\r\n ))}\r\n </tbody>\r\n {printable && (\r\n <tbody className=\"hidden print:table-row-group\">\r\n {data.map((row, rowIndex) => (\r\n <tr key={rowIndex}>\r\n {columns.map((col, colIndex) => {\r\n const cellContent = col.render\r\n ? col.render(row)\r\n : String(row[col.accessor!]);\r\n\r\n return (\r\n <td\r\n key={colIndex}\r\n style={{ width: colWidth }}\r\n className={clsx(\r\n \"px-6 py-4 text-sm text-gray-700\",\r\n col.excludeFromPrint && \"print:hidden\",\r\n )}\r\n >\r\n {cellContent}\r\n </td>\r\n );\r\n })}\r\n </tr>\r\n ))}\r\n </tbody>\r\n )}\r\n </table>\r\n </div>\r\n\r\n {showPagination && totalPages > 1 && (\r\n <div className=\"flex items-center justify-between mt-4 text-sm print:hidden\">\r\n <div className=\"flex items-center gap-2 text-gray-600\">\r\n <span>Lignes par page :</span>\r\n <select\r\n value={perPage}\r\n onChange={(e) => handlePageSizeChange(Number(e.target.value))}\r\n className=\"border border-gray-300 rounded px-2 py-1 text-sm bg-white focus:outline-none focus:ring-2 focus:ring-blue-400\"\r\n >\r\n {pageSizeOptions.map((opt) => (\r\n <option key={opt} value={opt}>\r\n {opt}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => setPage((p) => Math.max(1, p - 1))}\r\n disabled={safePage <= 1}\r\n className={clsx(\r\n \"p-1.5 rounded transition-colors\",\r\n safePage <= 1\r\n ? \"text-gray-300 cursor-not-allowed\"\r\n : \"text-gray-600 hover:bg-gray-100\",\r\n )}\r\n >\r\n <ChevronLeft className=\"w-4 h-4\" />\r\n </button>\r\n\r\n {paginationRange.map((item, i) =>\r\n item === \"...\" ? (\r\n <span key={`ellipsis-${i}`} className=\"px-2 text-gray-400\">\r\n ...\r\n </span>\r\n ) : (\r\n <button\r\n key={item}\r\n onClick={() => setPage(item)}\r\n className={clsx(\r\n \"min-w-8 px-2 py-1 rounded text-sm font-medium transition-colors\",\r\n item === safePage\r\n ? \"bg-blue-500 text-white\"\r\n : \"text-gray-600 hover:bg-gray-100\",\r\n )}\r\n >\r\n {item}\r\n </button>\r\n ),\r\n )}\r\n\r\n <button\r\n onClick={() => setPage((p) => Math.min(totalPages, p + 1))}\r\n disabled={safePage >= totalPages}\r\n className={clsx(\r\n \"p-1.5 rounded transition-colors\",\r\n safePage >= totalPages\r\n ? \"text-gray-300 cursor-not-allowed\"\r\n : \"text-gray-600 hover:bg-gray-100\",\r\n )}\r\n >\r\n <ChevronRight className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"text-gray-500\">\r\n Page {safePage} sur {totalPages}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {tooltip && (\r\n <div\r\n className=\"fixed z-20 px-3 py-2 text-sm text-white bg-gray-800 rounded-lg shadow-lg pointer-events-none whitespace-nowrap\"\r\n style={{\r\n left: tooltip.x,\r\n top: tooltip.y - 8,\r\n transform: \"translate(-50%, -100%)\",\r\n }}\r\n >\r\n {tooltip.content}\r\n </div>\r\n )}\r\n <style>{`\r\n @media print {\r\n body * { visibility: hidden; }\r\n .w-full.overflow-x-auto { visibility: visible; }\r\n .w-full.overflow-x-auto * { visibility: visible; }\r\n .w-full.overflow-x-auto { position: absolute; left: 0; top: 0; width: 100%; }\r\n }\r\n `}</style>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { X } from \"lucide-react\";\r\nimport { ApiError } from \"../../../utils/src\";\r\nimport { useState } from \"react\";\r\n\r\ninterface ErrorDisplayProps {\r\n error: ApiError | null;\r\n}\r\n\r\nexport function ErrorDisplay({ error }: ErrorDisplayProps) {\r\n const [dismissed, setDismissed] = useState(false);\r\n\r\n if (!error || dismissed) return null;\r\n\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n <div className=\"rounded-lg shadow-md border border-red-200 bg-red-50\">\r\n <div className=\"flex items-start justify-between gap-4 px-4 py-4\">\r\n <div className=\"flex flex-col gap-1\">\r\n <p className=\"text-red-700 font-medium\">Erreur</p>\r\n <p className=\"text-red-600 text-sm\">{error.message}</p>\r\n </div>\r\n <button\r\n onClick={() => setDismissed(true)}\r\n className=\"text-red-400 hover:text-red-600 shrink-0 cursor-pointer\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport React, { useState, useRef, useEffect } from \"react\";\r\nimport { Ellipsis } from \"lucide-react\";\r\n\r\nexport type TableAction<T> = {\r\n label: string;\r\n icon: React.ReactNode;\r\n callback: (row: T) => void;\r\n color?: string;\r\n};\r\n\r\ntype ActionsMenuProps<T> = {\r\n row: T;\r\n actions: TableAction<T>[];\r\n};\r\n\r\nexport function ActionsMenu<T>({ row, actions }: ActionsMenuProps<T>) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [coords, setCoords] = useState({ top: 0, left: 0 });\r\n const buttonRef = useRef<HTMLButtonElement>(null);\r\n const menuRef = useRef<HTMLDivElement>(null);\r\n\r\n // Fermer le menu si clic en dehors\r\n useEffect(() => {\r\n function handleClickOutside(event: MouseEvent) {\r\n if (\r\n menuRef.current &&\r\n buttonRef.current &&\r\n !menuRef.current.contains(event.target as Node) &&\r\n !buttonRef.current.contains(event.target as Node)\r\n ) {\r\n setIsOpen(false);\r\n }\r\n }\r\n\r\n document.addEventListener(\"mousedown\", handleClickOutside);\r\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\r\n }, []);\r\n\r\n const toggleMenu = () => {\r\n if (buttonRef.current) {\r\n const rect = buttonRef.current.getBoundingClientRect();\r\n const menuWidth = 180;\r\n const menuHeight = actions.length * 40;\r\n\r\n const spaceBelow = window.innerHeight - rect.bottom;\r\n const spaceRight = window.innerWidth - rect.left;\r\n\r\n let top = rect.bottom;\r\n let left = rect.left;\r\n\r\n // If not enough space below, show above\r\n if (spaceBelow < menuHeight + 20) {\r\n top = rect.top - menuHeight;\r\n }\r\n\r\n // If not enough space on the right, align to the left\r\n if (spaceRight < menuWidth + 20) {\r\n left = rect.left - menuWidth + 30;\r\n }\r\n\r\n setCoords({ top, left });\r\n }\r\n setIsOpen(!isOpen);\r\n };\r\n\r\n return (\r\n <>\r\n <button\r\n ref={buttonRef}\r\n onClick={toggleMenu}\r\n className=\"p-1 hover:bg-gray-100 rounded-full\"\r\n >\r\n <Ellipsis className=\"w-5 h-5\" />\r\n </button>\r\n\r\n {isOpen && (\r\n <div\r\n ref={menuRef}\r\n className=\"fixed bg-white border border-gray-200 rounded shadow-lg z-20\"\r\n style={{\r\n top: coords.top,\r\n left: coords.left,\r\n minWidth: 180,\r\n }}\r\n >\r\n {actions.map((action, idx) => (\r\n <button\r\n key={idx}\r\n className={`flex items-center gap-2 px-4 py-2 w-full text-sm hover:bg-gray-100 ${\r\n action.color || \"text-gray-700\"\r\n }`}\r\n onClick={() => {\r\n action.callback(row);\r\n setIsOpen(false);\r\n }}\r\n >\r\n {action.icon}\r\n {action.label}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { X } from \"lucide-react\";\r\nimport React, { useEffect } from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\n\r\ntype ModalProps = {\r\n title: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n children: React.ReactNode | ((requestClose: () => void) => React.ReactNode);\r\n};\r\n\r\nexport function Modal({ title, isOpen, onClose, children }: ModalProps) {\r\n const requestClose = () => {\r\n onClose();\r\n };\r\n\r\n useEffect(() => {\r\n if (isOpen) {\r\n document.body.style.overflow = \"hidden\";\r\n }\r\n\r\n return () => {\r\n document.body.style.overflow = \"\";\r\n };\r\n }, [isOpen]);\r\n\r\n useEffect(() => {\r\n function handleEsc(e: KeyboardEvent) {\r\n if (e.key === \"Escape\") {\r\n onClose();\r\n }\r\n }\r\n\r\n if (isOpen) {\r\n document.addEventListener(\"keydown\", handleEsc);\r\n }\r\n\r\n return () => {\r\n document.removeEventListener(\"keydown\", handleEsc);\r\n };\r\n }, [isOpen, onClose]);\r\n\r\n if (!isOpen) return null;\r\n\r\n const content =\r\n typeof children === \"function\" ? children(requestClose) : children;\r\n\r\n return createPortal(\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\r\n <div\r\n className=\"absolute inset-0 bg-black/20 backdrop-blur-sm\"\r\n onClick={onClose}\r\n />\r\n\r\n <div className=\"relative bg-white rounded-lg shadow-lg w-full max-w-2xl mx-4 p-6 flex flex-col max-h-[85vh]\">\r\n <div className=\"flex items-center justify-between mb-4 border-b-2 border-gray-400 pb-3 sticky top-0 bg-white z-10\">\r\n <h2 className=\"text-lg font-semibold text-gray-900\">{title}</h2>\r\n\r\n <button\r\n onClick={onClose}\r\n className=\"text-gray-500 hover:text-gray-700 text-xl cursor-pointer\"\r\n >\r\n <X />\r\n </button>\r\n </div>\r\n\r\n <div className=\"overflow-y-auto flex-1 min-h-0\">{content}</div>\r\n </div>\r\n </div>,\r\n document.body,\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useRef, useState } from \"react\";\r\nimport { ApiError } from \"../../../utils/src/fetcher\";\r\nimport { CircleQuestionMark } from \"lucide-react\";\r\n\r\nconst ERROR_COUNTDOWN = 10;\r\n\r\ninterface ConfirmationProps {\r\n question: string;\r\n messageYes: string;\r\n messageNo: string;\r\n requestClose: () => void;\r\n onAction: () =>\r\n | void\r\n | Promise<void>\r\n | Promise<boolean>\r\n | Promise<{ success: true }>;\r\n isProcessing: boolean;\r\n error: ApiError | null;\r\n resetRequest: () => void;\r\n}\r\n\r\nexport function Confirmation({\r\n question,\r\n messageYes,\r\n messageNo,\r\n requestClose,\r\n onAction,\r\n isProcessing,\r\n error,\r\n resetRequest,\r\n}: ConfirmationProps) {\r\n const [countdown, setCountdown] = useState(0);\r\n const countdownRef = useRef<number | null>(null);\r\n const resetRequestRef = useRef(resetRequest);\r\n\r\n useEffect(() => {\r\n resetRequestRef.current = resetRequest;\r\n }, [resetRequest]);\r\n\r\n const clearCountdown = useCallback(() => {\r\n if (countdownRef.current !== null) {\r\n window.clearInterval(countdownRef.current);\r\n countdownRef.current = null;\r\n }\r\n }, []);\r\n\r\n const resetConfirmationState = useCallback(() => {\r\n clearCountdown();\r\n setCountdown(0);\r\n }, [clearCountdown]);\r\n\r\n const handleResetRequest = useCallback(() => {\r\n resetConfirmationState();\r\n resetRequest();\r\n }, [resetConfirmationState, resetRequest]);\r\n\r\n const handleRequestClose = useCallback(() => {\r\n resetConfirmationState();\r\n resetRequest();\r\n requestClose();\r\n }, [requestClose, resetConfirmationState, resetRequest]);\r\n\r\n const handleAction = useCallback(async () => {\r\n try {\r\n await onAction();\r\n handleRequestClose();\r\n } catch {\r\n // L'erreur est propagée par le parent via la prop `error`.\r\n }\r\n }, [handleRequestClose, onAction]);\r\n\r\n useEffect(() => {\r\n clearCountdown();\r\n\r\n if (!error) {\r\n const resetTimeoutId = window.setTimeout(() => {\r\n setCountdown(0);\r\n }, 0);\r\n\r\n return () => {\r\n window.clearTimeout(resetTimeoutId);\r\n };\r\n }\r\n\r\n const startCountdownTimeoutId = window.setTimeout(() => {\r\n setCountdown(ERROR_COUNTDOWN);\r\n\r\n countdownRef.current = window.setInterval(() => {\r\n setCountdown((previousCountdown) => {\r\n if (previousCountdown <= 1) {\r\n clearCountdown();\r\n window.setTimeout(() => {\r\n resetRequestRef.current();\r\n }, 0);\r\n\r\n return 0;\r\n }\r\n\r\n return previousCountdown - 1;\r\n });\r\n }, 1000);\r\n }, 0);\r\n\r\n return () => {\r\n window.clearTimeout(startCountdownTimeoutId);\r\n clearCountdown();\r\n };\r\n }, [clearCountdown, error]);\r\n\r\n useEffect(() => {\r\n return () => {\r\n clearCountdown();\r\n resetRequestRef.current();\r\n };\r\n }, [clearCountdown]);\r\n\r\n const isErrorVisible = Boolean(error) && countdown > 0;\r\n\r\n if (!question) return null;\r\n\r\n return (\r\n <div className=\"flex flex-col items-center gap-3 z-40\">\r\n <CircleQuestionMark className=\"text-red-500 text-5xl\" />\r\n <h2 className=\"text-xl font-bold text-red-500\">Confirmation requise</h2>\r\n\r\n <p className=\"mt-4 text-md leading-relaxed text-gray-700\">{question}</p>\r\n\r\n <div className=\"mt-6 flex w-full gap-3\">\r\n <button\r\n type=\"button\"\r\n onClick={handleRequestClose}\r\n disabled={isProcessing}\r\n className=\"w-full rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-semibold text-gray-700 transition hover:cursor-pointer hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-white\"\r\n >\r\n {messageNo}\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n onClick={handleAction}\r\n disabled={isProcessing}\r\n className=\"w-full rounded-lg bg-red-400 px-4 py-2 text-sm font-semibold text-white transition hover:cursor-pointer hover:bg-red-500 active:scale-95 disabled:opacity-50 disabled:hover:bg-red-500\"\r\n >\r\n {isProcessing ? \"operation en cours\" : messageYes}\r\n </button>\r\n </div>\r\n\r\n {error && isErrorVisible && (\r\n <div className=\"mt-4 w-full rounded-lg border border-red-200 bg-red-50 p-4 text-left text-sm text-red-700\">\r\n <div className=\"flex items-start justify-between gap-3\">\r\n <div>\r\n <p className=\"font-semibold\">Erreur</p>\r\n <p className=\"mt-1 text-sm\">{error.message}</p>\r\n </div>\r\n\r\n <button\r\n type=\"button\"\r\n onClick={handleResetRequest}\r\n className=\"rounded-full bg-red-100 px-2 py-1 text-xs font-semibold text-red-700 hover:bg-red-200\"\r\n >\r\n Fermer\r\n </button>\r\n </div>\r\n\r\n <p className=\"mt-3 text-xs text-red-600\">\r\n Ce message disparait dans {countdown}s...\r\n </p>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\ntype HeaderContentProps = {\r\n title: string;\r\n description: string;\r\n\r\n actionLabel?: string;\r\n onAction?: () => void;\r\n icon?: React.ReactNode;\r\n};\r\n\r\nexport function HeaderContent({\r\n title,\r\n description,\r\n actionLabel,\r\n onAction,\r\n icon,\r\n}: HeaderContentProps) {\r\n return (\r\n <div className=\"flex flex-col md:flex-row md:items-center md:justify-between gap-4 mb-6\">\r\n <div>\r\n <h1 className=\"text-xl font-semibold text-gray-900 flex items-center gap-2\">\r\n {title}\r\n </h1>\r\n\r\n {description && (\r\n <p className=\"text-sm text-gray-500 mt-1\">{description}</p>\r\n )}\r\n </div>\r\n\r\n {actionLabel && onAction && (\r\n <button\r\n onClick={onAction}\r\n className=\"font-semibold md:inline-flex items-center gap-2 bg-gray-900 text-white px-4 py-2 rounded-md text-sm hover:bg-gray-700 transition hover:cursor-pointer\"\r\n >\r\n {icon && <span className=\"w-4 h-4\">{icon}</span>}\r\n {actionLabel}\r\n </button>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n","import React, { useState, useEffect, useRef, useCallback } from \"react\";\r\nimport { ApiError } from \"../../../utils/src/fetcher\";\r\nimport { X } from \"lucide-react\";\r\n\r\ninterface FormProps extends React.FormHTMLAttributes<HTMLFormElement> {\r\n erreurs?: ApiError | null;\r\n onErrorClose?: () => void;\r\n}\r\n\r\nconst Form: React.FC<FormProps> = ({\r\n erreurs,\r\n onErrorClose,\r\n children,\r\n className,\r\n ...props\r\n}) => {\r\n const formClassName = [\"flex flex-col gap-3\", className]\r\n .filter(Boolean)\r\n .join(\" \");\r\n const errorMessage = erreurs?.message || null;\r\n const [showError, setShowError] = useState(!!erreurs);\r\n const [countdown, setCountdown] = useState(erreurs ? 10 : 0);\r\n const [animating, setAnimating] = useState(!!erreurs);\r\n const intervalRef = useRef<number | null>(null);\r\n const hasClosedRef = useRef(false);\r\n\r\n const closeError = useCallback(\r\n (triggerCallback = true) => {\r\n if (intervalRef.current !== null) {\r\n window.clearInterval(intervalRef.current);\r\n intervalRef.current = null;\r\n }\r\n\r\n setShowError(false);\r\n setAnimating(false);\r\n setCountdown(0);\r\n\r\n if (triggerCallback && onErrorClose && !hasClosedRef.current) {\r\n hasClosedRef.current = true;\r\n onErrorClose();\r\n }\r\n },\r\n [onErrorClose],\r\n );\r\n\r\n useEffect(() => {\r\n hasClosedRef.current = false;\r\n\r\n if (!erreurs) {\r\n const closeTimeout = window.setTimeout(() => closeError(false), 0);\r\n return () => {\r\n window.clearTimeout(closeTimeout);\r\n };\r\n }\r\n\r\n const initTimeout = window.setTimeout(() => {\r\n setShowError(true);\r\n setAnimating(true);\r\n setCountdown(10);\r\n }, 0);\r\n\r\n intervalRef.current = window.setInterval(() => {\r\n setCountdown((prev) => {\r\n if (prev <= 1) {\r\n closeError(true);\r\n return 0;\r\n }\r\n return prev - 1;\r\n });\r\n }, 1000);\r\n\r\n return () => {\r\n window.clearTimeout(initTimeout);\r\n if (intervalRef.current !== null) {\r\n window.clearInterval(intervalRef.current);\r\n intervalRef.current = null;\r\n }\r\n };\r\n }, [erreurs, closeError]);\r\n\r\n return (\r\n <>\r\n <form className={formClassName} {...props}>\r\n {children}\r\n </form>\r\n {showError && errorMessage && (\r\n <div\r\n className={`fixed top-0 left-0 right-0 z-[9999] bg-red-500 text-white p-4 rounded-b-md shadow-lg flex justify-between items-center transition-transform duration-300 ${\r\n animating\r\n ? \"transform translate-y-0\"\r\n : \"transform -translate-y-full\"\r\n }`}\r\n >\r\n <span>{errorMessage}</span>\r\n <div className=\"flex items-center\">\r\n <span className=\"mr-2\">{countdown}s</span>\r\n <button onClick={() => closeError(true)}>\r\n <X size={20} />\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </>\r\n );\r\n};\r\n\r\nexport { Form };\r\n","import React from \"react\";\r\n\r\ninterface FieldContainerProps {\r\n children: React.ReactNode;\r\n className?: string;\r\n}\r\n\r\nexport function FieldContainer({ children, className }: FieldContainerProps) {\r\n return (\r\n <div className={`flex flex-col gap-2 mb-3 relative ${className ?? \"\"}`}>\r\n <div className=\"flex flex-col gap-1\">{children}</div>\r\n </div>\r\n );\r\n}\r\n","import React from \"react\";\r\n\r\ninterface LabelProps extends Omit<\r\n React.LabelHTMLAttributes<HTMLLabelElement>,\r\n \"required\"\r\n> {\r\n required?: boolean;\r\n}\r\n\r\nconst Label = React.forwardRef<HTMLLabelElement, LabelProps>(\r\n ({ required, children, className, ...props }, ref) => {\r\n return (\r\n <label\r\n ref={ref}\r\n className={`font-semibold text-gray-600 block ${className ?? \"\"}`.trim()}\r\n {...props}\r\n >\r\n {children}\r\n {required ? <span className=\"text-red-500 ml-1\">*</span> : null}\r\n </label>\r\n );\r\n },\r\n);\r\n\r\nLabel.displayName = \"Label\";\r\n\r\nexport { Label };\r\n","import React, { useState } from \"react\";\r\nimport { Eye, EyeOff } from \"lucide-react\";\r\n\r\nconst Input = React.forwardRef<\r\n HTMLInputElement,\r\n React.InputHTMLAttributes<HTMLInputElement>\r\n>(({ type, className, ...props }, ref) => {\r\n const [showPassword, setShowPassword] = useState(false);\r\n\r\n const isPassword = type === \"password\";\r\n const inputType = isPassword ? (showPassword ? \"text\" : \"password\") : type;\r\n\r\n return (\r\n <div className=\"relative\">\r\n <input\r\n ref={ref}\r\n type={inputType}\r\n className={`w-full px-3 py-2 pr-10 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500 focus:border-transparent transition duration-200 ${className || \"\"}`}\r\n {...props}\r\n />\r\n {isPassword && (\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowPassword(!showPassword)}\r\n className=\"absolute inset-y-0 right-0 pr-3 flex items-center text-gray-500 hover:text-gray-700\"\r\n >\r\n {showPassword ? <EyeOff size={20} /> : <Eye size={20} />}\r\n </button>\r\n )}\r\n </div>\r\n );\r\n});\r\n\r\nInput.displayName = \"Input\";\r\n\r\nexport { Input };\r\n","import React from \"react\";\r\n\r\nconst Select = React.forwardRef<\r\n HTMLSelectElement,\r\n React.SelectHTMLAttributes<HTMLSelectElement>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <select\r\n ref={ref}\r\n className={`w-full px-3 py-2 pr-10 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500 focus:border-transparent transition duration-200 bg-white cursor-pointer appearance-none bg-no-repeat bg-right bg-contain ${className || \"\"}`}\r\n style={{\r\n backgroundImage: `url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e\")`,\r\n backgroundPosition: \"right 0.75rem center\",\r\n backgroundSize: \"1.25em 1.25em\",\r\n }}\r\n {...props}\r\n />\r\n );\r\n});\r\n\r\nSelect.displayName = \"Select\";\r\n\r\nexport { Select };\r\n\r\n// Option Component\r\n\r\nconst Option = React.forwardRef<\r\n HTMLOptionElement,\r\n React.OptionHTMLAttributes<HTMLOptionElement>\r\n>(({ ...props }, ref) => {\r\n return <option ref={ref} {...props} />;\r\n});\r\n\r\nOption.displayName = \"Option\";\r\n\r\nexport { Option };\r\n","import React from \"react\";\r\n\r\nconst TextArea = React.forwardRef<\r\n HTMLTextAreaElement,\r\n React.TextareaHTMLAttributes<HTMLTextAreaElement>\r\n>(({ ...props }, ref) => {\r\n return (\r\n <textarea\r\n ref={ref}\r\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500 focus:border-transparent transition duration-200 resize-none\"\r\n {...props}\r\n />\r\n );\r\n});\r\n\r\nTextArea.displayName = \"TextArea\";\r\n\r\nexport { TextArea };\r\n","import React from \"react\";\r\n\r\nconst DatePicker = React.forwardRef<\r\n HTMLInputElement,\r\n React.InputHTMLAttributes<HTMLInputElement>\r\n>(({ className, placeholder, required, ...props }, ref) => {\r\n return (\r\n <div className=\"relative\">\r\n <input\r\n ref={ref}\r\n type=\"date\"\r\n required={required ?? true}\r\n className={`peer w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500 focus:border-transparent transition duration-200 ${className ?? \"\"}`}\r\n {...props}\r\n />\r\n <span className=\"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none peer-valid:hidden md:hidden\">\r\n {placeholder ?? \"jj/mm/aaaa\"}\r\n </span>\r\n </div>\r\n );\r\n});\r\n\r\nDatePicker.displayName = \"DatePicker\";\r\n\r\nexport { DatePicker };\r\n","import { Loader } from \"lucide-react\";\r\n\r\ninterface LoadingProps {\r\n text: string;\r\n}\r\n\r\nexport function Loading(props: LoadingProps) {\r\n return (\r\n <div className=\"flex items-center justify-center\">\r\n <div className=\"flex flex-col items-center gap-4\">\r\n <Loader className=\"animate-spin\" size={40} />\r\n\r\n <p className=\"text-gray-600 text-md font-medium\">{props.text}</p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { LoaderCircle } from \"lucide-react\";\r\n\r\ninterface LoaderSubmitProps {\r\n label: string;\r\n loadingLabel: string;\r\n isLoading: boolean;\r\n}\r\n\r\nexport function LoaderSubmit({ label, loadingLabel, isLoading }: LoaderSubmitProps) {\r\n return (\r\n <>\r\n {isLoading ? (\r\n <div className=\"flex flex-row gap-2 items-center\">\r\n <LoaderCircle className=\"animate-spin text-gray-500\" />\r\n <p className=\"text-gray-500 font-semibold\">{loadingLabel}</p>\r\n </div>\r\n ) : (\r\n <button\r\n type=\"submit\"\r\n className=\"bg-gray-900 text-white px-6 py-2 rounded-md hover:bg-gray-700 hover:cursor-pointer transition-colors duration-300 font-semibold shadow-md\"\r\n disabled={isLoading}\r\n >\r\n {label}\r\n </button>\r\n )}\r\n </>\r\n );\r\n}\r\n","\"use client\";\n\nimport { useRouter } from \"next/navigation\";\nimport { useEffect, useState } from \"react\";\n\ninterface SessionExpiredProps {\n redirectUrl?: string;\n}\n\nexport function SessionExpired({ redirectUrl = \"/\" }: SessionExpiredProps) {\n const router = useRouter();\n const [countdown, setCountdown] = useState(10);\n\n useEffect(() => {\n if (countdown <= 0) {\n router.push(redirectUrl);\n return;\n }\n const timer = setTimeout(() => setCountdown((c) => c - 1), 1000);\n return () => clearTimeout(timer);\n }, [countdown, router, redirectUrl]);\n\n const handleConnect = () => {\n router.push(redirectUrl);\n };\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-50\">\n <div className=\"max-w-md w-full text-center space-y-8 p-8\">\n <div className=\"space-y-3\">\n <div className=\"flex justify-center\">\n <svg\n className=\"w-16 h-16 text-gray-300\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={1.5}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-semibold text-gray-900\">\n Session expirée\n </h1>\n <p className=\"text-gray-500\">\n Votre session a expiré ou vous n'êtes pas connecté.\n Veuillez vous reconnecter pour accéder à cette page.\n </p>\n </div>\n\n <button\n onClick={handleConnect}\n className=\"bg-gray-900 text-white px-6 py-2.5 rounded-md text-sm font-semibold hover:bg-gray-700 transition-colors\"\n >\n Me connecter\n </button>\n\n <p className=\"text-sm text-gray-400\">\n Redirection automatique dans {countdown}s...\n </p>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport Image from \"next/image\";\nimport Link from \"next/link\";\n\ninterface AccessDeniedProps {\n logo: string;\n redirectTo: string;\n textRedirection: string;\n}\n\nexport function AccessDenied({ logo, redirectTo, textRedirection }: AccessDeniedProps) {\n return (\n <main className=\"min-h-screen py-16 px-4 bg-gradient-to-b from-gray-100 to-white text-gray-900 flex items-center justify-center\">\n <div className=\"max-w-md mx-auto text-center\">\n <div className=\"flex justify-center mb-6\">\n <Image\n alt=\"Logo\"\n height={100}\n width={100}\n src={logo}\n />\n </div>\n\n <h1 className=\"text-2xl font-bold text-red-600 mb-4\">\n Accès refusé\n </h1>\n\n <p className=\"text-gray-500 mb-8\">\n Vous ne disposez pas des droits nécessaires pour accéder à cette page.\n </p>\n\n <Link\n href={redirectTo}\n className=\"inline-block px-6 py-3 bg-gray-900 text-white rounded-lg font-semibold hover:bg-gray-700 transition-colors\"\n >\n {textRedirection}\n </Link>\n </div>\n </main>\n );\n}\n","\"use client\";\r\n\r\nimport {\r\n createContext,\r\n useContext,\r\n useMemo,\r\n type ComponentType,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { redirect, usePathname } from \"next/navigation\";\r\n\r\nexport type UseCurrentUser = () => {\r\n data?: { role: { name: string } } | null;\r\n isLoading: boolean;\r\n};\r\n\r\nexport interface RouteGuardInputConfig {\r\n useCurrentUser: UseCurrentUser;\r\n pagePermissions: Record<string, string[]>;\r\n deniedPath?: string;\r\n}\r\n\r\nexport interface RouteGuardConfig {\r\n useCurrentUser: UseCurrentUser;\r\n pagePermissions: Record<string, string[]>;\r\n deniedPath: string;\r\n}\r\n\r\nexport function createRouteGuardConfig(\r\n input: RouteGuardInputConfig\r\n): RouteGuardConfig {\r\n return {\r\n useCurrentUser: input.useCurrentUser,\r\n pagePermissions: input.pagePermissions,\r\n deniedPath: input.deniedPath ?? \"/access-denied\",\r\n };\r\n}\r\n\r\nconst RouteGuardContext = createContext<RouteGuardConfig | null>(null);\r\n\r\ninterface RouteGuardProviderProps {\r\n children: ReactNode;\r\n config?: RouteGuardConfig;\r\n useCurrentUser?: UseCurrentUser;\r\n pagePermissions?: Record<string, string[]>;\r\n deniedPath?: string;\r\n}\r\n\r\nexport function RouteGuardProvider({\r\n children,\r\n config,\r\n useCurrentUser,\r\n pagePermissions,\r\n deniedPath,\r\n}: RouteGuardProviderProps) {\r\n const resolved = useMemo<RouteGuardConfig>(() => {\r\n if (config) return config;\r\n return {\r\n useCurrentUser: useCurrentUser!,\r\n pagePermissions: pagePermissions!,\r\n deniedPath: deniedPath ?? \"/access-denied\",\r\n };\r\n }, [config, useCurrentUser, pagePermissions, deniedPath]);\r\n\r\n if (!resolved.useCurrentUser || !resolved.pagePermissions) {\r\n throw new Error(\r\n \"RouteGuardProvider requires either a `config` prop (from createRouteGuardConfig) \" +\r\n \"or `useCurrentUser` + `pagePermissions` directly.\"\r\n );\r\n }\r\n\r\n return (\r\n <RouteGuardContext.Provider value={resolved}>\r\n <AutoRouteGuard config={resolved}>{children}</AutoRouteGuard>\r\n </RouteGuardContext.Provider>\r\n );\r\n}\r\n\r\nfunction AutoRouteGuard({\r\n config,\r\n children,\r\n}: {\r\n config: RouteGuardConfig;\r\n children: ReactNode;\r\n}) {\r\n const pathname = usePathname();\r\n const { data: user, isLoading } = config.useCurrentUser();\r\n\r\n const allowedRoles = useMemo(\r\n () => findAllowedRoles(pathname, config.pagePermissions),\r\n [pathname, config.pagePermissions]\r\n );\r\n\r\n if (!allowedRoles) {\r\n return <>{children}</>;\r\n }\r\n\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-screen\">\r\n <p className=\"text-gray-500\">Chargement...</p>\r\n </div>\r\n );\r\n }\r\n\r\n if (!user || !allowedRoles.includes(user.role.name)) {\r\n redirect(config.deniedPath);\r\n }\r\n\r\n return <>{children}</>;\r\n}\r\n\r\nexport function routeGuard(page: string, Component: ComponentType) {\r\n return function GuardedPage(props: Record<string, unknown>) {\r\n const config = useContext(RouteGuardContext);\r\n\r\n if (!config) {\r\n throw new Error(\r\n \"routeGuard requires a RouteGuardProvider ancestor. \" +\r\n \"Wrap your layout with <RouteGuardProvider>.\"\r\n );\r\n }\r\n\r\n const { data: user, isLoading } = config.useCurrentUser();\r\n const allowedRoles = findAllowedRoles(page, config.pagePermissions);\r\n\r\n if (!allowedRoles) {\r\n return <Component {...props} />;\r\n }\r\n\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-screen\">\r\n <p className=\"text-gray-500\">Chargement...</p>\r\n </div>\r\n );\r\n }\r\n\r\n if (!user || !allowedRoles.includes(user.role.name)) {\r\n redirect(config.deniedPath);\r\n }\r\n\r\n return <Component {...props} />;\r\n };\r\n}\r\n\r\nfunction findAllowedRoles(\r\n page: string,\r\n pagePermissions: Record<string, string[]>\r\n): string[] | undefined {\r\n const segments = page.split(\"/\").filter(Boolean);\r\n\r\n for (let i = 0; i <= segments.length; i++) {\r\n const candidate = \"/\" + segments.slice(0, i).join(\"/\");\r\n const roles = pagePermissions[candidate];\r\n if (roles) return roles;\r\n }\r\n\r\n return undefined;\r\n}\r\n","export class ApiError extends Error {\r\n public status: number;\r\n public code?: string;\r\n public data?: unknown;\r\n\r\n constructor(params: {\r\n message: string;\r\n status: number;\r\n code?: string;\r\n data?: unknown;\r\n }) {\r\n super(params.message);\r\n this.status = params.status;\r\n this.code = params.code;\r\n this.data = params.data;\r\n }\r\n}\r\n\r\ntype BackendErrorShape = {\r\n code?: string;\r\n status?: number;\r\n message?: string;\r\n};\r\n\r\nexport type FetcherOptions = RequestInit & {\r\n skipJsonParsing?: boolean;\r\n};\r\n\r\nexport async function fetcher<T = unknown>(\r\n url: string,\r\n options: FetcherOptions = {},\r\n): Promise<T> {\r\n const { headers, skipJsonParsing = false, ...rest } = options;\r\n\r\n const response = await fetch(url, {\r\n credentials: \"include\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n ...headers,\r\n },\r\n ...rest,\r\n });\r\n\r\n let responseData: unknown = null;\r\n const contentType = response.headers.get(\"content-type\");\r\n\r\n if (!skipJsonParsing && contentType?.includes(\"application/json\")) {\r\n responseData = await response.json();\r\n }\r\n\r\n if (!response.ok) {\r\n const backendError = responseData as BackendErrorShape;\r\n\r\n throw new ApiError({\r\n message: backendError?.message || \"Une erreur est survenue\",\r\n status: backendError?.status || response.status,\r\n code: backendError?.code,\r\n data: responseData,\r\n });\r\n }\r\n\r\n return responseData as T;\r\n}\r\n"],"mappings":";AAEA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAyFK,SAGM,KAHN;AA3DZ,SAAS,SAAS,MAAc,aAAqB;AACnD,SAAO,gBAAgB,QAAQ,YAAY,WAAW,OAAO,GAAG;AAClE;AAEA,SAAS,cAAc,MAAc,aAAqB;AACxD,SAAO,gBAAgB;AACzB;AAEO,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAiB;AACf,QAAM,aAAa,UAAU,KAAK,CAAC,SAAS,SAAS,KAAK,MAAM,WAAW,CAAC;AAC5E,QAAM,cAAc,SAAS,YAAY,SAAS,YAAY;AAC9D,QAAM,CAAC,iBAAiB,kBAAkB,IAAI;AAAA,IAC5C,YAAY,MAAM;AAAA,EACpB;AAEA,QAAM,gBAAgB,CAAC,OAAe;AACpC,uBAAmB,CAAC,SAAU,SAAS,KAAK,OAAO,EAAG;AAAA,EACxD;AAEA,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AAEtD,YAAU,MAAM;AACd,UAAM,eAAe,CAAC,MAAqB;AACzC,UAAI,EAAE,QAAQ,SAAU,iBAAgB,KAAK;AAAA,IAC/C;AACA,aAAS,iBAAiB,WAAW,YAAY;AACjD,WAAO,MAAM,SAAS,oBAAoB,WAAW,YAAY;AAAA,EACnE,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,QAAI,cAAc;AAChB,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC,OAAO;AACL,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AACA,WAAO,MAAM;AACX,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,iBAAiB,MAAM,gBAAgB,KAAK;AAElD,SACE,qBAAC,SAAI,WAAU,qBACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,yIACT,eAAe,kBAAkB,mBACnC;AAAA,QAEC;AAAA,mBACC,oBAAC,SAAI,WAAU,sCACb,+BAAC,SAAI,WAAU,oCACZ;AAAA,kBAAM,SACJ,OAAO,MAAM,SAAS,WACrB;AAAA,cAAC;AAAA;AAAA,gBACC,KAAK,MAAM;AAAA,gBACX,KAAK,MAAM,QAAQ;AAAA,gBACnB,WAAU;AAAA;AAAA,YACZ,IAEA,MAAM;AAAA,YAET,MAAM,QACL,oBAAC,OAAE,WAAU,yCACV,gBAAM,MACT;AAAA,aAEJ,GACF;AAAA,UAGF,oBAAC,SAAI,WAAU,8BACb,8BAAC,QAAG,WAAU,aACX,oBAAU,IAAI,CAAC,SAAS;AACvB,kBAAM,SAAS,SAAS,KAAK,MAAM,WAAW;AAC9C,kBAAM,aAAa,oBAAoB,KAAK;AAC5C,kBAAM,cAAc,KAAK,YAAY,KAAK,SAAS,SAAS;AAE5D,mBACE,qBAAC,QACC;AAAA,mCAAC,SAAI,WAAU,2BACb;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAM,KAAK;AAAA,oBACX,SAAS;AAAA,oBACT,WAAW,+FACT,SACI,2BACA,iCACN;AAAA,oBAEC;AAAA,2BAAK,SACH,OAAO,KAAK,SAAS,WACpB,oBAAC,UAAK,WAAU,WAAW,eAAK,MAAK,IACnC,eAAe,KAAK,IAAI,IAC1B,KAAK,OAEL;AAAA,wBACE,KAAK;AAAA,wBACL,EAAE,MAAM,GAAG;AAAA,sBACb;AAAA,sBAEH,KAAK;AAAA;AAAA;AAAA,gBACR;AAAA,gBACC,UAAU,eACT;AAAA,kBAAC;AAAA;AAAA,oBACC,SAAS,MAAM,cAAc,KAAK,EAAE;AAAA,oBACpC,WAAW,sCACT,SACI,iCACA,iCACN;AAAA,oBACA,OAAO,aAAa,eAAY;AAAA,oBAE/B,uBACC;AAAA,sBAAC;AAAA;AAAA,wBACC,WAAW,kDACT,aAAa,aAAa,YAC5B;AAAA,wBAEC;AAAA;AAAA,oBACH,IAEA,oBAAC,UAAK,WAAU,WACb,uBAAa,WAAM,UACtB;AAAA;AAAA,gBAEJ;AAAA,iBAEJ;AAAA,cAEC,UAAU,eACT;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAW,gDACT,aAAa,oBAAoB,iBACnC;AAAA,kBAEA,8BAAC,SAAI,WAAU,mBACb,8BAAC,QAAG,WAAU,4BACX,eAAK,SAAU,IAAI,CAAC,QACnB,oBAAC,QACC;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAM,IAAI;AAAA,sBACV,SAAS;AAAA,sBACT,WAAW,sFACT,cAAc,IAAI,MAAM,WAAW,IAC/B,2BACA,iCACN;AAAA,sBAEC,cAAI;AAAA;AAAA,kBACP,KAXO,IAAI,EAYb,CACD,GACH,GACF;AAAA;AAAA,cACF;AAAA,iBA5EK,KAAK,EA8Ed;AAAA,UAEJ,CAAC,GACH,GACF;AAAA,UAEC,UAAU,OAAO,SAAS,KACzB,oBAAC,SAAI,WAAU,0CACZ,iBAAO,IAAI,CAAC,SACX;AAAA,YAAC;AAAA;AAAA,cAEC,MAAM,KAAK;AAAA,cACX,SAAS;AAAA,cACT,WAAU;AAAA,cAET;AAAA,uBAAO,KAAK,SAAS,WACpB,oBAAC,UAAK,WAAU,WAAW,eAAK,MAAK,IACnC,eAAe,KAAK,IAAI,IAC1B,KAAK,OAEL,cAAc,KAAK,MAA0C;AAAA,kBAC3D,MAAM;AAAA,gBACR,CAAC;AAAA,gBAEF,KAAK;AAAA;AAAA;AAAA,YAdD,KAAK;AAAA,UAeZ,CACD,GACH;AAAA;AAAA;AAAA,IAEJ;AAAA,IAEC,gBACC;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS;AAAA,QACT,eAAY;AAAA;AAAA,IACd;AAAA,IAGF,qBAAC,SAAI,WAAU,oCACZ;AAAA,qBACC,qBAAC,YAAO,WAAU,gIAChB;AAAA,6BAAC,SAAI,WAAU,2BACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS,MAAM,gBAAgB,CAAC,YAAY;AAAA,cAC5C,cAAY,eAAe,mBAAmB;AAAA,cAC9C,iBAAe;AAAA,cAEd,yBACC;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,MAAK;AAAA,kBACL,SAAQ;AAAA,kBACR,QAAO;AAAA,kBACP,aAAa;AAAA,kBAEb;AAAA,oBAAC;AAAA;AAAA,sBACC,eAAc;AAAA,sBACd,gBAAe;AAAA,sBACf,GAAE;AAAA;AAAA,kBACJ;AAAA;AAAA,cACF,IAEA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,MAAK;AAAA,kBACL,SAAQ;AAAA,kBACR,QAAO;AAAA,kBACP,aAAa;AAAA,kBAEb;AAAA,oBAAC;AAAA;AAAA,sBACC,eAAc;AAAA,sBACd,gBAAe;AAAA,sBACf,GAAE;AAAA;AAAA,kBACJ;AAAA;AAAA,cACF;AAAA;AAAA,UAEJ;AAAA,UACA,oBAAC,QAAG,WAAU,yCACX,uBACH;AAAA,WACF;AAAA,QACC,OAAO,WACN,oBAAC,UAAK,WAAU,uCACb,gBAAM,SACT;AAAA,SAEJ;AAAA,MAED,CAAC,eACA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,SAAS,MAAM,gBAAgB,CAAC,YAAY;AAAA,UAC5C,cAAY,eAAe,mBAAmB;AAAA,UAC9C,iBAAe;AAAA,UAEd,yBACC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,QAAO;AAAA,cACP,aAAa;AAAA,cAEb;AAAA,gBAAC;AAAA;AAAA,kBACC,eAAc;AAAA,kBACd,gBAAe;AAAA,kBACf,GAAE;AAAA;AAAA,cACJ;AAAA;AAAA,UACF,IAEA;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,QAAO;AAAA,cACP,aAAa;AAAA,cAEb;AAAA,gBAAC;AAAA;AAAA,kBACC,eAAc;AAAA,kBACd,gBAAe;AAAA,kBACf,GAAE;AAAA;AAAA,cACJ;AAAA;AAAA,UACF;AAAA;AAAA,MAEJ;AAAA,MAEF;AAAA,QAAC;AAAA;AAAA,UACC,YAAY,cAAc,cAAc,SAAS;AAAA,UAEhD;AAAA;AAAA,MACH;AAAA,OACF;AAAA,KACF;AAEJ;;;ACzUM,gBAAAA,YAAA;AATC,SAAS,cAAc,QAA6B;AACzD,SAAO,SAAS,kBAAkB;AAAA,IAChC;AAAA,IACA;AAAA,EACF,GAGG;AACD,WACE,gBAAAA,KAAC,WAAS,GAAG,QAAQ,aAClB,UACH;AAAA,EAEJ;AACF;;;ACdA,SAAS,SAAS,aAAa,oBAAoB;AACnD,OAAO,UAAU;AACjB,SAAS,YAAAC,WAAU,SAAS,mBAAmB;;;ACF/C,SAAS,SAAS;AAElB,SAAS,YAAAC,iBAAgB;AAef,SACE,OAAAC,MADF,QAAAC,aAAA;AATH,SAAS,aAAa,EAAE,MAAM,GAAsB;AACzD,QAAM,CAAC,WAAW,YAAY,IAAIF,UAAS,KAAK;AAEhD,MAAI,CAAC,SAAS,UAAW,QAAO;AAEhC,SACE,gBAAAC,KAAC,SAAI,WAAU,0BACb,0BAAAA,KAAC,SAAI,WAAU,wDACb,0BAAAC,MAAC,SAAI,WAAU,oDACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,uBACb;AAAA,sBAAAD,KAAC,OAAE,WAAU,4BAA2B,oBAAM;AAAA,MAC9C,gBAAAA,KAAC,OAAE,WAAU,wBAAwB,gBAAM,SAAQ;AAAA,OACrD;AAAA,IACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,SAAS,MAAM,aAAa,IAAI;AAAA,QAChC,WAAU;AAAA,QAEV,0BAAAA,KAAC,KAAE,WAAU,WAAU;AAAA;AAAA,IACzB;AAAA,KACF,GACF,GACF;AAEJ;;;ADyEM,gBAAAE,MAMA,QAAAC,aANA;AA/EN,IAAM,gBAAgB;AAEf,SAAS,MAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,kBAAkB,CAAC,GAAG,IAAI,EAAE;AAAA,EAC5B,iBAAiB;AACnB,GAAkB;AAChB,QAAM,CAAC,SAAS,UAAU,IAAIC,UAIpB,IAAI;AACd,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAS,CAAC;AAClC,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,QAAQ;AAE/C,QAAM,aAAa;AAAA,IACjB,MAAM,KAAK,IAAI,GAAG,KAAK,KAAK,KAAK,SAAS,OAAO,CAAC;AAAA,IAClD,CAAC,KAAK,QAAQ,OAAO;AAAA,EACvB;AAEA,QAAM,WAAW,KAAK,IAAI,MAAM,UAAU;AAE1C,QAAM,cAAc;AAAA,IAClB,MAAM,KAAK,OAAO,WAAW,KAAK,SAAS,WAAW,OAAO;AAAA,IAC7D,CAAC,MAAM,UAAU,OAAO;AAAA,EAC1B;AAEA,QAAM,kBAAkB,QAAQ,MAAM;AACpC,UAAM,OAAO,KAAK,MAAM,gBAAgB,CAAC;AACzC,QAAI,QAAQ,KAAK,IAAI,GAAG,WAAW,IAAI;AACvC,QAAI,MAAM,KAAK,IAAI,YAAY,QAAQ,gBAAgB,CAAC;AACxD,QAAI,MAAM,QAAQ,IAAI,eAAe;AACnC,cAAQ,KAAK,IAAI,GAAG,MAAM,gBAAgB,CAAC;AAAA,IAC7C;AACA,UAAM,QAA4B,CAAC;AACnC,QAAI,QAAQ,GAAG;AACb,YAAM,KAAK,CAAC;AACZ,UAAI,QAAQ,EAAG,OAAM,KAAK,KAAK;AAAA,IACjC;AACA,aAAS,IAAI,OAAO,KAAK,KAAK,IAAK,OAAM,KAAK,CAAC;AAC/C,QAAI,MAAM,YAAY;AACpB,UAAI,MAAM,aAAa,EAAG,OAAM,KAAK,KAAK;AAC1C,YAAM,KAAK,UAAU;AAAA,IACvB;AACA,WAAO;AAAA,EACT,GAAG,CAAC,UAAU,UAAU,CAAC;AAEzB,QAAM,uBAAuB,YAAY,CAAC,UAAkB;AAC1D,eAAW,KAAK;AAChB,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,CAAC;AAEL,QAAM,WAAW,QAAQ;AACzB,QAAM,WAAW,WAAW,IAAI,GAAG,KAAK,MAAM,MAAM,QAAQ,CAAC,MAAM;AAEnE,QAAM,mBAAmB,CACvB,GACA,YACG;AACH,UAAM,OAAO,EAAE,cAAc,sBAAsB;AACnD,eAAW;AAAA,MACT;AAAA,MACA,GAAG,KAAK,OAAO,KAAK,QAAQ;AAAA,MAC5B,GAAG,KAAK;AAAA,IACV,CAAC;AAAA,EACH;AAEA,QAAM,mBAAmB,MAAM;AAC7B,eAAW,IAAI;AAAA,EACjB;AAEA,QAAM,SAAS,QACb,gBAAAF,KAAC,SAAI,WAAU,QACb,0BAAAA,KAAC,gBAAiC,SAAf,MAAM,OAAuB,GAClD,IACE;AAEJ,MAAI,SAAS;AACX,WACE,gBAAAC,MAAC,SAAI,WAAU,0BACZ;AAAA;AAAA,MACD,gBAAAD,KAAC,SAAI,WAAU,+CACb,0BAAAA,KAAC,SAAI,WAAU,wDAAuD,2BAEtE,GACF;AAAA,OACF;AAAA,EAEJ;AAEA,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,WACE,gBAAAC,MAAC,SAAI,WAAU,0BACZ;AAAA;AAAA,MACD,gBAAAD,KAAC,SAAI,WAAU,+CACb,0BAAAA,KAAC,SAAI,WAAU,wDAAuD,iCAEtE,GACF;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,gBAAAC,MAAC,SAAI,WAAU,0BACZ;AAAA;AAAA,IACD,gBAAAA,MAAC,SAAI,WAAU,0CACZ;AAAA,eACC,gBAAAA,MAAC,SAAI,WAAU,uCACZ;AAAA;AAAA,QAAM;AAAA,QAAG,KAAK;AAAA,SACjB;AAAA,MAED,aACC,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAM,OAAO,MAAM;AAAA,UAC5B,WAAU;AAAA,UAEV;AAAA,4BAAAD,KAAC,WAAQ,WAAU,WAAU;AAAA,YAAE;AAAA;AAAA;AAAA,MAEjC;AAAA,OAEJ;AAAA,IACA,gBAAAA,KAAC,SAAI,WAAU,+CACb,0BAAAC,MAAC,WAAM,WAAU,iEACf;AAAA,sBAAAD,KAAC,WAAM,WAAU,4BACf,0BAAAA,KAAC,QACE,kBAAQ,IAAI,CAAC,KAAK,UACjB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO,EAAE,OAAO,SAAS;AAAA,UACzB,WAAW;AAAA,YACT;AAAA,YACA,IAAI,oBAAoB;AAAA,UAC1B;AAAA,UAEC,cAAI;AAAA;AAAA,QAPA;AAAA,MAQP,CACD,GACH,GACF;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA,aAAa;AAAA,UACf;AAAA,UAEC,sBAAY,IAAI,CAAC,KAAK,aACrB,gBAAAA;AAAA,YAAC;AAAA;AAAA,cAEC,WAAU;AAAA,cAET,kBAAQ,IAAI,CAAC,KAAK,aAAa;AAC9B,sBAAM,cAAc,IAAI,SACpB,IAAI,OAAO,GAAG,IACd,OAAO,IAAI,IAAI,QAAS,CAAC;AAC7B,sBAAM,cACJ,OAAO,gBAAgB,WAAW,cAAc;AAElD,uBACE,gBAAAA;AAAA,kBAAC;AAAA;AAAA,oBAEC,OAAO,EAAE,OAAO,SAAS;AAAA,oBACzB,WAAW;AAAA,sBACT;AAAA,sBACA,IAAI,oBAAoB;AAAA,oBAC1B;AAAA,oBAEC,iBAAO,gBAAgB,WACtB,gBAAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,WAAU;AAAA,wBACV,cAAc,CAAC,MAAM,iBAAiB,GAAG,WAAW;AAAA,wBACpD,cAAc;AAAA,wBAEb;AAAA;AAAA,oBACH,IAEA;AAAA;AAAA,kBAhBG;AAAA,gBAkBP;AAAA,cAEJ,CAAC;AAAA;AAAA,YAhCI;AAAA,UAiCP,CACD;AAAA;AAAA,MACH;AAAA,MACC,aACC,gBAAAA,KAAC,WAAM,WAAU,gCACd,eAAK,IAAI,CAAC,KAAK,aACd,gBAAAA,KAAC,QACE,kBAAQ,IAAI,CAAC,KAAK,aAAa;AAC9B,cAAM,cAAc,IAAI,SACpB,IAAI,OAAO,GAAG,IACd,OAAO,IAAI,IAAI,QAAS,CAAC;AAE7B,eACE,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,OAAO,EAAE,OAAO,SAAS;AAAA,YACzB,WAAW;AAAA,cACT;AAAA,cACA,IAAI,oBAAoB;AAAA,YAC1B;AAAA,YAEC;AAAA;AAAA,UAPI;AAAA,QAQP;AAAA,MAEJ,CAAC,KAlBM,QAmBT,CACD,GACH;AAAA,OAEJ,GACF;AAAA,IAEC,kBAAkB,aAAa,KAC9B,gBAAAC,MAAC,SAAI,WAAU,+DACb;AAAA,sBAAAA,MAAC,SAAI,WAAU,yCACb;AAAA,wBAAAD,KAAC,UAAK,+BAAiB;AAAA,QACvB,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP,UAAU,CAAC,MAAM,qBAAqB,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,YAC5D,WAAU;AAAA,YAET,0BAAgB,IAAI,CAAC,QACpB,gBAAAA,KAAC,YAAiB,OAAO,KACtB,iBADU,GAEb,CACD;AAAA;AAAA,QACH;AAAA,SACF;AAAA,MAEA,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,QAAQ,CAAC,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC;AAAA,YAChD,UAAU,YAAY;AAAA,YACtB,WAAW;AAAA,cACT;AAAA,cACA,YAAY,IACR,qCACA;AAAA,YACN;AAAA,YAEA,0BAAAA,KAAC,eAAY,WAAU,WAAU;AAAA;AAAA,QACnC;AAAA,QAEC,gBAAgB;AAAA,UAAI,CAAC,MAAM,MAC1B,SAAS,QACP,gBAAAA,KAAC,UAA2B,WAAU,sBAAqB,mBAAhD,YAAY,CAAC,EAExB,IAEA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cAEC,SAAS,MAAM,QAAQ,IAAI;AAAA,cAC3B,WAAW;AAAA,gBACT;AAAA,gBACA,SAAS,WACL,2BACA;AAAA,cACN;AAAA,cAEC;AAAA;AAAA,YATI;AAAA,UAUP;AAAA,QAEJ;AAAA,QAEA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,QAAQ,CAAC,MAAM,KAAK,IAAI,YAAY,IAAI,CAAC,CAAC;AAAA,YACzD,UAAU,YAAY;AAAA,YACtB,WAAW;AAAA,cACT;AAAA,cACA,YAAY,aACR,qCACA;AAAA,YACN;AAAA,YAEA,0BAAAA,KAAC,gBAAa,WAAU,WAAU;AAAA;AAAA,QACpC;AAAA,SACF;AAAA,MAEA,gBAAAC,MAAC,SAAI,WAAU,iBAAgB;AAAA;AAAA,QACvB;AAAA,QAAS;AAAA,QAAM;AAAA,SACvB;AAAA,OACF;AAAA,IAGD,WACC,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO;AAAA,UACL,MAAM,QAAQ;AAAA,UACd,KAAK,QAAQ,IAAI;AAAA,UACjB,WAAW;AAAA,QACb;AAAA,QAEC,kBAAQ;AAAA;AAAA,IACX;AAAA,IAEF,gBAAAA,KAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAON;AAAA,KACJ;AAEJ;;;AElVA,SAAgB,YAAAG,WAAU,QAAQ,aAAAC,kBAAiB;AACnD,SAAS,gBAAgB;AAiErB,mBAMI,OAAAC,MAcI,QAAAC,aApBR;AAnDG,SAAS,YAAe,EAAE,KAAK,QAAQ,GAAwB;AACpE,QAAM,CAAC,QAAQ,SAAS,IAAIH,UAAS,KAAK;AAC1C,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAAS,EAAE,KAAK,GAAG,MAAM,EAAE,CAAC;AACxD,QAAM,YAAY,OAA0B,IAAI;AAChD,QAAM,UAAU,OAAuB,IAAI;AAG3C,EAAAC,WAAU,MAAM;AACd,aAAS,mBAAmB,OAAmB;AAC7C,UACE,QAAQ,WACR,UAAU,WACV,CAAC,QAAQ,QAAQ,SAAS,MAAM,MAAc,KAC9C,CAAC,UAAU,QAAQ,SAAS,MAAM,MAAc,GAChD;AACA,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAEA,aAAS,iBAAiB,aAAa,kBAAkB;AACzD,WAAO,MAAM,SAAS,oBAAoB,aAAa,kBAAkB;AAAA,EAC3E,GAAG,CAAC,CAAC;AAEL,QAAM,aAAa,MAAM;AACvB,QAAI,UAAU,SAAS;AACrB,YAAM,OAAO,UAAU,QAAQ,sBAAsB;AACrD,YAAM,YAAY;AAClB,YAAM,aAAa,QAAQ,SAAS;AAEpC,YAAM,aAAa,OAAO,cAAc,KAAK;AAC7C,YAAM,aAAa,OAAO,aAAa,KAAK;AAE5C,UAAI,MAAM,KAAK;AACf,UAAI,OAAO,KAAK;AAGhB,UAAI,aAAa,aAAa,IAAI;AAChC,cAAM,KAAK,MAAM;AAAA,MACnB;AAGA,UAAI,aAAa,YAAY,IAAI;AAC/B,eAAO,KAAK,OAAO,YAAY;AAAA,MACjC;AAEA,gBAAU,EAAE,KAAK,KAAK,CAAC;AAAA,IACzB;AACA,cAAU,CAAC,MAAM;AAAA,EACnB;AAEA,SACE,gBAAAE,MAAA,YACE;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,SAAS;AAAA,QACT,WAAU;AAAA,QAEV,0BAAAA,KAAC,YAAS,WAAU,WAAU;AAAA;AAAA,IAChC;AAAA,IAEC,UACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,WAAU;AAAA,QACV,OAAO;AAAA,UACL,KAAK,OAAO;AAAA,UACZ,MAAM,OAAO;AAAA,UACb,UAAU;AAAA,QACZ;AAAA,QAEC,kBAAQ,IAAI,CAAC,QAAQ,QACpB,gBAAAC;AAAA,UAAC;AAAA;AAAA,YAEC,WAAW,sEACT,OAAO,SAAS,eAClB;AAAA,YACA,SAAS,MAAM;AACb,qBAAO,SAAS,GAAG;AACnB,wBAAU,KAAK;AAAA,YACjB;AAAA,YAEC;AAAA,qBAAO;AAAA,cACP,OAAO;AAAA;AAAA;AAAA,UAVH;AAAA,QAWP,CACD;AAAA;AAAA,IACH;AAAA,KAEJ;AAEJ;;;ACxGA,SAAS,KAAAC,UAAS;AAClB,SAAgB,aAAAC,kBAAiB;AACjC,SAAS,oBAAoB;AA+CvB,gBAAAC,MAME,QAAAC,aANF;AAtCC,SAAS,MAAM,EAAE,OAAO,QAAQ,SAAS,SAAS,GAAe;AACtE,QAAM,eAAe,MAAM;AACzB,YAAQ;AAAA,EACV;AAEA,EAAAF,WAAU,MAAM;AACd,QAAI,QAAQ;AACV,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAEA,WAAO,MAAM;AACX,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,EAAAA,WAAU,MAAM;AACd,aAAS,UAAU,GAAkB;AACnC,UAAI,EAAE,QAAQ,UAAU;AACtB,gBAAQ;AAAA,MACV;AAAA,IACF;AAEA,QAAI,QAAQ;AACV,eAAS,iBAAiB,WAAW,SAAS;AAAA,IAChD;AAEA,WAAO,MAAM;AACX,eAAS,oBAAoB,WAAW,SAAS;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,UACJ,OAAO,aAAa,aAAa,SAAS,YAAY,IAAI;AAE5D,SAAO;AAAA,IACL,gBAAAE,MAAC,SAAI,WAAU,uDACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,SAAS;AAAA;AAAA,MACX;AAAA,MAEA,gBAAAC,MAAC,SAAI,WAAU,+FACb;AAAA,wBAAAA,MAAC,SAAI,WAAU,qGACb;AAAA,0BAAAD,KAAC,QAAG,WAAU,uCAAuC,iBAAM;AAAA,UAE3D,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAU;AAAA,cAEV,0BAAAA,KAACF,IAAA,EAAE;AAAA;AAAA,UACL;AAAA,WACF;AAAA,QAEA,gBAAAE,KAAC,SAAI,WAAU,kCAAkC,mBAAQ;AAAA,SAC3D;AAAA,OACF;AAAA,IACA,SAAS;AAAA,EACX;AACF;;;ACvEA,SAAS,eAAAE,cAAa,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAEzD,SAAS,0BAA0B;AAwH7B,gBAAAC,MAKA,QAAAC,aALA;AAtHN,IAAM,kBAAkB;AAiBjB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,QAAM,CAAC,WAAW,YAAY,IAAIF,UAAS,CAAC;AAC5C,QAAM,eAAeD,QAAsB,IAAI;AAC/C,QAAM,kBAAkBA,QAAO,YAAY;AAE3C,EAAAD,WAAU,MAAM;AACd,oBAAgB,UAAU;AAAA,EAC5B,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,iBAAiBD,aAAY,MAAM;AACvC,QAAI,aAAa,YAAY,MAAM;AACjC,aAAO,cAAc,aAAa,OAAO;AACzC,mBAAa,UAAU;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAyBA,aAAY,MAAM;AAC/C,mBAAe;AACf,iBAAa,CAAC;AAAA,EAChB,GAAG,CAAC,cAAc,CAAC;AAEnB,QAAM,qBAAqBA,aAAY,MAAM;AAC3C,2BAAuB;AACvB,iBAAa;AAAA,EACf,GAAG,CAAC,wBAAwB,YAAY,CAAC;AAEzC,QAAM,qBAAqBA,aAAY,MAAM;AAC3C,2BAAuB;AACvB,iBAAa;AACb,iBAAa;AAAA,EACf,GAAG,CAAC,cAAc,wBAAwB,YAAY,CAAC;AAEvD,QAAM,eAAeA,aAAY,YAAY;AAC3C,QAAI;AACF,YAAM,SAAS;AACf,yBAAmB;AAAA,IACrB,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,oBAAoB,QAAQ,CAAC;AAEjC,EAAAC,WAAU,MAAM;AACd,mBAAe;AAEf,QAAI,CAAC,OAAO;AACV,YAAM,iBAAiB,OAAO,WAAW,MAAM;AAC7C,qBAAa,CAAC;AAAA,MAChB,GAAG,CAAC;AAEJ,aAAO,MAAM;AACX,eAAO,aAAa,cAAc;AAAA,MACpC;AAAA,IACF;AAEA,UAAM,0BAA0B,OAAO,WAAW,MAAM;AACtD,mBAAa,eAAe;AAE5B,mBAAa,UAAU,OAAO,YAAY,MAAM;AAC9C,qBAAa,CAAC,sBAAsB;AAClC,cAAI,qBAAqB,GAAG;AAC1B,2BAAe;AACf,mBAAO,WAAW,MAAM;AACtB,8BAAgB,QAAQ;AAAA,YAC1B,GAAG,CAAC;AAEJ,mBAAO;AAAA,UACT;AAEA,iBAAO,oBAAoB;AAAA,QAC7B,CAAC;AAAA,MACH,GAAG,GAAI;AAAA,IACT,GAAG,CAAC;AAEJ,WAAO,MAAM;AACX,aAAO,aAAa,uBAAuB;AAC3C,qBAAe;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,gBAAgB,KAAK,CAAC;AAE1B,EAAAA,WAAU,MAAM;AACd,WAAO,MAAM;AACX,qBAAe;AACf,sBAAgB,QAAQ;AAAA,IAC1B;AAAA,EACF,GAAG,CAAC,cAAc,CAAC;AAEnB,QAAM,iBAAiB,QAAQ,KAAK,KAAK,YAAY;AAErD,MAAI,CAAC,SAAU,QAAO;AAEtB,SACE,gBAAAI,MAAC,SAAI,WAAU,yCACb;AAAA,oBAAAD,KAAC,sBAAmB,WAAU,yBAAwB;AAAA,IACtD,gBAAAA,KAAC,QAAG,WAAU,kCAAiC,kCAAoB;AAAA,IAEnE,gBAAAA,KAAC,OAAE,WAAU,8CAA8C,oBAAS;AAAA,IAEpE,gBAAAC,MAAC,SAAI,WAAU,0BACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,UAAU;AAAA,UACV,WAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,MAEA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,UAAU;AAAA,UACV,WAAU;AAAA,UAET,yBAAe,uBAAuB;AAAA;AAAA,MACzC;AAAA,OACF;AAAA,IAEC,SAAS,kBACR,gBAAAC,MAAC,SAAI,WAAU,6FACb;AAAA,sBAAAA,MAAC,SAAI,WAAU,0CACb;AAAA,wBAAAA,MAAC,SACC;AAAA,0BAAAD,KAAC,OAAE,WAAU,iBAAgB,oBAAM;AAAA,UACnC,gBAAAA,KAAC,OAAE,WAAU,gBAAgB,gBAAM,SAAQ;AAAA,WAC7C;AAAA,QAEA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS;AAAA,YACT,WAAU;AAAA,YACX;AAAA;AAAA,QAED;AAAA,SACF;AAAA,MAEA,gBAAAC,MAAC,OAAE,WAAU,6BAA4B;AAAA;AAAA,QACZ;AAAA,QAAU;AAAA,SACvC;AAAA,OACF;AAAA,KAEJ;AAEJ;;;ACvJM,SACE,OAAAC,MADF,QAAAC,aAAA;AATC,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,SACE,gBAAAA,MAAC,SAAI,WAAU,2EACb;AAAA,oBAAAA,MAAC,SACC;AAAA,sBAAAD,KAAC,QAAG,WAAU,+DACX,iBACH;AAAA,MAEC,eACC,gBAAAA,KAAC,OAAE,WAAU,8BAA8B,uBAAY;AAAA,OAE3D;AAAA,IAEC,eAAe,YACd,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAU;AAAA,QAET;AAAA,kBAAQ,gBAAAD,KAAC,UAAK,WAAU,WAAW,gBAAK;AAAA,UACxC;AAAA;AAAA;AAAA,IACH;AAAA,KAEJ;AAEJ;;;AC3CA,SAAgB,YAAAE,WAAU,aAAAC,YAAW,UAAAC,SAAQ,eAAAC,oBAAmB;AAEhE,SAAS,KAAAC,UAAS;AA+Ed,qBAAAC,WACE,OAAAC,MAaM,QAAAC,aAdR;AAxEJ,IAAM,OAA4B,CAAC;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;AACJ,QAAM,gBAAgB,CAAC,uBAAuB,SAAS,EACpD,OAAO,OAAO,EACd,KAAK,GAAG;AACX,QAAM,eAAe,SAAS,WAAW;AACzC,QAAM,CAAC,WAAW,YAAY,IAAIP,UAAS,CAAC,CAAC,OAAO;AACpD,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,UAAU,KAAK,CAAC;AAC3D,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,CAAC,CAAC,OAAO;AACpD,QAAM,cAAcE,QAAsB,IAAI;AAC9C,QAAM,eAAeA,QAAO,KAAK;AAEjC,QAAM,aAAaC;AAAA,IACjB,CAAC,kBAAkB,SAAS;AAC1B,UAAI,YAAY,YAAY,MAAM;AAChC,eAAO,cAAc,YAAY,OAAO;AACxC,oBAAY,UAAU;AAAA,MACxB;AAEA,mBAAa,KAAK;AAClB,mBAAa,KAAK;AAClB,mBAAa,CAAC;AAEd,UAAI,mBAAmB,gBAAgB,CAAC,aAAa,SAAS;AAC5D,qBAAa,UAAU;AACvB,qBAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,CAAC,YAAY;AAAA,EACf;AAEA,EAAAF,WAAU,MAAM;AACd,iBAAa,UAAU;AAEvB,QAAI,CAAC,SAAS;AACZ,YAAM,eAAe,OAAO,WAAW,MAAM,WAAW,KAAK,GAAG,CAAC;AACjE,aAAO,MAAM;AACX,eAAO,aAAa,YAAY;AAAA,MAClC;AAAA,IACF;AAEA,UAAM,cAAc,OAAO,WAAW,MAAM;AAC1C,mBAAa,IAAI;AACjB,mBAAa,IAAI;AACjB,mBAAa,EAAE;AAAA,IACjB,GAAG,CAAC;AAEJ,gBAAY,UAAU,OAAO,YAAY,MAAM;AAC7C,mBAAa,CAAC,SAAS;AACrB,YAAI,QAAQ,GAAG;AACb,qBAAW,IAAI;AACf,iBAAO;AAAA,QACT;AACA,eAAO,OAAO;AAAA,MAChB,CAAC;AAAA,IACH,GAAG,GAAI;AAEP,WAAO,MAAM;AACX,aAAO,aAAa,WAAW;AAC/B,UAAI,YAAY,YAAY,MAAM;AAChC,eAAO,cAAc,YAAY,OAAO;AACxC,oBAAY,UAAU;AAAA,MACxB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,UAAU,CAAC;AAExB,SACE,gBAAAM,MAAAF,WAAA,EACE;AAAA,oBAAAC,KAAC,UAAK,WAAW,eAAgB,GAAG,OACjC,UACH;AAAA,IACC,aAAa,gBACZ,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,4JACT,YACI,4BACA,6BACN;AAAA,QAEA;AAAA,0BAAAD,KAAC,UAAM,wBAAa;AAAA,UACpB,gBAAAC,MAAC,SAAI,WAAU,qBACb;AAAA,4BAAAA,MAAC,UAAK,WAAU,QAAQ;AAAA;AAAA,cAAU;AAAA,eAAC;AAAA,YACnC,gBAAAD,KAAC,YAAO,SAAS,MAAM,WAAW,IAAI,GACpC,0BAAAA,KAACF,IAAA,EAAE,MAAM,IAAI,GACf;AAAA,aACF;AAAA;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;;;AC9FM,gBAAAI,aAAA;AAHC,SAAS,eAAe,EAAE,UAAU,UAAU,GAAwB;AAC3E,SACE,gBAAAA,MAAC,SAAI,WAAW,qCAAqC,aAAa,EAAE,IAClE,0BAAAA,MAAC,SAAI,WAAU,uBAAuB,UAAS,GACjD;AAEJ;;;ACbA,OAAOC,YAAW;AAYZ,SAMc,OAAAC,OANd,QAAAC,aAAA;AAHN,IAAM,QAAQF,OAAM;AAAA,EAClB,CAAC,EAAE,UAAU,UAAU,WAAW,GAAG,MAAM,GAAG,QAAQ;AACpD,WACE,gBAAAE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW,qCAAqC,aAAa,EAAE,GAAG,KAAK;AAAA,QACtE,GAAG;AAAA,QAEH;AAAA;AAAA,UACA,WAAW,gBAAAD,MAAC,UAAK,WAAU,qBAAoB,eAAC,IAAU;AAAA;AAAA;AAAA,IAC7D;AAAA,EAEJ;AACF;AAEA,MAAM,cAAc;;;ACxBpB,OAAOE,UAAS,YAAAC,iBAAgB;AAChC,SAAS,KAAK,cAAc;AAYxB,SACE,OAAAC,OADF,QAAAC,cAAA;AAVJ,IAAM,QAAQH,OAAM,WAGlB,CAAC,EAAE,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ;AACxC,QAAM,CAAC,cAAc,eAAe,IAAIC,UAAS,KAAK;AAEtD,QAAM,aAAa,SAAS;AAC5B,QAAM,YAAY,aAAc,eAAe,SAAS,aAAc;AAEtE,SACE,gBAAAE,OAAC,SAAI,WAAU,YACb;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAM;AAAA,QACN,WAAW,iKAAiK,aAAa,EAAE;AAAA,QAC1L,GAAG;AAAA;AAAA,IACN;AAAA,IACC,cACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM,gBAAgB,CAAC,YAAY;AAAA,QAC5C,WAAU;AAAA,QAET,yBAAe,gBAAAA,MAAC,UAAO,MAAM,IAAI,IAAK,gBAAAA,MAAC,OAAI,MAAM,IAAI;AAAA;AAAA,IACxD;AAAA,KAEJ;AAEJ,CAAC;AAED,MAAM,cAAc;;;ACjCpB,OAAOE,YAAW;AAOd,gBAAAC,aAAA;AALJ,IAAM,SAASD,OAAM,WAGnB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,0OAA0O,aAAa,EAAE;AAAA,MACpQ,OAAO;AAAA,QACL,iBAAiB;AAAA,QACjB,oBAAoB;AAAA,QACpB,gBAAgB;AAAA,MAClB;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AAED,OAAO,cAAc;AAMrB,IAAM,SAASC,OAAM,WAGnB,CAAC,EAAE,GAAG,MAAM,GAAG,QAAQ;AACvB,SAAO,gBAAAC,MAAC,YAAO,KAAW,GAAG,OAAO;AACtC,CAAC;AAED,OAAO,cAAc;;;ACjCrB,OAAOC,YAAW;AAOd,gBAAAC,aAAA;AALJ,IAAM,WAAWD,OAAM,WAGrB,CAAC,EAAE,GAAG,MAAM,GAAG,QAAQ;AACvB,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAU;AAAA,MACT,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AAED,SAAS,cAAc;;;ACfvB,OAAOC,YAAW;AAOd,SACE,OAAAC,OADF,QAAAC,cAAA;AALJ,IAAM,aAAaF,OAAM,WAGvB,CAAC,EAAE,WAAW,aAAa,UAAU,GAAG,MAAM,GAAG,QAAQ;AACzD,SACE,gBAAAE,OAAC,SAAI,WAAU,YACb;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,UAAU,YAAY;AAAA,QACtB,WAAW,gKAAgK,aAAa,EAAE;AAAA,QACzL,GAAG;AAAA;AAAA,IACN;AAAA,IACA,gBAAAA,MAAC,UAAK,WAAU,0GACb,yBAAe,cAClB;AAAA,KACF;AAEJ,CAAC;AAED,WAAW,cAAc;;;ACtBzB,SAAS,cAAc;AASjB,SACE,OAAAE,OADF,QAAAC,cAAA;AAHC,SAAS,QAAQ,OAAqB;AAC3C,SACE,gBAAAD,MAAC,SAAI,WAAU,oCACb,0BAAAC,OAAC,SAAI,WAAU,oCACb;AAAA,oBAAAD,MAAC,UAAO,WAAU,gBAAe,MAAM,IAAI;AAAA,IAE3C,gBAAAA,MAAC,OAAE,WAAU,qCAAqC,gBAAM,MAAK;AAAA,KAC/D,GACF;AAEJ;;;ACdA,SAAS,oBAAoB;AAUzB,qBAAAE,WAGM,OAAAC,OADF,QAAAC,cAFJ;AAFG,SAAS,aAAa,EAAE,OAAO,cAAc,UAAU,GAAsB;AAClF,SACE,gBAAAD,MAAAD,WAAA,EACG,sBACC,gBAAAE,OAAC,SAAI,WAAU,oCACb;AAAA,oBAAAD,MAAC,gBAAa,WAAU,8BAA6B;AAAA,IACrD,gBAAAA,MAAC,OAAE,WAAU,+BAA+B,wBAAa;AAAA,KAC3D,IAEA,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MACV,UAAU;AAAA,MAET;AAAA;AAAA,EACH,GAEJ;AAEJ;;;AC3BA,SAAS,iBAAiB;AAC1B,SAAS,aAAAE,YAAW,YAAAC,iBAAgB;AA0B5B,SASM,OAAAC,OATN,QAAAC,cAAA;AApBD,SAAS,eAAe,EAAE,cAAc,IAAI,GAAwB;AACzE,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,WAAW,YAAY,IAAIF,UAAS,EAAE;AAE7C,EAAAD,WAAU,MAAM;AACd,QAAI,aAAa,GAAG;AAClB,aAAO,KAAK,WAAW;AACvB;AAAA,IACF;AACA,UAAM,QAAQ,WAAW,MAAM,aAAa,CAAC,MAAM,IAAI,CAAC,GAAG,GAAI;AAC/D,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,WAAW,QAAQ,WAAW,CAAC;AAEnC,QAAM,gBAAgB,MAAM;AAC1B,WAAO,KAAK,WAAW;AAAA,EACzB;AAEA,SACE,gBAAAE,MAAC,SAAI,WAAU,4DACb,0BAAAC,OAAC,SAAI,WAAU,6CACb;AAAA,oBAAAA,OAAC,SAAI,WAAU,aACb;AAAA,sBAAAD,MAAC,SAAI,WAAU,uBACb,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,QAAO;AAAA,UACP,aAAa;AAAA,UAEb,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,eAAc;AAAA,cACd,gBAAe;AAAA,cACf,GAAE;AAAA;AAAA,UACJ;AAAA;AAAA,MACF,GACF;AAAA,MACA,gBAAAA,MAAC,QAAG,WAAU,wCAAuC,gCAErD;AAAA,MACA,gBAAAA,MAAC,OAAE,WAAU,iBAAgB,qIAG7B;AAAA,OACF;AAAA,IAEA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAU;AAAA,QACX;AAAA;AAAA,IAED;AAAA,IAEA,gBAAAC,OAAC,OAAE,WAAU,yBAAwB;AAAA;AAAA,MACL;AAAA,MAAU;AAAA,OAC1C;AAAA,KACF,GACF;AAEJ;;;ACjEA,OAAO,WAAW;AAClB,OAAO,UAAU;AAWX,SAEI,OAAAC,OAFJ,QAAAC,cAAA;AAHC,SAAS,aAAa,EAAE,MAAM,YAAY,gBAAgB,GAAsB;AACrF,SACE,gBAAAD,MAAC,UAAK,WAAU,kHACd,0BAAAC,OAAC,SAAI,WAAU,gCACb;AAAA,oBAAAD,MAAC,SAAI,WAAU,4BACb,0BAAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAI;AAAA,QACJ,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,KAAK;AAAA;AAAA,IACP,GACF;AAAA,IAEA,gBAAAA,MAAC,QAAG,WAAU,wCAAuC,gCAErD;AAAA,IAEA,gBAAAA,MAAC,OAAE,WAAU,sBAAqB,6FAElC;AAAA,IAEA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,WAAU;AAAA,QAET;AAAA;AAAA,IACH;AAAA,KACF,GACF;AAEJ;;;ACvCA;AAAA,EACE;AAAA,EACA;AAAA,EACA,WAAAE;AAAA,OAGK;AACP,SAAS,UAAU,mBAAmB;AAgEhC,SAqBK,YAAAC,WArBL,OAAAC,aAAA;AA7CC,SAAS,uBACd,OACkB;AAClB,SAAO;AAAA,IACL,gBAAgB,MAAM;AAAA,IACtB,iBAAiB,MAAM;AAAA,IACvB,YAAY,MAAM,cAAc;AAAA,EAClC;AACF;AAEA,IAAM,oBAAoB,cAAuC,IAAI;AAU9D,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,WAAWF,SAA0B,MAAM;AAC/C,QAAI,OAAQ,QAAO;AACnB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,YAAY,cAAc;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,QAAQ,gBAAgB,iBAAiB,UAAU,CAAC;AAExD,MAAI,CAAC,SAAS,kBAAkB,CAAC,SAAS,iBAAiB;AACzD,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,SACE,gBAAAE,MAAC,kBAAkB,UAAlB,EAA2B,OAAO,UACjC,0BAAAA,MAAC,kBAAe,QAAQ,UAAW,UAAS,GAC9C;AAEJ;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AACF,GAGG;AACD,QAAM,WAAW,YAAY;AAC7B,QAAM,EAAE,MAAM,MAAM,UAAU,IAAI,OAAO,eAAe;AAExD,QAAM,eAAeF;AAAA,IACnB,MAAM,iBAAiB,UAAU,OAAO,eAAe;AAAA,IACvD,CAAC,UAAU,OAAO,eAAe;AAAA,EACnC;AAEA,MAAI,CAAC,cAAc;AACjB,WAAO,gBAAAE,MAAAD,WAAA,EAAG,UAAS;AAAA,EACrB;AAEA,MAAI,WAAW;AACb,WACE,gBAAAC,MAAC,SAAI,WAAU,iDACb,0BAAAA,MAAC,OAAE,WAAU,iBAAgB,2BAAa,GAC5C;AAAA,EAEJ;AAEA,MAAI,CAAC,QAAQ,CAAC,aAAa,SAAS,KAAK,KAAK,IAAI,GAAG;AACnD,aAAS,OAAO,UAAU;AAAA,EAC5B;AAEA,SAAO,gBAAAA,MAAAD,WAAA,EAAG,UAAS;AACrB;AAEO,SAAS,WAAW,MAAc,WAA0B;AACjE,SAAO,SAAS,YAAY,OAAgC;AAC1D,UAAM,SAAS,WAAW,iBAAiB;AAE3C,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,MAAM,UAAU,IAAI,OAAO,eAAe;AACxD,UAAM,eAAe,iBAAiB,MAAM,OAAO,eAAe;AAElE,QAAI,CAAC,cAAc;AACjB,aAAO,gBAAAC,MAAC,aAAW,GAAG,OAAO;AAAA,IAC/B;AAEA,QAAI,WAAW;AACb,aACE,gBAAAA,MAAC,SAAI,WAAU,iDACb,0BAAAA,MAAC,OAAE,WAAU,iBAAgB,2BAAa,GAC5C;AAAA,IAEJ;AAEA,QAAI,CAAC,QAAQ,CAAC,aAAa,SAAS,KAAK,KAAK,IAAI,GAAG;AACnD,eAAS,OAAO,UAAU;AAAA,IAC5B;AAEA,WAAO,gBAAAA,MAAC,aAAW,GAAG,OAAO;AAAA,EAC/B;AACF;AAEA,SAAS,iBACP,MACA,iBACsB;AACtB,QAAM,WAAW,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAE/C,WAAS,IAAI,GAAG,KAAK,SAAS,QAAQ,KAAK;AACzC,UAAM,YAAY,MAAM,SAAS,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG;AACrD,UAAM,QAAQ,gBAAgB,SAAS;AACvC,QAAI,MAAO,QAAO;AAAA,EACpB;AAEA,SAAO;AACT;;;AC/JO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EAEP,YAAY,QAKT;AACD,UAAM,OAAO,OAAO;AACpB,SAAK,SAAS,OAAO;AACrB,SAAK,OAAO,OAAO;AACnB,SAAK,OAAO,OAAO;AAAA,EACrB;AACF;AAYA,eAAsB,QACpB,KACA,UAA0B,CAAC,GACf;AACZ,QAAM,EAAE,SAAS,kBAAkB,OAAO,GAAG,KAAK,IAAI;AAEtD,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,aAAa;AAAA,IACb,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,GAAG;AAAA,IACL;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AAED,MAAI,eAAwB;AAC5B,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;AAEvD,MAAI,CAAC,mBAAmB,aAAa,SAAS,kBAAkB,GAAG;AACjE,mBAAe,MAAM,SAAS,KAAK;AAAA,EACrC;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,eAAe;AAErB,UAAM,IAAI,SAAS;AAAA,MACjB,SAAS,cAAc,WAAW;AAAA,MAClC,QAAQ,cAAc,UAAU,SAAS;AAAA,MACzC,MAAM,cAAc;AAAA,MACpB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,SAAO;AACT;","names":["jsx","useState","useState","jsx","jsxs","jsx","jsxs","useState","useState","useEffect","jsx","jsxs","X","useEffect","jsx","jsxs","useCallback","useEffect","useRef","useState","jsx","jsxs","jsx","jsxs","useState","useEffect","useRef","useCallback","X","Fragment","jsx","jsxs","jsx","React","jsx","jsxs","React","useState","jsx","jsxs","React","jsx","React","jsx","React","jsx","React","jsx","jsxs","jsx","jsxs","Fragment","jsx","jsxs","useEffect","useState","jsx","jsxs","jsx","jsxs","useMemo","Fragment","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../packages/ui/src/layouts/side-nav.tsx","../packages/ui/src/modals/modal.tsx","../packages/ui/src/feedback/confirmation.tsx","../packages/utils/src/fetcher.ts","../packages/ui/src/config/create-side-nav.tsx","../packages/ui/src/table/table.tsx","../packages/ui/src/feedback/error-display.tsx","../packages/ui/src/table/actions-menu.tsx","../packages/ui/src/headers/header-content.tsx","../packages/ui/src/forms/form.tsx","../packages/ui/src/forms/field-container.tsx","../packages/ui/src/forms/label.tsx","../packages/ui/src/forms/input.tsx","../packages/ui/src/forms/select.tsx","../packages/ui/src/forms/textarea.tsx","../packages/ui/src/forms/date-picker.tsx","../packages/ui/src/loaders/loading.tsx","../packages/ui/src/loaders/loader-submit.tsx","../packages/ui/src/pages/session-expired.tsx","../packages/ui/src/pages/access-denied.tsx","../packages/ui/src/route-guard/route-guard.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n ReactNode,\r\n useState,\r\n useEffect,\r\n createElement,\r\n isValidElement,\r\n type ComponentType,\r\n} from \"react\";\r\nimport { Modal } from \"../modals/modal\";\r\nimport { Confirmation } from \"../feedback/confirmation\";\r\nimport { ApiError } from \"../../../utils/src/fetcher\";\r\n\r\ntype IconType = ReactNode | ComponentType<{ size?: number }>;\r\n\r\nexport interface NavItem {\r\n id: string;\r\n label: string;\r\n title?: string;\r\n icon?: IconType;\r\n href: string;\r\n subItems?: NavItem[];\r\n}\r\n\r\nexport type FooterItem =\r\n | { icon?: IconType; label: string; href: string }\r\n | {\r\n icon?: IconType;\r\n label: string;\r\n confirm: {\r\n title?: string;\r\n question: string;\r\n messageYes: string;\r\n messageNo: string;\r\n onAction: () => Promise<void> | void;\r\n };\r\n };\r\n\r\nexport interface SideNavStaticConfig {\r\n brand?: {\r\n logo?: ReactNode;\r\n name?: string;\r\n tagline?: string;\r\n };\r\n mainItems: NavItem[];\r\n title?: string;\r\n footer?: FooterItem[];\r\n toggleIcon?: ReactNode;\r\n}\r\n\r\nexport interface SideNavProps extends SideNavStaticConfig {\r\n children: ReactNode;\r\n currentPath: string;\r\n}\r\n\r\nfunction isActive(href: string, currentPath: string) {\r\n return currentPath === href || currentPath.startsWith(href + \"/\");\r\n}\r\n\r\nfunction isExactActive(href: string, currentPath: string) {\r\n return currentPath === href;\r\n}\r\n\r\nfunction findActiveTitleSource(\r\n mainItems: NavItem[],\r\n footer: FooterItem[] | undefined,\r\n currentPath: string,\r\n): { href: string; label: string; title?: string } | undefined {\r\n let best: { href: string; label: string; title?: string } | undefined;\r\n const consider = (item: { href: string; label: string; title?: string }) => {\r\n if (!isActive(item.href, currentPath)) return;\r\n if (!best || item.href.length > best.href.length) {\r\n best = item;\r\n }\r\n };\r\n const visit = (items: NavItem[]) => {\r\n for (const item of items) {\r\n consider(item);\r\n if (item.subItems && item.subItems.length > 0) visit(item.subItems);\r\n }\r\n };\r\n visit(mainItems);\r\n footer?.forEach((item) => {\r\n if (!(\"confirm\" in item)) consider(item);\r\n });\r\n return best;\r\n}\r\n\r\nfunction renderItemIcon(icon: IconType | undefined) {\r\n if (!icon) return null;\r\n if (typeof icon === \"string\") return <span className=\"text-lg\">{icon}</span>;\r\n if (isValidElement(icon)) return icon;\r\n return createElement(icon as ComponentType<{ size?: number }>, { size: 20 });\r\n}\r\n\r\nexport function SideNav({\r\n children,\r\n title,\r\n mainItems,\r\n currentPath,\r\n brand,\r\n footer,\r\n toggleIcon,\r\n}: SideNavProps) {\r\n const activeMain = mainItems.find((item) => isActive(item.href, currentPath));\r\n const activeTitleSource = findActiveTitleSource(mainItems, footer, currentPath);\r\n const headerTitle =\r\n title ?? activeTitleSource?.title ?? activeTitleSource?.label ?? activeMain?.label;\r\n const [expandedSection, setExpandedSection] = useState<string | null>(\r\n activeMain?.id ?? null,\r\n );\r\n\r\n const toggleSection = (id: string) => {\r\n setExpandedSection((prev) => (prev === id ? null : id));\r\n };\r\n\r\n const [isMobileOpen, setIsMobileOpen] = useState(false);\r\n\r\n useEffect(() => {\r\n const handleEscape = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") setIsMobileOpen(false);\r\n };\r\n document.addEventListener(\"keydown\", handleEscape);\r\n return () => document.removeEventListener(\"keydown\", handleEscape);\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (isMobileOpen) {\r\n document.body.style.overflow = \"hidden\";\r\n } else {\r\n document.body.style.overflow = \"\";\r\n }\r\n return () => {\r\n document.body.style.overflow = \"\";\r\n };\r\n }, [isMobileOpen]);\r\n\r\n const closeMobileNav = () => setIsMobileOpen(false);\r\n\r\n const [confirmingItem, setConfirmingItem] = useState<FooterItem | null>(null);\r\n const [pending, setPending] = useState(false);\r\n const [error, setError] = useState<ApiError | null>(null);\r\n\r\n const openConfirm = (item: FooterItem) => {\r\n setError(null);\r\n setConfirmingItem(item);\r\n closeMobileNav();\r\n };\r\n\r\n const closeConfirm = () => {\r\n if (pending) return;\r\n setConfirmingItem(null);\r\n setError(null);\r\n };\r\n\r\n const handleConfirmAction = async () => {\r\n if (!confirmingItem || !(\"confirm\" in confirmingItem)) return;\r\n setPending(true);\r\n setError(null);\r\n try {\r\n await confirmingItem.confirm.onAction();\r\n } catch (e) {\r\n setError(\r\n e instanceof ApiError\r\n ? e\r\n : new ApiError({\r\n message:\r\n e instanceof Error ? e.message : \"Une erreur est survenue\",\r\n status: 500,\r\n }),\r\n );\r\n throw e;\r\n } finally {\r\n setPending(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"flex min-h-screen\">\r\n <aside\r\n className={`w-64 bg-white border-r border-gray-200 flex flex-col fixed h-full z-50 transition-transform duration-300 ease-in-out md:translate-x-0 ${\r\n isMobileOpen ? \"translate-x-0\" : \"-translate-x-full\"\r\n }`}\r\n >\r\n {brand && (\r\n <div className=\"p-[6.5px] border-b border-gray-100\">\r\n <div className=\"flex flex-row gap-2 items-center\">\r\n {brand.logo &&\r\n (typeof brand.logo === \"string\" ? (\r\n <img\r\n src={brand.logo}\r\n alt={brand.name ?? \"\"}\r\n className=\"w-12.5 h-12.5\"\r\n />\r\n ) : (\r\n brand.logo\r\n ))}\r\n {brand.name && (\r\n <p className=\"text-gray-500 text-base font-semibold\">\r\n {brand.name}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n <nav className=\"flex-1 p-4 overflow-y-auto\">\r\n <ul className=\"space-y-1\">\r\n {mainItems.map((item) => {\r\n const active = isActive(item.href, currentPath);\r\n const isExpanded = expandedSection === item.id;\r\n const hasSubItems = item.subItems && item.subItems.length > 0;\r\n\r\n return (\r\n <li key={item.id}>\r\n <div className=\"flex items-center gap-1\">\r\n <a\r\n href={item.href}\r\n onClick={closeMobileNav}\r\n className={`flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors flex-1 ${\r\n active\r\n ? \"bg-gray-200 text-black\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n >\r\n {item.icon &&\r\n (typeof item.icon === \"string\" ? (\r\n <span className=\"text-lg\">{item.icon}</span>\r\n ) : isValidElement(item.icon) ? (\r\n item.icon\r\n ) : (\r\n createElement(\r\n item.icon as ComponentType<{ size?: number }>,\r\n { size: 20 },\r\n )\r\n ))}\r\n {item.label}\r\n </a>\r\n {active && hasSubItems && (\r\n <button\r\n onClick={() => toggleSection(item.id)}\r\n className={`p-1.5 rounded-lg transition-colors ${\r\n active\r\n ? \"text-black hover:bg-gray-100\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n title={isExpanded ? \"Réduire\" : \"Développer\"}\r\n >\r\n {toggleIcon ? (\r\n <span\r\n className={`inline-block transition-transform duration-200 ${\r\n isExpanded ? \"rotate-0\" : \"-rotate-90\"\r\n }`}\r\n >\r\n {toggleIcon}\r\n </span>\r\n ) : (\r\n <span className=\"text-xs\">\r\n {isExpanded ? \"▼\" : \"▶\"}\r\n </span>\r\n )}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {active && hasSubItems && (\r\n <div\r\n className={`grid transition-all duration-300 ease-in-out ${\r\n isExpanded ? \"grid-rows-[1fr]\" : \"grid-rows-[0fr]\"\r\n }`}\r\n >\r\n <div className=\"overflow-hidden\">\r\n <ul className=\"ml-4 mt-1 space-y-1 pl-2\">\r\n {item.subItems!.map((sub) => (\r\n <li key={sub.id}>\r\n <a\r\n href={sub.href}\r\n onClick={closeMobileNav}\r\n className={`flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium transition-colors ${\r\n isExactActive(sub.href, currentPath)\r\n ? \"bg-gray-200 text-black\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n >\r\n {sub.label}\r\n </a>\r\n </li>\r\n ))}\r\n </ul>\r\n </div>\r\n </div>\r\n )}\r\n </li>\r\n );\r\n })}\r\n </ul>\r\n </nav>\r\n\r\n {footer && footer.length > 0 && (\r\n <div className=\"p-4 border-t border-gray-100 space-y-1\">\r\n {footer.map((item) =>\r\n \"confirm\" in item ? (\r\n <button\r\n key={item.label}\r\n type=\"button\"\r\n onClick={() => openConfirm(item)}\r\n className=\"flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-100 transition-colors bg-transparent cursor-pointer\"\r\n >\r\n {renderItemIcon(item.icon)}\r\n {item.label}\r\n </button>\r\n ) : (\r\n <a\r\n key={item.label}\r\n href={item.href}\r\n onClick={closeMobileNav}\r\n className=\"flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-100 transition-colors\"\r\n >\r\n {renderItemIcon(item.icon)}\r\n {item.label}\r\n </a>\r\n ),\r\n )}\r\n </div>\r\n )}\r\n </aside>\r\n\r\n {confirmingItem && \"confirm\" in confirmingItem && (\r\n <Modal\r\n title={confirmingItem.confirm.title ?? confirmingItem.label}\r\n isOpen\r\n onClose={closeConfirm}\r\n >\r\n {(requestClose) => (\r\n <Confirmation\r\n question={confirmingItem.confirm.question}\r\n messageYes={confirmingItem.confirm.messageYes}\r\n messageNo={confirmingItem.confirm.messageNo}\r\n requestClose={() => {\r\n setConfirmingItem(null);\r\n setError(null);\r\n }}\r\n onAction={handleConfirmAction}\r\n isProcessing={pending}\r\n error={error}\r\n resetRequest={() => setError(null)}\r\n />\r\n )}\r\n </Modal>\r\n )}\r\n\r\n {isMobileOpen && (\r\n <div\r\n className=\"fixed inset-0 z-40 bg-black/50 md:hidden\"\r\n onClick={closeMobileNav}\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n\r\n <div className=\"flex-1 ml-64 max-md:ml-0 min-w-0\">\r\n {headerTitle && (\r\n <header className=\"h-16 bg-white border-b border-gray-200 flex items-center justify-between px-6 fixed top-0 right-0 left-64 max-md:left-0 z-20\">\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n className=\"md:hidden p-2 -ml-2 rounded-lg hover:bg-gray-100 transition-colors\"\r\n onClick={() => setIsMobileOpen(!isMobileOpen)}\r\n aria-label={isMobileOpen ? \"Fermer le menu\" : \"Menu\"}\r\n aria-expanded={isMobileOpen}\r\n >\r\n {isMobileOpen ? (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M6 18L18 6M6 6l12 12\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M4 6h16M4 12h16M4 18h16\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n <h1 className=\"text-base font-semibold text-gray-500\">\r\n {headerTitle}\r\n </h1>\r\n </div>\r\n {brand?.tagline && (\r\n <span className=\"text-sm text-gray-500 max-md:hidden\">\r\n {brand.tagline}\r\n </span>\r\n )}\r\n </header>\r\n )}\r\n {!headerTitle && (\r\n <button\r\n className=\"md:hidden fixed top-4 left-4 z-10 p-2 rounded-lg bg-white border border-gray-200 shadow-sm hover:bg-gray-100 transition-colors\"\r\n onClick={() => setIsMobileOpen(!isMobileOpen)}\r\n aria-label={isMobileOpen ? \"Fermer le menu\" : \"Menu\"}\r\n aria-expanded={isMobileOpen}\r\n >\r\n {isMobileOpen ? (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M6 18L18 6M6 6l12 12\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M4 6h16M4 12h16M4 18h16\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n )}\r\n <main\r\n className={(headerTitle ? \"p-6 pt-20\" : \"p-6\") + \" overflow-x-auto\"}\r\n >\r\n {children}\r\n </main>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { X } from \"lucide-react\";\r\nimport React, { useEffect } from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\n\r\ntype ModalProps = {\r\n title: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n children: React.ReactNode | ((requestClose: () => void) => React.ReactNode);\r\n};\r\n\r\nexport function Modal({ title, isOpen, onClose, children }: ModalProps) {\r\n const requestClose = () => {\r\n onClose();\r\n };\r\n\r\n useEffect(() => {\r\n if (isOpen) {\r\n document.body.style.overflow = \"hidden\";\r\n }\r\n\r\n return () => {\r\n document.body.style.overflow = \"\";\r\n };\r\n }, [isOpen]);\r\n\r\n useEffect(() => {\r\n function handleEsc(e: KeyboardEvent) {\r\n if (e.key === \"Escape\") {\r\n onClose();\r\n }\r\n }\r\n\r\n if (isOpen) {\r\n document.addEventListener(\"keydown\", handleEsc);\r\n }\r\n\r\n return () => {\r\n document.removeEventListener(\"keydown\", handleEsc);\r\n };\r\n }, [isOpen, onClose]);\r\n\r\n if (!isOpen) return null;\r\n\r\n const content =\r\n typeof children === \"function\" ? children(requestClose) : children;\r\n\r\n return createPortal(\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\r\n <div\r\n className=\"absolute inset-0 bg-black/20 backdrop-blur-sm\"\r\n onClick={onClose}\r\n />\r\n\r\n <div className=\"relative bg-white rounded-lg shadow-lg w-full max-w-2xl mx-4 p-6 flex flex-col max-h-[85vh]\">\r\n <div className=\"flex items-center justify-between mb-4 border-b-2 border-gray-400 pb-3 sticky top-0 bg-white z-10\">\r\n <h2 className=\"text-lg font-semibold text-gray-900\">{title}</h2>\r\n\r\n <button\r\n onClick={onClose}\r\n className=\"text-gray-500 hover:text-gray-700 text-xl cursor-pointer\"\r\n >\r\n <X />\r\n </button>\r\n </div>\r\n\r\n <div className=\"overflow-y-auto flex-1 min-h-0\">{content}</div>\r\n </div>\r\n </div>,\r\n document.body,\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useRef, useState } from \"react\";\r\nimport { ApiError } from \"../../../utils/src/fetcher\";\r\nimport { CircleQuestionMark } from \"lucide-react\";\r\n\r\nconst ERROR_COUNTDOWN = 10;\r\n\r\ninterface ConfirmationProps {\r\n question: string;\r\n messageYes: string;\r\n messageNo: string;\r\n requestClose: () => void;\r\n onAction: () =>\r\n | void\r\n | Promise<void>\r\n | Promise<boolean>\r\n | Promise<{ success: true }>;\r\n isProcessing: boolean;\r\n error: ApiError | null;\r\n resetRequest: () => void;\r\n}\r\n\r\nexport function Confirmation({\r\n question,\r\n messageYes,\r\n messageNo,\r\n requestClose,\r\n onAction,\r\n isProcessing,\r\n error,\r\n resetRequest,\r\n}: ConfirmationProps) {\r\n const [countdown, setCountdown] = useState(0);\r\n const countdownRef = useRef<number | null>(null);\r\n const resetRequestRef = useRef(resetRequest);\r\n\r\n useEffect(() => {\r\n resetRequestRef.current = resetRequest;\r\n }, [resetRequest]);\r\n\r\n const clearCountdown = useCallback(() => {\r\n if (countdownRef.current !== null) {\r\n window.clearInterval(countdownRef.current);\r\n countdownRef.current = null;\r\n }\r\n }, []);\r\n\r\n const resetConfirmationState = useCallback(() => {\r\n clearCountdown();\r\n setCountdown(0);\r\n }, [clearCountdown]);\r\n\r\n const handleResetRequest = useCallback(() => {\r\n resetConfirmationState();\r\n resetRequest();\r\n }, [resetConfirmationState, resetRequest]);\r\n\r\n const handleRequestClose = useCallback(() => {\r\n resetConfirmationState();\r\n resetRequest();\r\n requestClose();\r\n }, [requestClose, resetConfirmationState, resetRequest]);\r\n\r\n const handleAction = useCallback(async () => {\r\n try {\r\n await onAction();\r\n handleRequestClose();\r\n } catch {\r\n // L'erreur est propagée par le parent via la prop `error`.\r\n }\r\n }, [handleRequestClose, onAction]);\r\n\r\n useEffect(() => {\r\n clearCountdown();\r\n\r\n if (!error) {\r\n const resetTimeoutId = window.setTimeout(() => {\r\n setCountdown(0);\r\n }, 0);\r\n\r\n return () => {\r\n window.clearTimeout(resetTimeoutId);\r\n };\r\n }\r\n\r\n const startCountdownTimeoutId = window.setTimeout(() => {\r\n setCountdown(ERROR_COUNTDOWN);\r\n\r\n countdownRef.current = window.setInterval(() => {\r\n setCountdown((previousCountdown) => {\r\n if (previousCountdown <= 1) {\r\n clearCountdown();\r\n window.setTimeout(() => {\r\n resetRequestRef.current();\r\n }, 0);\r\n\r\n return 0;\r\n }\r\n\r\n return previousCountdown - 1;\r\n });\r\n }, 1000);\r\n }, 0);\r\n\r\n return () => {\r\n window.clearTimeout(startCountdownTimeoutId);\r\n clearCountdown();\r\n };\r\n }, [clearCountdown, error]);\r\n\r\n useEffect(() => {\r\n return () => {\r\n clearCountdown();\r\n resetRequestRef.current();\r\n };\r\n }, [clearCountdown]);\r\n\r\n const isErrorVisible = Boolean(error) && countdown > 0;\r\n\r\n if (!question) return null;\r\n\r\n return (\r\n <div className=\"flex flex-col items-center gap-3 z-40\">\r\n <CircleQuestionMark className=\"text-red-500 text-5xl\" />\r\n <h2 className=\"text-xl font-bold text-red-500\">Confirmation requise</h2>\r\n\r\n <p className=\"mt-4 text-md leading-relaxed text-gray-700\">{question}</p>\r\n\r\n <div className=\"mt-6 flex w-full gap-3\">\r\n <button\r\n type=\"button\"\r\n onClick={handleRequestClose}\r\n disabled={isProcessing}\r\n className=\"w-full rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-semibold text-gray-700 transition hover:cursor-pointer hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-white\"\r\n >\r\n {messageNo}\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n onClick={handleAction}\r\n disabled={isProcessing}\r\n className=\"w-full rounded-lg bg-red-400 px-4 py-2 text-sm font-semibold text-white transition hover:cursor-pointer hover:bg-red-500 active:scale-95 disabled:opacity-50 disabled:hover:bg-red-500\"\r\n >\r\n {isProcessing ? \"operation en cours\" : messageYes}\r\n </button>\r\n </div>\r\n\r\n {error && isErrorVisible && (\r\n <div className=\"mt-4 w-full rounded-lg border border-red-200 bg-red-50 p-4 text-left text-sm text-red-700\">\r\n <div className=\"flex items-start justify-between gap-3\">\r\n <div>\r\n <p className=\"font-semibold\">Erreur</p>\r\n <p className=\"mt-1 text-sm\">{error.message}</p>\r\n </div>\r\n\r\n <button\r\n type=\"button\"\r\n onClick={handleResetRequest}\r\n className=\"rounded-full bg-red-100 px-2 py-1 text-xs font-semibold text-red-700 hover:bg-red-200\"\r\n >\r\n Fermer\r\n </button>\r\n </div>\r\n\r\n <p className=\"mt-3 text-xs text-red-600\">\r\n Ce message disparait dans {countdown}s...\r\n </p>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","export class ApiError extends Error {\r\n public status: number;\r\n public code?: string;\r\n public data?: unknown;\r\n\r\n constructor(params: {\r\n message: string;\r\n status: number;\r\n code?: string;\r\n data?: unknown;\r\n }) {\r\n super(params.message);\r\n this.status = params.status;\r\n this.code = params.code;\r\n this.data = params.data;\r\n }\r\n}\r\n\r\ntype BackendErrorShape = {\r\n code?: string;\r\n status?: number;\r\n message?: string;\r\n};\r\n\r\nexport type FetcherOptions = RequestInit & {\r\n skipJsonParsing?: boolean;\r\n};\r\n\r\nexport async function fetcher<T = unknown>(\r\n url: string,\r\n options: FetcherOptions = {},\r\n): Promise<T> {\r\n const { headers, skipJsonParsing = false, ...rest } = options;\r\n\r\n const response = await fetch(url, {\r\n credentials: \"include\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n ...headers,\r\n },\r\n ...rest,\r\n });\r\n\r\n let responseData: unknown = null;\r\n const contentType = response.headers.get(\"content-type\");\r\n\r\n if (!skipJsonParsing && contentType?.includes(\"application/json\")) {\r\n responseData = await response.json();\r\n }\r\n\r\n if (!response.ok) {\r\n const backendError = responseData as BackendErrorShape;\r\n\r\n throw new ApiError({\r\n message: backendError?.message || \"Une erreur est survenue\",\r\n status: backendError?.status || response.status,\r\n code: backendError?.code,\r\n data: responseData,\r\n });\r\n }\r\n\r\n return responseData as T;\r\n}\r\n","import { SideNav, type SideNavStaticConfig } from \"../layouts/side-nav\";\n\nexport function createSideNav(config: SideNavStaticConfig) {\n return function ConfiguredSideNav({\n children,\n currentPath,\n }: {\n children: React.ReactNode;\n currentPath: string;\n }) {\n return (\n <SideNav {...config} currentPath={currentPath}>\n {children}\n </SideNav>\n );\n };\n}\n","\"use client\";\r\n\r\nimport { Printer, ChevronLeft, ChevronRight } from \"lucide-react\";\r\nimport clsx from \"clsx\";\r\nimport { useState, useMemo, useCallback } from \"react\";\r\nimport { ErrorDisplay } from \"../feedback/error-display\";\r\nimport { ApiError } from \"../../../utils/src/fetcher\";\r\n\r\nexport type Column<T> = {\r\n header: string;\r\n accessor?: keyof T;\r\n render?: (row: T) => React.ReactNode;\r\n excludeFromPrint?: boolean;\r\n};\r\n\r\ntype TableProps<T> = {\r\n data: T[];\r\n columns: Column<T>[];\r\n loading?: boolean;\r\n error?: ApiError | null;\r\n label?: string;\r\n printable?: boolean;\r\n pageSize?: number;\r\n pageSizeOptions?: number[];\r\n showPagination?: boolean;\r\n};\r\n\r\nconst VISIBLE_PAGES = 5;\r\n\r\nexport function Table<T>({\r\n data,\r\n columns,\r\n loading,\r\n error,\r\n label,\r\n printable,\r\n pageSize = 5,\r\n pageSizeOptions = [5, 10, 20],\r\n showPagination = true,\r\n}: TableProps<T>) {\r\n const [tooltip, setTooltip] = useState<{\r\n content: string;\r\n x: number;\r\n y: number;\r\n } | null>(null);\r\n const [page, setPage] = useState(1);\r\n const [perPage, setPerPage] = useState(pageSize);\r\n\r\n const totalPages = useMemo(\r\n () => Math.max(1, Math.ceil(data.length / perPage)),\r\n [data.length, perPage],\r\n );\r\n\r\n const safePage = Math.min(page, totalPages);\r\n\r\n const displayData = useMemo(\r\n () => data.slice((safePage - 1) * perPage, safePage * perPage),\r\n [data, safePage, perPage],\r\n );\r\n\r\n const paginationRange = useMemo(() => {\r\n const half = Math.floor(VISIBLE_PAGES / 2);\r\n let start = Math.max(1, safePage - half);\r\n let end = Math.min(totalPages, start + VISIBLE_PAGES - 1);\r\n if (end - start + 1 < VISIBLE_PAGES) {\r\n start = Math.max(1, end - VISIBLE_PAGES + 1);\r\n }\r\n const range: (number | \"...\")[] = [];\r\n if (start > 1) {\r\n range.push(1);\r\n if (start > 2) range.push(\"...\");\r\n }\r\n for (let i = start; i <= end; i++) range.push(i);\r\n if (end < totalPages) {\r\n if (end < totalPages - 1) range.push(\"...\");\r\n range.push(totalPages);\r\n }\r\n return range;\r\n }, [safePage, totalPages]);\r\n\r\n const handlePageSizeChange = useCallback((value: number) => {\r\n setPerPage(value);\r\n setPage(1);\r\n }, []);\r\n\r\n const colCount = columns.length;\r\n const colWidth = colCount > 0 ? `${Math.round(100 / colCount)}%` : \"auto\";\r\n\r\n const handleMouseEnter = (\r\n e: React.MouseEvent<HTMLDivElement>,\r\n content: string,\r\n ) => {\r\n const rect = e.currentTarget.getBoundingClientRect();\r\n setTooltip({\r\n content,\r\n x: rect.left + rect.width / 2,\r\n y: rect.top,\r\n });\r\n };\r\n\r\n const handleMouseLeave = () => {\r\n setTooltip(null);\r\n };\r\n\r\n const banner = error ? (\r\n <div className=\"mb-4\">\r\n <ErrorDisplay key={error.message} error={error} />\r\n </div>\r\n ) : null;\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n {banner}\r\n <div className=\"rounded-lg shadow-md border border-gray-200\">\r\n <div className=\"flex items-center justify-center py-20 text-gray-500\">\r\n Chargement...\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!data || data.length === 0) {\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n {banner}\r\n <div className=\"rounded-lg shadow-md border border-gray-200\">\r\n <div className=\"flex items-center justify-center py-20 text-gray-500\">\r\n Aucun élément\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n {banner}\r\n <div className=\"flex items-center justify-between mb-2\">\r\n {label && (\r\n <div className=\"text-sm font-semibold text-gray-700\">\r\n {label}: {data.length}\r\n </div>\r\n )}\r\n {printable && (\r\n <button\r\n onClick={() => window.print()}\r\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-blue-500 rounded-lg hover:bg-blue-600 transition-colors print:hidden\"\r\n >\r\n <Printer className=\"w-4 h-4\" />\r\n Imprimer\r\n </button>\r\n )}\r\n </div>\r\n <div className=\"rounded-lg shadow-md border border-gray-200\">\r\n <table className=\"w-full table-fixed divide-y divide-gray-200 print:table-fixed\">\r\n <thead className=\"bg-blue-500 rounded-t-lg\">\r\n <tr>\r\n {columns.map((col, index) => (\r\n <th\r\n key={index}\r\n style={{ width: colWidth }}\r\n className={clsx(\r\n \"px-6 py-3 text-left text-xs font-bold text-white uppercase tracking-wider truncate\",\r\n col.excludeFromPrint && \"print:hidden\",\r\n )}\r\n >\r\n {col.header}\r\n </th>\r\n ))}\r\n </tr>\r\n </thead>\r\n <tbody\r\n className={clsx(\r\n \"bg-white divide-y divide-gray-200\",\r\n printable && \"print:hidden\",\r\n )}\r\n >\r\n {displayData.map((row, rowIndex) => (\r\n <tr\r\n key={rowIndex}\r\n className=\"hover:bg-gray-100 transition-colors duration-200\"\r\n >\r\n {columns.map((col, colIndex) => {\r\n const cellContent = col.render\r\n ? col.render(row)\r\n : String(row[col.accessor!]);\r\n const textContent =\r\n typeof cellContent === \"string\" ? cellContent : \"\";\r\n\r\n return (\r\n <td\r\n key={colIndex}\r\n style={{ width: colWidth }}\r\n className={clsx(\r\n \"px-6 py-4 text-sm text-gray-700\",\r\n col.excludeFromPrint && \"print:hidden\",\r\n )}\r\n >\r\n {typeof cellContent === \"string\" ? (\r\n <div\r\n className=\"truncate\"\r\n onMouseEnter={(e) => handleMouseEnter(e, textContent)}\r\n onMouseLeave={handleMouseLeave}\r\n >\r\n {cellContent}\r\n </div>\r\n ) : (\r\n cellContent\r\n )}\r\n </td>\r\n );\r\n })}\r\n </tr>\r\n ))}\r\n </tbody>\r\n {printable && (\r\n <tbody className=\"hidden print:table-row-group\">\r\n {data.map((row, rowIndex) => (\r\n <tr key={rowIndex}>\r\n {columns.map((col, colIndex) => {\r\n const cellContent = col.render\r\n ? col.render(row)\r\n : String(row[col.accessor!]);\r\n\r\n return (\r\n <td\r\n key={colIndex}\r\n style={{ width: colWidth }}\r\n className={clsx(\r\n \"px-6 py-4 text-sm text-gray-700\",\r\n col.excludeFromPrint && \"print:hidden\",\r\n )}\r\n >\r\n {cellContent}\r\n </td>\r\n );\r\n })}\r\n </tr>\r\n ))}\r\n </tbody>\r\n )}\r\n </table>\r\n </div>\r\n\r\n {showPagination && totalPages > 1 && (\r\n <div className=\"flex items-center justify-between mt-4 text-sm print:hidden\">\r\n <div className=\"flex items-center gap-2 text-gray-600\">\r\n <span>Lignes par page :</span>\r\n <select\r\n value={perPage}\r\n onChange={(e) => handlePageSizeChange(Number(e.target.value))}\r\n className=\"border border-gray-300 rounded px-2 py-1 text-sm bg-white focus:outline-none focus:ring-2 focus:ring-blue-400\"\r\n >\r\n {pageSizeOptions.map((opt) => (\r\n <option key={opt} value={opt}>\r\n {opt}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => setPage((p) => Math.max(1, p - 1))}\r\n disabled={safePage <= 1}\r\n className={clsx(\r\n \"p-1.5 rounded transition-colors\",\r\n safePage <= 1\r\n ? \"text-gray-300 cursor-not-allowed\"\r\n : \"text-gray-600 hover:bg-gray-100\",\r\n )}\r\n >\r\n <ChevronLeft className=\"w-4 h-4\" />\r\n </button>\r\n\r\n {paginationRange.map((item, i) =>\r\n item === \"...\" ? (\r\n <span key={`ellipsis-${i}`} className=\"px-2 text-gray-400\">\r\n ...\r\n </span>\r\n ) : (\r\n <button\r\n key={item}\r\n onClick={() => setPage(item)}\r\n className={clsx(\r\n \"min-w-8 px-2 py-1 rounded text-sm font-medium transition-colors\",\r\n item === safePage\r\n ? \"bg-blue-500 text-white\"\r\n : \"text-gray-600 hover:bg-gray-100\",\r\n )}\r\n >\r\n {item}\r\n </button>\r\n ),\r\n )}\r\n\r\n <button\r\n onClick={() => setPage((p) => Math.min(totalPages, p + 1))}\r\n disabled={safePage >= totalPages}\r\n className={clsx(\r\n \"p-1.5 rounded transition-colors\",\r\n safePage >= totalPages\r\n ? \"text-gray-300 cursor-not-allowed\"\r\n : \"text-gray-600 hover:bg-gray-100\",\r\n )}\r\n >\r\n <ChevronRight className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"text-gray-500\">\r\n Page {safePage} sur {totalPages}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {tooltip && (\r\n <div\r\n className=\"fixed z-20 px-3 py-2 text-sm text-white bg-gray-800 rounded-lg shadow-lg pointer-events-none whitespace-nowrap\"\r\n style={{\r\n left: tooltip.x,\r\n top: tooltip.y - 8,\r\n transform: \"translate(-50%, -100%)\",\r\n }}\r\n >\r\n {tooltip.content}\r\n </div>\r\n )}\r\n <style>{`\r\n @media print {\r\n body * { visibility: hidden; }\r\n .w-full.overflow-x-auto { visibility: visible; }\r\n .w-full.overflow-x-auto * { visibility: visible; }\r\n .w-full.overflow-x-auto { position: absolute; left: 0; top: 0; width: 100%; }\r\n }\r\n `}</style>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { X } from \"lucide-react\";\r\nimport { ApiError } from \"../../../utils/src\";\r\nimport { useState } from \"react\";\r\n\r\ninterface ErrorDisplayProps {\r\n error: ApiError | null;\r\n}\r\n\r\nexport function ErrorDisplay({ error }: ErrorDisplayProps) {\r\n const [dismissed, setDismissed] = useState(false);\r\n\r\n if (!error || dismissed) return null;\r\n\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n <div className=\"rounded-lg shadow-md border border-red-200 bg-red-50\">\r\n <div className=\"flex items-start justify-between gap-4 px-4 py-4\">\r\n <div className=\"flex flex-col gap-1\">\r\n <p className=\"text-red-700 font-medium\">Erreur</p>\r\n <p className=\"text-red-600 text-sm\">{error.message}</p>\r\n </div>\r\n <button\r\n onClick={() => setDismissed(true)}\r\n className=\"text-red-400 hover:text-red-600 shrink-0 cursor-pointer\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport React, { useState, useRef, useEffect } from \"react\";\r\nimport { Ellipsis } from \"lucide-react\";\r\n\r\nexport type TableAction<T> = {\r\n label: string;\r\n icon: React.ReactNode;\r\n callback: (row: T) => void;\r\n color?: string;\r\n};\r\n\r\ntype ActionsMenuProps<T> = {\r\n row: T;\r\n actions: TableAction<T>[];\r\n};\r\n\r\nexport function ActionsMenu<T>({ row, actions }: ActionsMenuProps<T>) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [coords, setCoords] = useState({ top: 0, left: 0 });\r\n const buttonRef = useRef<HTMLButtonElement>(null);\r\n const menuRef = useRef<HTMLDivElement>(null);\r\n\r\n // Fermer le menu si clic en dehors\r\n useEffect(() => {\r\n function handleClickOutside(event: MouseEvent) {\r\n if (\r\n menuRef.current &&\r\n buttonRef.current &&\r\n !menuRef.current.contains(event.target as Node) &&\r\n !buttonRef.current.contains(event.target as Node)\r\n ) {\r\n setIsOpen(false);\r\n }\r\n }\r\n\r\n document.addEventListener(\"mousedown\", handleClickOutside);\r\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\r\n }, []);\r\n\r\n const toggleMenu = () => {\r\n if (buttonRef.current) {\r\n const rect = buttonRef.current.getBoundingClientRect();\r\n const menuWidth = 180;\r\n const menuHeight = actions.length * 40;\r\n\r\n const spaceBelow = window.innerHeight - rect.bottom;\r\n const spaceRight = window.innerWidth - rect.left;\r\n\r\n let top = rect.bottom;\r\n let left = rect.left;\r\n\r\n // If not enough space below, show above\r\n if (spaceBelow < menuHeight + 20) {\r\n top = rect.top - menuHeight;\r\n }\r\n\r\n // If not enough space on the right, align to the left\r\n if (spaceRight < menuWidth + 20) {\r\n left = rect.left - menuWidth + 30;\r\n }\r\n\r\n setCoords({ top, left });\r\n }\r\n setIsOpen(!isOpen);\r\n };\r\n\r\n return (\r\n <>\r\n <button\r\n ref={buttonRef}\r\n onClick={toggleMenu}\r\n className=\"p-1 hover:bg-gray-100 rounded-full\"\r\n >\r\n <Ellipsis className=\"w-5 h-5\" />\r\n </button>\r\n\r\n {isOpen && (\r\n <div\r\n ref={menuRef}\r\n className=\"fixed bg-white border border-gray-200 rounded shadow-lg z-20\"\r\n style={{\r\n top: coords.top,\r\n left: coords.left,\r\n minWidth: 180,\r\n }}\r\n >\r\n {actions.map((action, idx) => (\r\n <button\r\n key={idx}\r\n className={`flex items-center gap-2 px-4 py-2 w-full text-sm hover:bg-gray-100 ${\r\n action.color || \"text-gray-700\"\r\n }`}\r\n onClick={() => {\r\n action.callback(row);\r\n setIsOpen(false);\r\n }}\r\n >\r\n {action.icon}\r\n {action.label}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\ntype HeaderContentProps = {\r\n title: string;\r\n description: string;\r\n\r\n actionLabel?: string;\r\n onAction?: () => void;\r\n icon?: React.ReactNode;\r\n};\r\n\r\nexport function HeaderContent({\r\n title,\r\n description,\r\n actionLabel,\r\n onAction,\r\n icon,\r\n}: HeaderContentProps) {\r\n return (\r\n <div className=\"flex flex-col md:flex-row md:items-center md:justify-between gap-4 mb-6\">\r\n <div>\r\n <h1 className=\"text-xl font-semibold text-gray-900 flex items-center gap-2\">\r\n {title}\r\n </h1>\r\n\r\n {description && (\r\n <p className=\"text-sm text-gray-500 mt-1\">{description}</p>\r\n )}\r\n </div>\r\n\r\n {actionLabel && onAction && (\r\n <button\r\n onClick={onAction}\r\n className=\"font-semibold md:inline-flex items-center gap-2 bg-gray-900 text-white px-4 py-2 rounded-md text-sm hover:bg-gray-700 transition hover:cursor-pointer\"\r\n >\r\n {icon && <span className=\"w-4 h-4\">{icon}</span>}\r\n {actionLabel}\r\n </button>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n","import React, { useState, useEffect, useRef, useCallback } from \"react\";\r\nimport { ApiError } from \"../../../utils/src/fetcher\";\r\nimport { X } from \"lucide-react\";\r\n\r\ninterface FormProps extends React.FormHTMLAttributes<HTMLFormElement> {\r\n erreurs?: ApiError | null;\r\n onErrorClose?: () => void;\r\n}\r\n\r\nconst Form: React.FC<FormProps> = ({\r\n erreurs,\r\n onErrorClose,\r\n children,\r\n className,\r\n ...props\r\n}) => {\r\n const formClassName = [\"flex flex-col gap-3\", className]\r\n .filter(Boolean)\r\n .join(\" \");\r\n const errorMessage = erreurs?.message || null;\r\n const [showError, setShowError] = useState(!!erreurs);\r\n const [countdown, setCountdown] = useState(erreurs ? 10 : 0);\r\n const [animating, setAnimating] = useState(!!erreurs);\r\n const intervalRef = useRef<number | null>(null);\r\n const hasClosedRef = useRef(false);\r\n\r\n const closeError = useCallback(\r\n (triggerCallback = true) => {\r\n if (intervalRef.current !== null) {\r\n window.clearInterval(intervalRef.current);\r\n intervalRef.current = null;\r\n }\r\n\r\n setShowError(false);\r\n setAnimating(false);\r\n setCountdown(0);\r\n\r\n if (triggerCallback && onErrorClose && !hasClosedRef.current) {\r\n hasClosedRef.current = true;\r\n onErrorClose();\r\n }\r\n },\r\n [onErrorClose],\r\n );\r\n\r\n useEffect(() => {\r\n hasClosedRef.current = false;\r\n\r\n if (!erreurs) {\r\n const closeTimeout = window.setTimeout(() => closeError(false), 0);\r\n return () => {\r\n window.clearTimeout(closeTimeout);\r\n };\r\n }\r\n\r\n const initTimeout = window.setTimeout(() => {\r\n setShowError(true);\r\n setAnimating(true);\r\n setCountdown(10);\r\n }, 0);\r\n\r\n intervalRef.current = window.setInterval(() => {\r\n setCountdown((prev) => {\r\n if (prev <= 1) {\r\n closeError(true);\r\n return 0;\r\n }\r\n return prev - 1;\r\n });\r\n }, 1000);\r\n\r\n return () => {\r\n window.clearTimeout(initTimeout);\r\n if (intervalRef.current !== null) {\r\n window.clearInterval(intervalRef.current);\r\n intervalRef.current = null;\r\n }\r\n };\r\n }, [erreurs, closeError]);\r\n\r\n return (\r\n <>\r\n <form className={formClassName} {...props}>\r\n {children}\r\n </form>\r\n {showError && errorMessage && (\r\n <div\r\n className={`fixed top-0 left-0 right-0 z-[9999] bg-red-500 text-white p-4 rounded-b-md shadow-lg flex justify-between items-center transition-transform duration-300 ${\r\n animating\r\n ? \"transform translate-y-0\"\r\n : \"transform -translate-y-full\"\r\n }`}\r\n >\r\n <span>{errorMessage}</span>\r\n <div className=\"flex items-center\">\r\n <span className=\"mr-2\">{countdown}s</span>\r\n <button onClick={() => closeError(true)}>\r\n <X size={20} />\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </>\r\n );\r\n};\r\n\r\nexport { Form };\r\n","import React from \"react\";\r\n\r\ninterface FieldContainerProps {\r\n children: React.ReactNode;\r\n className?: string;\r\n}\r\n\r\nexport function FieldContainer({ children, className }: FieldContainerProps) {\r\n return (\r\n <div className={`flex flex-col gap-2 mb-3 relative ${className ?? \"\"}`}>\r\n <div className=\"flex flex-col gap-1\">{children}</div>\r\n </div>\r\n );\r\n}\r\n","import React from \"react\";\r\n\r\ninterface LabelProps extends Omit<\r\n React.LabelHTMLAttributes<HTMLLabelElement>,\r\n \"required\"\r\n> {\r\n required?: boolean;\r\n}\r\n\r\nconst Label = React.forwardRef<HTMLLabelElement, LabelProps>(\r\n ({ required, children, className, ...props }, ref) => {\r\n return (\r\n <label\r\n ref={ref}\r\n className={`font-semibold text-gray-600 block ${className ?? \"\"}`.trim()}\r\n {...props}\r\n >\r\n {children}\r\n {required ? <span className=\"text-red-500 ml-1\">*</span> : null}\r\n </label>\r\n );\r\n },\r\n);\r\n\r\nLabel.displayName = \"Label\";\r\n\r\nexport { Label };\r\n","import React, { useState } from \"react\";\r\nimport { Eye, EyeOff } from \"lucide-react\";\r\n\r\nconst Input = React.forwardRef<\r\n HTMLInputElement,\r\n React.InputHTMLAttributes<HTMLInputElement>\r\n>(({ type, className, ...props }, ref) => {\r\n const [showPassword, setShowPassword] = useState(false);\r\n\r\n const isPassword = type === \"password\";\r\n const inputType = isPassword ? (showPassword ? \"text\" : \"password\") : type;\r\n\r\n return (\r\n <div className=\"relative\">\r\n <input\r\n ref={ref}\r\n type={inputType}\r\n className={`w-full px-3 py-2 pr-10 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500 focus:border-transparent transition duration-200 ${className || \"\"}`}\r\n {...props}\r\n />\r\n {isPassword && (\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowPassword(!showPassword)}\r\n className=\"absolute inset-y-0 right-0 pr-3 flex items-center text-gray-500 hover:text-gray-700\"\r\n >\r\n {showPassword ? <EyeOff size={20} /> : <Eye size={20} />}\r\n </button>\r\n )}\r\n </div>\r\n );\r\n});\r\n\r\nInput.displayName = \"Input\";\r\n\r\nexport { Input };\r\n","import React from \"react\";\r\n\r\nconst Select = React.forwardRef<\r\n HTMLSelectElement,\r\n React.SelectHTMLAttributes<HTMLSelectElement>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <select\r\n ref={ref}\r\n className={`w-full px-3 py-2 pr-10 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500 focus:border-transparent transition duration-200 bg-white cursor-pointer appearance-none bg-no-repeat bg-right bg-contain ${className || \"\"}`}\r\n style={{\r\n backgroundImage: `url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e\")`,\r\n backgroundPosition: \"right 0.75rem center\",\r\n backgroundSize: \"1.25em 1.25em\",\r\n }}\r\n {...props}\r\n />\r\n );\r\n});\r\n\r\nSelect.displayName = \"Select\";\r\n\r\nexport { Select };\r\n\r\n// Option Component\r\n\r\nconst Option = React.forwardRef<\r\n HTMLOptionElement,\r\n React.OptionHTMLAttributes<HTMLOptionElement>\r\n>(({ ...props }, ref) => {\r\n return <option ref={ref} {...props} />;\r\n});\r\n\r\nOption.displayName = \"Option\";\r\n\r\nexport { Option };\r\n","import React from \"react\";\r\n\r\nconst TextArea = React.forwardRef<\r\n HTMLTextAreaElement,\r\n React.TextareaHTMLAttributes<HTMLTextAreaElement>\r\n>(({ ...props }, ref) => {\r\n return (\r\n <textarea\r\n ref={ref}\r\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500 focus:border-transparent transition duration-200 resize-none\"\r\n {...props}\r\n />\r\n );\r\n});\r\n\r\nTextArea.displayName = \"TextArea\";\r\n\r\nexport { TextArea };\r\n","import React from \"react\";\r\n\r\nconst DatePicker = React.forwardRef<\r\n HTMLInputElement,\r\n React.InputHTMLAttributes<HTMLInputElement>\r\n>(({ className, placeholder, required, ...props }, ref) => {\r\n return (\r\n <div className=\"relative\">\r\n <input\r\n ref={ref}\r\n type=\"date\"\r\n required={required ?? true}\r\n className={`peer w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500 focus:border-transparent transition duration-200 ${className ?? \"\"}`}\r\n {...props}\r\n />\r\n <span className=\"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none peer-valid:hidden md:hidden\">\r\n {placeholder ?? \"jj/mm/aaaa\"}\r\n </span>\r\n </div>\r\n );\r\n});\r\n\r\nDatePicker.displayName = \"DatePicker\";\r\n\r\nexport { DatePicker };\r\n","import { Loader } from \"lucide-react\";\r\n\r\ninterface LoadingProps {\r\n text: string;\r\n}\r\n\r\nexport function Loading(props: LoadingProps) {\r\n return (\r\n <div className=\"flex items-center justify-center\">\r\n <div className=\"flex flex-col items-center gap-4\">\r\n <Loader className=\"animate-spin\" size={40} />\r\n\r\n <p className=\"text-gray-600 text-md font-medium\">{props.text}</p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { LoaderCircle } from \"lucide-react\";\r\n\r\ninterface LoaderSubmitProps {\r\n label: string;\r\n loadingLabel: string;\r\n isLoading: boolean;\r\n}\r\n\r\nexport function LoaderSubmit({ label, loadingLabel, isLoading }: LoaderSubmitProps) {\r\n return (\r\n <>\r\n {isLoading ? (\r\n <div className=\"flex flex-row gap-2 items-center\">\r\n <LoaderCircle className=\"animate-spin text-gray-500\" />\r\n <p className=\"text-gray-500 font-semibold\">{loadingLabel}</p>\r\n </div>\r\n ) : (\r\n <button\r\n type=\"submit\"\r\n className=\"bg-gray-900 text-white px-6 py-2 rounded-md hover:bg-gray-700 hover:cursor-pointer transition-colors duration-300 font-semibold shadow-md\"\r\n disabled={isLoading}\r\n >\r\n {label}\r\n </button>\r\n )}\r\n </>\r\n );\r\n}\r\n","\"use client\";\n\nimport { useRouter } from \"next/navigation\";\nimport { useEffect, useState } from \"react\";\n\ninterface SessionExpiredProps {\n redirectUrl?: string;\n}\n\nexport function SessionExpired({ redirectUrl = \"/\" }: SessionExpiredProps) {\n const router = useRouter();\n const [countdown, setCountdown] = useState(10);\n\n useEffect(() => {\n if (countdown <= 0) {\n router.push(redirectUrl);\n return;\n }\n const timer = setTimeout(() => setCountdown((c) => c - 1), 1000);\n return () => clearTimeout(timer);\n }, [countdown, router, redirectUrl]);\n\n const handleConnect = () => {\n router.push(redirectUrl);\n };\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-50\">\n <div className=\"max-w-md w-full text-center space-y-8 p-8\">\n <div className=\"space-y-3\">\n <div className=\"flex justify-center\">\n <svg\n className=\"w-16 h-16 text-gray-300\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={1.5}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-semibold text-gray-900\">\n Session expirée\n </h1>\n <p className=\"text-gray-500\">\n Votre session a expiré ou vous n'êtes pas connecté.\n Veuillez vous reconnecter pour accéder à cette page.\n </p>\n </div>\n\n <button\n onClick={handleConnect}\n className=\"bg-gray-900 text-white px-6 py-2.5 rounded-md text-sm font-semibold hover:bg-gray-700 transition-colors\"\n >\n Me connecter\n </button>\n\n <p className=\"text-sm text-gray-400\">\n Redirection automatique dans {countdown}s...\n </p>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport Image from \"next/image\";\nimport Link from \"next/link\";\n\ninterface AccessDeniedProps {\n logo: string;\n redirectTo: string;\n textRedirection: string;\n}\n\nexport function AccessDenied({ logo, redirectTo, textRedirection }: AccessDeniedProps) {\n return (\n <main className=\"min-h-screen py-16 px-4 bg-gradient-to-b from-gray-100 to-white text-gray-900 flex items-center justify-center\">\n <div className=\"max-w-md mx-auto text-center\">\n <div className=\"flex justify-center mb-6\">\n <Image\n alt=\"Logo\"\n height={100}\n width={100}\n src={logo}\n />\n </div>\n\n <h1 className=\"text-2xl font-bold text-red-600 mb-4\">\n Accès refusé\n </h1>\n\n <p className=\"text-gray-500 mb-8\">\n Vous ne disposez pas des droits nécessaires pour accéder à cette page.\n </p>\n\n <Link\n href={redirectTo}\n className=\"inline-block px-6 py-3 bg-gray-900 text-white rounded-lg font-semibold hover:bg-gray-700 transition-colors\"\n >\n {textRedirection}\n </Link>\n </div>\n </main>\n );\n}\n","\"use client\";\r\n\r\nimport {\r\n createContext,\r\n useContext,\r\n useMemo,\r\n type ComponentType,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { redirect, usePathname } from \"next/navigation\";\r\n\r\nexport type UseCurrentUser = () => {\r\n data?: { role: { name: string } } | null;\r\n isLoading: boolean;\r\n};\r\n\r\nexport interface RouteGuardInputConfig {\r\n useCurrentUser: UseCurrentUser;\r\n pagePermissions: Record<string, string[]>;\r\n deniedPath?: string;\r\n}\r\n\r\nexport interface RouteGuardConfig {\r\n useCurrentUser: UseCurrentUser;\r\n pagePermissions: Record<string, string[]>;\r\n deniedPath: string;\r\n}\r\n\r\nexport function createRouteGuardConfig(\r\n input: RouteGuardInputConfig\r\n): RouteGuardConfig {\r\n return {\r\n useCurrentUser: input.useCurrentUser,\r\n pagePermissions: input.pagePermissions,\r\n deniedPath: input.deniedPath ?? \"/access-denied\",\r\n };\r\n}\r\n\r\nconst RouteGuardContext = createContext<RouteGuardConfig | null>(null);\r\n\r\ninterface RouteGuardProviderProps {\r\n children: ReactNode;\r\n config?: RouteGuardConfig;\r\n useCurrentUser?: UseCurrentUser;\r\n pagePermissions?: Record<string, string[]>;\r\n deniedPath?: string;\r\n}\r\n\r\nexport function RouteGuardProvider({\r\n children,\r\n config,\r\n useCurrentUser,\r\n pagePermissions,\r\n deniedPath,\r\n}: RouteGuardProviderProps) {\r\n const resolved = useMemo<RouteGuardConfig>(() => {\r\n if (config) return config;\r\n return {\r\n useCurrentUser: useCurrentUser!,\r\n pagePermissions: pagePermissions!,\r\n deniedPath: deniedPath ?? \"/access-denied\",\r\n };\r\n }, [config, useCurrentUser, pagePermissions, deniedPath]);\r\n\r\n if (!resolved.useCurrentUser || !resolved.pagePermissions) {\r\n throw new Error(\r\n \"RouteGuardProvider requires either a `config` prop (from createRouteGuardConfig) \" +\r\n \"or `useCurrentUser` + `pagePermissions` directly.\"\r\n );\r\n }\r\n\r\n return (\r\n <RouteGuardContext.Provider value={resolved}>\r\n <AutoRouteGuard config={resolved}>{children}</AutoRouteGuard>\r\n </RouteGuardContext.Provider>\r\n );\r\n}\r\n\r\nfunction AutoRouteGuard({\r\n config,\r\n children,\r\n}: {\r\n config: RouteGuardConfig;\r\n children: ReactNode;\r\n}) {\r\n const pathname = usePathname();\r\n const { data: user, isLoading } = config.useCurrentUser();\r\n\r\n const allowedRoles = useMemo(\r\n () => findAllowedRoles(pathname, config.pagePermissions),\r\n [pathname, config.pagePermissions]\r\n );\r\n\r\n if (!allowedRoles) {\r\n return <>{children}</>;\r\n }\r\n\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-screen\">\r\n <p className=\"text-gray-500\">Chargement...</p>\r\n </div>\r\n );\r\n }\r\n\r\n if (!user || !allowedRoles.includes(user.role.name)) {\r\n redirect(config.deniedPath);\r\n }\r\n\r\n return <>{children}</>;\r\n}\r\n\r\nexport function routeGuard(page: string, Component: ComponentType) {\r\n return function GuardedPage(props: Record<string, unknown>) {\r\n const config = useContext(RouteGuardContext);\r\n\r\n if (!config) {\r\n throw new Error(\r\n \"routeGuard requires a RouteGuardProvider ancestor. \" +\r\n \"Wrap your layout with <RouteGuardProvider>.\"\r\n );\r\n }\r\n\r\n const { data: user, isLoading } = config.useCurrentUser();\r\n const allowedRoles = findAllowedRoles(page, config.pagePermissions);\r\n\r\n if (!allowedRoles) {\r\n return <Component {...props} />;\r\n }\r\n\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-screen\">\r\n <p className=\"text-gray-500\">Chargement...</p>\r\n </div>\r\n );\r\n }\r\n\r\n if (!user || !allowedRoles.includes(user.role.name)) {\r\n redirect(config.deniedPath);\r\n }\r\n\r\n return <Component {...props} />;\r\n };\r\n}\r\n\r\nfunction findAllowedRoles(\r\n page: string,\r\n pagePermissions: Record<string, string[]>\r\n): string[] | undefined {\r\n const segments = page.split(\"/\").filter(Boolean);\r\n\r\n for (let i = 0; i <= segments.length; i++) {\r\n const candidate = \"/\" + segments.slice(0, i).join(\"/\");\r\n const roles = pagePermissions[candidate];\r\n if (roles) return roles;\r\n }\r\n\r\n return undefined;\r\n}\r\n"],"mappings":"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","names":["useState","useEffect","useEffect","jsx","jsxs","jsx","jsxs","useState","useEffect","jsx","useState","useCallback","X","useState","jsx","jsxs","jsx","jsxs","useState","useCallback","useState","useRef","useEffect","jsx","jsxs","jsx","jsxs","useState","useEffect","useRef","useCallback","X","Fragment","jsx","jsxs","jsx","React","jsx","jsxs","React","useState","jsx","jsxs","React","jsx","React","jsx","React","jsx","React","jsx","jsxs","jsx","jsxs","Fragment","jsx","jsxs","useEffect","useState","jsx","jsxs","jsx","jsxs","useMemo","Fragment","jsx"]}
|