import type { Metadata } from 'next'; import Link from 'next/link'; import { Boxes, Euro, ImageOff, Layers, PackageSearch } from 'lucide-react'; import { CollectionFilters } from '@/components/sammlung/collection-filters'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent } from '@/components/ui/card'; import { formatDate, formatNumber, pluralize } from '@/lib/format'; import { setImageSrc } from '@/lib/images'; import { completenessLabel, statusLabel } from '@/lib/labels'; import { formatEuro } from '@/lib/money'; import { countMissingSets, countOpenMissingParts, getCollectionStats, listCollectionItems, type CollectionFilters as Filters, } from '@/lib/queries/collection'; import { listLocations, listManufacturers } from '@/lib/queries/master-data'; import { requireUser } from '@/lib/session'; import type { CollectionStatus, Completeness } from '@/db/types'; export const metadata: Metadata = { title: 'Sammlung' }; type SearchParams = Promise>; function single(value: string | string[] | undefined): string | undefined { const raw = Array.isArray(value) ? value[0] : value; return raw && raw.length > 0 ? raw : undefined; } export default async function SammlungPage({ searchParams }: { searchParams: SearchParams }) { await requireUser(); const params = await searchParams; const filters: Filters = { q: single(params.q), status: single(params.status) as CollectionStatus | undefined, completeness: single(params.zustand) as Completeness | undefined, locationId: single(params.standort), manufacturerId: single(params.hersteller), }; const items = listCollectionItems(filters); const openParts = countOpenMissingParts(items.map((item) => item.id)); const stats = getCollectionStats(); const missing = countMissingSets(); const tiles = [ { icon: Boxes, label: 'Sets', value: formatNumber(stats.setCount) }, { icon: Layers, label: 'Teile gesamt', value: formatNumber(stats.pieceCount) }, { icon: Euro, label: 'Wert nach UVP', value: formatEuro(stats.retailValueCents) }, { icon: PackageSearch, label: 'Fehlt noch', value: formatNumber(missing) }, ] as const; return (

Sammlung

Alles, was tatsächlich da ist.

{tiles.map((tile) => (

{tile.value}

{tile.label}

))}
{stats.byManufacturer.length > 0 ? (
{stats.byManufacturer.map((row) => ( {row.name}: {formatNumber(row.count)} ))}
) : null} ({ id: row.id, name: row.name }))} manufacturers={listManufacturers().map((row) => ({ id: row.id, name: row.name }))} />

{pluralize(items.length, 'Eintrag', 'Einträge')}

{items.length === 0 ? (

Hier ist noch nichts. Sets kommen über den Katalog in die Sammlung.

Zum Katalog
) : (
    {items.map((item) => { const image = setImageSrc(item); return (
  • {image ? ( // eslint-disable-next-line @next/next/no-img-element ) : (
    )}

    {item.setName}

    {[item.setNumber, item.manufacturerName, item.locationName] .filter(Boolean) .join(' · ')}

    {statusLabel(item.status)} {item.completeness !== 'unknown' ? ( {completenessLabel(item.completeness)} ) : null} {openParts.get(item.id) ? ( {openParts.get(item.id)} Fehlteile ) : null} {item.acquiredAt ? ( seit {formatDate(item.acquiredAt)} ) : null}
  • ); })}
)}
); }