diff --git a/src/components/reports/ReportsTablePanel.tsx b/src/components/reports/ReportsTablePanel.tsx index cc1ea52..15ccd9c 100644 --- a/src/components/reports/ReportsTablePanel.tsx +++ b/src/components/reports/ReportsTablePanel.tsx @@ -92,6 +92,9 @@ const formatDisplayDateTime = (value: string, lang: "en" | "fa") => { const percentageMap = (rows?: PercentageRow[]) => new Map((rows || []).map((row) => [row.id, `${formatAmount(row.percentage, "en")}%`])); +const numericPercentageMap = (rows?: PercentageRow[]) => + new Map((rows || []).map((row) => [row.id, Number(row.percentage) || 0])); + function LoadingBlock({ className }: { className: string }) { return
; } @@ -152,14 +155,28 @@ function BreakdownTable({ financialOnly: boolean; }) { const hourPercentageById = useMemo(() => percentageMap(hourPercentages), [hourPercentages]); + const hourPercentageNumberById = useMemo(() => numericPercentageMap(hourPercentages), [hourPercentages]); const incomePercentageById = useMemo(() => percentageMap(incomePercentages), [incomePercentages]); + const sortedRows = useMemo( + () => + [...rows].sort((left, right) => { + const percentageDelta = + (hourPercentageNumberById.get(right.id) || 0) - (hourPercentageNumberById.get(left.id) || 0); + if (percentageDelta !== 0) return percentageDelta; + if (right.billable_seconds !== left.billable_seconds) { + return right.billable_seconds - left.billable_seconds; + } + return left.name.localeCompare(right.name); + }), + [hourPercentageNumberById, rows], + ); return (