diff --git a/app/components/Navbar.tsx b/app/components/Navbar.tsx index 74d8040..4548557 100644 --- a/app/components/Navbar.tsx +++ b/app/components/Navbar.tsx @@ -25,6 +25,12 @@ export default function Navbar() { > Analyze + {/* If you have an isAdmin helper, show Settings only for admins. Example: + {isAdmin(user) && ( + Settings + )} + */} + Settings diff --git a/app/routes/settings.tsx b/app/routes/settings.tsx new file mode 100644 index 0000000..6d5037a --- /dev/null +++ b/app/routes/settings.tsx @@ -0,0 +1,61 @@ +import type { LoaderFunction } from '@remix-run/node'; +import { json } from '@remix-run/node'; +import React, { useEffect, useState } from 'react'; +import { requireAdmin } from '~/lib/auth.server'; +import { settingsService } from '~/lib/settings.server'; + +export const loader: LoaderFunction = async ({ request }) => { + await requireAdmin(request); + await settingsService.init?.(); + const entries: any[] = []; + // @ts-ignore + for (const key of (settingsService as any).cache.keys()) { + entries.push({ key, value: await settingsService.get(key) }); + } + return json({ entries }); +}; + +export default function SettingsPage() { + const [items, setItems] = useState>([]); + useEffect(() => { + fetch('/api/admin/settings') + .then(r => r.json()) + .then(j => setItems(j)); + }, []); + + async function save(key: string, value: any) { + await fetch(`/api/admin/settings/${encodeURIComponent(key)}`, { + method: 'PUT', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ value }), + }); + setItems(s => s.map(i => (i.key === key ? { ...i, value } : i))); + } + + return ( +
+

Settings

+