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,25 +3,35 @@
import AppChrome from '$lib/sim/ui/AppChrome.svelte';
import { appController } from '$lib/app/controller';
import { appState } from '$lib/app/store';
import { Alert, AlertDescription, AlertTitle } from '$lib/components/ui/alert/index.js';
import { Button } from '$lib/components/ui/button/index.js';
import { Card, CardContent, CardHeader, CardTitle } from '$lib/components/ui/card/index.js';
import { ScrollArea } from '$lib/components/ui/scroll-area/index.js';
</script>
<AppChrome pageKey="activity">
<section id="screen-activity" class="flex flex-col gap-6 max-w-4xl mx-auto py-4">
<div class="flex items-center justify-between">
<h2 class="text-2xl font-bold text-white tracking-tight">Activity History</h2>
<button
<Button
id="clearActivityBtn"
class="btn btn-ghost text-gray-400 hover:bg-white/5 hover:text-white rounded-xl border border-transparent"
variant="ghost"
class="rounded-xl border border-transparent text-gray-400 hover:bg-white/5 hover:text-white"
onclick={() => appController.clearNotifications()}
>
Clear Read
</button>
</Button>
</div>
<div class="glass-card rounded-3xl border border-white/5 p-2 overflow-hidden">
<div id="activityFeedList" class="divide-y divide-white/5">
<Card class="glass-card rounded-3xl border-white/10 bg-[#16161d]/80">
<CardHeader>
<CardTitle class="text-sm font-semibold tracking-wide text-white">Motion Alerts</CardTitle>
</CardHeader>
<CardContent>
<ScrollArea class="max-h-[32rem] pr-3">
<div id="activityFeedList" class="flex flex-col gap-3">
{#if $appState.motionNotifications.length === 0}
<div class="text-center py-16 opacity-50">
<Alert class="border-white/10 bg-black/20 text-center opacity-70">
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto mb-4 text-gray-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
stroke-linecap="round"
@@ -30,21 +40,27 @@
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
/>
</svg>
<p class="text-sm font-medium text-gray-400">All quiet. No notifications yet.</p>
</div>
<AlertTitle class="justify-self-center text-sm text-gray-200">All quiet</AlertTitle>
<AlertDescription class="justify-self-center text-sm text-gray-400">
No notifications yet.
</AlertDescription>
</Alert>
{:else}
{#each $appState.motionNotifications as notification (notification.id)}
<button
type="button"
class="w-full text-left p-3 rounded-lg border border-white/5 {notification.isRead ? 'bg-gray-900/30' : 'bg-blue-900/20'}"
<Button
type="button"
variant="ghost"
class="h-auto w-full flex-col items-start gap-1 rounded-xl border border-white/5 px-4 py-3 text-left {notification.isRead ? 'bg-gray-900/30 text-gray-200' : 'bg-blue-900/20 text-white'}"
onclick={() => appController.openMotionNotificationTarget(notification.id, notification.cameraDeviceId)}
>
<p class="text-xs font-medium text-gray-200">{notification.message}</p>
<p class="text-[10px] text-gray-500 mt-1">{new Date(notification.createdAt).toLocaleString()}</p>
</button>
<p class="text-xs font-medium">{notification.message}</p>
<p class="text-[10px] text-gray-500">{new Date(notification.createdAt).toLocaleString()}</p>
</Button>
{/each}
{/if}
</div>
</div>
</div>
</ScrollArea>
</CardContent>
</Card>
</section>
</AppChrome>