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 15e2f676..e4c051a4 100644 --- a/.svelte-kit/types/src/routes/receipts/proxy+page.server.ts +++ b/.svelte-kit/types/src/routes/receipts/proxy+page.server.ts @@ -10,11 +10,16 @@ const COLLECTION = "Stackq_Receipts"; const TYPE_OPTIONS = ["Purchase", "Gas"] as const; export const load = async ({ locals }: Parameters[0]) => { + const user = locals.user as { id: string; Admin?: boolean } | null; + if (!user?.id) return { receipts: [] as StackqReceipt[] }; + + const isAdmin = user.Admin === true; const list = await locals.pb .collection(COLLECTION) .getFullList({ sort: "-created", expand: "User", + ...(isAdmin ? {} : { filter: `User = "${user.id}"` }), }) .catch((err) => { console.error(COLLECTION, err); @@ -31,11 +36,15 @@ export const actions = { const form = await request.formData(); const Type = (form.get("Type") as string)?.trim() || "Purchase"; + const Description = (form.get("Description") as string)?.trim() ?? ""; + if (!Description) { + return fail(400, { error: "Description is required.", Type }); + } const imageFile = form.get("Image") as File | null; const hasImage = imageFile && imageFile.size > 0; if (hasImage) { const imgError = validateImageUpload(imageFile); - if (imgError) return fail(400, { error: imgError, Type }); + if (imgError) return fail(400, { error: imgError, Type, Description }); } let imageToSave: File | null = hasImage ? imageFile : null; @@ -46,6 +55,7 @@ export const actions = { return fail(400, { error: "Could not convert HEIC image. Try saving as JPEG (iPhone: Settings → Camera → Formats) or use a different photo.", Type, + Description, }); } } @@ -53,6 +63,7 @@ export const actions = { const body: Record = { Status: "New", Type: TYPE_OPTIONS.includes(Type as (typeof TYPE_OPTIONS)[number]) ? Type : "Purchase", + Description, User: user.id, }; if (imageToSave) body.Image = imageToSave; @@ -64,7 +75,7 @@ export const actions = { err && typeof err === "object" && "message" in err ? String((err as { message: string }).message) : "Failed to create receipt."; - return fail(500, { error: message, Type }); + return fail(500, { error: message, Type, Description }); } return { success: true }; diff --git a/src/lib/types/receipts.ts b/src/lib/types/receipts.ts index 07814958..93e06ce3 100644 --- a/src/lib/types/receipts.ts +++ b/src/lib/types/receipts.ts @@ -19,6 +19,7 @@ export interface StackqReceipt { id: string; Status: string; Type: string; + Description?: string; User: string; Image?: string; Data?: ReceiptDataShape | Record; diff --git a/src/routes/receipts/+page.server.ts b/src/routes/receipts/+page.server.ts index 3d848884..6a3e0741 100644 --- a/src/routes/receipts/+page.server.ts +++ b/src/routes/receipts/+page.server.ts @@ -9,11 +9,16 @@ const COLLECTION = "Stackq_Receipts"; const TYPE_OPTIONS = ["Purchase", "Gas"] as const; export const load: PageServerLoad = async ({ locals }) => { + const user = locals.user as { id: string; Admin?: boolean } | null; + if (!user?.id) return { receipts: [] as StackqReceipt[] }; + + const isAdmin = user.Admin === true; const list = await locals.pb .collection(COLLECTION) .getFullList({ sort: "-created", expand: "User", + ...(isAdmin ? {} : { filter: `User = "${user.id}"` }), }) .catch((err) => { console.error(COLLECTION, err); @@ -30,11 +35,15 @@ export const actions: Actions = { const form = await request.formData(); const Type = (form.get("Type") as string)?.trim() || "Purchase"; + const Description = (form.get("Description") as string)?.trim() ?? ""; + if (!Description) { + return fail(400, { error: "Description is required.", Type }); + } const imageFile = form.get("Image") as File | null; const hasImage = imageFile && imageFile.size > 0; if (hasImage) { const imgError = validateImageUpload(imageFile); - if (imgError) return fail(400, { error: imgError, Type }); + if (imgError) return fail(400, { error: imgError, Type, Description }); } let imageToSave: File | null = hasImage ? imageFile : null; @@ -45,6 +54,7 @@ export const actions: Actions = { return fail(400, { error: "Could not convert HEIC image. Try saving as JPEG (iPhone: Settings → Camera → Formats) or use a different photo.", Type, + Description, }); } } @@ -52,6 +62,7 @@ export const actions: Actions = { const body: Record = { Status: "New", Type: TYPE_OPTIONS.includes(Type as (typeof TYPE_OPTIONS)[number]) ? Type : "Purchase", + Description, User: user.id, }; if (imageToSave) body.Image = imageToSave; @@ -63,7 +74,7 @@ export const actions: Actions = { err && typeof err === "object" && "message" in err ? String((err as { message: string }).message) : "Failed to create receipt."; - return fail(500, { error: message, Type }); + return fail(500, { error: message, Type, Description }); } return { success: true }; diff --git a/src/routes/receipts/+page.svelte b/src/routes/receipts/+page.svelte index 8892d171..88e8258b 100644 --- a/src/routes/receipts/+page.svelte +++ b/src/routes/receipts/+page.svelte @@ -128,6 +128,7 @@ submitLabel="Create" error={form?.error} defaultType={form?.Type ?? "Purchase"} + defaultDescription={form?.Description ?? ""} onSuccess={onReceiptCreateSuccess} /> diff --git a/src/routes/receipts/ReceiptForm.svelte b/src/routes/receipts/ReceiptForm.svelte index d1c7b02f..fc429a08 100644 --- a/src/routes/receipts/ReceiptForm.svelte +++ b/src/routes/receipts/ReceiptForm.svelte @@ -1,6 +1,8 @@