import { useNavigate } from 'react-router-dom'; import { useQuery } from '@tanstack/react-query'; import { Box, Typography, Card, CardContent, Grid, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Chip, Button, Skeleton, } from '@mui/material'; import AddCircleIcon from '@mui/icons-material/AddCircle'; import DescriptionIcon from '@mui/icons-material/Description'; import HourglassTopIcon from '@mui/icons-material/HourglassTop'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import SendIcon from '@mui/icons-material/Send'; import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; import WarningAmberIcon from '@mui/icons-material/WarningAmber'; import ReportIcon from '@mui/icons-material/Report'; import { proposalsApi, type ProposalListItem, type ProposalStats } from '../../lib/api/proposals'; import { QUERY_KEYS } from '../../constants/queryKeys'; import { STATUS_COLORS, STATUS_LABELS, PRIORITY_LABELS, PRIORITY_COLORS, PRIORITY_ROW_SX } from '../../constants'; import { formatBidAmount, formatDate } from '../../lib/format'; import { useDocumentTitle } from '../../hooks/useDocumentTitle'; import { useAuth } from '../../hooks/useAuth'; function KpiCard({ icon, label, value, onClick }: { icon: React.ReactNode; label: string; value: string; onClick: () => void }) { return ( {icon} {label} {value} ); } export default function Dashboard() { useDocumentTitle('Dashboard'); const navigate = useNavigate(); const { user } = useAuth(); const isAdmin = user?.role === 'Admin' || user?.role === 'SysAdmin'; const { data: recentData, isLoading: recentLoading, error: recentError } = useQuery<{ items: ProposalListItem[]; totalCount: number }>({ queryKey: [QUERY_KEYS.proposals, 'dashboard-recent', isAdmin], queryFn: () => proposalsApi.getAll({ page: 1, pageSize: 5, mine: !isAdmin }), }); const { data: stats, isLoading: statsLoading } = useQuery({ queryKey: [QUERY_KEYS.proposals, 'stats'], queryFn: () => proposalsApi.getStats(), }); const isLoading = recentLoading || statsLoading; const proposals = recentData?.items ?? []; const total = stats?.totalCount ?? 0; const counts = { inReview: stats?.inReviewCount ?? 0, approved: stats?.approvedCount ?? 0, sent: stats?.sentCount ?? 0, }; const kpiCards = isAdmin ? [ { icon: , label: 'All Proposals', value: String(total), onClick: () => navigate('/admin/proposals') }, { icon: , label: 'Pending Review', value: String(counts.inReview), onClick: () => navigate('/admin') }, { icon: , label: 'Approved', value: String(counts.approved), onClick: () => navigate('/admin/proposals?status=Approved') }, { icon: , label: 'Sent', value: String(counts.sent), onClick: () => navigate('/admin/proposals?status=Sent') }, ] : [ { icon: , label: 'Total Submitted', value: String(total), onClick: () => navigate('/proposals') }, { icon: , label: 'In Review', value: String(counts.inReview), onClick: () => navigate('/proposals?status=InReview') }, { icon: , label: 'Approved', value: String(counts.approved), onClick: () => navigate('/proposals?status=Approved') }, { icon: , label: 'Sent', value: String(counts.sent), onClick: () => navigate('/proposals?status=Sent') }, ]; return ( Dashboard {kpiCards.map((card) => ( {isLoading ? ( ) : ( )} ))} Recent Proposals Proposal # Customer WO # Category Priority Status Bid Amount Submitted {isLoading ? Array.from({ length: 5 }).map((_, i) => ( {Array.from({ length: 8 }).map((_, j) => ( ))} )) : proposals.map((row) => ( navigate(`/proposals/${row.id}`)} > {row.proposalNumber} {row.customerName} {row.workOrderNumber} {row.serviceCategory} : row.priority === 'Urgent' ? : undefined} /> {formatBidAmount(row.totalBidAmount)} {formatDate(row.submittedAt)} ))} {!isLoading && recentError && ( Failed to load proposals. Please try again. )} {!isLoading && !recentError && proposals.length === 0 && ( No proposals yet. Submit your first one! )}
); }