import { useNavigate } from 'react-router-dom';
import {
Box,
Typography,
Card,
CardContent,
Grid,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Chip,
Button,
Skeleton,
Alert,
} 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 ErrorOutlineIcon from '@mui/icons-material/ErrorOutlined';
import Tooltip from '@mui/material/Tooltip';
import { useProposals, useProposalStats } from '../../domain/proposals/use-cases';
import { STATUS_CHIP_STYLES } from '../../constants';
import { formatCurrency, formatDate, formatDateFull } from '../../lib/format';
import { useDocumentTitle } from '../../hooks/useDocumentTitle';
function KpiCard({
icon,
label,
value,
subtitle,
}: {
icon: React.ReactNode;
label: string;
value: string;
subtitle?: string;
}) {
return (
{icon}
{label}
{value}
{subtitle && (
{subtitle}
)}
);
}
export default function Dashboard() {
useDocumentTitle('Dashboard');
const navigate = useNavigate();
const {
data: recentData,
isLoading: recentLoading,
isError: recentError,
} = useProposals({ page: 1, pageSize: 5, mine: true });
// Fix: WEB-M8 — capture error state for stats to show error instead of misleading zeros
const {
data: stats,
isLoading: statsLoading,
isError: statsError,
refetch: refetchStats,
} = useProposalStats();
const proposals = recentData?.items ?? [];
const total = stats?.totalCount ?? 0;
const counts = {
inReview: stats?.inReviewCount ?? 0,
approved: stats?.approvedCount ?? 0,
sent: stats?.sentCount ?? 0,
};
return (
Dashboard
}
onClick={() => navigate('/proposals/new')}
>
New Proposal
{/* Fix: WEB-M8 — show error state instead of misleading zeros when stats fetch fails */}
{statsError ? (
}
action={
}
>
Failed to load dashboard statistics. Please try again.
) : (
<>
{statsLoading ? (
) : (
}
label="Total Submitted"
value={String(total)}
subtitle="All time"
/>
)}
{statsLoading ? (
) : (
}
label="In Review"
value={String(counts.inReview)}
subtitle="Awaiting pricing"
/>
)}
{statsLoading ? (
) : (
}
label="Approved"
value={String(counts.approved)}
subtitle="Ready to send"
/>
)}
{statsLoading ? (
) : (
}
label="Sent"
value={String(counts.sent)}
subtitle="Delivered to customer"
/>
)}
>
)}
Recent Proposals
Proposal #
Customer
Category
Status
Bid Amount
Submitted
{recentLoading
? Array.from({ length: 5 }).map((_, i) => (
{Array.from({ length: 6 }).map((_, j) => (
))}
))
: proposals.map((row) => (
navigate(`/proposals/${row.id}`)}
>
{row.proposalNumber}
{row.customerName}
{row.serviceCategory}
{formatCurrency(row.totalBidAmount)}
{formatDate(row.submittedAt)}
))}
{!recentLoading && recentError && (
Failed to load proposals. Please try again.
)}
{!recentLoading && !recentError && proposals.length === 0 && (
No proposals yet. Submit your first one!
)}
);
}