'use client'; import { CorrespondenceList } from '@/components/correspondences/list'; import { Pagination } from '@/components/common/pagination'; import { useCorrespondences } from '@/hooks/use-correspondence'; import { useSearchParams, useRouter, usePathname } from 'next/navigation'; import { Loader2, Search, X, Download } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import Link from 'next/link'; import { useCallback, useState } from 'react'; import apiClient from '@/lib/api/client'; const STATUS_FILTERS = [ { value: '', label: 'All Statuses' }, { value: 'DRAFT', label: 'Draft' }, { value: 'IN_REVIEW', label: 'In Review' }, { value: 'APPROVED', label: 'Approved' }, { value: 'CANCELLED', label: 'Cancelled' }, ]; export function CorrespondencesContent() { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); const page = Number(searchParams.get('page') || '1'); const statusFilter = searchParams.get('status') || ''; const search = searchParams.get('search') || undefined; const revisionStatus = (searchParams.get('revisionStatus') as 'CURRENT' | 'ALL' | 'OLD') || 'CURRENT'; const [searchInput, setSearchInput] = useState(search || ''); const [exporting, setExporting] = useState(false); const handleExportCsv = async () => { setExporting(true); try { const params: Record = {}; if (search) params.search = search; if (statusFilter) params.status = statusFilter; if (revisionStatus) params.revisionStatus = revisionStatus; const response = await apiClient.get('/correspondences/export-csv', { params, responseType: 'blob', }); const url = URL.createObjectURL(new Blob([response.data], { type: 'text/csv' })); const a = document.createElement('a'); a.href = url; a.download = `correspondences-${new Date().toISOString().split('T')[0]}.csv`; a.click(); URL.revokeObjectURL(url); } finally { setExporting(false); } }; const { data, isLoading, isError } = useCorrespondences({ page, search, status: statusFilter || undefined, revisionStatus, }); const buildUrl = useCallback((updates: Record) => { const params = new URLSearchParams(searchParams.toString()); Object.entries(updates).forEach(([k, v]) => { if (v) params.set(k, v); else params.delete(k); }); params.set('page', '1'); return `${pathname}?${params.toString()}`; }, [searchParams, pathname]); const handleSearch = () => { router.push(buildUrl({ search: searchInput })); }; const handleClearSearch = () => { setSearchInput(''); router.push(buildUrl({ search: '' })); }; if (isLoading) { return (
); } if (isError) { return
Failed to load correspondences.
; } return ( <> {/* Filters bar */}
{/* Search */}
setSearchInput(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} placeholder="Search by number or subject..." className="pl-8 pr-8 h-9 text-sm" /> {searchInput && ( )}
{/* Status filter */}
{STATUS_FILTERS.map(({ value, label }) => ( ))}
{/* Revision filter */}
{(['CURRENT', 'ALL', 'OLD'] as const).map((rs) => ( ))}
{/* Export */}
); }