"use client"; import React from "react"; import { Eye, FileText, RefreshCw } from "lucide-react"; import { getFiles, getDays, getMonths, getYears, } from "@/lib/frontend/apiClient"; import { dayPath, monthPath, branchPath } from "@/lib/frontend/routes"; import { sortFilesByNameAsc } from "@/lib/frontend/explorer/sorters"; import { mapExplorerError } from "@/lib/frontend/explorer/errorMapping"; import { buildLoginUrl, LOGIN_REASONS } from "@/lib/frontend/authRedirect"; import { useExplorerQuery } from "@/lib/frontend/hooks/useExplorerQuery"; import { buildPdfUrl } from "@/lib/frontend/explorer/pdfUrl"; import ExplorerBreadcrumbs from "@/components/explorer/breadcrumbs/ExplorerBreadcrumbs"; import ExplorerPageShell from "@/components/explorer/ExplorerPageShell"; import ExplorerSectionCard from "@/components/explorer/ExplorerSectionCard"; import ExplorerLoading from "@/components/explorer/states/ExplorerLoading"; import ExplorerEmpty from "@/components/explorer/states/ExplorerEmpty"; import ExplorerError from "@/components/explorer/states/ExplorerError"; import ExplorerNotFound from "@/components/explorer/states/ExplorerNotFound"; import ForbiddenView from "@/components/system/ForbiddenView"; import { Button } from "@/components/ui/button"; import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, TableCaption, } from "@/components/ui/table"; /** * FilesExplorer * * Explorer leaf level: lists files (PDFs) for a day. * Loads years/months/days for breadcrumb dropdowns (fail-open). * * @param {{ branch: string, year: string, month: string, day: string }} props */ export default function FilesExplorer({ branch, year, month, day }) { const filesLoadFn = React.useCallback( () => getFiles(branch, year, month, day), [branch, year, month, day] ); const filesQuery = useExplorerQuery(filesLoadFn, [filesLoadFn]); const yearsLoadFn = React.useCallback(() => getYears(branch), [branch]); const yearsQuery = useExplorerQuery(yearsLoadFn, [yearsLoadFn]); const monthsLoadFn = React.useCallback( () => getMonths(branch, year), [branch, year] ); const monthsQuery = useExplorerQuery(monthsLoadFn, [monthsLoadFn]); const daysLoadFn = React.useCallback( () => getDays(branch, year, month), [branch, year, month] ); const daysQuery = useExplorerQuery(daysLoadFn, [daysLoadFn]); const mapped = React.useMemo( () => mapExplorerError(filesQuery.error), [filesQuery.error] ); React.useEffect(() => { if (mapped?.kind !== "unauthenticated") return; const next = typeof window !== "undefined" ? `${window.location.pathname}${window.location.search}` : dayPath(branch, year, month, day); window.location.replace( buildLoginUrl({ reason: LOGIN_REASONS.EXPIRED, next }) ); }, [mapped?.kind, branch, year, month, day]); const yearOptions = yearsQuery.status === "success" && Array.isArray(yearsQuery.data?.years) ? yearsQuery.data.years : null; const monthOptions = monthsQuery.status === "success" && Array.isArray(monthsQuery.data?.months) ? monthsQuery.data.months : null; const dayOptions = daysQuery.status === "success" && Array.isArray(daysQuery.data?.days) ? daysQuery.data.days : null; const breadcrumbsNode = ( ); const actions = ( ); if (filesQuery.status === "loading") { return ( ); } if (filesQuery.status === "error" && mapped) { if (mapped.kind === "forbidden") return ; if (mapped.kind === "notfound") { return ( ); } if (mapped.kind === "unauthenticated") { return ( ); } return ( ); } const files = Array.isArray(filesQuery.data?.files) ? filesQuery.data.files : []; const sorted = sortFilesByNameAsc(files); return ( {sorted.length} Datei{sorted.length === 1 ? "" : "en"} } > {sorted.length === 0 ? ( ) : ( Hinweis: PDFs werden in einem neuen Tab geöffnet. Datei Pfad Aktion {sorted.map((f) => { const pdfUrl = buildPdfUrl({ branch, year, month, day, filename: f.name, }); return (

{f.name}

{f.relativePath}

{f.relativePath}
); })}
)}
); }