- Next.js 14 + Tailwind + TypeScript scaffolded - PocketBase v0.39.8 collections: JEI_invoices, JEI_invoice_lines, JEI_stock_codes (30 fields total, locked to superuser) - PDF extraction: scripts/extract_invoices.py parses 33 PDFs -> 38 records - Import script: scripts/import_to_pb.py idempotent push to PB - Imported: 24 invoices, 70+ stock codes, 118 invoice lines - Pages: /, /invoices, /invoices/[id], /stock-codes, /stock-codes/[code] - All 5 pages verified returning 200 with real data on port 6002
36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
import PocketBase from "pocketbase";
|
|
|
|
// Singleton PocketBase client. Created lazily so it picks up env at runtime,
|
|
// not at build time (Next.js server-side rendering).
|
|
let _pb: PocketBase | null = null;
|
|
|
|
export function getPb(): PocketBase {
|
|
if (_pb) return _pb;
|
|
const url =
|
|
process.env.NEXT_PUBLIC_PB_URL ||
|
|
process.env.PB_URL ||
|
|
"https://pb.agent.apphub.co.za";
|
|
_pb = new PocketBase(url);
|
|
const token = process.env.PB_TOKEN;
|
|
if (token) {
|
|
_pb.authStore.save(token);
|
|
}
|
|
return _pb;
|
|
}
|
|
|
|
// Helper: format a number as £ currency (just a prefix — values stay as numbers)
|
|
export function fmtGBP(n: number | undefined | null): string {
|
|
if (n === undefined || n === null || isNaN(n)) return "£0.00";
|
|
return "£" + n.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
}
|
|
|
|
export function fmtNum(n: number | undefined | null): string {
|
|
if (n === undefined || n === null || isNaN(n)) return "0";
|
|
return n.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
}
|
|
|
|
export function fmtDate(iso: string | undefined | null): string {
|
|
if (!iso) return "";
|
|
// PB date format is "YYYY-MM-DD HH:MM:SS.SSSZ"; show just the date part
|
|
return iso.substring(0, 10);
|
|
}
|