2026-08-10 18:00:51 -04:00
|
|
|
import {
|
|
|
|
|
AppBar,
|
|
|
|
|
Box,
|
|
|
|
|
Drawer,
|
2026-08-10 18:22:22 -04:00
|
|
|
FormControl,
|
|
|
|
|
InputLabel,
|
2026-08-10 18:00:51 -04:00
|
|
|
List,
|
|
|
|
|
ListItemButton,
|
|
|
|
|
ListItemText,
|
2026-08-10 18:22:22 -04:00
|
|
|
MenuItem,
|
|
|
|
|
Select,
|
2026-08-10 18:00:51 -04:00
|
|
|
Toolbar,
|
|
|
|
|
Typography,
|
|
|
|
|
} from "@mui/material";
|
|
|
|
|
import type { ReactNode } from "react";
|
|
|
|
|
import { useLocation } from "react-router";
|
|
|
|
|
import { useNavigate, type Path } from "@/router";
|
2026-08-10 18:22:22 -04:00
|
|
|
import { getMockUsers } from "@/mocks";
|
|
|
|
|
import { useMockSession } from "@/providers/use-mock-session";
|
2026-08-10 18:00:51 -04:00
|
|
|
|
|
|
|
|
const DRAWER_WIDTH = 240;
|
|
|
|
|
|
|
|
|
|
type NavItem = {
|
|
|
|
|
label: string;
|
|
|
|
|
to: Path;
|
|
|
|
|
testId: string;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const navItems: NavItem[] = [
|
|
|
|
|
{ label: "Dashboard", to: "/", testId: "nav-dashboard" },
|
|
|
|
|
{ label: "Approvals", to: "/approvals", testId: "nav-approvals" },
|
|
|
|
|
{ label: "Settings", to: "/settings", testId: "nav-settings" },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
type AppShellProps = {
|
|
|
|
|
children: ReactNode;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export function AppShell({ children }: AppShellProps) {
|
|
|
|
|
const location = useLocation();
|
|
|
|
|
const navigate = useNavigate();
|
2026-08-10 18:22:22 -04:00
|
|
|
const { user, setCurrentUserId } = useMockSession();
|
|
|
|
|
const users = getMockUsers();
|
2026-08-10 18:00:51 -04:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Box sx={{ display: "flex", minHeight: "100vh" }}>
|
|
|
|
|
<AppBar
|
|
|
|
|
position="fixed"
|
|
|
|
|
elevation={0}
|
|
|
|
|
sx={{
|
|
|
|
|
zIndex: (theme) => theme.zIndex.drawer + 1,
|
|
|
|
|
borderBottom: 1,
|
|
|
|
|
borderColor: "divider",
|
|
|
|
|
bgcolor: "background.paper",
|
|
|
|
|
color: "text.primary",
|
|
|
|
|
}}
|
|
|
|
|
>
|
2026-08-10 18:22:22 -04:00
|
|
|
<Toolbar sx={{ gap: 2 }}>
|
|
|
|
|
<Typography variant="h6" sx={{ fontFamily: "inherit", fontWeight: 600, flexGrow: 1 }}>
|
2026-08-10 18:00:51 -04:00
|
|
|
Sea Haven AP
|
|
|
|
|
</Typography>
|
2026-08-10 18:22:22 -04:00
|
|
|
<FormControl size="small" sx={{ minWidth: 260 }}>
|
|
|
|
|
<InputLabel id="mock-user-label">Mock user</InputLabel>
|
|
|
|
|
<Select
|
|
|
|
|
labelId="mock-user-label"
|
|
|
|
|
label="Mock user"
|
|
|
|
|
value={user.id}
|
|
|
|
|
data-testid="mock-user-switcher"
|
|
|
|
|
onChange={(event) => setCurrentUserId(String(event.target.value))}
|
|
|
|
|
>
|
|
|
|
|
{users.map((option) => (
|
|
|
|
|
<MenuItem key={option.id} value={option.id}>
|
|
|
|
|
{option.name} ({option.role})
|
|
|
|
|
</MenuItem>
|
|
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormControl>
|
2026-08-10 18:00:51 -04:00
|
|
|
</Toolbar>
|
|
|
|
|
</AppBar>
|
|
|
|
|
|
|
|
|
|
<Drawer
|
|
|
|
|
variant="permanent"
|
|
|
|
|
sx={{
|
|
|
|
|
width: DRAWER_WIDTH,
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
[`& .MuiDrawer-paper`]: {
|
|
|
|
|
width: DRAWER_WIDTH,
|
|
|
|
|
boxSizing: "border-box",
|
|
|
|
|
borderRight: 1,
|
|
|
|
|
borderColor: "divider",
|
|
|
|
|
},
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Toolbar />
|
|
|
|
|
<Box sx={{ overflow: "auto", py: 1 }}>
|
|
|
|
|
<List dense>
|
|
|
|
|
{navItems.map((item) => {
|
|
|
|
|
const selected =
|
|
|
|
|
item.to === "/"
|
|
|
|
|
? location.pathname === "/"
|
|
|
|
|
: location.pathname === item.to || location.pathname.startsWith(`${item.to}/`);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<ListItemButton
|
|
|
|
|
key={item.to}
|
|
|
|
|
selected={selected}
|
|
|
|
|
data-testid={item.testId}
|
|
|
|
|
onClick={() => navigate(item.to)}
|
|
|
|
|
>
|
|
|
|
|
<ListItemText primary={item.label} />
|
|
|
|
|
</ListItemButton>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</List>
|
|
|
|
|
</Box>
|
|
|
|
|
</Drawer>
|
|
|
|
|
|
|
|
|
|
<Box
|
|
|
|
|
component="main"
|
|
|
|
|
sx={{
|
|
|
|
|
flexGrow: 1,
|
|
|
|
|
width: `calc(100% - ${DRAWER_WIDTH}px)`,
|
|
|
|
|
bgcolor: "background.default",
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Toolbar />
|
|
|
|
|
{children}
|
|
|
|
|
</Box>
|
|
|
|
|
</Box>
|
|
|
|
|
);
|
|
|
|
|
}
|