feat(ui): simplify A3 workspace and refresh saved AI availability
This commit is contained in:
@@ -421,17 +421,17 @@ export default function AppShell({
|
||||
>
|
||||
<Toolbar
|
||||
sx={{
|
||||
gap: 1.25,
|
||||
px: { xs: 2, md: 3 },
|
||||
py: { xs: 1.25, md: 0 },
|
||||
minHeight: { xs: 68, md: 76 },
|
||||
alignItems: { xs: "stretch", md: "center" },
|
||||
flexWrap: { xs: "wrap", md: "nowrap" },
|
||||
gap: { xs: 0.5, md: 1.25 },
|
||||
px: { xs: 1.5, md: 3 },
|
||||
py: 0,
|
||||
minHeight: { xs: 56, md: 64 },
|
||||
alignItems: "center",
|
||||
flexWrap: "nowrap",
|
||||
}}
|
||||
>
|
||||
{isMobile ? (
|
||||
<>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 1, width: "100%", minWidth: 0 }}>
|
||||
<Box sx={{ display: "contents" }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1, minWidth: 0 }}>
|
||||
<IconButton
|
||||
edge="start"
|
||||
@@ -442,34 +442,23 @@ export default function AppShell({
|
||||
aria-expanded={drawerOpen}
|
||||
aria-controls={mobileDrawerId}
|
||||
onClick={() => onToggleDrawer(true)}
|
||||
sx={{ border: "1px solid", borderColor: "divider", borderRadius: 2.5, width: 42, height: 42 }}
|
||||
sx={{ width: 44, height: 44 }}
|
||||
>
|
||||
<MenuIcon fontSize="small" />
|
||||
</IconButton>
|
||||
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 0.9, minWidth: 0, pl: 0.25 }}>
|
||||
<JobbjaktMark style={{ width: 18, height: 18, flex: "0 0 auto" }} />
|
||||
<Typography variant="subtitle1" sx={{ fontWeight: 800, letterSpacing: -0.2 }} noWrap>
|
||||
<Typography variant="subtitle1" sx={{ fontWeight: 800, letterSpacing: -0.2, display: "none", "@media (min-width:430px)": { display: "block" } }} noWrap>
|
||||
Jobbjakt
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<StackLanguageToggle language={language} setLanguage={setLanguage} />
|
||||
{user ? (
|
||||
<IconButton
|
||||
size="small"
|
||||
aria-label={t("user")}
|
||||
onClick={(e) => setUserMenuAnchor(e.currentTarget)}
|
||||
sx={{ borderRadius: 2.5, border: "1px solid", borderColor: "divider", width: 42, height: 42, flex: "0 0 auto" }}
|
||||
>
|
||||
<Avatar src={user.avatarImageDataUrl || undefined} sx={{ width: 28, height: 28, fontWeight: 900, bgcolor: "primary.main", color: "primary.contrastText" }}>{initials}</Avatar>
|
||||
</IconButton>
|
||||
) : <Box sx={{ width: 42, height: 42 }} />}
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1, width: "100%" }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1, flex: "0 0 auto" }}>
|
||||
<Box sx={{ display: "contents" }}>
|
||||
<Box sx={{ display: "contents" }}>
|
||||
<IconButton
|
||||
color="secondary"
|
||||
size="small"
|
||||
@@ -477,30 +466,20 @@ export default function AppShell({
|
||||
aria-label={t("notifications")}
|
||||
aria-describedby={notificationCountId}
|
||||
onClick={(event) => onOpenNotifications?.(event.currentTarget)}
|
||||
sx={{ border: "1px solid", borderColor: "divider", borderRadius: 2.5, width: 42, height: 42 }}
|
||||
sx={{ width: 44, height: 44 }}
|
||||
>
|
||||
<Badge color="primary" badgeContent={notificationsCount || 0} max={99} slotProps={{ badge: { "aria-hidden": true } }}>
|
||||
<NotificationsNoneIcon fontSize="small" />
|
||||
</Badge>
|
||||
</IconButton>
|
||||
<IconButton
|
||||
color="secondary"
|
||||
size="small"
|
||||
title={t("settings")}
|
||||
aria-label={t("settings")}
|
||||
onClick={() => runShellRouteAction("/settings", onOpenSettings)}
|
||||
sx={{ border: "1px solid", borderColor: "divider", borderRadius: 2.5, width: 42, height: 42 }}
|
||||
>
|
||||
<SettingsOutlinedIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 1,
|
||||
flex: 1,
|
||||
gap: 0.5,
|
||||
ml: "auto",
|
||||
minWidth: 0,
|
||||
'& > *': { minWidth: 0 },
|
||||
}}
|
||||
@@ -508,17 +487,20 @@ export default function AppShell({
|
||||
{rightActions}
|
||||
</Box>
|
||||
</Box>
|
||||
{user ? <IconButton size="small" aria-label={t("user")} onClick={(event) => setUserMenuAnchor(event.currentTarget)} sx={{ width: 44, height: 44, flex: "0 0 auto" }}>
|
||||
<Avatar src={user.avatarImageDataUrl || undefined} sx={{ width: 28, height: 28, fontWeight: 900, bgcolor: "primary.main", color: "primary.contrastText" }}>{initials}</Avatar>
|
||||
</IconButton> : null}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1, minWidth: 0, flex: 1 }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1, minWidth: 44, flex: "1 0 44px" }}>
|
||||
<IconButton
|
||||
size="small"
|
||||
color="secondary"
|
||||
onClick={() => setDesktopNavCollapsed((value) => !value)}
|
||||
title={desktopNavCollapsed ? t("expandSidebar") : t("collapseSidebar")}
|
||||
aria-label={desktopNavCollapsed ? t("expandSidebar") : t("collapseSidebar")}
|
||||
sx={{ border: "1px solid", borderColor: "divider", borderRadius: 2, width: 40, height: 40 }}
|
||||
sx={{ width: 44, height: 44 }}
|
||||
>
|
||||
<MenuOpenIcon fontSize="small" sx={{ transform: desktopNavCollapsed ? "scaleX(-1)" : "none" }} />
|
||||
</IconButton>
|
||||
@@ -530,13 +512,12 @@ export default function AppShell({
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-end",
|
||||
gap: 1,
|
||||
flexWrap: "wrap",
|
||||
width: { xs: "100%", md: "auto" },
|
||||
flex: { xs: "1 1 100%", md: "0 1 auto" },
|
||||
flexWrap: "nowrap",
|
||||
flex: "0 0 auto",
|
||||
}}
|
||||
>
|
||||
{buildBadge}
|
||||
<StackLanguageToggle language={language} setLanguage={setLanguage} />
|
||||
<Box sx={{ display: "none", "@media (min-width:1280px)": { display: "contents" } }}>{buildBadge}</Box>
|
||||
<Box sx={{ display: "none", "@media (min-width:1024px)": { display: "block" } }}><StackLanguageToggle language={language} setLanguage={setLanguage} /></Box>
|
||||
<IconButton
|
||||
color="secondary"
|
||||
size="small"
|
||||
@@ -544,7 +525,7 @@ export default function AppShell({
|
||||
aria-label={t("notifications")}
|
||||
aria-describedby={notificationCountId}
|
||||
onClick={(event) => onOpenNotifications?.(event.currentTarget)}
|
||||
sx={{ border: "1px solid", borderColor: "divider", borderRadius: 2 }}
|
||||
sx={{ width: 44, height: 44 }}
|
||||
>
|
||||
<Badge color="primary" badgeContent={notificationsCount || 0} max={99} slotProps={{ badge: { "aria-hidden": true } }}>
|
||||
<NotificationsNoneIcon fontSize="small" />
|
||||
@@ -556,7 +537,7 @@ export default function AppShell({
|
||||
title={t("settings")}
|
||||
aria-label={t("settings")}
|
||||
onClick={() => runShellRouteAction("/settings", onOpenSettings)}
|
||||
sx={{ border: "1px solid", borderColor: "divider", borderRadius: 2 }}
|
||||
sx={{ width: 44, height: 44 }}
|
||||
>
|
||||
<SettingsOutlinedIcon fontSize="small" />
|
||||
</IconButton>
|
||||
@@ -571,11 +552,11 @@ export default function AppShell({
|
||||
size="small"
|
||||
aria-label={t("user")}
|
||||
onClick={(e) => setUserMenuAnchor(e.currentTarget)}
|
||||
sx={{ borderRadius: 2, border: "1px solid", borderColor: "divider" }}
|
||||
sx={{ width: 44, height: 44 }}
|
||||
>
|
||||
<Avatar src={user.avatarImageDataUrl || undefined} sx={{ width: 30, height: 30, fontWeight: 900, bgcolor: "primary.main", color: "primary.contrastText" }}>{initials}</Avatar>
|
||||
</IconButton>
|
||||
<Box sx={{ display: { xs: "none", sm: "block" }, minWidth: 0 }}>
|
||||
<Box sx={{ display: "none", "@media (min-width:1280px)": { display: "block" }, minWidth: 0, maxWidth: 180 }}>
|
||||
<Typography sx={{ fontWeight: 600, lineHeight: 1.2 }} noWrap>
|
||||
{user.userName || user.displayName || user.email || t("user")}
|
||||
</Typography>
|
||||
@@ -595,7 +576,7 @@ export default function AppShell({
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
|
||||
transformOrigin={{ vertical: "top", horizontal: "right" }}
|
||||
>
|
||||
{isMobile && buildVersion ? (
|
||||
{buildVersion ? (
|
||||
<ListSubheader disableSticky role="presentation" sx={{ maxWidth: 280, py: 1, lineHeight: 1.5, overflowWrap: "anywhere" }}>
|
||||
<Typography variant="body2">{buildCommit ? t("applicationVersionCommit", { version: buildVersion, commit: buildCommit }) : t("applicationVersion", { version: buildVersion })}</Typography>
|
||||
</ListSubheader>
|
||||
@@ -616,6 +597,9 @@ export default function AppShell({
|
||||
>
|
||||
{t("settingsMenu")}
|
||||
</MenuItem>
|
||||
{(["en", "nb"] as const).map(value => <MenuItem key={value} role="menuitemradio" aria-checked={language === value} onClick={() => { setLanguage(value); setUserMenuAnchor(null); }}>
|
||||
{t(value === "en" ? "languageEnglish" : "languageNorwegianBokmal")}
|
||||
</MenuItem>)}
|
||||
<Divider />
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
@@ -647,7 +631,7 @@ export default function AppShell({
|
||||
}}
|
||||
open
|
||||
>
|
||||
<Box aria-hidden sx={{ height: headerHeight ?? { xs: 68, md: 76 }, flexShrink: 0 }} />
|
||||
<Box aria-hidden sx={{ height: headerHeight ?? { xs: 56, md: 64 }, flexShrink: 0 }} />
|
||||
{drawerContent}
|
||||
</Drawer>
|
||||
|
||||
@@ -687,7 +671,7 @@ export default function AppShell({
|
||||
tabIndex={-1}
|
||||
sx={{
|
||||
flex: 1,
|
||||
"--app-shell-header-height": `${headerHeight ?? (isMobile ? 124 : 76)}px`,
|
||||
"--app-shell-header-height": `${headerHeight ?? (isMobile ? 56 : 64)}px`,
|
||||
p: "var(--app-page-gutter)",
|
||||
// Keep the usual feedback lane stable before a delayed toast arrives.
|
||||
pb: "calc(var(--app-page-gutter) + var(--app-bottom-nav-height, 0px) + max(96px, var(--app-toast-clearance, 0px)) + env(safe-area-inset-bottom, 0px))",
|
||||
@@ -697,7 +681,7 @@ export default function AppShell({
|
||||
}}
|
||||
>
|
||||
<Box sx={{ mx: "auto", maxWidth: pageLayout ? `var(--app-page-width-${pageLayout})` : 1320, width: "100%", minWidth: 0 }}>
|
||||
<Box aria-hidden sx={{ height: headerHeight ?? { xs: isMobile ? 124 : 68, md: 76 } }} />
|
||||
<Box aria-hidden sx={{ height: headerHeight ?? { xs: 56, md: 64 } }} />
|
||||
<Box sx={{ display: "flex", flexDirection: "column", gap: 0.75, mb: "var(--app-section-gap)", minWidth: 0 }}>
|
||||
<Box sx={{ minWidth: 0 }}>
|
||||
<Breadcrumbs sx={{ color: "text.secondary", mb: 0.5, '& .MuiBreadcrumbs-ol': { flexWrap: 'wrap' } }}>
|
||||
|
||||
Reference in New Issue
Block a user