@hed-hog/finance 0.0.300 → 0.0.302

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 (41) hide show
  1. package/dist/finance.contract-activated.subscriber.d.ts +24 -0
  2. package/dist/finance.contract-activated.subscriber.d.ts.map +1 -0
  3. package/dist/finance.contract-activated.subscriber.js +519 -0
  4. package/dist/finance.contract-activated.subscriber.js.map +1 -0
  5. package/dist/finance.contract-activated.subscriber.spec.d.ts +2 -0
  6. package/dist/finance.contract-activated.subscriber.spec.d.ts.map +1 -0
  7. package/dist/finance.contract-activated.subscriber.spec.js +302 -0
  8. package/dist/finance.contract-activated.subscriber.spec.js.map +1 -0
  9. package/dist/finance.module.d.ts.map +1 -1
  10. package/dist/finance.module.js +6 -1
  11. package/dist/finance.module.js.map +1 -1
  12. package/hedhog/data/menu.yaml +0 -17
  13. package/hedhog/frontend/app/_components/finance-layout.tsx.ejs +108 -0
  14. package/hedhog/frontend/app/accounts-payable/approvals/page.tsx.ejs +51 -69
  15. package/hedhog/frontend/app/accounts-payable/installments/page.tsx.ejs +1312 -1138
  16. package/hedhog/frontend/app/accounts-receivable/collections-default/page.tsx.ejs +288 -268
  17. package/hedhog/frontend/app/accounts-receivable/installments/page.tsx.ejs +1175 -1016
  18. package/hedhog/frontend/app/administration/audit-logs/page.tsx.ejs +157 -173
  19. package/hedhog/frontend/app/administration/categories/page.tsx.ejs +44 -62
  20. package/hedhog/frontend/app/administration/cost-centers/page.tsx.ejs +62 -80
  21. package/hedhog/frontend/app/administration/period-close/page.tsx.ejs +151 -170
  22. package/hedhog/frontend/app/cash-and-banks/bank-accounts/page.tsx.ejs +369 -322
  23. package/hedhog/frontend/app/cash-and-banks/bank-reconciliation/page.tsx.ejs +204 -226
  24. package/hedhog/frontend/app/cash-and-banks/statements/page.tsx.ejs +122 -140
  25. package/hedhog/frontend/app/cash-and-banks/transfers/page.tsx.ejs +31 -49
  26. package/hedhog/frontend/app/page.tsx.ejs +3 -370
  27. package/hedhog/frontend/app/planning/cash-flow-forecast/page.tsx.ejs +150 -182
  28. package/hedhog/frontend/app/planning/receivables-calendar/page.tsx.ejs +52 -70
  29. package/hedhog/frontend/app/planning/scenarios/page.tsx.ejs +101 -95
  30. package/hedhog/frontend/app/reports/actual-vs-forecast/page.tsx.ejs +100 -125
  31. package/hedhog/frontend/app/reports/aging-default/page.tsx.ejs +77 -105
  32. package/hedhog/frontend/app/reports/cash-position/page.tsx.ejs +99 -134
  33. package/hedhog/frontend/app/reports/overview-results/page.tsx.ejs +147 -182
  34. package/hedhog/frontend/app/reports/top-customers/page.tsx.ejs +49 -61
  35. package/hedhog/frontend/app/reports/top-operational-expenses/page.tsx.ejs +49 -67
  36. package/hedhog/frontend/messages/en.json +176 -68
  37. package/hedhog/frontend/messages/pt.json +176 -68
  38. package/package.json +6 -5
  39. package/src/finance.contract-activated.subscriber.spec.ts +392 -0
  40. package/src/finance.contract-activated.subscriber.ts +780 -0
  41. package/src/finance.module.ts +6 -1
@@ -1,14 +1,9 @@
1
1
  'use client';
2
2
 
3
+ import { FinancePageSection } from '@/app/(app)/(libraries)/finance/_components/finance-layout';
3
4
  import { EmptyState, Page, PageHeader } from '@/components/entity-list';
4
5
  import { Button } from '@/components/ui/button';
5
- import {
6
- Card,
7
- CardContent,
8
- CardDescription,
9
- CardHeader,
10
- CardTitle,
11
- } from '@/components/ui/card';
6
+ import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
12
7
  import {
13
8
  Dialog,
14
9
  DialogContent,
@@ -659,6 +654,35 @@ export default function ExtratosPage() {
659
654
  const totalSaidas = extratos
660
655
  .filter((e) => e.tipo === 'saida')
661
656
  .reduce((acc, e) => acc + e.valor, 0);
657
+ const summaryCards = [
658
+ {
659
+ key: 'inflows',
660
+ title: t('cards.inflows'),
661
+ value: <Money value={totalEntradas} />,
662
+ icon: ArrowUpRight,
663
+ layout: 'compact' as const,
664
+ valueClassName: 'text-green-600',
665
+ iconContainerClassName: 'bg-green-500/10 text-green-700',
666
+ accentClassName: 'from-green-500/20 via-emerald-500/10 to-transparent',
667
+ },
668
+ {
669
+ key: 'outflows',
670
+ title: t('cards.outflows'),
671
+ value: <Money value={totalSaidas} />,
672
+ icon: ArrowDownRight,
673
+ layout: 'compact' as const,
674
+ valueClassName: 'text-red-600',
675
+ iconContainerClassName: 'bg-red-500/10 text-red-700',
676
+ accentClassName: 'from-red-500/20 via-rose-500/10 to-transparent',
677
+ },
678
+ {
679
+ key: 'balance',
680
+ title: t('cards.accountBalance'),
681
+ value: <Money value={conta?.saldoAtual || 0} />,
682
+ description: conta?.descricao,
683
+ layout: 'compact' as const,
684
+ },
685
+ ];
662
686
 
663
687
  const handleExport = async () => {
664
688
  if (!contaFilter) {
@@ -749,7 +773,7 @@ export default function ExtratosPage() {
749
773
  router.replace(`${pathname}?${params.toString()}`);
750
774
  }}
751
775
  >
752
- <SelectTrigger className="w-full sm:w-[280px]">
776
+ <SelectTrigger className="w-full sm:w-70">
753
777
  <SelectValue placeholder={t('filters.selectAccount')} />
754
778
  </SelectTrigger>
755
779
  <SelectContent>
@@ -769,141 +793,99 @@ export default function ExtratosPage() {
769
793
  </div>
770
794
  </div>
771
795
 
772
- <div className="grid gap-4 md:grid-cols-3">
773
- <Card>
774
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
775
- <CardTitle className="text-sm font-medium">
776
- {t('cards.inflows')}
777
- </CardTitle>
778
- <ArrowUpRight className="h-4 w-4 text-green-500" />
779
- </CardHeader>
780
- <CardContent>
781
- <div className="text-2xl font-bold text-green-600">
782
- <Money value={totalEntradas} />
783
- </div>
784
- </CardContent>
785
- </Card>
786
- <Card>
787
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
788
- <CardTitle className="text-sm font-medium">
789
- {t('cards.outflows')}
790
- </CardTitle>
791
- <ArrowDownRight className="h-4 w-4 text-red-500" />
792
- </CardHeader>
793
- <CardContent>
794
- <div className="text-2xl font-bold text-red-600">
795
- <Money value={totalSaidas} />
796
- </div>
797
- </CardContent>
798
- </Card>
799
- <Card>
800
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
801
- <CardTitle className="text-sm font-medium">
802
- {t('cards.accountBalance')}
803
- </CardTitle>
804
- </CardHeader>
805
- <CardContent>
806
- <div className="text-2xl font-bold">
807
- <Money value={conta?.saldoAtual || 0} />
808
- </div>
809
- <p className="text-xs text-muted-foreground">{conta?.descricao}</p>
810
- </CardContent>
811
- </Card>
812
- </div>
796
+ <KpiCardsGrid items={summaryCards} columns={3} />
813
797
 
814
- {extratos.length > 0 ? (
815
- <Card>
816
- <CardHeader>
817
- <CardTitle>{t('table.title')}</CardTitle>
818
- <CardDescription>
819
- {t('table.foundTransactions', { count: extratos.length })}
820
- </CardDescription>
821
- </CardHeader>
822
- <CardContent>
823
- <div className="overflow-x-auto">
824
- <Table className="min-w-[760px] table-fixed">
825
- <TableHeader>
826
- <TableRow>
827
- <TableHead className="w-[110px]">
828
- {t('table.headers.date')}
829
- </TableHead>
830
- <TableHead>{t('table.headers.description')}</TableHead>
831
- <TableHead className="w-[130px] text-right">
832
- {t('table.headers.value')}
833
- </TableHead>
834
- <TableHead className="w-[110px]">
835
- {t('table.headers.type')}
836
- </TableHead>
837
- <TableHead className="w-[140px]">
838
- {t('table.headers.reconciliation')}
839
- </TableHead>
840
- </TableRow>
841
- </TableHeader>
842
- <TableBody>
843
- {extratos.map((extrato) => (
844
- <TableRow
845
- key={extrato.id}
846
- className="cursor-pointer"
847
- onClick={() => setExtratoSelecionado(extrato)}
848
- onKeyDown={(event) => {
849
- if (event.key === 'Enter' || event.key === ' ') {
850
- event.preventDefault();
851
- setExtratoSelecionado(extrato);
798
+ <FinancePageSection
799
+ title={t('table.title')}
800
+ description={t('table.foundTransactions', { count: extratos.length })}
801
+ contentClassName="p-4 sm:p-5"
802
+ >
803
+ {extratos.length > 0 ? (
804
+ <div className="overflow-x-auto">
805
+ <Table className="min-w-190 table-fixed">
806
+ <TableHeader>
807
+ <TableRow>
808
+ <TableHead className="w-27.5">
809
+ {t('table.headers.date')}
810
+ </TableHead>
811
+ <TableHead>{t('table.headers.description')}</TableHead>
812
+ <TableHead className="w-32.5 text-right">
813
+ {t('table.headers.value')}
814
+ </TableHead>
815
+ <TableHead className="w-27.5">
816
+ {t('table.headers.type')}
817
+ </TableHead>
818
+ <TableHead className="w-35">
819
+ {t('table.headers.reconciliation')}
820
+ </TableHead>
821
+ </TableRow>
822
+ </TableHeader>
823
+ <TableBody>
824
+ {extratos.map((extrato) => (
825
+ <TableRow
826
+ key={extrato.id}
827
+ className="cursor-pointer"
828
+ onClick={() => setExtratoSelecionado(extrato)}
829
+ onKeyDown={(event) => {
830
+ if (event.key === 'Enter' || event.key === ' ') {
831
+ event.preventDefault();
832
+ setExtratoSelecionado(extrato);
833
+ }
834
+ }}
835
+ role="button"
836
+ tabIndex={0}
837
+ >
838
+ <TableCell>{formatarData(extrato.data)}</TableCell>
839
+ <TableCell className="truncate" title={extrato.descricao}>
840
+ {extrato.descricao}
841
+ </TableCell>
842
+ <TableCell className="text-right">
843
+ <span
844
+ className={
845
+ extrato.tipo === 'entrada'
846
+ ? 'text-green-600'
847
+ : 'text-red-600'
852
848
  }
853
- }}
854
- role="button"
855
- tabIndex={0}
856
- >
857
- <TableCell>{formatarData(extrato.data)}</TableCell>
858
- <TableCell className="truncate" title={extrato.descricao}>
859
- {extrato.descricao}
860
- </TableCell>
861
- <TableCell className="text-right">
862
- <span
863
- className={
864
- extrato.tipo === 'entrada'
865
- ? 'text-green-600'
866
- : 'text-red-600'
867
- }
868
- >
869
- <Money value={extrato.valor} />
849
+ >
850
+ <Money value={extrato.valor} />
851
+ </span>
852
+ </TableCell>
853
+ <TableCell>
854
+ {extrato.tipo === 'entrada' ? (
855
+ <span className="flex items-center gap-1 text-green-600">
856
+ <ArrowUpRight className="h-4 w-4" />
857
+ {t('types.inflow')}
870
858
  </span>
871
- </TableCell>
872
- <TableCell>
873
- {extrato.tipo === 'entrada' ? (
874
- <span className="flex items-center gap-1 text-green-600">
875
- <ArrowUpRight className="h-4 w-4" />
876
- {t('types.inflow')}
877
- </span>
878
- ) : (
879
- <span className="flex items-center gap-1 text-red-600">
880
- <ArrowDownRight className="h-4 w-4" />
881
- {t('types.outflow')}
882
- </span>
883
- )}
884
- </TableCell>
885
- <TableCell>
886
- <StatusBadge
887
- status={extrato.statusConciliacao}
888
- type="conciliacao"
889
- />
890
- </TableCell>
891
- </TableRow>
892
- ))}
893
- </TableBody>
894
- </Table>
895
- </div>
896
- </CardContent>
897
- </Card>
898
- ) : (
899
- <EmptyState
900
- icon={<Upload className="h-12 w-12" />}
901
- title={t('empty.title')}
902
- description={t('empty.description')}
903
- actionLabel={t('importDialog.action')}
904
- onAction={() => setIsImportSheetOpen(true)}
905
- />
906
- )}
859
+ ) : (
860
+ <span className="flex items-center gap-1 text-red-600">
861
+ <ArrowDownRight className="h-4 w-4" />
862
+ {t('types.outflow')}
863
+ </span>
864
+ )}
865
+ </TableCell>
866
+ <TableCell>
867
+ <StatusBadge
868
+ status={extrato.statusConciliacao}
869
+ type="conciliacao"
870
+ />
871
+ </TableCell>
872
+ </TableRow>
873
+ ))}
874
+ </TableBody>
875
+ </Table>
876
+ </div>
877
+ ) : (
878
+ <div className="p-2 sm:p-4">
879
+ <EmptyState
880
+ icon={<Upload className="h-12 w-12" />}
881
+ title={t('empty.title')}
882
+ description={t('empty.description')}
883
+ actionLabel={t('importDialog.action')}
884
+ onAction={() => setIsImportSheetOpen(true)}
885
+ />
886
+ </div>
887
+ )}
888
+ </FinancePageSection>
907
889
 
908
890
  <Dialog
909
891
  open={!!extratoSelecionado}
@@ -1,14 +1,9 @@
1
1
  'use client';
2
2
 
3
+ import { FinancePageSection } from '@/app/(app)/(libraries)/finance/_components/finance-layout';
3
4
  import { Page, PageHeader } from '@/components/entity-list';
4
5
  import { Button } from '@/components/ui/button';
5
- import {
6
- Card,
7
- CardContent,
8
- CardDescription,
9
- CardHeader,
10
- CardTitle,
11
- } from '@/components/ui/card';
6
+ import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
12
7
  import { FilterBar } from '@/components/ui/filter-bar';
13
8
  import {
14
9
  Form,
@@ -347,6 +342,25 @@ export default function TransferenciasPage() {
347
342
  };
348
343
 
349
344
  const totalTransferido = transferencias.reduce((acc, t) => acc + t.valor, 0);
345
+ const summaryCards = [
346
+ {
347
+ key: 'transferred',
348
+ title: t('cards.totalTransferred'),
349
+ value: <Money value={totalTransferido} />,
350
+ description: t('cards.transferCount', { count: transferencias.length }),
351
+ icon: ArrowRight,
352
+ layout: 'compact' as const,
353
+ iconContainerClassName: 'bg-blue-500/10 text-blue-700',
354
+ accentClassName: 'from-blue-500/20 via-sky-500/10 to-transparent',
355
+ },
356
+ {
357
+ key: 'activeAccounts',
358
+ title: t('cards.activeAccounts'),
359
+ value: contasBancarias.filter((conta) => conta.ativo).length,
360
+ description: t('cards.available'),
361
+ layout: 'compact' as const,
362
+ },
363
+ ];
350
364
 
351
365
  return (
352
366
  <Page>
@@ -369,7 +383,7 @@ export default function TransferenciasPage() {
369
383
 
370
384
  <div className="flex flex-col gap-4 sm:flex-row sm:items-center">
371
385
  <Select value={accountFilter} onValueChange={setAccountFilter}>
372
- <SelectTrigger className="w-full sm:w-[280px]">
386
+ <SelectTrigger className="w-full sm:w-70">
373
387
  <SelectValue placeholder={t('common.select')} />
374
388
  </SelectTrigger>
375
389
  <SelectContent>
@@ -391,45 +405,13 @@ export default function TransferenciasPage() {
391
405
  </div>
392
406
  </div>
393
407
 
394
- <div className="grid gap-4 md:grid-cols-2">
395
- <Card>
396
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
397
- <CardTitle className="text-sm font-medium">
398
- {t('cards.totalTransferred')}
399
- </CardTitle>
400
- </CardHeader>
401
- <CardContent>
402
- <div className="text-2xl font-bold">
403
- <Money value={totalTransferido} />
404
- </div>
405
- <p className="text-xs text-muted-foreground">
406
- {t('cards.transferCount', { count: transferencias.length })}
407
- </p>
408
- </CardContent>
409
- </Card>
410
- <Card>
411
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
412
- <CardTitle className="text-sm font-medium">
413
- {t('cards.activeAccounts')}
414
- </CardTitle>
415
- </CardHeader>
416
- <CardContent>
417
- <div className="text-2xl font-bold">
418
- {contasBancarias.filter((conta) => conta.ativo).length}
419
- </div>
420
- <p className="text-xs text-muted-foreground">
421
- {t('cards.available')}
422
- </p>
423
- </CardContent>
424
- </Card>
425
- </div>
408
+ <KpiCardsGrid items={summaryCards} columns={2} />
426
409
 
427
- <Card>
428
- <CardHeader>
429
- <CardTitle>{t('table.title')}</CardTitle>
430
- <CardDescription>{t('table.description')}</CardDescription>
431
- </CardHeader>
432
- <CardContent>
410
+ <FinancePageSection
411
+ contentClassName="p-0"
412
+ className="border-none shadow-none"
413
+ >
414
+ <div className="overflow-x-auto">
433
415
  <Table>
434
416
  <TableHeader>
435
417
  <TableRow>
@@ -464,7 +446,7 @@ export default function TransferenciasPage() {
464
446
  </div>
465
447
  </TableCell>
466
448
  <TableCell className="text-center">
467
- <ArrowRight className="h-4 w-4 text-muted-foreground mx-auto" />
449
+ <ArrowRight className="mx-auto h-4 w-4 text-muted-foreground" />
468
450
  </TableCell>
469
451
  <TableCell>
470
452
  <div>
@@ -485,8 +467,8 @@ export default function TransferenciasPage() {
485
467
  })}
486
468
  </TableBody>
487
469
  </Table>
488
- </CardContent>
489
- </Card>
470
+ </div>
471
+ </FinancePageSection>
490
472
  </Page>
491
473
  );
492
474
  }