From ef052a81ac71fcc232ca5e542179d5adbccf329c Mon Sep 17 00:00:00 2001 From: Adam Moussa <166072409+amoussa1229@users.noreply.github.com> Date: Fri, 22 May 2026 17:29:26 -0400 Subject: [PATCH] Add role-aware dashboard stats and recent proposals GetStatsAsync now returns global counts for admins/sysadmins instead of filtering by submitter. Dashboard recent proposals query uses mine=false for admins so they see all proposals, not just their own. --- .../Services/ProposalService.cs | 8 +++++--- web/src/pages/dashboard/Dashboard.tsx | 11 +++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/api/src/ProposalSystem.Infrastructure/Services/ProposalService.cs b/api/src/ProposalSystem.Infrastructure/Services/ProposalService.cs index adfed94..9af22d1 100644 --- a/api/src/ProposalSystem.Infrastructure/Services/ProposalService.cs +++ b/api/src/ProposalSystem.Infrastructure/Services/ProposalService.cs @@ -376,10 +376,12 @@ public class ProposalService : IProposalService public async Task GetStatsAsync(CancellationToken ct = default) { - var userId = _currentUser.UserId; + var query = _db.Proposals.AsQueryable(); - var counts = await _db.Proposals - .Where(p => p.SubmittedById == userId) + if (_currentUser.Role == UserRole.Dispatcher) + query = query.Where(p => p.SubmittedById == _currentUser.UserId); + + var counts = await query .GroupBy(_ => 1) .Select(g => new { diff --git a/web/src/pages/dashboard/Dashboard.tsx b/web/src/pages/dashboard/Dashboard.tsx index 00e1d95..7084af9 100644 --- a/web/src/pages/dashboard/Dashboard.tsx +++ b/web/src/pages/dashboard/Dashboard.tsx @@ -24,8 +24,9 @@ import SendIcon from '@mui/icons-material/Send'; import { proposalsApi, type ProposalListItem, type ProposalStats } from '../../lib/api/proposals'; import { QUERY_KEYS } from '../../constants/queryKeys'; import { STATUS_COLORS, STATUS_LABELS, PRIORITY_ROW_SX } from '../../constants'; -import { formatCurrency, formatDate } from '../../lib/format'; +import { formatBidAmount, formatDate } from '../../lib/format'; import { useDocumentTitle } from '../../hooks/useDocumentTitle'; +import { useAuth } from '../../hooks/useAuth'; function KpiCard({ icon, label, value }: { icon: React.ReactNode; label: string; value: string }) { return ( @@ -46,10 +47,12 @@ function KpiCard({ icon, label, value }: { icon: React.ReactNode; label: string; 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'], - queryFn: () => proposalsApi.getAll({ page: 1, pageSize: 5, mine: true }), + queryKey: [QUERY_KEYS.proposals, 'dashboard-recent', isAdmin], + queryFn: () => proposalsApi.getAll({ page: 1, pageSize: 5, mine: !isAdmin }), }); const { data: stats, isLoading: statsLoading } = useQuery({ @@ -153,7 +156,7 @@ export default function Dashboard() { - {formatCurrency(row.totalBidAmount)} + {formatBidAmount(row.totalBidAmount)} {formatDate(row.submittedAt)} ))}