@gelabs/ovr 0.2.2 → 0.4.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.
- package/dist/auth-auth.js +1 -1
- package/dist/auth.js +1 -1
- package/dist/{chunk-MDTRBOPQ.js → chunk-2C3VCTYJ.js} +1 -1
- package/dist/chunk-3YKVH4Y7.js +126 -0
- package/dist/chunk-6YFZLXFP.js +84 -0
- package/dist/{chunk-3NZ2XUBO.js → chunk-AJ2RZTVX.js} +9 -2
- package/dist/chunk-BI4EGLPG.js +298 -0
- package/dist/{chunk-3KIDW4LT.js → chunk-BVI5XDDA.js} +1 -1
- package/dist/chunk-DJMUW5T2.js +298 -0
- package/dist/{chunk-BIQ2J75Y.js → chunk-GLIK5BHP.js} +2 -2
- package/dist/{chunk-JEYT63LE.js → chunk-IBZVIUNI.js} +1 -1
- package/dist/{chunk-4SZXBT56.js → chunk-NT72CQAI.js} +2 -2
- package/dist/{chunk-E2D7QT6N.js → chunk-TJSNVTVB.js} +1 -1
- package/dist/{chunk-5Z2IAD5I.js → chunk-TLG4C2XI.js} +2 -2
- package/dist/chunk-V7VQVDWS.js +237 -0
- package/dist/chunk-WUNTHINH.js +98 -0
- package/dist/{chunk-IF5UAVIE.js → chunk-YC7G2IOZ.js} +1 -1
- package/dist/{chunk-IB4JVGKJ.js → chunk-YGYA7KEG.js} +47 -3
- package/dist/{chunk-GDOCD7LT.js → chunk-ZUMEOZ22.js} +5 -5
- package/dist/core-i18n.d.ts +2 -2
- package/dist/core-i18n.js +1 -1
- package/dist/core.d.ts +61 -1
- package/dist/core.js +1 -1
- package/dist/data-mock-store.js +330 -12
- package/dist/data-prisma-store.js +319 -9
- package/dist/data-seed-runner.js +18 -15
- package/dist/data.d.ts +64 -3
- package/dist/generated/client/edge.js +31 -10
- package/dist/generated/client/index-browser.js +28 -7
- package/dist/generated/client/index.d.ts +3583 -577
- package/dist/generated/client/index.js +31 -10
- package/dist/generated/client/package.json +1 -1
- package/dist/generated/client/schema.prisma +48 -9
- package/dist/generated/client/wasm.js +31 -10
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/offline.d.ts +34 -1
- package/dist/offline.js +2 -2
- package/dist/types-B8MopM4b.d.ts +281 -0
- package/dist/types.d.ts +104 -1
- package/dist/types.js +1 -1
- package/dist/ui-components-admin/accounts-manager.d.ts +52 -0
- package/dist/ui-components-admin/accounts-manager.js +471 -0
- package/dist/ui-components-admin/admin-nav.d.ts +15 -1
- package/dist/ui-components-admin/admin-nav.js +388 -60
- package/dist/ui-components-admin/issuance-form.js +72 -13
- package/dist/ui-components-admin/logs-viewer.d.ts +13 -0
- package/dist/ui-components-admin/logs-viewer.js +102 -0
- package/dist/ui-components-admin/notifications-list.d.ts +5 -0
- package/dist/ui-components-admin/notifications-list.js +70 -0
- package/dist/ui-components-admin/officers-manager.d.ts +27 -0
- package/dist/ui-components-admin/officers-manager.js +271 -0
- package/dist/ui-components-admin/roles-manager.d.ts +37 -0
- package/dist/ui-components-admin/roles-manager.js +406 -0
- package/dist/ui-components-admin/ticket-preview.js +7 -7
- package/dist/ui-components-admin/tickets-table.js +56 -33
- package/dist/ui-components-admin/violations-manager.d.ts +32 -0
- package/dist/ui-components-admin/violations-manager.js +385 -0
- package/dist/ui-components-citizen/citizen-nav.js +2 -2
- package/dist/ui-components-citizen/payment-form.js +5 -5
- package/dist/ui-components-citizen/payment-qr-dialog.js +4 -4
- package/dist/ui-components-citizen/ticket-not-found.js +2 -2
- package/dist/ui-components-citizen/violation-history-table.js +3 -3
- package/dist/ui-components-shared/amount-summary.js +4 -4
- package/dist/ui-components-shared/money.js +3 -3
- package/dist/ui-components-shared/municipal-seal.js +3 -3
- package/dist/ui-components-shared/official-header.js +4 -4
- package/dist/ui-components-shared/site-header.js +4 -4
- package/dist/ui-components-shared/sonner.js +2 -2
- package/dist/ui-components-shared/theme-toggle.js +3 -3
- package/dist/ui-components-shared/ticket-receipt.js +13 -6
- package/dist/ui-components-shared/violations-table.js +4 -4
- package/dist/ui-components-ui/badge.d.ts +1 -1
- package/dist/ui-components-ui/button.d.ts +1 -1
- package/dist/ui-components-ui/dropdown-menu.js +2 -237
- package/dist/ui-components-ui/sheet.js +3 -126
- package/dist/ui-config.d.ts +1 -1
- package/dist/ui-config.js +2 -2
- package/dist/ui-server.d.ts +1 -1
- package/dist/ui-server.js +2 -2
- package/package.json +6 -6
- package/prisma/migrations/20260622010000_add_super_admin_role/migration.sql +3 -0
- package/prisma/migrations/20260622020000_add_apprehending_enforcer/migration.sql +4 -0
- package/prisma/migrations/20260622030000_custom_roles/migration.sql +30 -0
- package/prisma/migrations/20260622040000_add_activity_log/migration.sql +18 -0
- package/prisma/migrations/20260622050000_violation_catalog_management/migration.sql +5 -0
- package/prisma/schema.prisma +48 -9
- package/dist/chunk-5YYR37CF.js +0 -146
- package/dist/chunk-B634JHKZ.js +0 -181
- package/dist/types-CtBC5-TW.d.ts +0 -129
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base (neutral) copy dictionary for OVR — the single source of user-facing
|
|
3
|
+
* strings, config-agnostic. The `{municipality}` token is resolved at read time
|
|
4
|
+
* by `mergeCopy()` against the active LGU's config (so this stays free of any app
|
|
5
|
+
* import). A per-LGU app supplies overrides; a Tagalog `baseCopyTl` can drop in
|
|
6
|
+
* later behind the same token/merge structure.
|
|
7
|
+
*/
|
|
8
|
+
declare const baseCopy: {
|
|
9
|
+
readonly app: {
|
|
10
|
+
readonly name: "e-OVR";
|
|
11
|
+
readonly tagline: "Online Ordinance Violation Receipt";
|
|
12
|
+
readonly description: "Issue, look up, and settle traffic and ordinance violation tickets online.";
|
|
13
|
+
};
|
|
14
|
+
readonly common: {
|
|
15
|
+
readonly search: "Search";
|
|
16
|
+
readonly clear: "Clear";
|
|
17
|
+
readonly cancel: "Cancel";
|
|
18
|
+
readonly confirm: "Confirm";
|
|
19
|
+
readonly back: "Back";
|
|
20
|
+
readonly print: "Print";
|
|
21
|
+
readonly payNow: "Pay now";
|
|
22
|
+
readonly payFine: "Pay fine";
|
|
23
|
+
readonly loading: "Loading…";
|
|
24
|
+
readonly notFound: "Not found";
|
|
25
|
+
readonly amountDue: "Amount due";
|
|
26
|
+
readonly totalDue: "Total amount due";
|
|
27
|
+
readonly dueDate: "Due date";
|
|
28
|
+
readonly status: "Status";
|
|
29
|
+
};
|
|
30
|
+
readonly landing: {
|
|
31
|
+
readonly heroTitle: "Settle violations online — fast, clear, and official.";
|
|
32
|
+
readonly heroSubtitle: "The {municipality}'s modern portal for traffic and ordinance violation receipts.";
|
|
33
|
+
readonly citizenCardTitle: "I have a ticket";
|
|
34
|
+
readonly citizenCardBody: "Look up your Ordinance Violation Receipt, review the details, and pay your fine online.";
|
|
35
|
+
readonly citizenCardCta: "Find my ticket";
|
|
36
|
+
readonly adminCardTitle: "I'm an enforcer";
|
|
37
|
+
readonly adminCardBody: "Issue a violation ticket on the spot and manage issued receipts.";
|
|
38
|
+
readonly adminCardCta: "Open enforcer portal";
|
|
39
|
+
};
|
|
40
|
+
readonly citizen: {
|
|
41
|
+
readonly searchTitle: "OVR Ticket Search";
|
|
42
|
+
readonly searchHelp: "Enter your OVR ticket number and last name to retrieve your violation record.";
|
|
43
|
+
readonly ticketNoLabel: "OVR Ticket No.";
|
|
44
|
+
readonly lastNameLabel: "Last name";
|
|
45
|
+
readonly euaLabel: "I accept the End-User Agreement";
|
|
46
|
+
readonly searchCta: "Search ticket";
|
|
47
|
+
readonly notFoundTitle: "No matching ticket";
|
|
48
|
+
readonly notFoundBody: "We couldn't find a ticket with that number and last name. Check your details and try again.";
|
|
49
|
+
readonly home: {
|
|
50
|
+
readonly title: "Find and settle your violation receipt";
|
|
51
|
+
readonly subtitle: "Enter your OVR ticket number and last name to view your Order of Payment and pay online.";
|
|
52
|
+
readonly searchCta: "Find my ticket";
|
|
53
|
+
readonly step1Title: "Find your ticket";
|
|
54
|
+
readonly step1Body: "Search using your OVR ticket number and last name.";
|
|
55
|
+
readonly step2Title: "Review the details";
|
|
56
|
+
readonly step2Body: "Check the violation, the basic fines, and any surcharge.";
|
|
57
|
+
readonly step3Title: "Pay online";
|
|
58
|
+
readonly step3Body: "Settle via GCash, Maya, or Landbank and keep your receipt.";
|
|
59
|
+
};
|
|
60
|
+
readonly ticket: {
|
|
61
|
+
readonly orderOfPayment: "Order of Payment";
|
|
62
|
+
readonly violationDetails: "Violation details";
|
|
63
|
+
readonly reminders: "Reminders & end-user notice";
|
|
64
|
+
readonly payFine: "Pay fine";
|
|
65
|
+
readonly printReceipt: "Print receipt";
|
|
66
|
+
readonly viewReceipt: "View / print receipt";
|
|
67
|
+
readonly backToSearch: "Back to search";
|
|
68
|
+
readonly alreadyPaid: "This ticket has already been paid.";
|
|
69
|
+
readonly history: {
|
|
70
|
+
readonly title: "Violation history";
|
|
71
|
+
readonly subtitle: "All OVR tickets on record under this name.";
|
|
72
|
+
readonly current: "Current";
|
|
73
|
+
readonly empty: "No other violation records found under this name.";
|
|
74
|
+
readonly colTicketNo: "OVR Ticket No.";
|
|
75
|
+
readonly colDate: "Apprehended";
|
|
76
|
+
readonly colViolations: "Violation(s)";
|
|
77
|
+
readonly colStatus: "Status";
|
|
78
|
+
readonly colAmount: "Amount";
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
readonly pay: {
|
|
82
|
+
readonly title: "Pay your fine";
|
|
83
|
+
readonly subtitle: "Choose a payment method to settle this violation.";
|
|
84
|
+
readonly choose: "Choose payment method";
|
|
85
|
+
readonly payNow: "Pay";
|
|
86
|
+
readonly processing: "Processing payment…";
|
|
87
|
+
readonly secure: "Simulated checkout — no real payment is processed.";
|
|
88
|
+
readonly success: "Payment successful — your receipt is ready.";
|
|
89
|
+
readonly qr: {
|
|
90
|
+
readonly title: "Scan to pay";
|
|
91
|
+
readonly instruction: "Open your e-wallet app, scan this QR, then tap below once your payment is complete.";
|
|
92
|
+
readonly placeholderNote: "Demo placeholder — the official merchant QR will appear here once the payment gateway is live.";
|
|
93
|
+
readonly amountToPay: "Amount to pay";
|
|
94
|
+
readonly confirm: "I've completed payment";
|
|
95
|
+
readonly cancel: "Cancel";
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
readonly admin: {
|
|
100
|
+
readonly portal: "Enforcer Portal";
|
|
101
|
+
readonly dashboard: "Dashboard";
|
|
102
|
+
readonly tickets: "Tickets";
|
|
103
|
+
readonly issueTicket: "Issue ticket";
|
|
104
|
+
readonly accounts: "Accounts";
|
|
105
|
+
readonly roles: "Roles";
|
|
106
|
+
readonly officers: "Officers";
|
|
107
|
+
readonly violations: "Violations";
|
|
108
|
+
readonly logs: "Activity log";
|
|
109
|
+
readonly more: "More";
|
|
110
|
+
readonly signOut: "Sign out";
|
|
111
|
+
readonly signOutConfirmTitle: "Sign out?";
|
|
112
|
+
readonly signOutConfirmBody: "You'll need to sign in again to issue or manage tickets.";
|
|
113
|
+
readonly cancel: "Cancel";
|
|
114
|
+
readonly newTicketTitle: "Issue Violation Ticket";
|
|
115
|
+
readonly accountsPage: {
|
|
116
|
+
readonly title: "Accounts";
|
|
117
|
+
readonly subtitle: "Create and manage who can sign in to the enforcer portal. Each account's role decides what it can see and do.";
|
|
118
|
+
readonly newAccount: "New account";
|
|
119
|
+
readonly edit: "Edit";
|
|
120
|
+
readonly editTitle: "Edit account";
|
|
121
|
+
readonly saveChanges: "Save changes";
|
|
122
|
+
readonly username: "Username";
|
|
123
|
+
readonly password: "Password";
|
|
124
|
+
readonly role: "Role";
|
|
125
|
+
readonly officer: "Linked officer";
|
|
126
|
+
readonly officerNone: "— None —";
|
|
127
|
+
readonly officerHint: "Link an enforcer to an officer record so issued tickets are attributed.";
|
|
128
|
+
readonly status: "Status";
|
|
129
|
+
readonly active: "Active";
|
|
130
|
+
readonly inactive: "Inactive";
|
|
131
|
+
readonly created: "Created";
|
|
132
|
+
readonly actions: "Actions";
|
|
133
|
+
readonly create: "Create account";
|
|
134
|
+
readonly creating: "Creating…";
|
|
135
|
+
readonly deactivate: "Deactivate";
|
|
136
|
+
readonly activate: "Activate";
|
|
137
|
+
readonly resetPassword: "Reset password";
|
|
138
|
+
readonly newPassword: "New password";
|
|
139
|
+
readonly save: "Save";
|
|
140
|
+
readonly saving: "Saving…";
|
|
141
|
+
readonly cancel: "Cancel";
|
|
142
|
+
readonly empty: "No accounts yet — create the first one.";
|
|
143
|
+
readonly you: "You";
|
|
144
|
+
};
|
|
145
|
+
readonly rolesPage: {
|
|
146
|
+
readonly title: "Roles & permissions";
|
|
147
|
+
readonly subtitle: "Define what each role can do. Create custom roles, set their permissions, then assign them to accounts.";
|
|
148
|
+
readonly newRole: "New role";
|
|
149
|
+
readonly roleName: "Role name";
|
|
150
|
+
readonly roleNamePlaceholder: "e.g. Cashier, Supervisor";
|
|
151
|
+
readonly permissions: "Permissions";
|
|
152
|
+
readonly editPermissions: "Edit permissions";
|
|
153
|
+
readonly noPermissions: "No permissions";
|
|
154
|
+
readonly permissionsCount: "permissions";
|
|
155
|
+
readonly system: "System";
|
|
156
|
+
readonly custom: "Custom";
|
|
157
|
+
readonly create: "Create role";
|
|
158
|
+
readonly creating: "Creating…";
|
|
159
|
+
readonly save: "Save";
|
|
160
|
+
readonly saving: "Saving…";
|
|
161
|
+
readonly saved: "Saved";
|
|
162
|
+
readonly cancel: "Cancel";
|
|
163
|
+
readonly delete: "Delete";
|
|
164
|
+
readonly deleteConfirmTitle: "Delete this role?";
|
|
165
|
+
readonly deleteConfirmBody: "Move any accounts off this role first. This can't be undone.";
|
|
166
|
+
readonly lockedHint: "Super Admin always keeps account & role management.";
|
|
167
|
+
readonly empty: "No roles yet — create the first one.";
|
|
168
|
+
readonly inUseSuffix: "in use";
|
|
169
|
+
};
|
|
170
|
+
readonly logsPage: {
|
|
171
|
+
readonly title: "Activity log";
|
|
172
|
+
readonly subtitle: "Audit trail of what accounts did — sign-ins, ticket issuance, and account & role changes.";
|
|
173
|
+
readonly allActions: "All actions";
|
|
174
|
+
readonly search: "Search actor or detail…";
|
|
175
|
+
readonly actor: "Actor";
|
|
176
|
+
readonly action: "Action";
|
|
177
|
+
readonly detail: "Detail";
|
|
178
|
+
readonly when: "When";
|
|
179
|
+
readonly empty: "No activity recorded yet.";
|
|
180
|
+
readonly system: "system";
|
|
181
|
+
};
|
|
182
|
+
readonly officersPage: {
|
|
183
|
+
readonly title: "Apprehending officers";
|
|
184
|
+
readonly subtitle: "Officers who apprehend violations — shown in the Issue-Ticket form and linked to enforcer accounts.";
|
|
185
|
+
readonly newOfficer: "New officer";
|
|
186
|
+
readonly name: "Full name";
|
|
187
|
+
readonly namePlaceholder: "e.g. DELA CRUZ, JUAN P.";
|
|
188
|
+
readonly badge: "Badge no.";
|
|
189
|
+
readonly badgePlaceholder: "e.g. A176";
|
|
190
|
+
readonly office: "Office";
|
|
191
|
+
readonly officePlaceholder: "e.g. POSO";
|
|
192
|
+
readonly edit: "Edit";
|
|
193
|
+
readonly editTitle: "Edit officer";
|
|
194
|
+
readonly create: "Add officer";
|
|
195
|
+
readonly creating: "Adding…";
|
|
196
|
+
readonly save: "Save";
|
|
197
|
+
readonly saving: "Saving…";
|
|
198
|
+
readonly cancel: "Cancel";
|
|
199
|
+
readonly delete: "Remove";
|
|
200
|
+
readonly deleteConfirmTitle: "Remove this officer?";
|
|
201
|
+
readonly deleteConfirmBody: "This can't be undone. Officers with issued tickets or a linked account can't be removed.";
|
|
202
|
+
readonly empty: "No officers yet — add the first one.";
|
|
203
|
+
readonly actions: "Actions";
|
|
204
|
+
};
|
|
205
|
+
readonly violationsPage: {
|
|
206
|
+
readonly title: "Violation catalog";
|
|
207
|
+
readonly subtitle: "The ordinance / violation schedule enforcers issue against. Archived entries are hidden from the Issue-Ticket form but kept for old tickets.";
|
|
208
|
+
readonly newViolation: "New violation";
|
|
209
|
+
readonly code: "Code";
|
|
210
|
+
readonly codePlaceholder: "e.g. ORD 2021-05 S.4";
|
|
211
|
+
readonly titleLabel: "Title";
|
|
212
|
+
readonly titlePlaceholder: "e.g. No helmet (driver)";
|
|
213
|
+
readonly category: "Category";
|
|
214
|
+
readonly categoryTraffic: "Traffic";
|
|
215
|
+
readonly categoryOrdinance: "Ordinance";
|
|
216
|
+
readonly fine: "Basic fine (₱)";
|
|
217
|
+
readonly finePlaceholder: "e.g. 500";
|
|
218
|
+
readonly legalText: "Legal basis (optional)";
|
|
219
|
+
readonly legalTextPlaceholder: "e.g. Sec. 4, Municipal Ordinance No. 2021-05";
|
|
220
|
+
readonly status: "Status";
|
|
221
|
+
readonly active: "Active";
|
|
222
|
+
readonly archived: "Archived";
|
|
223
|
+
readonly edit: "Edit";
|
|
224
|
+
readonly editTitle: "Edit violation";
|
|
225
|
+
readonly create: "Add violation";
|
|
226
|
+
readonly creating: "Adding…";
|
|
227
|
+
readonly save: "Save";
|
|
228
|
+
readonly saving: "Saving…";
|
|
229
|
+
readonly cancel: "Cancel";
|
|
230
|
+
readonly archive: "Archive";
|
|
231
|
+
readonly restore: "Restore";
|
|
232
|
+
readonly archiveConfirmTitle: "Archive this violation?";
|
|
233
|
+
readonly archiveConfirmBody: "It will be hidden from the Issue-Ticket form. Already-issued tickets keep their copy, and you can restore it anytime.";
|
|
234
|
+
readonly empty: "No violations yet — add the first one.";
|
|
235
|
+
readonly actions: "Actions";
|
|
236
|
+
};
|
|
237
|
+
readonly notifications: {
|
|
238
|
+
readonly title: "Notifications";
|
|
239
|
+
readonly subtitle: "Tickets that need attention — overdue and outstanding.";
|
|
240
|
+
readonly empty: "You're all caught up.";
|
|
241
|
+
readonly overdue: "Overdue";
|
|
242
|
+
readonly outstanding: "Outstanding";
|
|
243
|
+
readonly viewAll: "View all";
|
|
244
|
+
};
|
|
245
|
+
readonly changePassword: {
|
|
246
|
+
readonly title: "Change password";
|
|
247
|
+
readonly subtitle: "Enter your current password, then your new one.";
|
|
248
|
+
readonly current: "Current password";
|
|
249
|
+
readonly new: "New password";
|
|
250
|
+
readonly confirm: "Confirm new password";
|
|
251
|
+
readonly submit: "Update password";
|
|
252
|
+
readonly saving: "Updating…";
|
|
253
|
+
readonly cancel: "Cancel";
|
|
254
|
+
readonly mismatch: "New passwords don't match.";
|
|
255
|
+
readonly success: "Password updated.";
|
|
256
|
+
};
|
|
257
|
+
readonly sync: {
|
|
258
|
+
readonly offline: "Offline";
|
|
259
|
+
readonly syncing: "Syncing…";
|
|
260
|
+
readonly synced: "Synced";
|
|
261
|
+
readonly pending: "pending sync";
|
|
262
|
+
readonly notSynced: "Not synced";
|
|
263
|
+
readonly willSync: "Saved on this device — will sync when back online.";
|
|
264
|
+
};
|
|
265
|
+
};
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
type DeepMutable<T> = T extends string ? string : {
|
|
269
|
+
-readonly [K in keyof T]: DeepMutable<T[K]>;
|
|
270
|
+
};
|
|
271
|
+
/** Deep-mutable mirror of the base shape (leaves widen to string). */
|
|
272
|
+
type Dictionary = {
|
|
273
|
+
[K in keyof typeof baseCopy]: DeepMutable<(typeof baseCopy)[K]>;
|
|
274
|
+
};
|
|
275
|
+
type DeepPartial<T> = T extends string ? T : {
|
|
276
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
277
|
+
};
|
|
278
|
+
/** Per-LGU partial override (any subtree, any depth). NOT shallow Partial. */
|
|
279
|
+
type CopyOverrides = DeepPartial<Dictionary>;
|
|
280
|
+
|
|
281
|
+
export { type CopyOverrides as C, type Dictionary as D, baseCopy as b };
|
package/dist/types.d.ts
CHANGED
|
@@ -16,6 +16,17 @@ interface ViolationCatalogItem {
|
|
|
16
16
|
category: ViolationCategory;
|
|
17
17
|
basicFine: number;
|
|
18
18
|
legalText?: string;
|
|
19
|
+
/** false = archived: hidden from issuance but kept so old tickets stay
|
|
20
|
+
* resolvable. Absent = active (back-compat with un-migrated seed data). */
|
|
21
|
+
active?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** What an admin submits to create a catalog entry (GE-031). `code` is the id. */
|
|
24
|
+
interface NewViolationInput {
|
|
25
|
+
code: string;
|
|
26
|
+
title: string;
|
|
27
|
+
category: ViolationCategory;
|
|
28
|
+
basicFine: number;
|
|
29
|
+
legalText?: string;
|
|
19
30
|
}
|
|
20
31
|
/** A catalog item as attached to a ticket, snapshotted + enforcer details. */
|
|
21
32
|
interface IssuedViolation {
|
|
@@ -42,6 +53,12 @@ interface Officer {
|
|
|
42
53
|
badgeNo?: string;
|
|
43
54
|
office: string;
|
|
44
55
|
}
|
|
56
|
+
/** What an admin submits to add/edit an apprehending officer (GE-025). */
|
|
57
|
+
interface NewOfficerInput {
|
|
58
|
+
name: string;
|
|
59
|
+
badgeNo?: string;
|
|
60
|
+
office: string;
|
|
61
|
+
}
|
|
45
62
|
type PaymentMethod = "GCASH" | "MAYA" | "LANDBANK" | "OVER_THE_COUNTER";
|
|
46
63
|
interface Payment {
|
|
47
64
|
method: PaymentMethod;
|
|
@@ -65,6 +82,8 @@ interface TicketRecord {
|
|
|
65
82
|
violations: IssuedViolation[];
|
|
66
83
|
remarks?: string;
|
|
67
84
|
issuedBy?: string;
|
|
85
|
+
apprehendingEnforcerId?: string;
|
|
86
|
+
apprehendingEnforcerName?: string;
|
|
68
87
|
assessedAt: string;
|
|
69
88
|
dueDate: string;
|
|
70
89
|
basicFinesTotal: number;
|
|
@@ -78,5 +97,89 @@ interface Ticket extends TicketRecord {
|
|
|
78
97
|
penaltyAmount: number;
|
|
79
98
|
totalAmountDue: number;
|
|
80
99
|
}
|
|
100
|
+
/** Every capability the app gates on. Add a gate by extending this + the catalog. */
|
|
101
|
+
type Permission = "dashboard:view" | "tickets:view" | "tickets:create" | "accounts:manage" | "roles:manage" | "officers:manage" | "violations:manage" | "logs:view" | "notifications:view";
|
|
102
|
+
interface PermissionDef {
|
|
103
|
+
key: Permission;
|
|
104
|
+
label: string;
|
|
105
|
+
description: string;
|
|
106
|
+
}
|
|
107
|
+
/** The catalog shown in the Roles editor (array order = display order). */
|
|
108
|
+
declare const PERMISSION_CATALOG: PermissionDef[];
|
|
109
|
+
declare const ALL_PERMISSIONS: Permission[];
|
|
110
|
+
/** A role + its permission set. `isSystem` roles can't be renamed or deleted. */
|
|
111
|
+
interface RoleDef {
|
|
112
|
+
name: string;
|
|
113
|
+
label: string;
|
|
114
|
+
isSystem: boolean;
|
|
115
|
+
permissions: Permission[];
|
|
116
|
+
}
|
|
117
|
+
/** What an admin submits to create a custom role. */
|
|
118
|
+
interface NewRoleInput {
|
|
119
|
+
label: string;
|
|
120
|
+
permissions: Permission[];
|
|
121
|
+
}
|
|
122
|
+
/** The built-in roles, seeded into every deployment. */
|
|
123
|
+
declare const SYSTEM_ROLES: RoleDef[];
|
|
124
|
+
/** Default role assigned to a new account / seeded login. */
|
|
125
|
+
declare const DEFAULT_ROLE_NAME = "ENFORCER";
|
|
126
|
+
/** SUPER_ADMIN ALWAYS keeps these (anti-lockout): locked-on in the Roles editor
|
|
127
|
+
* and re-asserted server-side, so no one can revoke their own ability to manage
|
|
128
|
+
* accounts/roles and lock everyone out. */
|
|
129
|
+
declare const SUPER_ADMIN_LOCKED_PERMISSIONS: Permission[];
|
|
130
|
+
/** Whether a permission set grants a capability. Safe with null/undefined. */
|
|
131
|
+
declare function hasPermission(permissions: readonly string[] | null | undefined, permission: Permission): boolean;
|
|
132
|
+
/** A user account as shown to admins (NEVER carries the password hash). */
|
|
133
|
+
interface UserAccount {
|
|
134
|
+
id: string;
|
|
135
|
+
username: string;
|
|
136
|
+
role: string;
|
|
137
|
+
roleLabel?: string;
|
|
138
|
+
active: boolean;
|
|
139
|
+
officerId: string | null;
|
|
140
|
+
/** Convenience: the linked officer's display name, if any. */
|
|
141
|
+
officerName?: string;
|
|
142
|
+
createdAt: string;
|
|
143
|
+
}
|
|
144
|
+
/** What an admin submits to create an account. The password hash is computed by
|
|
145
|
+
* the app (argon2 stays out of the data layer), mirroring the seed path. */
|
|
146
|
+
interface NewUserInput {
|
|
147
|
+
username: string;
|
|
148
|
+
passwordHash: string;
|
|
149
|
+
role: string;
|
|
150
|
+
officerId?: string | null;
|
|
151
|
+
}
|
|
152
|
+
/** The recorded action kinds (extensible; stored as a string for forward-compat). */
|
|
153
|
+
declare const ACTIVITY_ACTIONS: readonly ["auth.login", "auth.logout", "ticket.issued", "account.create", "account.update", "account.activate", "account.deactivate", "account.password_reset", "account.password_change", "role.create", "role.update", "role.delete", "officer.create", "officer.update", "officer.delete", "violation.create", "violation.update", "violation.delete"];
|
|
154
|
+
type ActivityAction = (typeof ACTIVITY_ACTIONS)[number];
|
|
155
|
+
declare const ACTIVITY_ACTION_LABELS: Record<ActivityAction, string>;
|
|
156
|
+
/** One audit-trail entry: who did what, when. */
|
|
157
|
+
interface ActivityLog {
|
|
158
|
+
id: string;
|
|
159
|
+
actorId: string | null;
|
|
160
|
+
actorUsername: string | null;
|
|
161
|
+
action: string;
|
|
162
|
+
summary: string;
|
|
163
|
+
targetType?: string;
|
|
164
|
+
targetId?: string;
|
|
165
|
+
createdAt: string;
|
|
166
|
+
}
|
|
167
|
+
/** What the app records for an event (id + createdAt are assigned by the store). */
|
|
168
|
+
interface NewActivityInput {
|
|
169
|
+
actorId?: string | null;
|
|
170
|
+
actorUsername?: string | null;
|
|
171
|
+
action: ActivityAction;
|
|
172
|
+
summary: string;
|
|
173
|
+
targetType?: string;
|
|
174
|
+
targetId?: string;
|
|
175
|
+
}
|
|
176
|
+
/** Filter for an activity-log query. */
|
|
177
|
+
interface ActivityFilter {
|
|
178
|
+
action?: string;
|
|
179
|
+
actorId?: string;
|
|
180
|
+
fromISO?: string;
|
|
181
|
+
toISO?: string;
|
|
182
|
+
limit?: number;
|
|
183
|
+
}
|
|
81
184
|
|
|
82
|
-
export type
|
|
185
|
+
export { ACTIVITY_ACTIONS, ACTIVITY_ACTION_LABELS, ALL_PERMISSIONS, type ActivityAction, type ActivityFilter, type ActivityLog, DEFAULT_ROLE_NAME, type IssuedViolation, type NewActivityInput, type NewOfficerInput, type NewRoleInput, type NewUserInput, type NewViolationInput, type Officer, PERMISSION_CATALOG, type Payment, type PaymentMethod, type PaymentStatus, type Permission, type PermissionDef, type RoleDef, SUPER_ADMIN_LOCKED_PERMISSIONS, SYSTEM_ROLES, type Ticket, type TicketRecord, type TicketStatus, type UserAccount, type ViolationCatalogItem, type ViolationCategory, type Violator, hasPermission };
|
package/dist/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export { ACTIVITY_ACTIONS, ACTIVITY_ACTION_LABELS, ALL_PERMISSIONS, DEFAULT_ROLE_NAME, PERMISSION_CATALOG, SUPER_ADMIN_LOCKED_PERMISSIONS, SYSTEM_ROLES, hasPermission } from './chunk-WUNTHINH.js';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { UserAccount, Officer, RoleDef } from '../types.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Account management UI (GE-013). Super admins create & manage who can sign in to
|
|
6
|
+
* the enforcer portal; each account's role decides what it can see/do. The server
|
|
7
|
+
* actions (create / activate / reset password) are INJECTED by the page so this
|
|
8
|
+
* component stays free of any app-specific data wiring — mirrors IssuanceForm.
|
|
9
|
+
*
|
|
10
|
+
* Online-only: account management needs the server (argon2 + DB). After a mutation
|
|
11
|
+
* we refresh the route so the server-rendered list reflects the change.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** What the create form submits — the page hashes the password server-side. */
|
|
15
|
+
interface CreateAccountInput {
|
|
16
|
+
username: string;
|
|
17
|
+
password: string;
|
|
18
|
+
role: string;
|
|
19
|
+
officerId: string | null;
|
|
20
|
+
}
|
|
21
|
+
type CreateAccountAction = (input: CreateAccountInput) => Promise<{
|
|
22
|
+
error?: string;
|
|
23
|
+
} | void>;
|
|
24
|
+
type SetAccountActiveAction = (id: string, active: boolean) => Promise<{
|
|
25
|
+
error?: string;
|
|
26
|
+
} | void>;
|
|
27
|
+
type ResetAccountPasswordAction = (id: string, password: string) => Promise<{
|
|
28
|
+
error?: string;
|
|
29
|
+
} | void>;
|
|
30
|
+
interface EditAccountInput {
|
|
31
|
+
username?: string;
|
|
32
|
+
role?: string;
|
|
33
|
+
officerId?: string | null;
|
|
34
|
+
}
|
|
35
|
+
type EditAccountAction = (id: string, patch: EditAccountInput) => Promise<{
|
|
36
|
+
error?: string;
|
|
37
|
+
} | void>;
|
|
38
|
+
interface AccountsManagerProps {
|
|
39
|
+
users: UserAccount[];
|
|
40
|
+
officers: Officer[];
|
|
41
|
+
/** Roles assignable to accounts (system + custom). */
|
|
42
|
+
roles: RoleDef[];
|
|
43
|
+
/** The signed-in user's id — so they can't deactivate their own account. */
|
|
44
|
+
currentUserId?: string;
|
|
45
|
+
createAction: CreateAccountAction;
|
|
46
|
+
editAction: EditAccountAction;
|
|
47
|
+
setActiveAction: SetAccountActiveAction;
|
|
48
|
+
resetPasswordAction: ResetAccountPasswordAction;
|
|
49
|
+
}
|
|
50
|
+
declare function AccountsManager({ users, officers, roles, currentUserId, createAction, editAction, setActiveAction, resetPasswordAction, }: AccountsManagerProps): React.JSX.Element;
|
|
51
|
+
|
|
52
|
+
export { AccountsManager, type AccountsManagerProps, type CreateAccountAction, type CreateAccountInput, type EditAccountAction, type EditAccountInput, type ResetAccountPasswordAction, type SetAccountActiveAction };
|