import { Fragment } from "react"; import { clsx } from "clsx"; import type { ReportExplainability } from "./reportBuilderExplainability.js"; interface ReportGroupSummary { key: string; label: string; rowCount: number; startIndex: number; } type ReportResultsPanelProps = { rows: Record[]; totalCount: number; outputColumns: string[]; groups: ReportGroupSummary[]; explainability: ReportExplainability | undefined; groupBy: string; sortBy: string; sortDir: "asc" | "desc"; isLoading: boolean; page: number; pageSize: number; columnLabelMap: Map; exportPending: boolean; onSort: (column: string) => void; onExport: () => void; onPageChange: (page: number) => void; summarizeMissing: (columns: string[], labelMap: Map, limit?: number) => string; }; function formatCellValue(value: unknown): string { if (value === null || value === undefined) return "--"; if (typeof value === "boolean") return value ? "Yes" : "No"; if (typeof value === "string") { if (/^\d{4}-\d{2}-\d{2}T/.test(value)) { return new Date(value).toLocaleDateString("de-DE", { year: "numeric", month: "2-digit", day: "2-digit", }); } return value; } if (typeof value === "number") { return value.toLocaleString("de-DE"); } return String(value); } export function ReportResultsPanel({ rows, totalCount, outputColumns, groups, explainability, groupBy, sortBy, sortDir, isLoading, page, pageSize, columnLabelMap, exportPending, onSort, onExport, onPageChange, summarizeMissing, }: ReportResultsPanelProps) { const totalPages = Math.ceil(totalCount / pageSize); const groupStartByIndex = new Map(groups.map((group) => [group.startIndex, group] as const)); return (
{/* Results Header */}

Results

{!isLoading && ( {totalCount.toLocaleString()} row{totalCount !== 1 ? "s" : ""} )}

{explainability?.entity === "resource_month" ? "Exports include the report sheet plus an Explainability sheet with location, holiday, absence and SAH basis." : "CSV exports include the selected basis columns and computed Nexus metrics exactly as shown here."}

{groupBy && rows.length > 0 ? (

Grouped by {columnLabelMap.get(groupBy) ?? groupBy} with page-local section headers.

) : null}
{explainability?.entity === "resource_month" ? (
Month: {explainability.periodMonth ?? "current"} Location:{" "} {(explainability.locationContextColumns.length > 0 ? explainability.locationContextColumns : ["none"] ) .map((column) => columnLabelMap.get(column) ?? column) .join(", ")} Holidays:{" "} {(explainability.holidayMetricColumns.length > 0 ? explainability.holidayMetricColumns : ["none"] ) .map((column) => columnLabelMap.get(column) ?? column) .join(", ")} Absences:{" "} {(explainability.absenceMetricColumns.length > 0 ? explainability.absenceMetricColumns : ["none"] ) .map((column) => columnLabelMap.get(column) ?? column) .join(", ")} Capacity:{" "} {(explainability.capacityMetricColumns.length > 0 ? explainability.capacityMetricColumns : ["none"] ) .map((column) => columnLabelMap.get(column) ?? column) .join(", ")}

{explainability.notes.join(" ")}

{explainability.missingRecommendedColumns.length > 0 ? (

Missing recommended audit columns:{" "} {summarizeMissing(explainability.missingRecommendedColumns, columnLabelMap)}

) : null}
) : null} {/* Table */}
{isLoading ? (
) : rows.length === 0 ? (
No data found. Try adjusting your filters.
) : ( {outputColumns.map((col) => { const isSortable = !col.includes("."); const isSorted = sortBy === col; return ( ); })} {rows.map((row, idx) => { const group = groupStartByIndex.get(idx); return ( {group ? ( ) : null} {outputColumns.map((col) => ( ))} ); })}
onSort(col) : undefined} className={clsx( "whitespace-nowrap px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400", isSortable && "cursor-pointer select-none hover:text-gray-700 dark:hover:text-gray-200", )} > {columnLabelMap.get(col) ?? col} {isSorted && ( )}
{columnLabelMap.get(groupBy) ?? groupBy}: {group.label} ยท {group.rowCount}{" "} row{group.rowCount === 1 ? "" : "s"}
{formatCellValue(row[col])}
)}
{/* Pagination */} {totalPages > 1 && (
Page {page + 1} of {totalPages}
)}
); }