import { useMemo, useState } from 'react' import { Badge, BulkActionBar, Button, DataTable, DeleteConfirmDialog, FilterBar, FilterBarActions, FilterBarFilters, FilterBarSearch, FilterSelect, PageHeader, ToastContainer, toast, type Column, } from '../../index' interface Order { id: number number: string customer: string status: 'paid' | 'pending' | 'refunded' amount: number } const STATUS_META: Record< Order['status'], { label: string; variant: 'success' | 'warning' | 'secondary' } > = { paid: { label: 'Paid', variant: 'success' }, pending: { label: 'Pending', variant: 'warning' }, refunded: { label: 'Refunded', variant: 'secondary' }, } const INITIAL_ORDERS: Order[] = Array.from({ length: 23 }, (_, i) => ({ id: i + 1, number: `ORD-${2100 + i}`, customer: ['Northwind', 'Acme Corp', 'Globex', 'Initech'][i % 4], status: (['paid', 'pending', 'refunded'] as const)[i % 3], amount: 1200 + i * 340, })) /** * Recipe: a complete CRUD list page. * * Composition: PageHeader → FilterBar (search + status filter) → * DataTable (sortable, selectable, paginated) → BulkActionBar appears on * selection → DeleteConfirmDialog guards the destructive action → toast * confirms the outcome. Search/filter state lives in the page; the * table's sorting and pagination stay uncontrolled (see the server-side * pagination recipe for the controlled variant). */ export function CrudListPage() { const [orders, setOrders] = useState(INITIAL_ORDERS) const [search, setSearch] = useState('') const [status, setStatus] = useState('') const [selected, setSelected] = useState>(new Set()) const [confirmOpen, setConfirmOpen] = useState(false) const filtered = useMemo( () => orders.filter( (o) => (!status || o.status === status) && (!search || o.number.toLowerCase().includes(search.toLowerCase()) || o.customer.toLowerCase().includes(search.toLowerCase())) ), [orders, search, status] ) const columns: Column[] = [ { key: 'number', header: 'Order', sortable: true }, { key: 'customer', header: 'Customer', sortable: true }, { key: 'status', header: 'Status', cell: (o) => ( {STATUS_META[o.status].label} ), }, { key: 'amount', header: 'Amount', align: 'right', sortable: true, cell: (o) => ${o.amount.toLocaleString()}, }, ] const deleteSelected = () => { setOrders((prev) => prev.filter((o) => !selected.has(o.id))) toast.success('Orders deleted', { description: `${selected.size} orders removed.` }) setSelected(new Set()) setConfirmOpen(false) } return (
o.id} selectable selectedRows={selected} onSelectionChange={setSelected} defaultPageSize={10} />
setSelected(new Set())}> setConfirmOpen(false)} onConfirm={deleteSelected} itemName={`${selected.size} orders`} />
) }