112 lines
3.7 KiB
Svelte
112 lines
3.7 KiB
Svelte
<script lang="ts">
|
||
import { Button } from "$lib/components/ui/button";
|
||
import { Card, CardContent } from "$lib/components/ui/card";
|
||
import { POCKETBASE_BASE_URL } from "$lib/pocketbase";
|
||
import type { StackqReceipt } from "$lib/types/receipts";
|
||
|
||
const COLLECTION = "Stackq_Receipts";
|
||
|
||
let { data }: { data: { receipt: StackqReceipt } } = $props();
|
||
|
||
const receipt = $derived(data?.receipt);
|
||
|
||
function imageUrl(r: StackqReceipt): string | null {
|
||
if (!r?.Image) return null;
|
||
return `${POCKETBASE_BASE_URL}/api/files/${COLLECTION}/${r.id}/${r.Image}`;
|
||
}
|
||
|
||
function formatDate(iso: string): string {
|
||
try {
|
||
return new Date(iso).toLocaleString(undefined, {
|
||
dateStyle: "medium",
|
||
timeStyle: "short",
|
||
});
|
||
} catch {
|
||
return iso;
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<svelte:head>
|
||
<title>Receipt {receipt?.Status ?? receipt?.id ?? "—"} – Stackq</title>
|
||
</svelte:head>
|
||
|
||
<main class="container mx-auto flex flex-col gap-6 px-4 py-6 sm:px-6 sm:py-8">
|
||
<div class="flex items-center gap-3">
|
||
<a href="/receipts" class="text-muted-foreground hover:text-foreground shrink-0 text-sm" title="Back to receipts">Back</a>
|
||
<h1 class="text-xl font-semibold sm:text-2xl">Receipt</h1>
|
||
</div>
|
||
|
||
{#if receipt}
|
||
<Card>
|
||
<CardContent class="flex flex-col gap-4 py-6">
|
||
<dl class="grid gap-3 text-sm">
|
||
<div class="flex gap-2">
|
||
<dt class="text-muted-foreground w-24 shrink-0">Status</dt>
|
||
<dd>{receipt.Status ?? "—"}</dd>
|
||
</div>
|
||
<div class="flex gap-2">
|
||
<dt class="text-muted-foreground w-24 shrink-0">Type</dt>
|
||
<dd>{receipt.Type ?? "—"}</dd>
|
||
</div>
|
||
<div class="flex gap-2">
|
||
<dt class="text-muted-foreground w-24 shrink-0">User</dt>
|
||
<dd>
|
||
{#if receipt.expand?.User}
|
||
{receipt.expand.User.name ?? receipt.expand.User.email ?? receipt.expand.User.id}
|
||
{:else}
|
||
—
|
||
{/if}
|
||
</dd>
|
||
</div>
|
||
<div class="flex gap-2">
|
||
<dt class="text-muted-foreground w-24 shrink-0">Created</dt>
|
||
<dd>{formatDate(receipt.created)}</dd>
|
||
</div>
|
||
<div class="flex gap-2">
|
||
<dt class="text-muted-foreground w-24 shrink-0">Updated</dt>
|
||
<dd>{formatDate(receipt.updated)}</dd>
|
||
</div>
|
||
{#if receipt.Data && Object.keys(receipt.Data).length > 0}
|
||
<div class="flex gap-2">
|
||
<dt class="text-muted-foreground w-24 shrink-0">Data</dt>
|
||
<dd class="min-w-0 overflow-auto rounded border bg-muted/30 p-2 font-mono text-xs">
|
||
<pre>{JSON.stringify(receipt.Data, null, 2)}</pre>
|
||
</dd>
|
||
</div>
|
||
{/if}
|
||
{#if receipt.Image}
|
||
{@const url = imageUrl(receipt)}
|
||
<div class="flex gap-2">
|
||
<dt class="text-muted-foreground w-24 shrink-0">Image</dt>
|
||
<dd>
|
||
{#if url}
|
||
<img
|
||
src={url}
|
||
alt="Receipt"
|
||
class="max-h-48 rounded border object-contain"
|
||
/>
|
||
{:else}
|
||
—
|
||
{/if}
|
||
</dd>
|
||
</div>
|
||
{/if}
|
||
</dl>
|
||
<a href="/receipts">
|
||
<Button variant="outline">Back to receipts</Button>
|
||
</a>
|
||
</CardContent>
|
||
</Card>
|
||
{:else}
|
||
<Card>
|
||
<CardContent class="py-8">
|
||
<p class="text-muted-foreground text-center text-sm">Receipt not found.</p>
|
||
<a href="/receipts" class="mt-4 flex justify-center">
|
||
<Button variant="outline">Back to receipts</Button>
|
||
</a>
|
||
</CardContent>
|
||
</Card>
|
||
{/if}
|
||
</main>
|