diff --git a/apps/web/src/components/features/settings/GeneralSettingsTab.tsx b/apps/web/src/components/features/settings/GeneralSettingsTab.tsx new file mode 100644 index 0000000..77e5cfd --- /dev/null +++ b/apps/web/src/components/features/settings/GeneralSettingsTab.tsx @@ -0,0 +1,149 @@ +import { useOutletContext } from "react-router-dom"; +import { Icon } from "../../icon"; +import type { UserConfig, UserConfigUpdate } from "../../../api/settings"; + +type SettingsOutletContext = { + config: UserConfig; + handleChange: ( + key: keyof UserConfigUpdate, + value: string | string[] | null, + ) => void; + handleSave: () => Promise; + saveStatus: "idle" | "saving" | "saved" | "error"; +}; + +const THEME_OPTIONS = [ + { value: "system", label: "System" }, + { value: "light", label: "Light" }, + { value: "dark", label: "Dark" }, +]; + +const TOAST_LEVEL_OPTIONS = [ + { value: "all", label: "All" }, + { value: "errors", label: "Errors only" }, + { value: "none", label: "None" }, +]; + +const MUTE_CATEGORIES = ["instance", "system", "health", "security"]; + +export const GeneralSettingsTab = () => { + const { config, handleChange, handleSave, saveStatus } = + useOutletContext(); + + return ( +
+

General

+ + + + +

Notifications

+ +
+ Mute categories +
+ {MUTE_CATEGORIES.map((cat) => ( + + ))} +
+
+
+ + {saveStatus === "saved" && ( + Settings saved! + )} + {saveStatus === "error" && ( + Failed to save + )} +
+
+ ); +}; diff --git a/apps/web/src/pages/SettingsPage.tsx b/apps/web/src/pages/SettingsPage.tsx index e2f8fa3..8c3b06e 100644 --- a/apps/web/src/pages/SettingsPage.tsx +++ b/apps/web/src/pages/SettingsPage.tsx @@ -1,6 +1,5 @@ import { useEffect, useState } from "react"; -import { Link, Outlet, useLocation, useOutletContext } from "react-router-dom"; - +import { Link, Outlet, useLocation } from "react-router-dom"; import { getUserConfig, updateUserConfig, @@ -8,7 +7,6 @@ import { type UserConfigUpdate, } from "../api/settings"; import { ErrorState, LoadingState } from "../components/data-states"; -import { Icon } from "../components/icon"; import { useAsyncData } from "../hooks/use-async-data"; const TABS = [ @@ -16,29 +14,7 @@ const TABS = [ { label: "SSH Keys", path: "ssh-keys" }, ] as const; -const THEME_OPTIONS = [ - { value: "system", label: "System" }, - { value: "light", label: "Light" }, - { value: "dark", label: "Dark" }, -]; - -const TOAST_LEVEL_OPTIONS = [ - { value: "all", label: "All" }, - { value: "errors", label: "Errors only" }, - { value: "none", label: "None" }, -]; - -const MUTE_CATEGORIES = ["instance", "system", "health", "security"]; - -type SettingsOutletContext = { - config: UserConfig; - handleChange: ( - key: keyof UserConfigUpdate, - value: string | string[] | null, - ) => void; - handleSave: () => Promise; - saveStatus: "idle" | "saving" | "saved" | "error"; -}; +export { GeneralSettingsTab } from "../components/features/settings/GeneralSettingsTab"; export const SettingsPage = () => { const location = useLocation(); @@ -60,7 +36,6 @@ export const SettingsPage = () => { "idle" | "saving" | "saved" | "error" >("idle"); - // Sync loaded config into local editable state useEffect(() => { if (loadedConfig) { setConfig({ @@ -160,125 +135,3 @@ export const SettingsPage = () => { ); }; - -export const GeneralSettingsTab = () => { - const { config, handleChange, handleSave, saveStatus } = - useOutletContext(); - - return ( -
-

General

- - - - -

Notifications

- -
- Mute categories -
- {MUTE_CATEGORIES.map((cat) => ( - - ))} -
-
-
- - {saveStatus === "saved" && ( - Settings saved! - )} - {saveStatus === "error" && ( - Failed to save - )} -
-
- ); -};