@hed-hog/billing 0.0.2 → 0.0.286

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 (51) hide show
  1. package/README.md +420 -0
  2. package/dist/billing-contracts.controller.d.ts +85 -4
  3. package/dist/billing-contracts.controller.d.ts.map +1 -1
  4. package/dist/billing-coupons.controller.d.ts +60 -4
  5. package/dist/billing-coupons.controller.d.ts.map +1 -1
  6. package/dist/billing-dashboard.controller.d.ts +20 -5
  7. package/dist/billing-dashboard.controller.d.ts.map +1 -1
  8. package/dist/billing-entitlements.controller.d.ts +28 -2
  9. package/dist/billing-entitlements.controller.d.ts.map +1 -1
  10. package/dist/billing-gateways.controller.d.ts +18 -2
  11. package/dist/billing-gateways.controller.d.ts.map +1 -1
  12. package/dist/billing-invoices.controller.d.ts +56 -2
  13. package/dist/billing-invoices.controller.d.ts.map +1 -1
  14. package/dist/billing-offers.controller.d.ts +61 -4
  15. package/dist/billing-offers.controller.d.ts.map +1 -1
  16. package/dist/billing-orders.controller.d.ts +39 -2
  17. package/dist/billing-orders.controller.d.ts.map +1 -1
  18. package/dist/billing-payments.controller.d.ts +16 -1
  19. package/dist/billing-payments.controller.d.ts.map +1 -1
  20. package/dist/billing-prices.controller.d.ts +80 -4
  21. package/dist/billing-prices.controller.d.ts.map +1 -1
  22. package/dist/billing-products.controller.d.ts +62 -4
  23. package/dist/billing-products.controller.d.ts.map +1 -1
  24. package/dist/billing-subscriptions.controller.d.ts +138 -5
  25. package/dist/billing-subscriptions.controller.d.ts.map +1 -1
  26. package/dist/billing.service.d.ts +663 -39
  27. package/dist/billing.service.d.ts.map +1 -1
  28. package/dist/billing.service.js +135 -16
  29. package/dist/billing.service.js.map +1 -1
  30. package/hedhog/data/menu.yaml +1 -1
  31. package/hedhog/frontend/app/contracts/page.tsx.ejs +68 -64
  32. package/hedhog/frontend/app/coupons/page.tsx.ejs +81 -77
  33. package/hedhog/frontend/app/entitlements/page.tsx.ejs +59 -58
  34. package/hedhog/frontend/app/gateways/page.tsx.ejs +125 -57
  35. package/hedhog/frontend/app/invoices/page.tsx.ejs +49 -43
  36. package/hedhog/frontend/app/offers/page.tsx.ejs +68 -64
  37. package/hedhog/frontend/app/orders/page.tsx.ejs +47 -46
  38. package/hedhog/frontend/app/page.tsx.ejs +186 -186
  39. package/hedhog/frontend/app/payments/page.tsx.ejs +51 -45
  40. package/hedhog/frontend/app/prices/page.tsx.ejs +81 -75
  41. package/hedhog/frontend/app/products/page.tsx.ejs +79 -73
  42. package/hedhog/frontend/app/refunds/page.tsx.ejs +50 -44
  43. package/hedhog/frontend/app/reports/page.tsx.ejs +1 -1
  44. package/hedhog/frontend/app/seats/page.tsx.ejs +826 -0
  45. package/hedhog/frontend/app/subscriptions/page.tsx.ejs +95 -90
  46. package/hedhog/frontend/app/webhooks/page.tsx.ejs +47 -39
  47. package/hedhog/frontend/messages/en.json +640 -551
  48. package/hedhog/frontend/messages/pt.json +652 -563
  49. package/hedhog/table/billing_payment_method.yaml +1 -1
  50. package/package.json +4 -3
  51. package/src/billing.service.ts +299 -17
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import {
4
+ EmptyState,
4
5
  Page,
5
6
  PageHeader,
6
7
  PaginationFooter,
@@ -16,6 +17,7 @@ import {
16
17
  TableRow,
17
18
  } from '@/components/ui/table';
18
19
  import { useApp, useQuery } from '@hed-hog/next-app-provider';
20
+ import { FileText } from 'lucide-react';
19
21
  import { useTranslations } from 'next-intl';
20
22
  import { useState } from 'react';
21
23
 
@@ -63,7 +65,7 @@ const formatDate = (value: string | null) => {
63
65
  };
64
66
 
65
67
  export default function BillingInvoicesPage() {
66
- const t = useTranslations('BillingInvoicesPage');
68
+ const t = useTranslations('billing.BillingInvoicesPage');
67
69
  const { request, currentLocaleCode } = useApp();
68
70
  const [search, setSearch] = useState('');
69
71
  const [page, setPage] = useState(1);
@@ -119,50 +121,54 @@ export default function BillingInvoicesPage() {
119
121
  placeholder={t('filters.searchPlaceholder')}
120
122
  />
121
123
 
122
- <div className="overflow-x-auto rounded-md border">
123
- <Table>
124
- <TableHeader>
125
- <TableRow>
126
- <TableHead>{t('table.columns.invoiceNumber')}</TableHead>
127
- <TableHead>{t('table.columns.status')}</TableHead>
128
- <TableHead>{t('table.columns.currency')}</TableHead>
129
- <TableHead>{t('table.columns.total')}</TableHead>
130
- <TableHead>{t('table.columns.dueDate')}</TableHead>
131
- <TableHead>{t('table.columns.paidAt')}</TableHead>
132
- </TableRow>
133
- </TableHeader>
134
- <TableBody>
135
- {items.length === 0 && (
124
+ {items.length > 0 ? (
125
+ <div className="overflow-x-auto rounded-md border">
126
+ <Table>
127
+ <TableHeader>
136
128
  <TableRow>
137
- <TableCell
138
- colSpan={6}
139
- className="text-center text-muted-foreground"
140
- >
141
- {t('table.empty')}
142
- </TableCell>
129
+ <TableHead>{t('table.columns.invoiceNumber')}</TableHead>
130
+ <TableHead>{t('table.columns.status')}</TableHead>
131
+ <TableHead>{t('table.columns.currency')}</TableHead>
132
+ <TableHead>{t('table.columns.total')}</TableHead>
133
+ <TableHead>{t('table.columns.dueDate')}</TableHead>
134
+ <TableHead>{t('table.columns.paidAt')}</TableHead>
143
135
  </TableRow>
144
- )}
145
- {items.map((item) => (
146
- <TableRow key={item.id}>
147
- <TableCell className="font-medium">
148
- {item.invoice_number}
149
- </TableCell>
150
- <TableCell>
151
- <Badge className={badgeClass(item.status)}>
152
- {item.status}
153
- </Badge>
154
- </TableCell>
155
- <TableCell>{item.currency}</TableCell>
156
- <TableCell>
157
- {formatCurrency(item.total_cents, item.currency)}
158
- </TableCell>
159
- <TableCell>{formatDate(item.due_date)}</TableCell>
160
- <TableCell>{formatDate(item.paid_at)}</TableCell>
161
- </TableRow>
162
- ))}
163
- </TableBody>
164
- </Table>
165
- </div>
136
+ </TableHeader>
137
+ <TableBody>
138
+ {items.map((item) => (
139
+ <TableRow key={item.id}>
140
+ <TableCell className="font-medium">
141
+ {item.invoice_number}
142
+ </TableCell>
143
+ <TableCell>
144
+ <Badge className={badgeClass(item.status)}>
145
+ {item.status}
146
+ </Badge>
147
+ </TableCell>
148
+ <TableCell>{item.currency}</TableCell>
149
+ <TableCell>
150
+ {formatCurrency(item.total_cents, item.currency)}
151
+ </TableCell>
152
+ <TableCell>{formatDate(item.due_date)}</TableCell>
153
+ <TableCell>{formatDate(item.paid_at)}</TableCell>
154
+ </TableRow>
155
+ ))}
156
+ </TableBody>
157
+ </Table>
158
+ </div>
159
+ ) : (
160
+ <EmptyState
161
+ icon={<FileText className="h-12 w-12" />}
162
+ title={t('table.empty')}
163
+ description={t('description')}
164
+ actionLabel={t('emptyAction')}
165
+ onAction={() => {
166
+ setSearch('');
167
+ setPage(1);
168
+ void refetch();
169
+ }}
170
+ />
171
+ )}
166
172
 
167
173
  <PaginationFooter
168
174
  currentPage={page}
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import {
4
+ EmptyState,
4
5
  Page,
5
6
  PageHeader,
6
7
  PaginationFooter,
@@ -52,7 +53,7 @@ import {
52
53
  import { Textarea } from '@/components/ui/textarea';
53
54
  import { useApp, useQuery } from '@hed-hog/next-app-provider';
54
55
  import { zodResolver } from '@hookform/resolvers/zod';
55
- import { Pencil, Plus, Trash2 } from 'lucide-react';
56
+ import { FileText, Pencil, Plus, Trash2 } from 'lucide-react';
56
57
  import { useTranslations } from 'next-intl';
57
58
  import { useEffect, useState } from 'react';
58
59
  import { useForm } from 'react-hook-form';
@@ -98,7 +99,7 @@ const badgeClass = (value: string) => {
98
99
  };
99
100
 
100
101
  export default function BillingOffersPage() {
101
- const t = useTranslations('BillingOffersPage');
102
+ const t = useTranslations('billing.BillingOffersPage');
102
103
  const { request, currentLocaleCode, showToastHandler } = useApp();
103
104
  const [search, setSearch] = useState('');
104
105
  const [statusFilter, setStatusFilter] = useState('all');
@@ -278,70 +279,73 @@ export default function BillingOffersPage() {
278
279
  }}
279
280
  />
280
281
 
281
- <div className="overflow-x-auto rounded-md border">
282
- <Table>
283
- <TableHeader>
284
- <TableRow>
285
- <TableHead>{t('table.columns.code')}</TableHead>
286
- <TableHead>{t('table.columns.name')}</TableHead>
287
- <TableHead>{t('table.columns.status')}</TableHead>
288
- <TableHead>{t('table.columns.createdAt')}</TableHead>
289
- <TableHead className="w-[120px] text-right">
290
- {t('table.columns.actions')}
291
- </TableHead>
292
- </TableRow>
293
- </TableHeader>
294
- <TableBody>
295
- {items.length === 0 && (
282
+ {items.length > 0 ? (
283
+ <div className="overflow-x-auto rounded-md border">
284
+ <Table>
285
+ <TableHeader>
296
286
  <TableRow>
297
- <TableCell
298
- colSpan={5}
299
- className="text-center text-muted-foreground"
300
- >
301
- {t('table.empty')}
302
- </TableCell>
287
+ <TableHead>{t('table.columns.code')}</TableHead>
288
+ <TableHead>{t('table.columns.name')}</TableHead>
289
+ <TableHead>{t('table.columns.status')}</TableHead>
290
+ <TableHead>{t('table.columns.createdAt')}</TableHead>
291
+ <TableHead className="w-[120px] text-right">
292
+ {t('table.columns.actions')}
293
+ </TableHead>
303
294
  </TableRow>
304
- )}
305
- {items.map((item) => (
306
- <TableRow key={item.id}>
307
- <TableCell className="font-medium">{item.code}</TableCell>
308
- <TableCell>{item.name}</TableCell>
309
- <TableCell>
310
- <Badge className={badgeClass(item.status)}>
311
- {item.status}
312
- </Badge>
313
- </TableCell>
314
- <TableCell>
315
- {new Intl.DateTimeFormat('pt-BR', {
316
- dateStyle: 'short',
317
- }).format(new Date(item.created_at))}
318
- </TableCell>
319
- <TableCell>
320
- <div className="flex justify-end gap-2">
321
- <Button
322
- variant="outline"
323
- size="icon"
324
- onClick={() => {
325
- setEditingOffer(item);
326
- setSheetOpen(true);
327
- }}
328
- >
329
- <Pencil className="size-4" />
330
- </Button>
331
- <Button
332
- variant="destructive"
333
- size="icon"
334
- onClick={() => setDeleteId(item.id)}
335
- >
336
- <Trash2 className="size-4" />
337
- </Button>
338
- </div>
339
- </TableCell>
340
- </TableRow>
341
- ))}
342
- </TableBody>
343
- </Table>
344
- </div>
295
+ </TableHeader>
296
+ <TableBody>
297
+ {items.map((item) => (
298
+ <TableRow key={item.id}>
299
+ <TableCell className="font-medium">{item.code}</TableCell>
300
+ <TableCell>{item.name}</TableCell>
301
+ <TableCell>
302
+ <Badge className={badgeClass(item.status)}>
303
+ {item.status}
304
+ </Badge>
305
+ </TableCell>
306
+ <TableCell>
307
+ {new Intl.DateTimeFormat('pt-BR', {
308
+ dateStyle: 'short',
309
+ }).format(new Date(item.created_at))}
310
+ </TableCell>
311
+ <TableCell>
312
+ <div className="flex justify-end gap-2">
313
+ <Button
314
+ variant="outline"
315
+ size="icon"
316
+ onClick={() => {
317
+ setEditingOffer(item);
318
+ setSheetOpen(true);
319
+ }}
320
+ >
321
+ <Pencil className="size-4" />
322
+ </Button>
323
+ <Button
324
+ variant="destructive"
325
+ size="icon"
326
+ onClick={() => setDeleteId(item.id)}
327
+ >
328
+ <Trash2 className="size-4" />
329
+ </Button>
330
+ </div>
331
+ </TableCell>
332
+ </TableRow>
333
+ ))}
334
+ </TableBody>
335
+ </Table>
336
+ </div>
337
+ ) : (
338
+ <EmptyState
339
+ icon={<FileText className="h-12 w-12" />}
340
+ title={t('table.empty')}
341
+ description={t('description')}
342
+ actionLabel={t('actions.create')}
343
+ onAction={() => {
344
+ setEditingOffer(null);
345
+ setSheetOpen(true);
346
+ }}
347
+ />
348
+ )}
345
349
 
346
350
  <PaginationFooter
347
351
  currentPage={page}
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import {
4
+ EmptyState,
4
5
  Page,
5
6
  PageHeader,
6
7
  PaginationFooter,
@@ -43,7 +44,7 @@ import {
43
44
  import { Textarea } from '@/components/ui/textarea';
44
45
  import { useApp, useQuery } from '@hed-hog/next-app-provider';
45
46
  import { zodResolver } from '@hookform/resolvers/zod';
46
- import { Plus } from 'lucide-react';
47
+ import { FileText, Plus } from 'lucide-react';
47
48
  import { useTranslations } from 'next-intl';
48
49
  import { useState } from 'react';
49
50
  import { useForm } from 'react-hook-form';
@@ -97,7 +98,7 @@ const badgeClass = (value: string) => {
97
98
  };
98
99
 
99
100
  export default function BillingOrdersPage() {
100
- const t = useTranslations('BillingOrdersPage');
101
+ const t = useTranslations('billing.BillingOrdersPage');
101
102
  const { request, currentLocaleCode, showToastHandler } = useApp();
102
103
  const [search, setSearch] = useState('');
103
104
  const [page, setPage] = useState(1);
@@ -205,52 +206,52 @@ export default function BillingOrdersPage() {
205
206
  placeholder={t('filters.searchPlaceholder')}
206
207
  />
207
208
 
208
- <div className="overflow-x-auto rounded-md border">
209
- <Table>
210
- <TableHeader>
211
- <TableRow>
212
- <TableHead>{t('table.columns.id')}</TableHead>
213
- <TableHead>{t('table.columns.status')}</TableHead>
214
- <TableHead>{t('table.columns.currency')}</TableHead>
215
- <TableHead>{t('table.columns.total')}</TableHead>
216
- <TableHead>{t('table.columns.source')}</TableHead>
217
- <TableHead>{t('table.columns.createdAt')}</TableHead>
218
- </TableRow>
219
- </TableHeader>
220
- <TableBody>
221
- {items.length === 0 && (
209
+ {items.length > 0 ? (
210
+ <div className="overflow-x-auto rounded-md border">
211
+ <Table>
212
+ <TableHeader>
222
213
  <TableRow>
223
- <TableCell
224
- colSpan={6}
225
- className="text-center text-muted-foreground"
226
- >
227
- {t('table.empty')}
228
- </TableCell>
214
+ <TableHead>{t('table.columns.id')}</TableHead>
215
+ <TableHead>{t('table.columns.status')}</TableHead>
216
+ <TableHead>{t('table.columns.currency')}</TableHead>
217
+ <TableHead>{t('table.columns.total')}</TableHead>
218
+ <TableHead>{t('table.columns.source')}</TableHead>
219
+ <TableHead>{t('table.columns.createdAt')}</TableHead>
229
220
  </TableRow>
230
- )}
231
- {items.map((item) => (
232
- <TableRow key={item.id}>
233
- <TableCell className="font-medium">#{item.id}</TableCell>
234
- <TableCell>
235
- <Badge className={badgeClass(item.status)}>
236
- {item.status}
237
- </Badge>
238
- </TableCell>
239
- <TableCell>{item.currency}</TableCell>
240
- <TableCell>
241
- {formatCurrency(item.total_cents, item.currency)}
242
- </TableCell>
243
- <TableCell>{item.source ?? '-'}</TableCell>
244
- <TableCell>
245
- {new Intl.DateTimeFormat('pt-BR', {
246
- dateStyle: 'short',
247
- }).format(new Date(item.created_at))}
248
- </TableCell>
249
- </TableRow>
250
- ))}
251
- </TableBody>
252
- </Table>
253
- </div>
221
+ </TableHeader>
222
+ <TableBody>
223
+ {items.map((item) => (
224
+ <TableRow key={item.id}>
225
+ <TableCell className="font-medium">#{item.id}</TableCell>
226
+ <TableCell>
227
+ <Badge className={badgeClass(item.status)}>
228
+ {item.status}
229
+ </Badge>
230
+ </TableCell>
231
+ <TableCell>{item.currency}</TableCell>
232
+ <TableCell>
233
+ {formatCurrency(item.total_cents, item.currency)}
234
+ </TableCell>
235
+ <TableCell>{item.source ?? '-'}</TableCell>
236
+ <TableCell>
237
+ {new Intl.DateTimeFormat('pt-BR', {
238
+ dateStyle: 'short',
239
+ }).format(new Date(item.created_at))}
240
+ </TableCell>
241
+ </TableRow>
242
+ ))}
243
+ </TableBody>
244
+ </Table>
245
+ </div>
246
+ ) : (
247
+ <EmptyState
248
+ icon={<FileText className="h-12 w-12" />}
249
+ title={t('table.empty')}
250
+ description={t('description')}
251
+ actionLabel={t('actions.create')}
252
+ onAction={() => setSheetOpen(true)}
253
+ />
254
+ )}
254
255
 
255
256
  <PaginationFooter
256
257
  currentPage={page}