diff options
| author | Fuwn <[email protected]> | 2026-02-07 01:42:57 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-07 01:42:57 -0800 |
| commit | 5c5b1993edd890a80870ee05607ac5f088191d4e (patch) | |
| tree | a721b76bcd49ba10826c53efc87302c7a689512f /apps/web/app/reader/settings/_components/settings-shell.tsx | |
| download | asa.news-5c5b1993edd890a80870ee05607ac5f088191d4e.tar.xz asa.news-5c5b1993edd890a80870ee05607ac5f088191d4e.zip | |
feat: asa.news RSS reader with developer tier, REST API, and webhooks
Full-stack RSS reader SaaS: Supabase + Next.js + Go worker.
Includes three subscription tiers (free/pro/developer), API key auth,
read-only REST API, webhook push notifications, Stripe billing with
proration, and PWA support.
Diffstat (limited to 'apps/web/app/reader/settings/_components/settings-shell.tsx')
| -rw-r--r-- | apps/web/app/reader/settings/_components/settings-shell.tsx | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/apps/web/app/reader/settings/_components/settings-shell.tsx b/apps/web/app/reader/settings/_components/settings-shell.tsx new file mode 100644 index 0000000..ae432f3 --- /dev/null +++ b/apps/web/app/reader/settings/_components/settings-shell.tsx @@ -0,0 +1,86 @@ +"use client" + +import { useUserInterfaceStore } from "@/lib/stores/user-interface-store" +import { SubscriptionsSettings } from "./subscriptions-settings" +import { FoldersSettings } from "./folders-settings" +import { MutedKeywordsSettings } from "./muted-keywords-settings" +import { CustomFeedsSettings } from "./custom-feeds-settings" +import { ImportExportSettings } from "./import-export-settings" +import { AppearanceSettings } from "./appearance-settings" +import { AccountSettings } from "./account-settings" +import { SecuritySettings } from "./security-settings" +import { BillingSettings } from "./billing-settings" +import { ApiSettings } from "./api-settings" +import { DangerZoneSettings } from "./danger-zone-settings" + +const TABS = [ + { key: "subscriptions", label: "subscriptions" }, + { key: "folders", label: "folders" }, + { key: "muted-keywords", label: "muted keywords" }, + { key: "custom-feeds", label: "custom feeds" }, + { key: "import-export", label: "import / export" }, + { key: "appearance", label: "appearance" }, + { key: "account", label: "account" }, + { key: "security", label: "security" }, + { key: "billing", label: "billing" }, + { key: "api", label: "API" }, + { key: "danger", label: "danger zone" }, +] as const + +export function SettingsShell() { + const activeTab = useUserInterfaceStore((state) => state.activeSettingsTab) + const setActiveTab = useUserInterfaceStore( + (state) => state.setActiveSettingsTab + ) + + return ( + <div className="flex h-full flex-col"> + <header className="flex items-center border-b border-border px-4 py-3"> + <h1 className="text-text-primary">settings</h1> + </header> + <nav className="border-b border-border"> + <select + value={activeTab} + onChange={(event) => setActiveTab(event.target.value as typeof activeTab)} + className="w-full border-none bg-background-primary px-4 py-2 text-text-primary outline-none md:hidden" + > + {TABS.map((tab) => ( + <option key={tab.key} value={tab.key}> + {tab.label} + </option> + ))} + </select> + <div className="hidden md:flex"> + {TABS.map((tab) => ( + <button + key={tab.key} + onClick={() => setActiveTab(tab.key)} + className={`shrink-0 px-4 py-2 transition-colors ${ + activeTab === tab.key + ? "border-b-2 border-text-primary text-text-primary" + : "text-text-dim hover:text-text-secondary" + }`} + > + {tab.label} + </button> + ))} + </div> + </nav> + <div className="flex-1 overflow-y-auto"> + <div className="max-w-3xl"> + {activeTab === "subscriptions" && <SubscriptionsSettings />} + {activeTab === "folders" && <FoldersSettings />} + {activeTab === "muted-keywords" && <MutedKeywordsSettings />} + {activeTab === "custom-feeds" && <CustomFeedsSettings />} + {activeTab === "import-export" && <ImportExportSettings />} + {activeTab === "appearance" && <AppearanceSettings />} + {activeTab === "account" && <AccountSettings />} + {activeTab === "security" && <SecuritySettings />} + {activeTab === "billing" && <BillingSettings />} + {activeTab === "api" && <ApiSettings />} + {activeTab === "danger" && <DangerZoneSettings />} + </div> + </div> + </div> + ) +} |