refactor: move dashboard screens into shell routes
This commit is contained in:
175
WebApp/src/routes/(shell)/app/settings/+page.svelte
Normal file
175
WebApp/src/routes/(shell)/app/settings/+page.svelte
Normal file
@@ -0,0 +1,175 @@
|
||||
<script lang="ts">
|
||||
// @ts-nocheck
|
||||
import { api } from '$lib/app/api';
|
||||
import AppChrome from '$lib/sim/ui/AppChrome.svelte';
|
||||
import { appController } from '$lib/app/controller';
|
||||
import { appState } from '$lib/app/store';
|
||||
import { Avatar, AvatarFallback } from '$lib/components/ui/avatar/index.js';
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '$lib/components/ui/card/index.js';
|
||||
import { Separator } from '$lib/components/ui/separator/index.js';
|
||||
import {
|
||||
BarChart3,
|
||||
ChevronRight,
|
||||
Settings,
|
||||
LogOut,
|
||||
Database,
|
||||
ShieldCheck,
|
||||
Activity
|
||||
} from '@lucide/svelte';
|
||||
|
||||
const profileName = () => $appState.session?.user?.name || 'User';
|
||||
const profileEmail = () => $appState.session?.user?.email || 'user@example.com';
|
||||
const profileInitial = () => ($appState.session?.user?.name?.[0] || 'U').toUpperCase();
|
||||
|
||||
let isCheckingMinio = false;
|
||||
let minioStatus: 'idle' | 'ok' | 'error' = 'idle';
|
||||
let minioStatusMessage = '';
|
||||
let minioCheckedAt = '';
|
||||
|
||||
const checkMinioServer = async () => {
|
||||
isCheckingMinio = true;
|
||||
minioStatus = 'idle';
|
||||
minioStatusMessage = '';
|
||||
|
||||
try {
|
||||
const readiness = await api.ops.getReadiness();
|
||||
const minioCheck = readiness?.checks?.minio;
|
||||
minioStatus = minioCheck === 'ok' ? 'ok' : 'error';
|
||||
minioStatusMessage =
|
||||
minioCheck === 'ok'
|
||||
? 'MinIO is reachable and the configured bucket responded successfully.'
|
||||
: `MinIO readiness check returned: ${String(minioCheck ?? 'unknown')}`;
|
||||
minioCheckedAt = readiness?.timestamp ?? new Date().toISOString();
|
||||
} catch (error) {
|
||||
minioStatus = 'error';
|
||||
minioStatusMessage = error instanceof Error ? error.message : 'MinIO check failed';
|
||||
minioCheckedAt = new Date().toISOString();
|
||||
} finally {
|
||||
isCheckingMinio = false;
|
||||
}
|
||||
};
|
||||
|
||||
const formatCheckedAt = (value) => {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
return new Date(value).toLocaleString();
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<AppChrome pageKey="settings">
|
||||
<section id="screen-settings" class="flex flex-col gap-6 max-w-2xl mx-auto py-8">
|
||||
<h2 class="text-2xl font-bold text-white tracking-tight px-2">Settings</h2>
|
||||
|
||||
<Card variant="glass" class="rounded-3xl">
|
||||
<CardContent class="flex items-center gap-6 py-6">
|
||||
<Avatar id="profileInitials" size="lg" class="size-20 bg-blue-600/20 text-2xl font-bold text-blue-500">
|
||||
<AvatarFallback>{profileInitial()}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold tracking-wide text-white" id="profileName">{profileName()}</h3>
|
||||
<p class="mt-1 text-gray-400" id="profileEmail">{profileEmail()}</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card variant="glass" class="overflow-hidden rounded-3xl">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-sm font-semibold tracking-wide text-white">Tools & Diagnostics</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent class="flex flex-col gap-0 p-0">
|
||||
<Button
|
||||
id="checkOpsBtn"
|
||||
variant="ghost"
|
||||
class="group h-auto w-full justify-between rounded-none px-5 py-5 text-left text-gray-300 hover:bg-white/5"
|
||||
onclick={() => appController.runDiagnostics()}
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="p-2 rounded-lg bg-white/5 group-hover:bg-blue-500/20 group-hover:text-blue-400 transition-colors">
|
||||
<BarChart3 class="h-5 w-5" />
|
||||
</div>
|
||||
<span class="font-medium">Run System Diagnostics</span>
|
||||
</div>
|
||||
<ChevronRight class="h-4 w-4 text-gray-600 group-hover:text-gray-400 transition-colors" />
|
||||
</Button>
|
||||
<Separator class="bg-white/5" />
|
||||
<div class="px-5 py-5">
|
||||
<div class="flex flex-col gap-4 rounded-2xl border border-white/8 bg-white/[0.03] p-4">
|
||||
<div class="flex items-start justify-between gap-4">
|
||||
<div class="space-y-1">
|
||||
<div class="flex items-center gap-2">
|
||||
<Database class="size-4 text-blue-500" />
|
||||
<h4 class="text-sm font-semibold tracking-wide text-white">MinIO Storage Check</h4>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400">
|
||||
Test backend connectivity to object storage.
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
id="checkMinioBtn"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
class="shrink-0 rounded-xl border-white/10"
|
||||
disabled={isCheckingMinio}
|
||||
onclick={checkMinioServer}
|
||||
>
|
||||
{isCheckingMinio ? 'Checking…' : 'Check Now'}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{#if minioStatus !== 'idle'}
|
||||
<div
|
||||
class={`rounded-xl border px-3 py-3 text-sm ${
|
||||
minioStatus === 'ok'
|
||||
? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-300'
|
||||
: 'border-red-500/30 bg-red-500/10 text-red-300'
|
||||
}`}
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
{#if minioStatus === 'ok'}
|
||||
<ShieldCheck class="size-4" />
|
||||
{:else}
|
||||
<Activity class="size-4" />
|
||||
{/if}
|
||||
<p class="font-medium">
|
||||
{minioStatus === 'ok' ? 'MinIO is up' : 'MinIO check failed'}
|
||||
</p>
|
||||
</div>
|
||||
<p class="mt-1 opacity-90 text-xs">{minioStatusMessage}</p>
|
||||
{#if minioCheckedAt}
|
||||
<p class="mt-2 text-[10px] opacity-75 italic">Last checked: {formatCheckedAt(minioCheckedAt)}</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<Separator class="bg-white/5" />
|
||||
<Button variant="ghost" class="group h-auto w-full justify-between rounded-none px-5 py-5 text-left text-gray-300 hover:bg-white/5">
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="p-2 rounded-lg bg-white/5 group-hover:bg-blue-500/20 group-hover:text-blue-400 transition-colors">
|
||||
<Settings class="h-5 w-5" />
|
||||
</div>
|
||||
<span class="font-medium">Device Information</span>
|
||||
</div>
|
||||
<ChevronRight class="h-4 w-4 text-gray-600 group-hover:text-gray-400 transition-colors" />
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Button
|
||||
id="signOutBtn"
|
||||
variant="destructive"
|
||||
class="mt-4 h-14 w-full rounded-2xl border border-red-500/50 text-base font-bold hover:border-red-500 hover:bg-red-500/10"
|
||||
onclick={() => appController.signOut()}
|
||||
>
|
||||
<LogOut class="mr-3 h-5 w-5" />
|
||||
Sign Out
|
||||
</Button>
|
||||
</section>
|
||||
</AppChrome>
|
||||
Reference in New Issue
Block a user