feat(ui): simplify A3 workspace and refresh saved AI availability

This commit is contained in:
cesnimda
2026-11-04 00:21:04 +01:00
parent 7aa54bff1f
commit 2218659ecf
216 changed files with 7935 additions and 115 deletions
@@ -39,6 +39,7 @@ interface Props {
onColumnsChange: (next: JobTableColumns) => void;
themeMode: ThemeModePref;
onThemeModeChange: (v: ThemeModePref) => void;
onAiPreferencesSaved?: () => Promise<void>;
}
function TabPanel({ value, index, label, children, keepMounted = false }: { value: number; index: number; label: string; children: React.ReactNode; keepMounted?: boolean }) {
@@ -63,6 +64,7 @@ export default function SettingsView({
onColumnsChange,
themeMode,
onThemeModeChange,
onAiPreferencesSaved,
}: Props) {
const navigate = useNavigate();
const location = useLocation();
@@ -227,7 +229,7 @@ export default function SettingsView({
const notificationReadStatus = (notificationError?.cause as { response?: { status?: number } } | undefined)?.response?.status;
const notificationCard = (
<PageSection surface title={t("settingsNotificationsTitle")} description={t("settingsNotificationsBody")}>
<PageSection title={t("settingsNotificationsTitle")} description={t("settingsNotificationsBody")}>
<Box ref={notificationBody} role="group" aria-label={t("settingsNotificationsTitle")} tabIndex={-1} aria-busy={loadingNotifications || savingNotifications} sx={{ minWidth: 0 }}>
{!notificationPrefs ? <ViewStateNotice compact loading={loadingNotifications} title={t("settingsNotificationsLoadFailed")} error={notificationError ? {
kind: notificationReadStatus === 401 || notificationReadStatus === 403 ? "unauthorized" : "error",
@@ -287,7 +289,7 @@ export default function SettingsView({
<TabPanel value={tab} index={0} label={t("settingsTabGeneral")} keepMounted>
<Box sx={{ display: "grid", gap: "var(--app-section-gap)", minWidth: 0 }}>
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "minmax(0, 1fr)", md: "repeat(2, minmax(0, 1fr))" }, gap: "var(--app-section-gap)" }}>
<PageSection surface title={t("settingsAppearance")}>
<PageSection title={t("settingsAppearance")}>
<FormControl fullWidth>
<InputLabel id="theme-mode-label">{t("settingsTheme")}</InputLabel>
<Select
@@ -303,7 +305,7 @@ export default function SettingsView({
</FormControl>
</PageSection>
<PageSection surface title={t("settingsLanguageTitle")} description={t("settingsLanguageBody")}>
<PageSection title={t("settingsLanguageTitle")} description={t("settingsLanguageBody")}>
<FormControl fullWidth>
<InputLabel id="language-label">{t("settingsPreferredLanguage")}</InputLabel>
<Select
@@ -319,7 +321,7 @@ export default function SettingsView({
</PageSection>
</Box>
<PageSection surface title={t("settingsJobs")}>
<PageSection title={t("settingsJobs")}>
<Box sx={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
<Box sx={{ flex: "1 1 15rem", minWidth: 0 }}>
<Typography component="h3" variant="subtitle2" sx={{ mb: 1, fontWeight: 700 }}>
@@ -366,10 +368,10 @@ export default function SettingsView({
</Box>
</PageSection>
<Box ref={aiControls} id="settings-ai-controls" role="group" aria-label={t("settingsAiPrivacyTitle")} tabIndex={-1}><AiPrivacySettingsCard /></Box>
<Box ref={aiControls} id="settings-ai-controls" role="group" aria-label={t("settingsAiPrivacyTitle")} tabIndex={-1}><AiPrivacySettingsCard onSaved={onAiPreferencesSaved} /></Box>
<AiUsageCard />
<QuickCaptureCard />
<PageSection surface title={t("connectedAccounts")} description={t("settingsConnectedAccountsBody")}
<PageSection title={t("connectedAccounts")} description={t("settingsConnectedAccountsBody")}
actions={<Button variant="outlined" onClick={() => navigate("/settings/connected-accounts")}>{t("settingsManageConnectedAccounts")}</Button>} />
</Box>
</TabPanel>
@@ -389,7 +391,7 @@ export default function SettingsView({
<TabPanel value={tab} index={4} label={t("settingsTabAutomation")}>
<Box sx={{ display: "grid", gap: "var(--app-section-gap)", minWidth: 0 }}>
<PageSection surface title={t("settingsTabAutomation")} description={t("settingsAutomationBody")}>
<PageSection title={t("settingsTabAutomation")} description={t("settingsAutomationBody")}>
<Typography variant="body2" color="text.secondary" sx={{ mb: 1.5 }}>{t("settingsAutomationEmailSchedule")}</Typography>
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 1 }}>
<Button onClick={() => { selectSection(0); requestAnimationFrame(() => aiControls.current?.focus()); }}>{t("settingsAutomationAi")}</Button>