import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useQuery } from '@tanstack/react-query'; import { Box, Typography, Card, CardContent, Grid, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TablePagination, Chip, TextField, InputAdornment, MenuItem, Skeleton, } from '@mui/material'; import SearchIcon from '@mui/icons-material/Search'; import PendingActionsIcon from '@mui/icons-material/PendingActions'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import TimerIcon from '@mui/icons-material/Timer'; import DescriptionIcon from '@mui/icons-material/Description'; import { usePaginatedList } from '../../../hooks/usePaginatedList'; import { proposalsApi, type ProposalListItem } from '../../../lib/api/proposals'; import { adminApi, type DashboardStats } from '../../../lib/api/admin'; import { QUERY_KEYS } from '../../../constants/queryKeys'; import { SERVICE_CATEGORIES, PRIORITIES, PROPOSAL_STATUSES, STATUS_CHIP_STYLES, PRIORITY_CHIP_STYLES } from '../../../constants'; import { formatCurrency, formatDate } from '../../../lib/format'; import { useDocumentTitle } from '../../../hooks/useDocumentTitle'; function StatCard({ icon, label, value, color }: { icon: React.ReactNode; label: string; value: string; color: string }) { return ( {icon} {label} {value} ); } export default function AdminDashboard({ defaultStatus }: { defaultStatus?: string }) { useDocumentTitle(defaultStatus ? 'Admin Queue' : 'Admin Dashboard'); const navigate = useNavigate(); const { data: stats, isLoading: statsLoading } = useQuery({ queryKey: [QUERY_KEYS.dashboard], queryFn: adminApi.getDashboard, }); const [statusFilter, setStatusFilter] = useState(defaultStatus ?? ''); const [categoryFilter, setCategoryFilter] = useState(''); const [priorityFilter, setPriorityFilter] = useState(''); const { rows, search, setSearch, page, setPage, pageSize, setPageSize, totalCount, loading, err, } = usePaginatedList(proposalsApi.getAll, { ...(statusFilter && { status: statusFilter }), ...(categoryFilter && { serviceCategory: categoryFilter }), ...(priorityFilter && { priority: priorityFilter }), }); return ( Admin Dashboard {statsLoading ? ( ) : ( } label="Pending Review" value={String(stats?.pendingCount ?? 0)} color="#1565c0" /> )} {statsLoading ? ( ) : ( } label="Approved This Week" value={String(stats?.approvedThisWeek ?? 0)} color="#2e7d32" /> )} {statsLoading ? ( ) : ( } label="Avg Turnaround" value={stats ? `${Math.round(stats.avgTurnaroundHours)}h` : '-'} color="#f57c00" /> )} {statsLoading ? ( ) : ( } label="Total Proposals" value={String(stats?.totalProposals ?? 0)} color="#5e35b1" /> )} setSearch(e.target.value)} sx={{ width: 240 }} slotProps={{ input: { startAdornment: ( ), }, }} /> setCategoryFilter(e.target.value)} > All {SERVICE_CATEGORIES.map((c) => ( {c} ))} setPriorityFilter(e.target.value)} > All {PRIORITIES.map((p) => ( {p} ))} setStatusFilter(e.target.value)} > All {PROPOSAL_STATUSES.map((s) => ( {s} ))} {err && ( {err} )} Proposal # Customer WO # Category Priority Status Bid Amount Submitted Submitted By {loading ? Array.from({ length: 5 }).map((_, i) => ( {Array.from({ length: 9 }).map((_, j) => ( ))} )) : rows.map((row) => ( navigate(`/admin/proposals/${row.id}`)} > {row.proposalNumber} {row.customerName} {row.workOrderNumber} {row.serviceCategory} {formatCurrency(row.totalBidAmount)} {formatDate(row.submittedAt)} {row.submittedByName || '-'} ))} {!loading && rows.length === 0 && ( No proposals in queue )}
setPage(newPage + 1)} rowsPerPage={pageSize} onRowsPerPageChange={(e) => setPageSize(parseInt(e.target.value, 10))} rowsPerPageOptions={[12, 24, 48]} />
); }