SIWE auth, API proxy fixes, dashboard, login, usage pages
- SIWE auth flow: challenge/login/logout/me API routes + JWT middleware
- Fixed [...path] catch-all: Kubo proxy with matchRoute() + mapToKuboAPI()
- Fixed session_id → nonce field mismatch in AuthProvider
- Fixed dashboard pins crash: Kubo returns {Keys: {...}}, not array
- Added middleware route guard (307 redirect to /login)
- Added login, register, profile, usage, upload pages
- Added dashboard components (StorageGauge, FreeTierProgress)
- Added SWR hooks + AuthGuard + Providers + Toast/ErrorBoundary
- Added payment integration (smart contract ABI, tiers, tokens)
- Fixed IPNS key listing: Name/Id → name/id mapping
- Added PWA support (manifest, service worker, icons)
- Added tests for helpers, limits, search-index, wallet
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useState } from 'react';
|
||||
import { getSettings, saveSettings, resetSettings, type PortalSettings } from '@/lib/storage';
|
||||
import { useTheme } from '@/lib/theme';
|
||||
import PortalLayout from '@/app/layout-portal';
|
||||
import {
|
||||
Settings, Globe, Server, HardDrive, RefreshCw,
|
||||
@@ -18,6 +19,7 @@ function formatStorageMB(mb: number): string {
|
||||
/* ════════════════════════════ Page ════════════════════════════ */
|
||||
|
||||
export default function SettingsPage() {
|
||||
const { setTheme: applyTheme } = useTheme();
|
||||
const [form, setForm] = useState<PortalSettings>(() => getSettings());
|
||||
const [original, setOriginal] = useState<PortalSettings>(() => getSettings());
|
||||
const [saved, setSaved] = useState(false);
|
||||
@@ -228,23 +230,23 @@ export default function SettingsPage() {
|
||||
<div>
|
||||
<label className="text-xs text-surface-400 mb-2 block">Appearance</label>
|
||||
<div className="flex gap-2">
|
||||
{(['dark', 'light'] as const).map(theme => (
|
||||
{(['dark', 'light'] as const).map(t => (
|
||||
<button
|
||||
key={theme}
|
||||
onClick={() => update('theme', theme)}
|
||||
key={t}
|
||||
onClick={() => { update('theme', t); applyTheme(t); }}
|
||||
className={`flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-medium transition-colors ${
|
||||
form.theme === theme
|
||||
form.theme === t
|
||||
? 'bg-brand-500/20 text-brand-400 border border-brand-500/30'
|
||||
: 'bg-surface-900 text-surface-400 border border-surface-700 hover:border-surface-500'
|
||||
}`}
|
||||
>
|
||||
{theme === 'dark' ? <Moon className="w-4 h-4" /> : <Sun className="w-4 h-4" />}
|
||||
{theme.charAt(0).toUpperCase() + theme.slice(1)}
|
||||
{t === 'dark' ? <Moon className="w-4 h-4" /> : <Sun className="w-4 h-4" />}
|
||||
{t.charAt(0).toUpperCase() + t.slice(1)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-1.5 text-[11px] text-surface-500">
|
||||
Theme preference is saved but only affects new sessions. Full theme switching coming soon.
|
||||
Theme wordt direct toegepast en opgeslagen in je browser.
|
||||
</p>
|
||||
</div>
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user