mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-06 10:02:04 +00:00
Workload and Performance page server-side at 10 rows and now return Page, PageSize, and TotalDispatchers on dev (backend#126/#127), so wire the pager that SH-346 and SH-347 require: getWorkload/getPerformance send a 1-based `page` and parse the paging envelope, the hooks and query keys carry the page, and each dispatcher table renders a 10-row pager. Page state is per-table and resets on a range change so switching range never lands on an out-of-range empty page that reads as a false "no dispatchers" state. Drop `docs=No` from the Aveta Pending drilldown. `docs` filters on completion-document status, not the Aveta clearance document the tile counts (SH-294 / backend#138), so it narrowed to the wrong rows. The board has no missing-Aveta-document filter, so the drilldown is now the Aveta-required work in the two-day open window — a deliberate superset of the count.
107 lines
3.1 KiB
TypeScript
107 lines
3.1 KiB
TypeScript
import { useNavigate } from "react-router";
|
|
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
|
|
import { Text } from "@/components/ui/text";
|
|
import type { DashboardRangeKey } from "@/domain/dashboard/types/dashboard-range";
|
|
import type { DispatcherWorkloadRow } from "@/domain/dashboard/types/dashboard-workload";
|
|
import {
|
|
workOrderDispatcherDrilldownSearch,
|
|
workOrderDrilldownUrl,
|
|
} from "@/domain/dashboard/utils/work-order-drilldown-links";
|
|
import { DashboardCard } from "./dashboard-card";
|
|
import { DispatcherTablePager } from "./dispatcher-table-pager";
|
|
|
|
const EMPTY_MESSAGE = "No dispatchers are set up yet.";
|
|
|
|
interface DispatcherWorkloadCardProps {
|
|
rows: DispatcherWorkloadRow[];
|
|
range: DashboardRangeKey;
|
|
page: number;
|
|
pageSize: number;
|
|
totalDispatchers: number;
|
|
onPageChange: (page: number) => void;
|
|
isLoading?: boolean;
|
|
error?: unknown;
|
|
}
|
|
|
|
function DispatcherNameCell({
|
|
row,
|
|
range,
|
|
}: {
|
|
row: DispatcherWorkloadRow;
|
|
range: DashboardRangeKey;
|
|
}) {
|
|
const navigate = useNavigate();
|
|
const drillable = Boolean(row.dispatcherId) && row.totalWorkOrders > 0;
|
|
|
|
if (!drillable) {
|
|
return <Text variant="description">{row.dispatcherName}</Text>;
|
|
}
|
|
|
|
return (
|
|
<Text
|
|
variant="description"
|
|
as="button"
|
|
className="cursor-pointer text-left font-medium underline-offset-2 hover:underline"
|
|
onClick={() =>
|
|
navigate(workOrderDrilldownUrl(workOrderDispatcherDrilldownSearch(row.dispatcherId, range)))
|
|
}
|
|
>
|
|
{row.dispatcherName}
|
|
</Text>
|
|
);
|
|
}
|
|
|
|
export function DispatcherWorkloadCard({
|
|
rows,
|
|
range,
|
|
page,
|
|
pageSize,
|
|
totalDispatchers,
|
|
onPageChange,
|
|
isLoading = false,
|
|
error,
|
|
}: DispatcherWorkloadCardProps) {
|
|
return (
|
|
<DashboardCard
|
|
title="Dispatcher Workload"
|
|
isLoading={isLoading}
|
|
error={error}
|
|
isEmpty={!isLoading && !error && rows.length === 0}
|
|
emptyMessage={EMPTY_MESSAGE}
|
|
>
|
|
<TableContainer>
|
|
<Table size="small" aria-label="Dispatcher Workload">
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell className="font-semibold">Dispatcher</TableCell>
|
|
<TableCell align="right" className="font-semibold">
|
|
Open
|
|
</TableCell>
|
|
<TableCell align="right" className="font-semibold">
|
|
Total
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{rows.map((row) => (
|
|
<TableRow key={row.dispatcherId || row.dispatcherName}>
|
|
<TableCell>
|
|
<DispatcherNameCell row={row} range={range} />
|
|
</TableCell>
|
|
<TableCell align="right">{row.openWorkOrders.toLocaleString()}</TableCell>
|
|
<TableCell align="right">{row.totalWorkOrders.toLocaleString()}</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</TableContainer>
|
|
<DispatcherTablePager
|
|
page={page}
|
|
pageSize={pageSize}
|
|
totalDispatchers={totalDispatchers}
|
|
onPageChange={onPageChange}
|
|
label="Dispatcher Workload pagination"
|
|
/>
|
|
</DashboardCard>
|
|
);
|
|
}
|