Implement receipt management features including creation, loading, and display of receipts. Refactor related components and enhance UI with dialogs for adding new receipts. Update type definitions and improve error handling for better user experience.
This commit is contained in:
@@ -1,12 +1,34 @@
|
||||
<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";
|
||||
|
||||
let { data, params }: { data: unknown; params: { id: string } } = $props();
|
||||
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 – Stackq</title>
|
||||
<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">
|
||||
@@ -15,12 +37,75 @@
|
||||
<h1 class="text-xl font-semibold sm:text-2xl">Receipt</h1>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent class="flex flex-col gap-4 py-8">
|
||||
<p class="text-muted-foreground text-sm">Receipt {params.id}</p>
|
||||
<a href="/receipts">
|
||||
<Button variant="outline">Back to receipts</Button>
|
||||
</a>
|
||||
</CardContent>
|
||||
</Card>
|
||||
{#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}
|
||||
<div class="flex gap-2">
|
||||
<dt class="text-muted-foreground w-24 shrink-0">Image</dt>
|
||||
<dd>
|
||||
{@const url = imageUrl(receipt)}
|
||||
{#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>
|
||||
|
||||
Reference in New Issue
Block a user