diff --git a/frontend/package.json b/frontend/package.json index a8d92d3..35271f0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -36,6 +36,7 @@ "eslint-plugin-svelte": "^3.0.0", "formsnap": "^2.0.1", "globals": "^17.3.0", + "jsdom": "^29.1.1", "mode-watcher": "^1.1.0", "prettier": "^3.8.1", "prettier-plugin-svelte": "^3.5.0", @@ -54,7 +55,8 @@ "tw-animate-css": "^1.4.0", "typescript": "^5.9.3", "typescript-eslint": "^8.20.0", - "vite": "^7.0.4" + "vite": "^7.0.4", + "vitest": "^4.1.9" }, "dependencies": { "@discourse/jxl": "^1.3.0", diff --git a/frontend/src/lib/stores/businessInfo.svelte.ts b/frontend/src/lib/stores/businessInfo.svelte.ts new file mode 100644 index 0000000..a18d175 --- /dev/null +++ b/frontend/src/lib/stores/businessInfo.svelte.ts @@ -0,0 +1,36 @@ +// src/lib/stores/businessInfo.svelte.ts +import type { BusinessSettings } from '$lib/types/settings'; + +let businessInfo = $state(null); +let loadingPromise: Promise | null = null; + +/** + * Fetches /api/business-info exactly once and caches the result. + * Subsequent calls return the cached promise or resolved value. + * Errors are handled gracefully — returns null. + */ +export async function ensureBusinessInfo(): Promise { + if (businessInfo !== null) return businessInfo; + if (loadingPromise) return loadingPromise; + + loadingPromise = fetch('/api/business-info') + .then((r) => (r.ok ? r.json() : null)) + .then((data) => { + businessInfo = data as BusinessSettings | null; + return businessInfo; + }) + .catch(() => { + businessInfo = null; + return null; + }); + + return loadingPromise; +} + +/** + * Returns the current cached business info (reactive via $state). + * Use in $derived or $effect to track changes. + */ +export function getBusinessInfo(): BusinessSettings | null { + return businessInfo; +} diff --git a/frontend/src/lib/types/index.ts b/frontend/src/lib/types/index.ts index 938c96a..1f43d8b 100644 --- a/frontend/src/lib/types/index.ts +++ b/frontend/src/lib/types/index.ts @@ -48,6 +48,8 @@ export interface PaymentSummary { paid_amount: number; refunded_amount: number; remaining_amount: number; + total_vat_amount: number; + total_net_amount: number; payments: Payment[]; refunds: Refund[]; }