80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
import { cache } from "react";
|
|
import type { Metadata } from "next";
|
|
import { readBillPayload } from "../../../lib/bills";
|
|
import { BILL_NOT_FOUND, formatBillDate, parseBill, type BillView } from "../../../lib/bill-view";
|
|
import { money } from "../../../lib/money";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
const loadBill = cache(async (token: string): Promise<BillView | null> => {
|
|
const raw = await readBillPayload(token);
|
|
if (!raw) return null;
|
|
return parseBill(raw);
|
|
});
|
|
|
|
export async function generateMetadata({
|
|
params,
|
|
}: {
|
|
params: Promise<{ token: string }>;
|
|
}): Promise<Metadata> {
|
|
const { token } = await params;
|
|
const bill = await loadBill(token);
|
|
if (!bill) return { title: "100kmph invoice" };
|
|
return { title: `${bill.number || "Invoice"} · 100kmph` };
|
|
}
|
|
|
|
export default async function BillPage({ params }: { params: Promise<{ token: string }> }) {
|
|
const { token } = await params;
|
|
const bill = await loadBill(token);
|
|
if (!bill) return <main id="bill">{BILL_NOT_FOUND}</main>;
|
|
|
|
const when = formatBillDate(bill.createdAt);
|
|
return (
|
|
<main id="bill">
|
|
<h1>{bill.shopName || "100kmph"}</h1>
|
|
<p className="muted">{bill.address}</p>
|
|
<p className="muted">{bill.phone ? `Ph: ${bill.phone}` : ""}</p>
|
|
<hr />
|
|
<p>
|
|
<strong>Invoice {bill.number}</strong>
|
|
<br />
|
|
{when}
|
|
</p>
|
|
<p>
|
|
Customer: {bill.customerName || "-"}
|
|
<br />
|
|
Phone: {bill.customerPhone || "-"}
|
|
{bill.vehicleReg ? (
|
|
<>
|
|
<br />
|
|
Vehicle: {bill.vehicleReg} {bill.vehicleModel}
|
|
</>
|
|
) : null}
|
|
</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Item</th>
|
|
<th className="num">Qty</th>
|
|
<th className="num">Rate</th>
|
|
<th className="num">Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{bill.lines.map((line, index) => (
|
|
<tr key={index}>
|
|
<td>{line.description}</td>
|
|
<td className="num">{line.qty ?? ""}</td>
|
|
<td className="num">{money(line.unitPrice)}</td>
|
|
<td className="num">{money(line.lineTotal)}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
<p className="total">Total {money(bill.total)}</p>
|
|
<p>Paid by: {bill.paymentMethod.toUpperCase()}</p>
|
|
<p className="foot">Digital invoice from 100kmph. You can print this page if you need paper.</p>
|
|
</main>
|
|
);
|
|
}
|