diff --git a/components/settings/settings-page.tsx b/components/settings/settings-page.tsx deleted file mode 100644 index edcae8a..0000000 --- a/components/settings/settings-page.tsx +++ /dev/null @@ -1,135 +0,0 @@ -"use client"; -/** - * THE SETTINGS PAGE (thin settings wave, 2026-09-19): one column, section - * blocks in fixed order — General, Agent, Appearance, Graph, Keyboard — - * over the versioned delta record at GET /api/settings, written per - * section through PUT /api/settings/[section] (replace-whole). - * - * Thin by owner decision: simple controls, real read/write, the point is - * a WORKING validation surface that exercises the whole settings schema — - * not the designed settings app. Polish lives in a later wave. - * - * The chat section (new-session defaults) is deliberately NOT here - * (owner decision): its controls live on the /chat/new surface; two - * editors for one value is a drift bug. The auth/provider-keys page is - * deliberately absent (needs auth.json plumbing that doesn't exist). - */ - -import { useCallback, useEffect, useState } from "react"; -import { CURRENT_SETTINGS_VERSION, type AgentSettings, type AppearanceSettings, type GraphSettings, type UserSettings } from "@/src/core"; -import { SidebarToggle } from "@/components/sidebar.tsx"; -import { useAppearance } from "./appearance.tsx"; -import { SettingsSection, SettingsRow, Toggle } from "./controls.tsx"; -import { AgentSection } from "./agent-section.tsx"; -import { AppearanceSection, GraphSection } from "./appearance-section.tsx"; -import { KeyboardSection } from "./keyboard-section.tsx"; - -export function SettingsPage() { - const { onAppearanceChange } = useAppearance(); - const [record, setRecord] = useState(undefined); - const [error, setError] = useState(null); - - useEffect(() => { - // 200 {settings: null} is FIRST BOOT (no record = factory everything), - // not a failure — the error state is a non-200 or a network throw only. - fetch("/api/settings") - .then((r) => (r.ok ? r.json() : Promise.reject(new Error(`status ${r.status}`)))) - .then((body: { settings: UserSettings | null }) => - setRecord(body.settings ?? { version: CURRENT_SETTINGS_VERSION }), - ) - .catch(() => setRecord(null)); - }, []); - - /** ONE writer per page: PUT the whole section, keep the record mirror - * in sync, surface route errors inline (a 400 is this wave's point — - * the validation surface catching schema mistakes). */ - const write = useCallback( - async (section: "general" | "agent" | "appearance" | "graph", body: object) => { - setError(null); - const res = await fetch(`/api/settings/${section}`, { - method: "PUT", - headers: { "content-type": "application/json" }, - body: JSON.stringify(body), - }); - if (!res.ok) { - const detail = (await res.json().catch(() => ({}))) as { error?: string }; - setError(`${section}: ${detail.error ?? res.status}`); - return; - } - setRecord((prev) => ({ ...(prev ?? {}), [section]: body }) as UserSettings); - if (section === "appearance") onAppearanceChange(body as AppearanceSettings); - }, - [onAppearanceChange], - ); - - return ( -
-
- {/* The app header — same 60px band, same border, same CMU title - (the alignment constant from header round 6). */} -
- -
Settings
-
- -
-
- {error && ( -

- {error} -

- )} - {record === undefined ? ( -

Loading settings…

- ) : record === null ? ( -

- Settings could not be loaded — refresh to retry. -

- ) : ( - <> - - - void write("general", { autoUpdate: on })} - /> - - - - - void write("agent", next)} - /> - - - - void write("appearance", next)} - /> - - - - void write("graph", next)} - /> - - - - - - - )} -
-
-
-
- ); -} \ No newline at end of file