@gelabs/ovr 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/chunk-3KIDW4LT.js +13 -0
  2. package/dist/chunk-4SZXBT56.js +26 -0
  3. package/dist/chunk-55FQP2DO.js +46 -0
  4. package/dist/{chunk-JV7QQ22Q.js → chunk-5YYR37CF.js} +10 -1
  5. package/dist/chunk-5Z2IAD5I.js +72 -0
  6. package/dist/chunk-BBQBKQA4.js +31 -0
  7. package/dist/chunk-BIQ2J75Y.js +54 -0
  8. package/dist/chunk-E2D7QT6N.js +92 -0
  9. package/dist/chunk-EGKFELO3.js +15 -0
  10. package/dist/chunk-EYFZWQ4J.js +74 -0
  11. package/dist/chunk-GDOCD7LT.js +46 -0
  12. package/dist/chunk-IF5UAVIE.js +25 -0
  13. package/dist/chunk-JEYT63LE.js +25 -0
  14. package/dist/chunk-K3KIBHJF.js +20 -0
  15. package/dist/chunk-M35R6JLA.js +142 -0
  16. package/dist/chunk-MDTRBOPQ.js +22 -0
  17. package/dist/chunk-NSCIBSCW.js +24 -0
  18. package/dist/chunk-OE525ZER.js +31 -0
  19. package/dist/chunk-OWCGEEAZ.js +107 -0
  20. package/dist/chunk-QCRVT2SS.js +18 -0
  21. package/dist/chunk-SETIN6XP.js +95 -0
  22. package/dist/chunk-WOPU6DI7.js +77 -0
  23. package/dist/chunk-XQTVSNHC.js +18 -0
  24. package/dist/core-i18n.d.ts +2 -2
  25. package/dist/core-i18n.js +1 -1
  26. package/dist/data-db.d.ts +1 -4
  27. package/dist/data-mock-store.js +53 -1
  28. package/dist/data-prisma-store.d.ts +3 -1
  29. package/dist/data-prisma-store.js +84 -1
  30. package/dist/data-seed-runner.d.ts +2 -1
  31. package/dist/data.d.ts +13 -1
  32. package/dist/offline.d.ts +126 -0
  33. package/dist/offline.js +376 -0
  34. package/dist/{types-DrrNO_Ak.d.ts → types-CtBC5-TW.d.ts} +8 -0
  35. package/dist/ui-components-admin/admin-nav.d.ts +7 -0
  36. package/dist/ui-components-admin/admin-nav.js +83 -0
  37. package/dist/ui-components-admin/issuance-form.d.ts +15 -0
  38. package/dist/ui-components-admin/issuance-form.js +367 -0
  39. package/dist/ui-components-admin/stat-card.d.ts +10 -0
  40. package/dist/ui-components-admin/stat-card.js +29 -0
  41. package/dist/ui-components-admin/ticket-preview.d.ts +9 -0
  42. package/dist/ui-components-admin/ticket-preview.js +13 -0
  43. package/dist/ui-components-admin/tickets-table.d.ts +8 -0
  44. package/dist/ui-components-admin/tickets-table.js +50 -0
  45. package/dist/ui-components-citizen/citizen-nav.d.ts +5 -0
  46. package/dist/ui-components-citizen/citizen-nav.js +33 -0
  47. package/dist/ui-components-citizen/payment-form.d.ts +14 -0
  48. package/dist/ui-components-citizen/payment-form.js +168 -0
  49. package/dist/ui-components-citizen/payment-qr-dialog.d.ts +30 -0
  50. package/dist/ui-components-citizen/payment-qr-dialog.js +9 -0
  51. package/dist/ui-components-citizen/ticket-not-found.d.ts +5 -0
  52. package/dist/ui-components-citizen/ticket-not-found.js +21 -0
  53. package/dist/ui-components-citizen/violation-history-table.d.ts +16 -0
  54. package/dist/ui-components-citizen/violation-history-table.js +77 -0
  55. package/dist/ui-components-shared/amount-summary.d.ts +8 -0
  56. package/dist/ui-components-shared/amount-summary.js +7 -0
  57. package/dist/ui-components-shared/money.d.ts +9 -0
  58. package/dist/ui-components-shared/money.js +5 -0
  59. package/dist/ui-components-shared/municipal-seal.d.ts +11 -0
  60. package/dist/ui-components-shared/municipal-seal.js +6 -0
  61. package/dist/ui-components-shared/official-header.d.ts +5 -0
  62. package/dist/ui-components-shared/official-header.js +7 -0
  63. package/dist/ui-components-shared/print-button.d.ts +8 -0
  64. package/dist/ui-components-shared/print-button.js +17 -0
  65. package/dist/ui-components-shared/seal.d.ts +12 -0
  66. package/dist/ui-components-shared/seal.js +2 -0
  67. package/dist/ui-components-shared/site-header.d.ts +13 -0
  68. package/dist/ui-components-shared/site-header.js +40 -0
  69. package/dist/ui-components-shared/sonner.d.ts +6 -0
  70. package/dist/ui-components-shared/sonner.js +38 -0
  71. package/dist/ui-components-shared/status-badge.d.ts +9 -0
  72. package/dist/ui-components-shared/status-badge.js +3 -0
  73. package/dist/ui-components-shared/theme-toggle.d.ts +7 -0
  74. package/dist/ui-components-shared/theme-toggle.js +6 -0
  75. package/dist/ui-components-shared/ticket-receipt.d.ts +12 -0
  76. package/dist/ui-components-shared/ticket-receipt.js +158 -0
  77. package/dist/ui-components-shared/violations-table.d.ts +8 -0
  78. package/dist/ui-components-shared/violations-table.js +7 -0
  79. package/dist/ui-components-ui/alert.js +2 -74
  80. package/dist/ui-components-ui/badge.d.ts +1 -1
  81. package/dist/ui-components-ui/badge.js +2 -46
  82. package/dist/ui-components-ui/button.d.ts +2 -2
  83. package/dist/ui-components-ui/card.js +2 -95
  84. package/dist/ui-components-ui/checkbox.js +2 -31
  85. package/dist/ui-components-ui/dialog.js +3 -142
  86. package/dist/ui-components-ui/input.js +2 -20
  87. package/dist/ui-components-ui/label.js +2 -18
  88. package/dist/ui-components-ui/separator.js +2 -24
  89. package/dist/ui-components-ui/skeleton.js +2 -15
  90. package/dist/ui-components-ui/table.js +2 -107
  91. package/dist/ui-components-ui/textarea.js +2 -18
  92. package/dist/ui-config.d.ts +19 -2
  93. package/dist/ui-config.js +2 -36
  94. package/dist/ui-server.d.ts +1 -1
  95. package/dist/ui-server.js +1 -1
  96. package/package.json +24 -4
@@ -0,0 +1,168 @@
1
+ "use client";
2
+ import { PaymentQrDialog } from '../chunk-5Z2IAD5I.js';
3
+ import { Separator } from '../chunk-NSCIBSCW.js';
4
+ import { Alert, AlertDescription } from '../chunk-EYFZWQ4J.js';
5
+ import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '../chunk-SETIN6XP.js';
6
+ import { Money } from '../chunk-3KIDW4LT.js';
7
+ import '../chunk-M35R6JLA.js';
8
+ import { Button } from '../chunk-I4WDVYHX.js';
9
+ import { useOvrConfig, useCopy } from '../chunk-E2D7QT6N.js';
10
+ import { cn } from '../chunk-77QBZC7J.js';
11
+ import '../chunk-B634JHKZ.js';
12
+ import * as React from 'react';
13
+ import { toast } from 'sonner';
14
+ import { Check, TriangleAlert, Loader2, Lock, Building2, Landmark, Smartphone, Wallet } from 'lucide-react';
15
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
16
+
17
+ var ICONS = {
18
+ GCASH: /* @__PURE__ */ jsx(Wallet, { className: "size-5" }),
19
+ MAYA: /* @__PURE__ */ jsx(Smartphone, { className: "size-5" }),
20
+ LANDBANK: /* @__PURE__ */ jsx(Landmark, { className: "size-5" }),
21
+ OVER_THE_COUNTER: /* @__PURE__ */ jsx(Building2, { className: "size-5" })
22
+ };
23
+ function PaymentForm({
24
+ ovrTicketNo,
25
+ lastName,
26
+ violatorName,
27
+ basicFines,
28
+ penalty,
29
+ amount,
30
+ payAction
31
+ }) {
32
+ const { paymentMethods } = useOvrConfig();
33
+ const copy = useCopy();
34
+ const payMethods = paymentMethods.filter((m) => m.id !== "OVER_THE_COUNTER");
35
+ const [method, setMethod] = React.useState(
36
+ () => payMethods[0]?.id ?? "GCASH"
37
+ );
38
+ const [error, setError] = React.useState(null);
39
+ const [isPending, startTransition] = React.useTransition();
40
+ const [qrOpen, setQrOpen] = React.useState(false);
41
+ function pay() {
42
+ setError(null);
43
+ startTransition(async () => {
44
+ const res = await payAction({ ovrTicketNo, lastName, method });
45
+ if (res?.error) {
46
+ setError(res.error);
47
+ toast.error(res.error);
48
+ }
49
+ });
50
+ }
51
+ const methodLabel = paymentMethods.find((m) => m.id === method)?.label ?? method;
52
+ function handlePay() {
53
+ if (method === "OVER_THE_COUNTER") {
54
+ pay();
55
+ } else {
56
+ setError(null);
57
+ setQrOpen(true);
58
+ }
59
+ }
60
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
61
+ /* @__PURE__ */ jsxs(Card, { className: "overflow-visible", children: [
62
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
63
+ /* @__PURE__ */ jsx(CardTitle, { className: "text-xl", children: copy.citizen.pay.title }),
64
+ /* @__PURE__ */ jsxs(CardDescription, { children: [
65
+ violatorName,
66
+ " \xB7 ",
67
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: ovrTicketNo })
68
+ ] })
69
+ ] }),
70
+ /* @__PURE__ */ jsxs(CardContent, { className: "space-y-5", children: [
71
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-lg border bg-muted/20 p-3 text-sm", children: [
72
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
73
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Basic fines" }),
74
+ /* @__PURE__ */ jsx(Money, { value: basicFines })
75
+ ] }),
76
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
77
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Penalty / surcharge" }),
78
+ /* @__PURE__ */ jsx(
79
+ Money,
80
+ {
81
+ value: penalty,
82
+ className: cn(penalty === 0 && "text-muted-foreground")
83
+ }
84
+ )
85
+ ] }),
86
+ /* @__PURE__ */ jsx(Separator, {}),
87
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between", children: [
88
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Total to pay" }),
89
+ /* @__PURE__ */ jsx(Money, { value: amount, className: "text-xl font-bold" })
90
+ ] })
91
+ ] }),
92
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
93
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: copy.citizen.pay.choose }),
94
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: payMethods.map((m) => {
95
+ const active = method === m.id;
96
+ return /* @__PURE__ */ jsxs(
97
+ "button",
98
+ {
99
+ type: "button",
100
+ onClick: () => setMethod(m.id),
101
+ "aria-pressed": active,
102
+ className: cn(
103
+ "flex items-center gap-2.5 rounded-lg border p-3 text-left transition-colors outline-none focus-visible:ring-3 focus-visible:ring-ring/50",
104
+ active ? "border-primary bg-primary/5 ring-1 ring-primary/30" : "hover:bg-muted/40"
105
+ ),
106
+ children: [
107
+ /* @__PURE__ */ jsx(
108
+ "span",
109
+ {
110
+ className: cn(
111
+ "flex size-9 shrink-0 items-center justify-center rounded-lg",
112
+ active ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
113
+ ),
114
+ children: ICONS[m.id]
115
+ }
116
+ ),
117
+ /* @__PURE__ */ jsx("span", { className: "min-w-0", children: /* @__PURE__ */ jsx("span", { className: "block truncate text-sm font-medium", children: m.label }) }),
118
+ active ? /* @__PURE__ */ jsx(Check, { className: "ml-auto size-4 shrink-0 text-primary" }) : null
119
+ ]
120
+ },
121
+ m.id
122
+ );
123
+ }) })
124
+ ] }),
125
+ error ? /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
126
+ /* @__PURE__ */ jsx(TriangleAlert, {}),
127
+ /* @__PURE__ */ jsx(AlertDescription, { children: error })
128
+ ] }) : null,
129
+ /* @__PURE__ */ jsx(
130
+ Button,
131
+ {
132
+ onClick: handlePay,
133
+ disabled: isPending,
134
+ className: "h-11 w-full gap-2 text-base",
135
+ children: isPending ? /* @__PURE__ */ jsxs(Fragment, { children: [
136
+ /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin" }),
137
+ copy.citizen.pay.processing
138
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
139
+ /* @__PURE__ */ jsx(Lock, { className: "size-4" }),
140
+ copy.citizen.pay.payNow,
141
+ " ",
142
+ /* @__PURE__ */ jsx(Money, { value: amount, className: "font-semibold" })
143
+ ] })
144
+ }
145
+ ),
146
+ /* @__PURE__ */ jsxs("p", { className: "flex items-center justify-center gap-1.5 text-center text-xs text-muted-foreground", children: [
147
+ /* @__PURE__ */ jsx(Lock, { className: "size-3" }),
148
+ copy.citizen.pay.secure
149
+ ] })
150
+ ] })
151
+ ] }),
152
+ /* @__PURE__ */ jsx(
153
+ PaymentQrDialog,
154
+ {
155
+ open: qrOpen,
156
+ onOpenChange: setQrOpen,
157
+ method,
158
+ methodLabel,
159
+ amount,
160
+ ovrTicketNo,
161
+ lastName,
162
+ payAction
163
+ }
164
+ )
165
+ ] });
166
+ }
167
+
168
+ export { PaymentForm };
@@ -0,0 +1,30 @@
1
+ import * as React from 'react';
2
+
3
+ /** The Server Action that settles the payment, injected by the consuming page. */
4
+ type PayAction = (args: {
5
+ ovrTicketNo: string;
6
+ lastName: string;
7
+ method: string;
8
+ }) => Promise<{
9
+ error?: string;
10
+ } | void>;
11
+ /**
12
+ * "Scan to pay" modal for the online payment methods (GCash / Maya / Landbank).
13
+ *
14
+ * The QR is a DEMO PLACEHOLDER — there is no real payment gateway yet. Once a
15
+ * gateway is integrated, the placeholder block is replaced by the gateway's
16
+ * per-transaction QR, and "I've completed payment" is replaced by a webhook/
17
+ * callback confirmation BEFORE the ticket is marked PAID.
18
+ */
19
+ declare function PaymentQrDialog({ open, onOpenChange, method, methodLabel, amount, ovrTicketNo, lastName, payAction, }: {
20
+ open: boolean;
21
+ onOpenChange: (open: boolean) => void;
22
+ method: string;
23
+ methodLabel: string;
24
+ amount: number;
25
+ ovrTicketNo: string;
26
+ lastName: string;
27
+ payAction: PayAction;
28
+ }): React.JSX.Element;
29
+
30
+ export { type PayAction, PaymentQrDialog };
@@ -0,0 +1,9 @@
1
+ "use client";
2
+ export { PaymentQrDialog } from '../chunk-5Z2IAD5I.js';
3
+ import '../chunk-EYFZWQ4J.js';
4
+ import '../chunk-3KIDW4LT.js';
5
+ import '../chunk-M35R6JLA.js';
6
+ import '../chunk-I4WDVYHX.js';
7
+ import '../chunk-E2D7QT6N.js';
8
+ import '../chunk-77QBZC7J.js';
9
+ import '../chunk-B634JHKZ.js';
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+
3
+ declare function TicketNotFound(): React.JSX.Element;
4
+
5
+ export { TicketNotFound };
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { Card, CardContent } from '../chunk-SETIN6XP.js';
3
+ import { buttonVariants } from '../chunk-I4WDVYHX.js';
4
+ import { useCopy } from '../chunk-E2D7QT6N.js';
5
+ import '../chunk-77QBZC7J.js';
6
+ import '../chunk-B634JHKZ.js';
7
+ import Link from 'next/link';
8
+ import { FileQuestion } from 'lucide-react';
9
+ import { jsx, jsxs } from 'react/jsx-runtime';
10
+
11
+ function TicketNotFound() {
12
+ const copy = useCopy();
13
+ return /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-lg px-4 py-16 text-center", children: /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(CardContent, { className: "flex flex-col items-center gap-3 py-8", children: [
14
+ /* @__PURE__ */ jsx("div", { className: "flex size-12 items-center justify-center rounded-full bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx(FileQuestion, { className: "size-6" }) }),
15
+ /* @__PURE__ */ jsx("h1", { className: "font-heading text-lg font-semibold", children: copy.citizen.notFoundTitle }),
16
+ /* @__PURE__ */ jsx("p", { className: "max-w-sm text-sm text-muted-foreground", children: copy.citizen.notFoundBody }),
17
+ /* @__PURE__ */ jsx(Link, { href: "/citizen/search", className: buttonVariants({}), children: copy.citizen.ticket.backToSearch })
18
+ ] }) }) });
19
+ }
20
+
21
+ export { TicketNotFound };
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ import { Ticket } from '../types.js';
3
+
4
+ /**
5
+ * Read-only "violation history" table for the citizen ticket page: every OVR
6
+ * ticket on record for the same violator (matched by name). Mirrors the admin
7
+ * `TicketsTable` layout but is citizen-scoped — its rows link back into the
8
+ * citizen flow (`/citizen/ticket/<no>?ln=...`), never the admin pages.
9
+ */
10
+ declare function ViolationHistoryTable({ tickets, currentTicketNo, lastName, }: {
11
+ tickets: Ticket[];
12
+ currentTicketNo: string;
13
+ lastName: string;
14
+ }): React.JSX.Element;
15
+
16
+ export { ViolationHistoryTable };
@@ -0,0 +1,77 @@
1
+ "use client";
2
+ import { StatusBadge } from '../chunk-OE525ZER.js';
3
+ import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from '../chunk-OWCGEEAZ.js';
4
+ import '../chunk-55FQP2DO.js';
5
+ import { Money } from '../chunk-3KIDW4LT.js';
6
+ import { useFormatters, useCopy } from '../chunk-E2D7QT6N.js';
7
+ import { cn } from '../chunk-77QBZC7J.js';
8
+ import '../chunk-B634JHKZ.js';
9
+ import Link from 'next/link';
10
+ import { ChevronRight } from 'lucide-react';
11
+ import { jsx, jsxs } from 'react/jsx-runtime';
12
+
13
+ function ViolationHistoryTable({
14
+ tickets,
15
+ currentTicketNo,
16
+ lastName
17
+ }) {
18
+ const { formatDate } = useFormatters();
19
+ const copy = useCopy();
20
+ const t = copy.citizen.ticket.history;
21
+ if (tickets.length === 0) {
22
+ return /* @__PURE__ */ jsx("div", { className: "px-4 py-10 text-center text-sm text-muted-foreground", children: t.empty });
23
+ }
24
+ return /* @__PURE__ */ jsxs(Table, { children: [
25
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
26
+ /* @__PURE__ */ jsx(TableHead, { children: t.colTicketNo }),
27
+ /* @__PURE__ */ jsx(TableHead, { className: "hidden sm:table-cell", children: t.colDate }),
28
+ /* @__PURE__ */ jsx(TableHead, { children: t.colViolations }),
29
+ /* @__PURE__ */ jsx(TableHead, { children: t.colStatus }),
30
+ /* @__PURE__ */ jsx(TableHead, { className: "text-right", children: t.colAmount }),
31
+ /* @__PURE__ */ jsx(TableHead, { className: "w-8" })
32
+ ] }) }),
33
+ /* @__PURE__ */ jsx(TableBody, { children: tickets.map((ticket) => {
34
+ const isCurrent = ticket.ovrTicketNo === currentTicketNo;
35
+ const href = `/citizen/ticket/${encodeURIComponent(
36
+ ticket.ovrTicketNo
37
+ )}?ln=${encodeURIComponent(lastName)}`;
38
+ const amount = ticket.status === "PAID" ? ticket.payment?.amount ?? 0 : ticket.totalAmountDue;
39
+ const first = ticket.violations[0];
40
+ const extra = ticket.violations.length - 1;
41
+ return /* @__PURE__ */ jsxs(
42
+ TableRow,
43
+ {
44
+ className: cn(isCurrent && "bg-muted/40"),
45
+ children: [
46
+ /* @__PURE__ */ jsx(TableCell, { className: "font-mono text-xs", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
47
+ /* @__PURE__ */ jsx(Link, { href, className: "hover:underline", children: ticket.ovrTicketNo }),
48
+ isCurrent ? /* @__PURE__ */ jsx("span", { className: "rounded bg-brand/12 px-1.5 py-0.5 text-[0.65rem] font-medium uppercase tracking-wide text-brand", children: t.current }) : null
49
+ ] }) }),
50
+ /* @__PURE__ */ jsx(TableCell, { className: "hidden text-muted-foreground sm:table-cell", children: formatDate(ticket.apprehendedAt) }),
51
+ /* @__PURE__ */ jsxs(TableCell, { className: "max-w-[16rem] truncate text-muted-foreground", children: [
52
+ first?.title ?? "\u2014",
53
+ extra > 0 ? /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
54
+ " +",
55
+ extra
56
+ ] }) : null
57
+ ] }),
58
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(StatusBadge, { status: ticket.status }) }),
59
+ /* @__PURE__ */ jsx(TableCell, { className: "text-right", children: /* @__PURE__ */ jsx(Money, { value: amount }) }),
60
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(
61
+ Link,
62
+ {
63
+ href,
64
+ className: "text-muted-foreground hover:text-foreground",
65
+ "aria-label": `Open ${ticket.ovrTicketNo}`,
66
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" })
67
+ }
68
+ ) })
69
+ ]
70
+ },
71
+ ticket.ovrTicketNo
72
+ );
73
+ }) })
74
+ ] });
75
+ }
76
+
77
+ export { ViolationHistoryTable };
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ import { Ticket } from '../types.js';
3
+
4
+ declare function AmountSummary({ ticket }: {
5
+ ticket: Ticket;
6
+ }): React.JSX.Element;
7
+
8
+ export { AmountSummary };
@@ -0,0 +1,7 @@
1
+ "use client";
2
+ export { AmountSummary } from '../chunk-BIQ2J75Y.js';
3
+ import '../chunk-NSCIBSCW.js';
4
+ import '../chunk-3KIDW4LT.js';
5
+ import '../chunk-E2D7QT6N.js';
6
+ import '../chunk-77QBZC7J.js';
7
+ import '../chunk-B634JHKZ.js';
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+
3
+ /** Peso amount with tabular figures so columns align. */
4
+ declare function Money({ value, className, }: {
5
+ value: number;
6
+ className?: string;
7
+ }): React.JSX.Element;
8
+
9
+ export { Money };
@@ -0,0 +1,5 @@
1
+ "use client";
2
+ export { Money } from '../chunk-3KIDW4LT.js';
3
+ import '../chunk-E2D7QT6N.js';
4
+ import '../chunk-77QBZC7J.js';
5
+ import '../chunk-B634JHKZ.js';
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * Renders the official municipal seal from the config `sealSrc` when present,
5
+ * falling back to the placeholder SVG emblem if the image is missing.
6
+ */
7
+ declare function MunicipalSeal({ className }: {
8
+ className?: string;
9
+ }): React.JSX.Element;
10
+
11
+ export { MunicipalSeal };
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ export { MunicipalSeal } from '../chunk-IF5UAVIE.js';
3
+ import '../chunk-WOPU6DI7.js';
4
+ import '../chunk-E2D7QT6N.js';
5
+ import '../chunk-77QBZC7J.js';
6
+ import '../chunk-B634JHKZ.js';
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+
3
+ declare function OfficialHeader(): React.JSX.Element;
4
+
5
+ export { OfficialHeader };
@@ -0,0 +1,7 @@
1
+ "use client";
2
+ export { OfficialHeader } from '../chunk-4SZXBT56.js';
3
+ import '../chunk-IF5UAVIE.js';
4
+ import '../chunk-WOPU6DI7.js';
5
+ import '../chunk-E2D7QT6N.js';
6
+ import '../chunk-77QBZC7J.js';
7
+ import '../chunk-B634JHKZ.js';
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+
3
+ declare function PrintButton({ className, label, }: {
4
+ className?: string;
5
+ label?: string;
6
+ }): React.JSX.Element;
7
+
8
+ export { PrintButton };
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { Button } from '../chunk-I4WDVYHX.js';
3
+ import { cn } from '../chunk-77QBZC7J.js';
4
+ import { Printer } from 'lucide-react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function PrintButton({
8
+ className,
9
+ label = "Print"
10
+ }) {
11
+ return /* @__PURE__ */ jsxs(Button, { onClick: () => window.print(), className: cn("gap-2", className), children: [
12
+ /* @__PURE__ */ jsx(Printer, { className: "size-4" }),
13
+ label
14
+ ] });
15
+ }
16
+
17
+ export { PrintButton };
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * Generic placeholder municipal emblem — a "sun over waves" mark in the brand
5
+ * palette, used as the fallback when an LGU has not supplied an official seal.
6
+ * The real seal is config-driven (see municipal-seal.tsx and the config sealSrc).
7
+ */
8
+ declare function Seal({ className }: {
9
+ className?: string;
10
+ }): React.JSX.Element;
11
+
12
+ export { Seal };
@@ -0,0 +1,2 @@
1
+ export { Seal } from '../chunk-WOPU6DI7.js';
2
+ import '../chunk-77QBZC7J.js';
@@ -0,0 +1,13 @@
1
+ import * as React$1 from 'react';
2
+
3
+ /**
4
+ * The single, official header used across the app: municipal seal + Municipality
5
+ * identity + e-OVR name/meaning on the left; a context nav slot (`children`) + a
6
+ * theme toggle on the right. One bar — no stacked headers.
7
+ */
8
+ declare function SiteHeader({ homeHref, children, }: {
9
+ homeHref?: string;
10
+ children?: React.ReactNode;
11
+ }): React$1.JSX.Element;
12
+
13
+ export { SiteHeader };
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { ThemeToggle } from '../chunk-MDTRBOPQ.js';
3
+ import { MunicipalSeal } from '../chunk-IF5UAVIE.js';
4
+ import '../chunk-WOPU6DI7.js';
5
+ import '../chunk-I4WDVYHX.js';
6
+ import { useOvrConfig, useCopy } from '../chunk-E2D7QT6N.js';
7
+ import '../chunk-77QBZC7J.js';
8
+ import '../chunk-B634JHKZ.js';
9
+ import Link from 'next/link';
10
+ import { jsx, jsxs } from 'react/jsx-runtime';
11
+
12
+ function SiteHeader({
13
+ homeHref = "/",
14
+ children
15
+ }) {
16
+ const { municipality } = useOvrConfig();
17
+ const copy = useCopy();
18
+ return /* @__PURE__ */ jsx("header", { className: "no-print sticky top-0 z-40 border-b border-white/10 bg-gov text-gov-foreground", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-6xl items-center justify-between gap-3 px-4 py-2.5 sm:px-6", children: [
19
+ /* @__PURE__ */ jsxs(Link, { href: homeHref, className: "flex items-center gap-3", children: [
20
+ /* @__PURE__ */ jsx(MunicipalSeal, { className: "size-10 shrink-0 sm:size-11" }),
21
+ /* @__PURE__ */ jsxs("span", { className: "leading-tight", children: [
22
+ /* @__PURE__ */ jsx("span", { className: "block text-[0.7rem] opacity-80", children: municipality.name }),
23
+ /* @__PURE__ */ jsxs("span", { className: "block text-sm font-bold tracking-tight sm:text-base", children: [
24
+ copy.app.name,
25
+ /* @__PURE__ */ jsxs("span", { className: "hidden font-normal opacity-80 sm:inline", children: [
26
+ " ",
27
+ "\u2014 ",
28
+ copy.app.tagline
29
+ ] })
30
+ ] })
31
+ ] })
32
+ ] }),
33
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
34
+ children,
35
+ /* @__PURE__ */ jsx(ThemeToggle, { className: "text-gov-foreground hover:bg-white/10 hover:text-gov-foreground" })
36
+ ] })
37
+ ] }) });
38
+ }
39
+
40
+ export { SiteHeader };
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ import { ToasterProps } from 'sonner';
3
+
4
+ declare const Toaster: ({ ...props }: ToasterProps) => React.JSX.Element;
5
+
6
+ export { Toaster };
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ import { useTheme } from '../chunk-E2D7QT6N.js';
3
+ import '../chunk-B634JHKZ.js';
4
+ import { Toaster as Toaster$1 } from 'sonner';
5
+ import { Loader2Icon, OctagonXIcon, TriangleAlertIcon, InfoIcon, CircleCheckIcon } from 'lucide-react';
6
+ import { jsx } from 'react/jsx-runtime';
7
+
8
+ var Toaster = ({ ...props }) => {
9
+ const { resolvedTheme } = useTheme();
10
+ return /* @__PURE__ */ jsx(
11
+ Toaster$1,
12
+ {
13
+ theme: resolvedTheme,
14
+ className: "toaster group",
15
+ icons: {
16
+ success: /* @__PURE__ */ jsx(CircleCheckIcon, { className: "size-4" }),
17
+ info: /* @__PURE__ */ jsx(InfoIcon, { className: "size-4" }),
18
+ warning: /* @__PURE__ */ jsx(TriangleAlertIcon, { className: "size-4" }),
19
+ error: /* @__PURE__ */ jsx(OctagonXIcon, { className: "size-4" }),
20
+ loading: /* @__PURE__ */ jsx(Loader2Icon, { className: "size-4 animate-spin" })
21
+ },
22
+ style: {
23
+ "--normal-bg": "var(--popover)",
24
+ "--normal-text": "var(--popover-foreground)",
25
+ "--normal-border": "var(--border)",
26
+ "--border-radius": "var(--radius)"
27
+ },
28
+ toastOptions: {
29
+ classNames: {
30
+ toast: "cn-toast"
31
+ }
32
+ },
33
+ ...props
34
+ }
35
+ );
36
+ };
37
+
38
+ export { Toaster };
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ import { TicketStatus } from '../types.js';
3
+
4
+ declare function StatusBadge({ status, className, }: {
5
+ status: TicketStatus;
6
+ className?: string;
7
+ }): React.JSX.Element;
8
+
9
+ export { StatusBadge };
@@ -0,0 +1,3 @@
1
+ export { StatusBadge } from '../chunk-OE525ZER.js';
2
+ import '../chunk-55FQP2DO.js';
3
+ import '../chunk-77QBZC7J.js';
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+
3
+ declare function ThemeToggle({ className }: {
4
+ className?: string;
5
+ }): React.JSX.Element;
6
+
7
+ export { ThemeToggle };
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ export { ThemeToggle } from '../chunk-MDTRBOPQ.js';
3
+ import '../chunk-I4WDVYHX.js';
4
+ import '../chunk-E2D7QT6N.js';
5
+ import '../chunk-77QBZC7J.js';
6
+ import '../chunk-B634JHKZ.js';
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+ import { Ticket } from '../types.js';
3
+
4
+ /**
5
+ * The canonical OVR "Order of Payment" document — rendered identically for the
6
+ * citizen receipt and the admin print view. Print-friendly (white paper look).
7
+ */
8
+ declare function TicketReceipt({ ticket }: {
9
+ ticket: Ticket;
10
+ }): React.JSX.Element;
11
+
12
+ export { TicketReceipt };