import { useEffect, useState } from "react"; import { Link, Outlet, useLocation, useOutletContext } from "react-router-dom"; import { getUserConfig, updateUserConfig, type UserConfig, type UserConfigUpdate } from "../api/settings"; import { EmptyState, ErrorState, LoadingState } from "../components/data-states"; import { Icon } from "../components/icon"; import { useAsyncData } from "../hooks/use-async-data"; const TABS = [ { label: "General", path: "general" }, { label: "SSH Keys", path: "ssh-keys" }, ] as const; const THEME_OPTIONS = [ { value: "system", label: "System" }, { value: "light", label: "Light" }, { value: "dark", label: "Dark" }, ]; type SettingsOutletContext = { config: UserConfig; handleChange: (key: keyof UserConfigUpdate, value: string | null) => void; handleSave: () => Promise; saveStatus: "idle" | "saving" | "saved" | "error"; }; export const SettingsPage = () => { const location = useLocation(); const { data: loadedConfig, status, reload } = useAsyncData(getUserConfig, []); const [config, setConfig] = useState({ theme: "system", default_editor: null, git_user_name: null, git_user_email: null, last_session_id: null, }); const [saveStatus, setSaveStatus] = useState<"idle" | "saving" | "saved" | "error">("idle"); // Sync loaded config into local editable state useEffect(() => { if (loadedConfig) { setConfig(loadedConfig); } }, [loadedConfig]); const handleChange = (key: keyof UserConfigUpdate, value: string | null) => { setConfig((prev) => ({ ...prev, [key]: value })); setSaveStatus("idle"); }; const handleSave = async () => { setSaveStatus("saving"); try { const update: UserConfigUpdate = { theme: config.theme, default_editor: config.default_editor, git_user_name: config.git_user_name, git_user_email: config.git_user_email, }; const updated = await updateUserConfig(update); setConfig(updated); setSaveStatus("saved"); if (updated.theme === "system") { document.documentElement.removeAttribute("data-theme"); } else { document.documentElement.setAttribute("data-theme", updated.theme); } window.setTimeout(() => setSaveStatus("idle"), 2000); } catch { setSaveStatus("error"); } }; if (status === "loading") { return
; } if (status === "error") { return (
); } const parts = location.pathname.split("/").filter(Boolean); const activePath = location.pathname.endsWith("/settings") ? "general" : (parts[parts.length - 1] ?? "general"); return (

Configuration

Settings

General preferences, SSH keys, and config profiles.

); }; export const GeneralSettingsTab = () => { const { config, handleChange, handleSave, saveStatus } = useOutletContext(); return (

General

{saveStatus === "saved" && Settings saved!} {saveStatus === "error" && Failed to save}
); };