Files
lemonspace_app/components/dashboard/CLAUDE.md

5.2 KiB

components/dashboard/ — Dashboard

UI-Komponenten für die Startseite nach dem Login.


Dateien

Datei Zweck
canvas-card.tsx Karte für einen Canvas in der Übersicht (Navigation, Umbenennen, Löschen mit Confirm-Dialog)
credit-overview.tsx Monatsverbrauch und verfügbare Credits als Balken-Visualisierung
credits-activity-chart.tsx Credits-Aktivitäts-Chart (Recharts AreaChart) mit Verbrauch, Aktivität und verfügbaren Credits
recent-transactions.tsx Liste der letzten Credit-Transaktionen

Layout-Seite

app/dashboard/page-client.tsx — Client Component, rendert Dashboard mit gebündelter Snapshot-Query.

Layout-Struktur:

Dashboard
├── Header (Logo, Suche, User-Menü mit Theme-Wechsel)
├── Begrüßung (Name, Untertitel)
├── Credit-Übersicht (Balance, Usage Bars)
├── Arbeitsbereiche (Canvas Grid)
├── Credits Verlauf + Transaktionen (zwei-spaltig)
│   ├── CreditsActivityChart (Recharts AreaChart)
│   └── Recent Transactions (List)

Dashboard Snapshot Architecture

Früher: Separate Convex-Queries für Balance, Subscription, UsageStats, Transactions, Canvases → 5+ gleichzeitige Queries.

Jetzt: Gebündelte Snapshot-Query (api.dashboard.getSnapshot) + localStorage-Cache.

Datenfluss

page-client.tsx
  └── useDashboardSnapshot(userId)
        ├── Convex Query: api.dashboard.getSnapshot (gebündelt)
        │     → Balance + Subscription + UsageStats + Transactions + Canvases
        ├── localStorage Cache: readDashboardSnapshotCache (12h TTL)
        │     → Sofortige Anzeige aus Cache während Query lädt
        └── Automatisches Cache-Write bei neuen Query-Daten

Snapshot Cache (lib/dashboard-snapshot-cache.ts)

  • Key: lemonspace.dashboard:snapshot:v1:<userId>
  • TTL: 12 Stunden (DEFAULT_TTL_MS)
  • Version: CACHE_VERSION = 1 — Version-Bumps invalidieren automatisch
  • Cache-Invalidierung: Bei Logout wird der Cache des vorherigen Users gelöscht (via sessionStorage("ls-last-dashboard-user"))
  • Defensiv: Alle Storage-Zugriffe sind try-catch-gewrappt (Quota-Fehler, Disabled Storage etc.)

Snapshot Query (convex/dashboard.ts)

  • getSnapshot — Gebündelte Query, lädt alle Dashboard-Daten in einem Convex-Call
  • Nutzt optionalAuth → Default-Werte bei fehlender Session (kein Error)
  • Transaktions-Priorisierung via prioritizeRecentCreditTransactions (Usage > Reservation > Refund > Topup > Subscription)

Datenquellen

Komponente Datenquelle
credit-overview.tsx dashboardSnapshot.balance, dashboardSnapshot.subscription, dashboardSnapshot.usageStats
credits-activity-chart.tsx dashboardSnapshot.balance, dashboardSnapshot.recentTransactions
recent-transactions.tsx dashboardSnapshot.recentTransactions
canvas-card.tsx dashboardSnapshot.canvases

Alle Daten kommen aus dem gebündelten Snapshot (useDashboardSnapshot). Keine separaten Queries mehr.

Mutations

Komponente Mutation
canvas-card.tsx api.canvases.update, api.canvases.remove
page-client.tsx api.canvases.create

Credits Activity Chart

Recharts-basiertes AreaChart (via ShadCN ChartContainer) mit drei Datenseries:

  • Usage (gefüllt): Tatsächlicher Credit-Verbrauch pro Tag (committed usage-Transactions)
  • Activity (gefüllt): Usage + aktive Reservationen pro Tag
  • Available (Linie): Aktueller verfügbarer Credit-Stand als Referenzlinie

Daten-Processing: lib/credits-activity.ts

  • buildCreditsActivitySeries() — Gruppiert Transactions nach Tag, aggregiert Usage/Activity
  • calculateUsageActivityDomain() — Berechnet Y-Achsen-Domain mit Headroom
  • prioritizeRecentCreditTransactions() — Sortiert Transactions nach Typ-Priorität

Chart Config: Teal für Usage, Accent-Foreground für Activity, Muted-Foreground für Available.


Konventionen

  • Kein lokaler State für Server-Daten — Snapshot kommt aus useDashboardSnapshot
  • Dashboard zeigt sofort Cache-Daten an, während Live-Query lädt (source: "cache" | "live" | "none")
  • Canvas-Thumbnails sind optional (thumbnail?: Id<"_storage">) — Fallback-State immer behandeln
  • Responsive Grid-Layout für Canvas-Cards (grid-cols-1 sm:grid-cols-3)
  • Leere Zustände (keine Canvases, keine Transaktionen, keine Chart-Daten) mit nutzerfreundlichen Platzhaltern zeigen
  • Chart-Komponente nutzt ShadCN ChartContainer (components/ui/chart.tsx) + Recharts 3.8

Error Handling

  • Auth-Race: useDashboardSnapshot nutzt useAuthQuery intern → skippt bis Auth bereit
  • Empty States: Wenn keine Canvases/Transaktionen vorhanden sind, informative Platzhalter zeigen
  • Cache-Fehler: localStorage-Zugriffe sind defensiv gewrappt (quota, disabled storage)
  • Offline: Snapshot-Cache bietet Fallback bei fehlender Verbindung

Performance

  • Gebündelte Snapshot-Query statt 5+ separater Queries → weniger WebSocket-Last
  • localStorage-Cache mit 12h TTL → sofortige Anzeige bei wiederholtem Besuch
  • Canvas-Thumbnails werden über den Snapshot geladen (nur wenn vorhanden)
  • Transaktions-Liste ist auf 20 Einträge limitiert (priorisiert nach Typ)