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' }}>
<Typography variant="h5" sx={{ mb: 1 }}>User Management</Typography> <CardContent>
<Typography variant="h6" color="text.secondary" sx={{ mb: 2, fontWeight: 400 }}>Coming Soon</Typography> <PeopleIcon sx={{ fontSize: 48, color: '#94A3B8', mb: 2 }} />
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}> <Typography variant="h5" sx={{ mb: 1 }}>User Management</Typography>
Users and roles are currently managed in Cognito. Contact the system administrator to update access. <Typography variant="body1" color="text.secondary" sx={{ mb: 3 }}>
</Typography> Users and roles are currently managed in AWS Cognito. Contact the system administrator to update access.
</Box> </Typography>
<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 && (