feat(webapp): redesign dashboard with shadcn-style UI shell

This commit is contained in:
2026-03-16 11:00:00 +00:00
parent c6919d8174
commit eb0fbf24f0
95 changed files with 5940 additions and 539 deletions

View File

@@ -3,74 +3,90 @@
import AppChrome from '$lib/sim/ui/AppChrome.svelte';
import { appController } from '$lib/app/controller';
import { appState } from '$lib/app/store';
import { Button } from '$lib/components/ui/button/index.js';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '$lib/components/ui/card/index.js';
import { Input } from '$lib/components/ui/input/index.js';
import { Label } from '$lib/components/ui/label/index.js';
import { ToggleGroup, ToggleGroupItem } from '$lib/components/ui/toggle-group/index.js';
</script>
<AppChrome pageKey="onboarding">
<section id="screen-onboarding" class="flex flex-col items-center justify-center min-h-[70vh] max-w-lg mx-auto">
<div class="text-center space-y-2 mb-8">
<h2 class="text-3xl font-bold text-white tracking-tight">Configure Device</h2>
<p class="text-sm text-gray-400">Set up this browser dashboard role</p>
</div>
<div class="w-full glass-card p-6 md:p-8 rounded-3xl space-y-6 shadow-2xl">
<div class="form-control w-full">
<label class="label" for="deviceName"
><span class="label-text text-xs font-semibold text-gray-400 tracking-wider">DEVICE NAME</span></label
>
<input
id="deviceName"
type="text"
placeholder="e.g. Living Room Cam"
class="input input-bordered h-12 rounded-xl bg-black/40 border-white/10 focus:border-blue-500"
value={$appState.onboardingForm.name}
oninput={(event) => appController.setOnboardingField('name', (event.currentTarget as HTMLInputElement).value)}
/>
</div>
<div class="form-control w-full">
<label class="label" for="role"
><span class="label-text text-xs font-semibold text-gray-400 tracking-wider">ROLE</span></label
>
<div class="grid grid-cols-2 gap-2 p-1.5 bg-black/40 rounded-xl border border-white/5">
<button
class="btn btn-ghost normal-case rounded-lg h-10 min-h-0 {$appState.onboardingForm.role === 'camera' ? 'bg-blue-600 text-white' : 'text-gray-400'}"
id="btn-role-camera"
onclick={() => appController.selectRole('camera')}
>
Camera
</button>
<button
class="btn btn-ghost normal-case rounded-lg h-10 min-h-0 {$appState.onboardingForm.role === 'client' ? 'bg-blue-600 text-white' : 'text-gray-400'}"
id="btn-role-client"
onclick={() => appController.selectRole('client')}
>
Client
</button>
<Card class="glass-card w-full rounded-3xl border-white/10 bg-[#16161d]/80 shadow-2xl">
<CardHeader class="px-6 pt-6 text-center">
<CardTitle class="text-3xl font-bold tracking-tight text-white">Configure Device</CardTitle>
<CardDescription class="text-sm text-gray-400">Set up this browser dashboard role</CardDescription>
</CardHeader>
<CardContent class="flex flex-col gap-6 px-6">
<div class="flex flex-col gap-2">
<Label class="text-xs font-semibold tracking-wider text-gray-400" for="deviceName">DEVICE NAME</Label>
<Input
id="deviceName"
type="text"
placeholder="e.g. Living Room Cam"
class="h-12 rounded-xl border-white/10 bg-black/40 text-white placeholder:text-gray-500"
value={$appState.onboardingForm.name}
oninput={(event) => appController.setOnboardingField('name', (event.currentTarget as HTMLInputElement).value)}
/>
</div>
</div>
<div class="form-control w-full">
<label class="label" for="pushToken"
><span class="label-text text-xs font-semibold text-gray-400 tracking-wider">PUSH TOKEN (OPTIONAL)</span></label
<div class="flex flex-col gap-2">
<Label class="text-xs font-semibold tracking-wider text-gray-400" for="role">ROLE</Label>
<ToggleGroup
id="role"
type="single"
value={$appState.onboardingForm.role}
variant="outline"
size="lg"
class="grid w-full grid-cols-2 gap-2 rounded-xl border border-white/5 bg-black/40 p-1.5"
onValueChange={(value) => value && appController.selectRole(value)}
>
<ToggleGroupItem
id="btn-role-camera"
value="camera"
class="h-10 justify-center rounded-lg border-white/0 text-sm font-medium text-gray-400 data-[state=on]:border-blue-500/30 data-[state=on]:bg-blue-600 data-[state=on]:text-white"
>
Camera
</ToggleGroupItem>
<ToggleGroupItem
id="btn-role-client"
value="client"
class="h-10 justify-center rounded-lg border-white/0 text-sm font-medium text-gray-400 data-[state=on]:border-blue-500/30 data-[state=on]:bg-blue-600 data-[state=on]:text-white"
>
Client
</ToggleGroupItem>
</ToggleGroup>
</div>
<div class="flex flex-col gap-2">
<Label class="text-xs font-semibold tracking-wider text-gray-400" for="pushToken">PUSH TOKEN (OPTIONAL)</Label>
<Input
id="pushToken"
type="text"
placeholder="simulated_token_123"
class="h-12 rounded-xl border-white/10 bg-black/40 text-white placeholder:text-gray-500"
value={$appState.onboardingForm.pushToken}
oninput={(event) => appController.setOnboardingField('pushToken', (event.currentTarget as HTMLInputElement).value)}
/>
</div>
</CardContent>
<CardFooter class="flex flex-col items-stretch gap-3 border-0 bg-transparent px-6 pb-6 pt-2">
<Button
id="registerBtn"
class="btn-premium h-12 w-full rounded-xl text-base text-white"
onclick={() => appController.registerDevice()}
>
<input
id="pushToken"
type="text"
placeholder="simulated_token_123"
class="input input-bordered h-12 rounded-xl bg-black/40 border-white/10 focus:border-blue-500"
value={$appState.onboardingForm.pushToken}
oninput={(event) => appController.setOnboardingField('pushToken', (event.currentTarget as HTMLInputElement).value)}
/>
</div>
<div class="pt-6">
<button id="registerBtn" class="btn btn-premium w-full h-12 rounded-xl text-base" onclick={() => appController.registerDevice()}>
Complete Setup
</button>
<button id="loadSavedBtn" class="btn btn-ghost w-full mt-3 text-gray-500 hover:text-white hover:bg-white/5" onclick={() => appController.loadSavedDevice()}>
</Button>
<Button
id="loadSavedBtn"
variant="ghost"
class="h-12 w-full rounded-xl text-gray-500 hover:bg-white/5 hover:text-white"
onclick={() => appController.loadSavedDevice()}
>
Load previously saved device
</button>
</div>
</div>
</Button>
</CardFooter>
</Card>
</section>
</AppChrome>