Enhance receipt management by adding support for image uploads and improving data handling in receipt forms. Update route parameters and type definitions for better data structure. Refactor UI components for improved user experience and responsiveness, including collapsible sections for receipt images and dynamic line item management.
This commit is contained in:
@@ -1,9 +1,19 @@
|
||||
import { error } from "@sveltejs/kit";
|
||||
import type { PageServerLoad } from "./$types";
|
||||
import { error, fail, redirect } from "@sveltejs/kit";
|
||||
import type { Actions, PageServerLoad } from "./$types";
|
||||
import type { StackqReceipt } from "$lib/types/receipts";
|
||||
import type { ReceiptDataShape } from "$lib/types/receipts";
|
||||
|
||||
const COLLECTION = "Stackq_Receipts";
|
||||
|
||||
const STATUS_OPTIONS = ["New", "Data Entered", "Reviewed", "Consolidated"] as const;
|
||||
const TYPE_OPTIONS = ["Purchase", "Gas"] as const;
|
||||
|
||||
function parseNum(val: unknown): number {
|
||||
if (val === "" || val === null || val === undefined) return 0;
|
||||
const n = Number(val);
|
||||
return Number.isFinite(n) ? n : 0;
|
||||
}
|
||||
|
||||
export const load: PageServerLoad = async ({ params, locals }) => {
|
||||
const { id } = params;
|
||||
try {
|
||||
@@ -21,3 +31,82 @@ export const load: PageServerLoad = async ({ params, locals }) => {
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
export const actions: Actions = {
|
||||
update: async ({ request, locals, params }) => {
|
||||
const id = params.id;
|
||||
if (!id) return fail(400, { error: "Missing id", form: "update" });
|
||||
|
||||
const form = await request.formData();
|
||||
const Status = (form.get("Status") as string)?.trim() || "New";
|
||||
const Type = (form.get("Type") as string)?.trim() || "Purchase";
|
||||
const dataJson = (form.get("dataJson") as string)?.trim() ?? "{}";
|
||||
const imageFile = form.get("Image") as File | null;
|
||||
const hasImage = imageFile && imageFile.size > 0;
|
||||
|
||||
let Data: ReceiptDataShape = {};
|
||||
try {
|
||||
const parsed = JSON.parse(dataJson) as unknown;
|
||||
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
||||
const o = parsed as Record<string, unknown>;
|
||||
if (Array.isArray(o.lineItems)) {
|
||||
Data.lineItems = o.lineItems.filter(
|
||||
(row: unknown): row is { item: string; description: string; quantity: number; price: number } =>
|
||||
row != null &&
|
||||
typeof row === "object" &&
|
||||
"item" in row &&
|
||||
"quantity" in row &&
|
||||
"price" in row
|
||||
).map((row) => ({
|
||||
item: String(row.item ?? ""),
|
||||
description: String(row.description ?? ""),
|
||||
quantity: parseNum(row.quantity),
|
||||
price: parseNum(row.price),
|
||||
}));
|
||||
}
|
||||
if (typeof o.tax === "number" && Number.isFinite(o.tax)) Data.tax = o.tax;
|
||||
else if (typeof o.tax === "string") Data.tax = parseNum(o.tax);
|
||||
if (typeof o.receiptTotal === "number" && Number.isFinite(o.receiptTotal)) {
|
||||
Data.receiptTotal = o.receiptTotal;
|
||||
} else if (typeof o.receiptTotal === "string") {
|
||||
Data.receiptTotal = parseNum(o.receiptTotal);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
return fail(400, { error: "Invalid receipt data JSON", form: "update" });
|
||||
}
|
||||
|
||||
const body: Record<string, unknown> = {
|
||||
Status: STATUS_OPTIONS.includes(Status as (typeof STATUS_OPTIONS)[number]) ? Status : "New",
|
||||
Type: TYPE_OPTIONS.includes(Type as (typeof TYPE_OPTIONS)[number]) ? Type : "Purchase",
|
||||
Data: Object.keys(Data).length ? Data : undefined,
|
||||
};
|
||||
if (hasImage) body.Image = imageFile;
|
||||
|
||||
try {
|
||||
await locals.pb.collection(COLLECTION).update(id, body);
|
||||
} catch (e: unknown) {
|
||||
const message =
|
||||
e && typeof e === "object" && "message" in e
|
||||
? String((e as { message: string }).message)
|
||||
: "Update failed";
|
||||
return fail(500, { error: message, form: "update" });
|
||||
}
|
||||
return { success: true };
|
||||
},
|
||||
|
||||
delete: async ({ locals, params }) => {
|
||||
const id = params.id;
|
||||
if (!id) return fail(400, { error: "Missing id", form: "delete" });
|
||||
try {
|
||||
await locals.pb.collection(COLLECTION).delete(id);
|
||||
} catch (e: unknown) {
|
||||
const message =
|
||||
e && typeof e === "object" && "message" in e
|
||||
? String((e as { message: string }).message)
|
||||
: "Delete failed";
|
||||
return fail(500, { error: message, form: "delete" });
|
||||
}
|
||||
throw redirect(303, "/receipts");
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user