import type { ListParams } from '@/types' export const PER_PAGE_OPTIONS = [10, 20, 50] as const export const DEFAULT_PER_PAGE = 20 export function parseListParams(searchParams: URLSearchParams): ListParams { const search = searchParams.get('search') || '' const perPage = Math.min( Math.max(parseInt(searchParams.get('perPage') || String(DEFAULT_PER_PAGE), 10), 1), 100, ) const page = Math.max(parseInt(searchParams.get('page') || '1', 10), 1) const sort = searchParams.get('sort') || undefined const order = (searchParams.get('order') === 'asc' ? 'asc' : 'desc') as 'asc' | 'desc' return { search, perPage, page, sort, order } } export function calcPagination(total: number, page: number, perPage: number) { const lastPage = Math.max(Math.ceil(total / perPage), 1) return { total, page: Math.min(page, lastPage), perPage, lastPage, offset: (Math.min(page, lastPage) - 1) * perPage, } } /** Generate CSV content from rows */ export function generateCsv( rows: Record[], columns: { key: string; label: string }[], ): string { const BOM = '\uFEFF' const header = columns.map((c) => escapeCsv(c.label)).join(',') const body = rows .map((row) => columns.map((c) => escapeCsv(String(row[c.key] ?? ''))).join(',')) .join('\n') return `${BOM + header}\n${body}` } function escapeCsv(value: string): string { if (value.includes(',') || value.includes('"') || value.includes('\n')) { return `"${value.replace(/"/g, '""')}"` } return value } export function formatTimestamp(ts: number): string { if (!ts) return 'N/A' return new Date(ts * 1000).toLocaleString() }