feat: build dashboard overview UI

This commit is contained in:
2026-06-25 11:40:09 +01:00
parent 9f8675fb30
commit 77cbb1d8d7
5 changed files with 403 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
<script lang="ts">
import ChartNoAxesColumnIncreasingIcon from '@lucide/svelte/icons/chart-no-axes-column-increasing';
import * as Card from '$lib/components/ui/card/index.js';
import * as Empty from '$lib/components/ui/empty/index.js';
import type { PageData } from './$types';
let {
records,
formatMoney
}: {
records: PageData['billingTrend'];
formatMoney: (value: unknown) => string;
} = $props();
const maxValue = $derived(Math.max(...records.map((record) => record.totalGbp), 0));
const hasValues = $derived(records.some((record) => record.totalGbp > 0));
</script>
<Card.Root>
<Card.Header>
<Card.Title>Billing trend</Card.Title>
<Card.Description>Issued invoice totals over the last six months.</Card.Description>
</Card.Header>
<Card.Content>
{#if hasValues}
<div class="grid h-52 grid-cols-6 items-end gap-3" aria-label="Billing trend chart">
{#each records as record (record.month)}
<div class="flex h-full min-w-0 flex-col justify-end gap-2">
<div class="flex min-h-0 flex-1 items-end">
<div
class="w-full rounded-t-md bg-primary/75"
style:height={`${Math.max((record.totalGbp / maxValue) * 100, record.totalGbp > 0 ? 4 : 0)}%`}
title={`${record.label}: ${formatMoney(record.totalGbp)}`}
></div>
</div>
<div class="min-w-0 text-center">
<div class="truncate text-xs font-medium">{formatMoney(record.totalGbp)}</div>
<div class="truncate text-xs text-muted-foreground">{record.label}</div>
</div>
</div>
{/each}
</div>
{:else}
<Empty.Root class="min-h-52 border">
<Empty.Media variant="icon"><ChartNoAxesColumnIncreasingIcon /></Empty.Media>
<Empty.Header>
<Empty.Title>No issued invoices yet</Empty.Title>
<Empty.Description
>Billing totals will appear once invoices are generated.</Empty.Description
>
</Empty.Header>
</Empty.Root>
{/if}
</Card.Content>
</Card.Root>