pages: users empty state card, form max-width, table display improvements

This commit is contained in:
Adam Moussa 2026-05-22 18:54:54 -04:00
parent cfee6690c0
commit 0c8ab31282
3 changed files with 37 additions and 15 deletions

View file

@ -1,5 +1,9 @@
import { Routes, Route, Navigate } from 'react-router-dom'; import { Routes, Route, Navigate } from 'react-router-dom';
import { Box, Toolbar, Typography } from '@mui/material'; import { useSelector } from 'react-redux';
import { Box, Button, Card, CardContent, Toolbar, Typography } from '@mui/material';
import PeopleIcon from '@mui/icons-material/People';
import { selectSidebarOpen } from './app/slices/uiSlice';
import type { RootState } from './app/store';
import ProtectedRoute, { RoleGuard } from './components/ProtectedRoute'; import ProtectedRoute, { RoleGuard } from './components/ProtectedRoute';
import Topbar from './components/Topbar'; import Topbar from './components/Topbar';
import Sidebar from './components/Sidebar'; import Sidebar from './components/Sidebar';
@ -11,7 +15,11 @@ import ProposalDetailPage from './pages/proposals/detail/ProposalDetailPage';
import ProposalListPage from './pages/proposals/list/ProposalListPage'; import ProposalListPage from './pages/proposals/list/ProposalListPage';
import AdminDashboard from './pages/admin/dashboard/AdminDashboard'; import AdminDashboard from './pages/admin/dashboard/AdminDashboard';
import AdminWorkspace from './pages/admin/workspace/AdminWorkspace'; import AdminWorkspace from './pages/admin/workspace/AdminWorkspace';
import { DRAWER_WIDTH } from './constants';
export default function App() { export default function App() {
const sidebarOpen = useSelector((state: RootState) => selectSidebarOpen(state));
return ( return (
<Routes> <Routes>
<Route path="/login" element={<LoginPage />} /> <Route path="/login" element={<LoginPage />} />
@ -29,6 +37,8 @@ export default function App() {
sx={{ sx={{
flexGrow: 1, flexGrow: 1,
p: 1.25, p: 1.25,
ml: sidebarOpen ? `${DRAWER_WIDTH}px` : 0,
transition: 'margin-left 250ms ease',
minHeight: '100vh', minHeight: '100vh',
}} }}
> >
@ -46,13 +56,18 @@ export default function App() {
<Route path="/admin/users" element={ <Route path="/admin/users" element={
<RoleGuard roles={['SysAdmin']}> <RoleGuard roles={['SysAdmin']}>
<Box sx={{ display: 'flex', justifyContent: 'center', pt: 6 }}> <Box sx={{ display: 'flex', justifyContent: 'center', pt: 6 }}>
<Box sx={{ textAlign: 'center', maxWidth: 400 }}> <Card sx={{ maxWidth: 520, p: 4, textAlign: 'center' }}>
<CardContent>
<PeopleIcon sx={{ fontSize: 48, color: '#94A3B8', mb: 2 }} />
<Typography variant="h5" sx={{ mb: 1 }}>User Management</Typography> <Typography variant="h5" sx={{ mb: 1 }}>User Management</Typography>
<Typography variant="h6" color="text.secondary" sx={{ mb: 2, fontWeight: 400 }}>Coming Soon</Typography> <Typography variant="body1" color="text.secondary" sx={{ mb: 3 }}>
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}> Users and roles are currently managed in AWS Cognito. Contact the system administrator to update access.
Users and roles are currently managed in Cognito. Contact the system administrator to update access.
</Typography> </Typography>
</Box> <Button variant="outlined" size="large">
View Access Roles
</Button>
</CardContent>
</Card>
</Box> </Box>
</RoleGuard> </RoleGuard>
} /> } />

View file

@ -147,7 +147,7 @@ export default function ProposalFormPage() {
}, [form.workOrderNumber, form.customerAddress, form.serviceCategory, form.scopeOfWork, customCategory]); }, [form.workOrderNumber, form.customerAddress, form.serviceCategory, form.scopeOfWork, customCategory]);
return ( return (
<Box> <Box sx={{ maxWidth: 1200 }}>
<Typography variant="h5" sx={{ mb: 3 }}> <Typography variant="h5" sx={{ mb: 3 }}>
New Proposal Request New Proposal Request
</Typography> </Typography>

View file

@ -21,8 +21,8 @@ import SearchIcon from '@mui/icons-material/Search';
import AddCircleIcon from '@mui/icons-material/AddCircle'; import AddCircleIcon from '@mui/icons-material/AddCircle';
import { usePaginatedList } from '../../../hooks/usePaginatedList'; import { usePaginatedList } from '../../../hooks/usePaginatedList';
import { proposalsApi, type ProposalListItem } from '../../../lib/api/proposals'; import { proposalsApi, type ProposalListItem } from '../../../lib/api/proposals';
import { STATUS_CHIP_STYLES } from '../../../constants'; import { STATUS_COLORS } from '../../../constants';
import { formatCurrency, formatDate } from '../../../lib/format'; import { formatBidAmount, formatDate, formatDateFull } from '../../../lib/format';
import { useDocumentTitle } from '../../../hooks/useDocumentTitle'; import { useDocumentTitle } from '../../../hooks/useDocumentTitle';
export default function ProposalListPage() { export default function ProposalListPage() {
@ -112,7 +112,7 @@ export default function ProposalListPage() {
sx={{ cursor: 'pointer' }} sx={{ cursor: 'pointer' }}
onClick={() => navigate(`/proposals/${row.id}`)} onClick={() => navigate(`/proposals/${row.id}`)}
> >
<TableCell sx={{ fontWeight: 600 }}>{row.proposalNumber}</TableCell> <TableCell sx={{ fontWeight: 700 }}>{row.proposalNumber}</TableCell>
<TableCell>{row.customerName}</TableCell> <TableCell>{row.customerName}</TableCell>
<TableCell>{row.workOrderNumber}</TableCell> <TableCell>{row.workOrderNumber}</TableCell>
<TableCell>{row.serviceCategory}</TableCell> <TableCell>{row.serviceCategory}</TableCell>
@ -121,11 +121,18 @@ export default function ProposalListPage() {
<Chip <Chip
label={row.status} label={row.status}
size="small" size="small"
sx={STATUS_CHIP_STYLES[row.status]} color={STATUS_COLORS[row.status] || 'default'}
/> />
</TableCell> </TableCell>
<TableCell align="right">{formatCurrency(row.totalBidAmount)}</TableCell> <TableCell align="right">
<TableCell>{formatDate(row.submittedAt)}</TableCell> {row.totalBidAmount > 0
? formatBidAmount(row.totalBidAmount)
: <Typography variant="body2" component="span" sx={{ color: '#64748B' }}>Not priced</Typography>
}
</TableCell>
<TableCell>
<span title={formatDateFull(row.submittedAt)}>{formatDate(row.submittedAt)}</span>
</TableCell>
</TableRow> </TableRow>
))} ))}
{!loading && rows.length === 0 && ( {!loading && rows.length === 0 && (