Refactor image upload handling across items and receipts routes to include validation for uploaded images, enhancing error handling and user feedback. Consolidate parsing functions by importing from a shared module, improving code maintainability. Update server hooks to ensure consistent cookie handling and error logging.
This commit is contained in:
@@ -2,17 +2,14 @@ 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";
|
||||
import { parseNumWithDefault } from "$lib/parse-form";
|
||||
import { validateImageUpload } from "$lib/validate-image-upload";
|
||||
|
||||
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;
|
||||
}
|
||||
const MAX_LINE_ITEMS = 500;
|
||||
|
||||
export const load: PageServerLoad = async ({ params, locals }) => {
|
||||
const { id } = params;
|
||||
@@ -43,6 +40,10 @@ export const actions: Actions = {
|
||||
const dataJson = (form.get("dataJson") as string)?.trim() ?? "{}";
|
||||
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, form: "update" });
|
||||
}
|
||||
|
||||
let Data: ReceiptDataShape = {};
|
||||
try {
|
||||
@@ -50,26 +51,27 @@ export const actions: Actions = {
|
||||
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(
|
||||
const filtered = 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) => ({
|
||||
);
|
||||
Data.lineItems = filtered.slice(0, MAX_LINE_ITEMS).map((row) => ({
|
||||
item: String(row.item ?? ""),
|
||||
description: String(row.description ?? ""),
|
||||
quantity: parseNum(row.quantity),
|
||||
price: parseNum(row.price),
|
||||
quantity: parseNumWithDefault(row.quantity, 0),
|
||||
price: parseNumWithDefault(row.price, 0),
|
||||
}));
|
||||
}
|
||||
if (typeof o.tax === "number" && Number.isFinite(o.tax)) Data.tax = o.tax;
|
||||
else if (typeof o.tax === "string") Data.tax = parseNum(o.tax);
|
||||
else if (typeof o.tax === "string") Data.tax = parseNumWithDefault(o.tax, 0);
|
||||
if (typeof o.receiptTotal === "number" && Number.isFinite(o.receiptTotal)) {
|
||||
Data.receiptTotal = o.receiptTotal;
|
||||
} else if (typeof o.receiptTotal === "string") {
|
||||
Data.receiptTotal = parseNum(o.receiptTotal);
|
||||
Data.receiptTotal = parseNumWithDefault(o.receiptTotal, 0);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user