diff --git a/.svelte-kit/types/src/routes/receipts/proxy+page.server.ts b/.svelte-kit/types/src/routes/receipts/proxy+page.server.ts index 1d6152c8..586640e1 100644 --- a/.svelte-kit/types/src/routes/receipts/proxy+page.server.ts +++ b/.svelte-kit/types/src/routes/receipts/proxy+page.server.ts @@ -27,7 +27,7 @@ export const load = async ({ locals }: Parameters[0]) => { return [] as StackqReceipt[]; }); - return { receipts: list }; + return { receipts: list, canEdit: isAdmin }; }; export const actions = { @@ -93,11 +93,9 @@ export const actions = { return fail(400, { error: "Invalid status", setStatus: null }); } const isAdmin = user.Admin === true; + if (!isAdmin) return fail(403, { error: "Only admins can change status.", setStatus: null }); try { - const existing = await locals.pb.collection(COLLECTION).getOne(id); - if (!isAdmin && existing.User !== user.id) { - return fail(404, { error: "Receipt not found", setStatus: null }); - } + await locals.pb.collection(COLLECTION).getOne(id); await locals.pb.collection(COLLECTION).update(id, { Status }); } catch (e: unknown) { const is404 = e && typeof e === "object" && "status" in e && (e as { status: number }).status === 404; diff --git a/src/routes/receipts/+page.server.ts b/src/routes/receipts/+page.server.ts index ebc7b27f..cb918d60 100644 --- a/src/routes/receipts/+page.server.ts +++ b/src/routes/receipts/+page.server.ts @@ -26,7 +26,7 @@ export const load: PageServerLoad = async ({ locals }) => { return [] as StackqReceipt[]; }); - return { receipts: list }; + return { receipts: list, canEdit: isAdmin }; }; export const actions: Actions = { @@ -92,11 +92,9 @@ export const actions: Actions = { return fail(400, { error: "Invalid status", setStatus: null }); } const isAdmin = user.Admin === true; + if (!isAdmin) return fail(403, { error: "Only admins can change status.", setStatus: null }); try { - const existing = await locals.pb.collection(COLLECTION).getOne(id); - if (!isAdmin && existing.User !== user.id) { - return fail(404, { error: "Receipt not found", setStatus: null }); - } + await locals.pb.collection(COLLECTION).getOne(id); await locals.pb.collection(COLLECTION).update(id, { Status }); } catch (e: unknown) { const is404 = e && typeof e === "object" && "status" in e && (e as { status: number }).status === 404; diff --git a/src/routes/receipts/+page.svelte b/src/routes/receipts/+page.svelte index c758ff47..ab6e2a17 100644 --- a/src/routes/receipts/+page.svelte +++ b/src/routes/receipts/+page.svelte @@ -11,7 +11,8 @@ import { STATUS_OPTIONS } from "$lib/types/receipts"; import { enhance } from "$app/forms"; - let { data, form }: { data: { receipts: StackqReceipt[] }; form?: ActionData } = $props(); + let { data, form }: { data: { receipts: StackqReceipt[]; canEdit?: boolean }; form?: ActionData } = $props(); + const canEdit = $derived(data?.canEdit ?? false); let searchQuery = $state(""); let createDialogOpen = $state(false); let activeTab = $state<(typeof STATUS_OPTIONS)[number]>("New"); @@ -168,7 +169,15 @@
- {userName(receipt)} +
+ {userName(receipt)} + {#if receipt.Description} +

{receipt.Description}

+ {:else} +

No description

+ {/if} +
+ {#if canEdit}
e.stopPropagation()} > - {receipt.Status ?? "New"} - - - {#each STATUS_OPTIONS as o} - - {/each} - - + {receipt.Status ?? "New"} + + + {#each STATUS_OPTIONS as o} + + {/each} + +
+ {:else} + {receipt.Status ?? "New"} + {/if}
{receipt.Type ?? "—"} {formatDateLocal(receipt.created)} - {#if receipt.Description} - {receipt.Description} - {/if}
diff --git a/src/routes/receipts/[id]/+page.server.ts b/src/routes/receipts/[id]/+page.server.ts index bd93ceed..8085b9eb 100644 --- a/src/routes/receipts/[id]/+page.server.ts +++ b/src/routes/receipts/[id]/+page.server.ts @@ -22,7 +22,7 @@ export const load: PageServerLoad = async ({ params, locals }) => { if (!isAdmin && user?.id && record.User !== user.id) { throw error(404, "Receipt not found"); } - return { receipt: record }; + return { receipt: record, canEdit: isAdmin }; } catch (err: unknown) { const is404 = err && @@ -40,11 +40,9 @@ export const actions: Actions = { if (!id) return fail(400, { error: "Missing id", form: "update" }); const user = locals.user as { id: string; Admin?: boolean } | null; const isAdmin = user?.Admin === true; + if (!isAdmin) return fail(403, { error: "Only admins can edit receipts.", form: "update" }); try { - const existing = await locals.pb.collection(COLLECTION).getOne(id); - if (!isAdmin && user?.id && existing.User !== user.id) { - return fail(404, { error: "Receipt not found", form: "update" }); - } + await locals.pb.collection(COLLECTION).getOne(id); } catch { return fail(404, { error: "Receipt not found", form: "update" }); } @@ -131,11 +129,8 @@ export const actions: Actions = { if (!id) return fail(400, { error: "Missing id", form: "delete" }); const user = locals.user as { id: string; Admin?: boolean } | null; const isAdmin = user?.Admin === true; + if (!isAdmin) return fail(403, { error: "Only admins can delete receipts.", form: "delete" }); try { - const existing = await locals.pb.collection(COLLECTION).getOne(id); - if (!isAdmin && user?.id && existing.User !== user.id) { - return fail(404, { error: "Receipt not found", form: "delete" }); - } await locals.pb.collection(COLLECTION).delete(id); } catch (e: unknown) { const message = diff --git a/src/routes/receipts/[id]/+page.svelte b/src/routes/receipts/[id]/+page.svelte index 6b74bbd5..993f7512 100644 --- a/src/routes/receipts/[id]/+page.svelte +++ b/src/routes/receipts/[id]/+page.svelte @@ -19,9 +19,10 @@ const COLLECTION = "Stackq_Receipts"; const TYPE_OPTIONS = ["Purchase", "Gas"] as const; - let { data, form }: { data: { receipt: StackqReceipt }; form?: { error?: string; form?: string } } = $props(); + let { data, form }: { data: { receipt: StackqReceipt; canEdit?: boolean }; form?: { error?: string; form?: string } } = $props(); const receipt = $derived(data?.receipt); + const canEdit = $derived(data?.canEdit ?? false); const formData = $state<{ lineItems: ReceiptLineItem[]; tax: number; receiptTotal: number }>({ lineItems: [{ item: "", description: "", quantity: 1, price: 0 }], @@ -243,7 +244,7 @@ {/if} {:else} -

No image. Add one in the form and save.

+

{canEdit ? "No image. Add one in the form and save." : "No image."}

{/if} @@ -252,6 +253,7 @@ + {#if canEdit}
+ {:else} +
+
+
+

Status

+

{statusValue}

+
+
+

Type

+

{typeValue}

+
+
+
+

Description

+

{descriptionValue || "—"}

+
+ {#if lineItems.length > 0} +
+

Line items

+
+ + + + Item + Description + Qty + Price + + + + {#each lineItems as row} + + {row.item || "—"} + {row.description || "—"} + {row.quantity} + ${Number(row.price).toFixed(2)} + + {/each} + +
+
+
+ {/if} +
+
+ Subtotal + ${subtotal.toFixed(2)} +
+
+ Tax + ${(Number(tax) || 0).toFixed(2)} +
+
+ Total + ${total.toFixed(2)} +
+
+ Receipt total + ${(Number(receiptTotal) || 0).toFixed(2)} +
+
+ +
+ {/if}
@@ -499,6 +569,7 @@

User: {receipt.expand?.User?.name ?? receipt.expand?.User?.email ?? "—"} · Created {formatDate(receipt.created)} · Updated {formatDate(receipt.updated)}

+ {#if canEdit}
+ {/if} {:else}