diff --git a/gerbil-manager-web/src/pages/WuerfeListPage.tsx b/gerbil-manager-web/src/pages/WuerfeListPage.tsx index 833457a..fe9a696 100644 --- a/gerbil-manager-web/src/pages/WuerfeListPage.tsx +++ b/gerbil-manager-web/src/pages/WuerfeListPage.tsx @@ -1,10 +1,152 @@ +import { useMemo, useState } from 'react' +import { Link } from 'react-router-dom' import { de } from '../strings/de' +import { listLitters } from '../api/litters' +import { listGerbils } from '../api/gerbils' +import { andFilter, condition, type GridifyQuery } from '../api/gridify' +import { useApi } from '../hooks/useApi' +import { formatDate } from '../format/labels' + +const PAGE_SIZE = 20 + +type SortKey = 'dateDesc' | 'dateAsc' +const SORT_ORDER_BY: Record = { + dateDesc: 'date desc', + dateAsc: 'date', +} + +/** Years offered in the filter: current year back through 15 years. */ +function yearOptions(): number[] { + const current = new Date().getFullYear() + return Array.from({ length: 16 }, (_, i) => current - i) +} export default function WuerfeListPage() { - // Fleshed out in the next FEAT-3 increment (Gridify list, year filter, sort). + const t = de.pages.litters + const [year, setYear] = useState('') + const [sort, setSort] = useState('dateDesc') + const [page, setPage] = useState(1) + + // Resolve parent names for the list rows. + const gerbils = useApi(() => listGerbils({ page: 1, pageSize: 1000, orderBy: 'name' }), []) + const nameById = useMemo(() => { + const map = new Map() + for (const g of gerbils.data?.items ?? []) map.set(g.id, g.name) + return map + }, [gerbils.data]) + + const filter = andFilter( + year && condition({ field: 'date', op: '>=', value: `${year}-01-01` }), + year && condition({ field: 'date', op: '<=', value: `${year}-12-31` }), + ) + const orderBy = SORT_ORDER_BY[sort] + const query: GridifyQuery = { filter: filter || undefined, orderBy, page, pageSize: PAGE_SIZE } + const litters = useApi(() => listLitters(query), [filter, orderBy, page]) + + const total = litters.data?.totalCount ?? 0 + const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE)) + const items = litters.data?.items ?? [] + const parentName = (id: string | null) => (id ? (nameById.get(id) ?? t.detail.unknownParent) : '—') + return (
-

{de.pages.litters.title}

+
+
+

{t.title}

+ {litters.data && ( +

+ {total} {t.countLabel} +

+ )} +
+ + + {t.newButton} + +
+ +
+ + +
+ + {litters.loading &&

{de.common.loading}

} + {litters.error && ( +
+ {litters.error} + +
+ )} + + {!litters.loading && !litters.error && items.length === 0 && ( +

{t.empty}

+ )} + + {items.length > 0 && ( +
    + {items.map((l) => ( +
  • + + {l.name} + {formatDate(l.date)} + + {parentName(l.fatherId)} × {parentName(l.motherId)} + + + {l.totalBorn != null ? `${l.totalBorn} ${t.fields.totalBorn}` : '—'} + + +
  • + ))} +
+ )} + + {totalPages > 1 && ( + + )}
) }