@hed-hog/core 0.0.297 → 0.0.299

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 (183) hide show
  1. package/dist/auth/auth.controller.d.ts +10 -10
  2. package/dist/auth/auth.service.d.ts +10 -10
  3. package/dist/dashboard/dashboard/dashboard.controller.d.ts +3 -0
  4. package/dist/dashboard/dashboard/dashboard.controller.d.ts.map +1 -1
  5. package/dist/dashboard/dashboard/dashboard.service.d.ts +3 -0
  6. package/dist/dashboard/dashboard/dashboard.service.d.ts.map +1 -1
  7. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +12 -0
  8. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts.map +1 -1
  9. package/dist/dashboard/dashboard-component/dashboard-component.controller.js +22 -0
  10. package/dist/dashboard/dashboard-component/dashboard-component.controller.js.map +1 -1
  11. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +15 -0
  12. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts.map +1 -1
  13. package/dist/dashboard/dashboard-component/dashboard-component.service.js +110 -3
  14. package/dist/dashboard/dashboard-component/dashboard-component.service.js.map +1 -1
  15. package/dist/dashboard/dashboard-component/dto/create.dto.d.ts +1 -0
  16. package/dist/dashboard/dashboard-component/dto/create.dto.d.ts.map +1 -1
  17. package/dist/dashboard/dashboard-component/dto/create.dto.js +5 -0
  18. package/dist/dashboard/dashboard-component/dto/create.dto.js.map +1 -1
  19. package/dist/dashboard/dashboard-component/dto/update.dto.d.ts +1 -0
  20. package/dist/dashboard/dashboard-component/dto/update.dto.d.ts.map +1 -1
  21. package/dist/dashboard/dashboard-component/dto/update.dto.js +5 -0
  22. package/dist/dashboard/dashboard-component/dto/update.dto.js.map +1 -1
  23. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +1 -0
  24. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts.map +1 -1
  25. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +1 -0
  26. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts.map +1 -1
  27. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +21 -1
  28. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts.map +1 -1
  29. package/dist/dashboard/dashboard-core/dashboard-core.controller.js +9 -0
  30. package/dist/dashboard/dashboard-core/dashboard-core.controller.js.map +1 -1
  31. package/dist/dashboard/dashboard-core/dashboard-core.module.d.ts.map +1 -1
  32. package/dist/dashboard/dashboard-core/dashboard-core.module.js +6 -1
  33. package/dist/dashboard/dashboard-core/dashboard-core.module.js.map +1 -1
  34. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +180 -2
  35. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts.map +1 -1
  36. package/dist/dashboard/dashboard-core/dashboard-core.service.js +619 -9
  37. package/dist/dashboard/dashboard-core/dashboard-core.service.js.map +1 -1
  38. package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts +1 -0
  39. package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts.map +1 -1
  40. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts +1 -0
  41. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
  42. package/dist/file/file.controller.d.ts.map +1 -1
  43. package/dist/file/file.controller.js +16 -0
  44. package/dist/file/file.controller.js.map +1 -1
  45. package/dist/file/file.service.d.ts +7 -1
  46. package/dist/file/file.service.d.ts.map +1 -1
  47. package/dist/file/file.service.js +38 -1
  48. package/dist/file/file.service.js.map +1 -1
  49. package/dist/file/provider/s3.provider.d.ts +1 -0
  50. package/dist/file/provider/s3.provider.d.ts.map +1 -1
  51. package/dist/file/provider/s3.provider.js +38 -29
  52. package/dist/file/provider/s3.provider.js.map +1 -1
  53. package/dist/oauth/oauth.service.d.ts.map +1 -1
  54. package/dist/oauth/oauth.service.js +2 -1
  55. package/dist/oauth/oauth.service.js.map +1 -1
  56. package/dist/user/constants/user.constants.d.ts +1 -0
  57. package/dist/user/constants/user.constants.d.ts.map +1 -1
  58. package/dist/user/constants/user.constants.js +2 -1
  59. package/dist/user/constants/user.constants.js.map +1 -1
  60. package/dist/user/user.controller.d.ts +10 -10
  61. package/dist/user/user.service.d.ts +30 -30
  62. package/dist/user/user.service.d.ts.map +1 -1
  63. package/dist/user/user.service.js +2 -1
  64. package/dist/user/user.service.js.map +1 -1
  65. package/hedhog/data/dashboard_item.yaml +10 -10
  66. package/hedhog/data/route.yaml +20 -0
  67. package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +212 -34
  68. package/hedhog/frontend/app/dashboard/[slug]/types.ts.ejs +3 -0
  69. package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +136 -23
  70. package/hedhog/frontend/app/dashboard/components/add-widget-selector-dialog.tsx.ejs +266 -85
  71. package/hedhog/frontend/app/dashboard/components/widgets/core..gitkeep.ejs +11 -0
  72. package/hedhog/frontend/app/dashboard/components/widgets/core.account-security.tsx.ejs +192 -0
  73. package/hedhog/frontend/app/dashboard/components/widgets/core.email-notifications.tsx.ejs +226 -0
  74. package/hedhog/frontend/app/dashboard/components/widgets/core.locale-config.tsx.ejs +168 -0
  75. package/hedhog/frontend/app/dashboard/components/widgets/core.mail-config.tsx.ejs +199 -0
  76. package/hedhog/frontend/app/dashboard/components/widgets/core.oauth-config.tsx.ejs +175 -0
  77. package/hedhog/frontend/app/dashboard/components/widgets/core.profile-card.tsx.ejs +186 -0
  78. package/hedhog/frontend/app/dashboard/components/widgets/core.storage-config.tsx.ejs +196 -0
  79. package/hedhog/frontend/app/dashboard/components/widgets/core.theme-config.tsx.ejs +213 -0
  80. package/hedhog/frontend/app/dashboard/components/widgets/core.user-roles.tsx.ejs +132 -0
  81. package/hedhog/frontend/app/dashboard/components/widgets/core.user-sessions.tsx.ejs +236 -0
  82. package/hedhog/frontend/app/dashboard/components/widgets/finance.alerts.tsx.ejs +108 -0
  83. package/hedhog/frontend/app/dashboard/components/widgets/finance.cash-balance-kpi.tsx.ejs +66 -0
  84. package/hedhog/frontend/app/dashboard/components/widgets/finance.cash-flow-chart.tsx.ejs +122 -0
  85. package/hedhog/frontend/app/dashboard/components/widgets/finance.default-kpi.tsx.ejs +63 -0
  86. package/hedhog/frontend/app/dashboard/components/widgets/finance.payable-30d-kpi.tsx.ejs +73 -0
  87. package/hedhog/frontend/app/dashboard/components/widgets/finance.receivable-30d-kpi.tsx.ejs +73 -0
  88. package/hedhog/frontend/app/dashboard/components/widgets/finance.upcoming-payable.tsx.ejs +123 -0
  89. package/hedhog/frontend/app/dashboard/components/widgets/finance.upcoming-receivable.tsx.ejs +118 -0
  90. package/hedhog/frontend/messages/en.json +93 -0
  91. package/hedhog/frontend/messages/pt.json +93 -0
  92. package/hedhog/frontend/public/dashboard-previews/.gitkeep +12 -0
  93. package/hedhog/frontend/public/dashboard-previews/account-security.png +0 -0
  94. package/hedhog/frontend/public/dashboard-previews/active-users-card.png +0 -0
  95. package/hedhog/frontend/public/dashboard-previews/activity-timeline.png +0 -0
  96. package/hedhog/frontend/public/dashboard-previews/cash-balance-kpi.png +0 -0
  97. package/hedhog/frontend/public/dashboard-previews/cash-flow-chart.png +0 -0
  98. package/hedhog/frontend/public/dashboard-previews/default-kpi.png +0 -0
  99. package/hedhog/frontend/public/dashboard-previews/email-notifications.png +0 -0
  100. package/hedhog/frontend/public/dashboard-previews/financial-alerts.png +0 -0
  101. package/hedhog/frontend/public/dashboard-previews/login-history-chart.png +0 -0
  102. package/hedhog/frontend/public/dashboard-previews/mail-sent-card.png +0 -0
  103. package/hedhog/frontend/public/dashboard-previews/mail-sent-chart.png +0 -0
  104. package/hedhog/frontend/public/dashboard-previews/menus-card.png +0 -0
  105. package/hedhog/frontend/public/dashboard-previews/payable-30d-kpi.png +0 -0
  106. package/hedhog/frontend/public/dashboard-previews/permissions-card.png +0 -0
  107. package/hedhog/frontend/public/dashboard-previews/permissions-chart.png +0 -0
  108. package/hedhog/frontend/public/dashboard-previews/profile-card.png +0 -0
  109. package/hedhog/frontend/public/dashboard-previews/receivable-30d-kpi.png +0 -0
  110. package/hedhog/frontend/public/dashboard-previews/routes-card.png +0 -0
  111. package/hedhog/frontend/public/dashboard-previews/session-activity-chart.png +0 -0
  112. package/hedhog/frontend/public/dashboard-previews/sessions-today-card.png +0 -0
  113. package/hedhog/frontend/public/dashboard-previews/stat-access-level.png +0 -0
  114. package/hedhog/frontend/public/dashboard-previews/stat-actions-today.png +0 -0
  115. package/hedhog/frontend/public/dashboard-previews/stat-consecutive-days.png +0 -0
  116. package/hedhog/frontend/public/dashboard-previews/stat-online-time.png +0 -0
  117. package/hedhog/frontend/public/dashboard-previews/upcoming-payable.png +0 -0
  118. package/hedhog/frontend/public/dashboard-previews/upcoming-receivable.png +0 -0
  119. package/hedhog/frontend/public/dashboard-previews/user-growth-chart.png +0 -0
  120. package/hedhog/frontend/public/dashboard-previews/user-roles.png +0 -0
  121. package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/account-security.tsx.ejs +33 -29
  122. package/hedhog/frontend/widgets/active-users-card.tsx.ejs +58 -0
  123. package/hedhog/frontend/widgets/activity-timeline.tsx.ejs +223 -0
  124. package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/email-notifications.tsx.ejs +85 -61
  125. package/hedhog/frontend/widgets/locale-config.tsx.ejs +168 -0
  126. package/hedhog/frontend/widgets/login-history-chart.tsx.ejs +115 -0
  127. package/hedhog/frontend/widgets/mail-config.tsx.ejs +199 -0
  128. package/hedhog/frontend/widgets/mail-sent-card.tsx.ejs +58 -0
  129. package/hedhog/frontend/widgets/mail-sent-chart.tsx.ejs +149 -0
  130. package/hedhog/frontend/widgets/menus-card.tsx.ejs +58 -0
  131. package/hedhog/frontend/widgets/oauth-config.tsx.ejs +175 -0
  132. package/hedhog/frontend/widgets/permissions-card.tsx.ejs +61 -0
  133. package/hedhog/frontend/widgets/permissions-chart.tsx.ejs +156 -0
  134. package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/profile-card.tsx.ejs +3 -3
  135. package/hedhog/frontend/widgets/routes-card.tsx.ejs +58 -0
  136. package/hedhog/frontend/widgets/session-activity-chart.tsx.ejs +183 -0
  137. package/hedhog/frontend/widgets/sessions-today-card.tsx.ejs +62 -0
  138. package/hedhog/frontend/widgets/stat-access-level.tsx.ejs +57 -0
  139. package/hedhog/frontend/widgets/stat-actions-today.tsx.ejs +57 -0
  140. package/hedhog/frontend/widgets/stat-consecutive-days.tsx.ejs +57 -0
  141. package/hedhog/frontend/widgets/stat-online-time.tsx.ejs +57 -0
  142. package/hedhog/frontend/widgets/storage-config.tsx.ejs +196 -0
  143. package/hedhog/frontend/widgets/theme-config.tsx.ejs +213 -0
  144. package/hedhog/frontend/widgets/user-growth-chart.tsx.ejs +210 -0
  145. package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/user-roles.tsx.ejs +12 -14
  146. package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/user-sessions.tsx.ejs +1 -1
  147. package/hedhog/table/dashboard_component.yaml +7 -0
  148. package/hedhog/table/mail_sent_user.yaml +75 -0
  149. package/package.json +4 -4
  150. package/src/dashboard/dashboard-component/dashboard-component.controller.ts +36 -12
  151. package/src/dashboard/dashboard-component/dashboard-component.service.ts +150 -3
  152. package/src/dashboard/dashboard-component/dto/create.dto.ts +4 -0
  153. package/src/dashboard/dashboard-component/dto/update.dto.ts +4 -0
  154. package/src/dashboard/dashboard-core/dashboard-core.controller.ts +5 -0
  155. package/src/dashboard/dashboard-core/dashboard-core.module.ts +6 -1
  156. package/src/dashboard/dashboard-core/dashboard-core.service.ts +874 -8
  157. package/src/file/file.controller.ts +37 -13
  158. package/src/file/file.service.ts +47 -5
  159. package/src/file/provider/s3.provider.ts +39 -29
  160. package/src/oauth/oauth.service.ts +8 -7
  161. package/src/user/constants/user.constants.ts +1 -0
  162. package/src/user/user.service.ts +2 -1
  163. package/hedhog/frontend/app/dashboard/components/widgets/locale-config.tsx.ejs +0 -309
  164. package/hedhog/frontend/app/dashboard/components/widgets/mail-config.tsx.ejs +0 -445
  165. package/hedhog/frontend/app/dashboard/components/widgets/oauth-config.tsx.ejs +0 -296
  166. package/hedhog/frontend/app/dashboard/components/widgets/storage-config.tsx.ejs +0 -340
  167. package/hedhog/frontend/app/dashboard/components/widgets/theme-config.tsx.ejs +0 -275
  168. /package/hedhog/frontend/app/dashboard/components/widgets/{active-users-card.tsx.ejs → core.active-users-card.tsx.ejs} +0 -0
  169. /package/hedhog/frontend/app/dashboard/components/widgets/{activity-timeline.tsx.ejs → core.activity-timeline.tsx.ejs} +0 -0
  170. /package/hedhog/frontend/app/dashboard/components/widgets/{login-history-chart.tsx.ejs → core.login-history-chart.tsx.ejs} +0 -0
  171. /package/hedhog/frontend/app/dashboard/components/widgets/{mail-sent-card.tsx.ejs → core.mail-sent-card.tsx.ejs} +0 -0
  172. /package/hedhog/frontend/app/dashboard/components/widgets/{mail-sent-chart.tsx.ejs → core.mail-sent-chart.tsx.ejs} +0 -0
  173. /package/hedhog/frontend/app/dashboard/components/widgets/{menus-card.tsx.ejs → core.menus-card.tsx.ejs} +0 -0
  174. /package/hedhog/frontend/app/dashboard/components/widgets/{permissions-card.tsx.ejs → core.permissions-card.tsx.ejs} +0 -0
  175. /package/hedhog/frontend/app/dashboard/components/widgets/{permissions-chart.tsx.ejs → core.permissions-chart.tsx.ejs} +0 -0
  176. /package/hedhog/frontend/app/dashboard/components/widgets/{routes-card.tsx.ejs → core.routes-card.tsx.ejs} +0 -0
  177. /package/hedhog/frontend/app/dashboard/components/widgets/{session-activity-chart.tsx.ejs → core.session-activity-chart.tsx.ejs} +0 -0
  178. /package/hedhog/frontend/app/dashboard/components/widgets/{sessions-today-card.tsx.ejs → core.sessions-today-card.tsx.ejs} +0 -0
  179. /package/hedhog/frontend/app/dashboard/components/widgets/{stat-access-level.tsx.ejs → core.stat-access-level.tsx.ejs} +0 -0
  180. /package/hedhog/frontend/app/dashboard/components/widgets/{stat-actions-today.tsx.ejs → core.stat-actions-today.tsx.ejs} +0 -0
  181. /package/hedhog/frontend/app/dashboard/components/widgets/{stat-consecutive-days.tsx.ejs → core.stat-consecutive-days.tsx.ejs} +0 -0
  182. /package/hedhog/frontend/app/dashboard/components/widgets/{stat-online-time.tsx.ejs → core.stat-online-time.tsx.ejs} +0 -0
  183. /package/hedhog/frontend/app/dashboard/components/widgets/{user-growth-chart.tsx.ejs → core.user-growth-chart.tsx.ejs} +0 -0
@@ -0,0 +1,66 @@
1
+ 'use client';
2
+
3
+ import { Card, CardContent } from '@/components/ui/card';
4
+ import { useWidgetData } from '@/hooks/use-widget-data';
5
+ import { Wallet } from 'lucide-react';
6
+ import { useTranslations } from 'next-intl';
7
+ import { WidgetWrapper } from '../widget-wrapper';
8
+
9
+ interface CashBalanceKpiProps {
10
+ widget?: { name?: string };
11
+ onRemove?: () => void;
12
+ }
13
+
14
+ interface FinanceData {
15
+ kpis?: {
16
+ saldoCaixa: number;
17
+ };
18
+ }
19
+
20
+ export default function CashBalanceKpi({
21
+ widget,
22
+ onRemove,
23
+ }: CashBalanceKpiProps) {
24
+ const t = useTranslations('finance.DashboardPage');
25
+
26
+ const { data, isLoading, isAccessDenied, isError } =
27
+ useWidgetData<FinanceData>({
28
+ endpoint: '/finance/data',
29
+ queryKey: 'finance-kpi-cash-balance',
30
+ });
31
+
32
+ const value = data?.kpis?.saldoCaixa ?? 0;
33
+ const formatted = new Intl.NumberFormat('pt-BR', {
34
+ style: 'currency',
35
+ currency: 'BRL',
36
+ }).format(value);
37
+
38
+ return (
39
+ <WidgetWrapper
40
+ isLoading={isLoading}
41
+ isAccessDenied={isAccessDenied}
42
+ isError={isError}
43
+ widgetName={widget?.name || t('kpis.cashBalance.title')}
44
+ onRemove={onRemove}
45
+ >
46
+ <Card className="h-full overflow-hidden transition-all duration-300 hover:shadow-md">
47
+ <CardContent className="flex h-full items-center gap-3 p-4">
48
+ <div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-emerald-50">
49
+ <Wallet className="h-5 w-5 text-emerald-600" />
50
+ </div>
51
+ <div className="flex min-w-0 flex-col">
52
+ <span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">
53
+ {t('kpis.cashBalance.title')}
54
+ </span>
55
+ <span className="truncate text-lg font-bold tracking-tight text-foreground">
56
+ {formatted}
57
+ </span>
58
+ <span className="text-[10px] text-muted-foreground">
59
+ {t('kpis.cashBalance.description')}
60
+ </span>
61
+ </div>
62
+ </CardContent>
63
+ </Card>
64
+ </WidgetWrapper>
65
+ );
66
+ }
@@ -0,0 +1,122 @@
1
+ 'use client';
2
+
3
+ import {
4
+ Card,
5
+ CardContent,
6
+ CardDescription,
7
+ CardHeader,
8
+ CardTitle,
9
+ } from '@/components/ui/card';
10
+ import { useWidgetData } from '@/hooks/use-widget-data';
11
+ import { useTranslations } from 'next-intl';
12
+ import {
13
+ CartesianGrid,
14
+ Legend,
15
+ Line,
16
+ LineChart,
17
+ ResponsiveContainer,
18
+ Tooltip,
19
+ XAxis,
20
+ YAxis,
21
+ } from 'recharts';
22
+ import { WidgetWrapper } from '../widget-wrapper';
23
+
24
+ interface CashFlowPoint {
25
+ data: string;
26
+ saldoPrevisto: number;
27
+ saldoRealizado: number;
28
+ }
29
+
30
+ interface FinanceData {
31
+ fluxoCaixaPrevisto?: CashFlowPoint[];
32
+ }
33
+
34
+ interface CashFlowChartProps {
35
+ widget?: { name?: string };
36
+ onRemove?: () => void;
37
+ }
38
+
39
+ export default function CashFlowChart({
40
+ widget,
41
+ onRemove,
42
+ }: CashFlowChartProps) {
43
+ const t = useTranslations('finance.DashboardPage');
44
+
45
+ const { data, isLoading, isAccessDenied, isError } =
46
+ useWidgetData<FinanceData>({
47
+ endpoint: '/finance/data',
48
+ queryKey: 'finance-cash-flow-chart',
49
+ });
50
+
51
+ const chartData = (data?.fluxoCaixaPrevisto || []).map((item) => ({
52
+ ...item,
53
+ data: new Date(item.data).toLocaleDateString('pt-BR', {
54
+ day: '2-digit',
55
+ month: '2-digit',
56
+ }),
57
+ }));
58
+
59
+ return (
60
+ <WidgetWrapper
61
+ isLoading={isLoading}
62
+ isAccessDenied={isAccessDenied}
63
+ isError={isError}
64
+ widgetName={widget?.name || t('cashFlow.title')}
65
+ onRemove={onRemove}
66
+ >
67
+ <Card className="h-full flex flex-col">
68
+ <CardHeader className="pb-2">
69
+ <CardTitle className="text-base">{t('cashFlow.title')}</CardTitle>
70
+ <CardDescription>{t('cashFlow.description')}</CardDescription>
71
+ </CardHeader>
72
+ <CardContent className="flex-1 pt-0">
73
+ <div className="h-[280px] w-full">
74
+ <ResponsiveContainer width="100%" height="100%">
75
+ <LineChart data={chartData}>
76
+ <CartesianGrid strokeDasharray="3 3" className="stroke-muted" />
77
+ <XAxis
78
+ dataKey="data"
79
+ tick={{ fontSize: 12 }}
80
+ tickLine={false}
81
+ axisLine={false}
82
+ />
83
+ <YAxis
84
+ tick={{ fontSize: 12 }}
85
+ tickLine={false}
86
+ axisLine={false}
87
+ tickFormatter={(value) => `${(value / 1000).toFixed(0)}k`}
88
+ />
89
+ <Tooltip
90
+ formatter={(value: number) =>
91
+ new Intl.NumberFormat('pt-BR', {
92
+ style: 'currency',
93
+ currency: 'BRL',
94
+ }).format(value)
95
+ }
96
+ />
97
+ <Legend />
98
+ <Line
99
+ type="monotone"
100
+ dataKey="saldoPrevisto"
101
+ name={t('chart.predicted')}
102
+ stroke="hsl(var(--primary))"
103
+ strokeWidth={2}
104
+ dot={false}
105
+ />
106
+ <Line
107
+ type="monotone"
108
+ dataKey="saldoRealizado"
109
+ name={t('chart.actual')}
110
+ stroke="hsl(var(--chart-2))"
111
+ strokeWidth={2}
112
+ dot={false}
113
+ connectNulls
114
+ />
115
+ </LineChart>
116
+ </ResponsiveContainer>
117
+ </div>
118
+ </CardContent>
119
+ </Card>
120
+ </WidgetWrapper>
121
+ );
122
+ }
@@ -0,0 +1,63 @@
1
+ 'use client';
2
+
3
+ import { Card, CardContent } from '@/components/ui/card';
4
+ import { useWidgetData } from '@/hooks/use-widget-data';
5
+ import { AlertTriangle } from 'lucide-react';
6
+ import { useTranslations } from 'next-intl';
7
+ import { WidgetWrapper } from '../widget-wrapper';
8
+
9
+ interface DefaultKpiProps {
10
+ widget?: { name?: string };
11
+ onRemove?: () => void;
12
+ }
13
+
14
+ interface FinanceData {
15
+ kpis?: {
16
+ inadimplencia: number;
17
+ };
18
+ }
19
+
20
+ export default function DefaultKpi({ widget, onRemove }: DefaultKpiProps) {
21
+ const t = useTranslations('finance.DashboardPage');
22
+
23
+ const { data, isLoading, isAccessDenied, isError } =
24
+ useWidgetData<FinanceData>({
25
+ endpoint: '/finance/data',
26
+ queryKey: 'finance-kpi-default',
27
+ });
28
+
29
+ const value = data?.kpis?.inadimplencia ?? 0;
30
+ const formatted = new Intl.NumberFormat('pt-BR', {
31
+ style: 'currency',
32
+ currency: 'BRL',
33
+ }).format(value);
34
+
35
+ return (
36
+ <WidgetWrapper
37
+ isLoading={isLoading}
38
+ isAccessDenied={isAccessDenied}
39
+ isError={isError}
40
+ widgetName={widget?.name || t('kpis.default.title')}
41
+ onRemove={onRemove}
42
+ >
43
+ <Card className="h-full overflow-hidden transition-all duration-300 hover:shadow-md">
44
+ <CardContent className="flex h-full items-center gap-3 p-4">
45
+ <div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-amber-50">
46
+ <AlertTriangle className="h-5 w-5 text-amber-600" />
47
+ </div>
48
+ <div className="flex min-w-0 flex-col">
49
+ <span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">
50
+ {t('kpis.default.title')}
51
+ </span>
52
+ <span className="truncate text-lg font-bold tracking-tight text-foreground">
53
+ {formatted}
54
+ </span>
55
+ <span className="text-[10px] text-muted-foreground">
56
+ {t('kpis.default.description')}
57
+ </span>
58
+ </div>
59
+ </CardContent>
60
+ </Card>
61
+ </WidgetWrapper>
62
+ );
63
+ }
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+
3
+ import { Card, CardContent } from '@/components/ui/card';
4
+ import { useWidgetData } from '@/hooks/use-widget-data';
5
+ import { TrendingDown } from 'lucide-react';
6
+ import { useTranslations } from 'next-intl';
7
+ import { WidgetWrapper } from '../widget-wrapper';
8
+
9
+ interface Payable30dKpiProps {
10
+ widget?: { name?: string };
11
+ onRemove?: () => void;
12
+ }
13
+
14
+ interface FinanceData {
15
+ kpis?: {
16
+ aPagar30dias: number;
17
+ aPagar7dias: number;
18
+ };
19
+ }
20
+
21
+ export default function Payable30dKpi({
22
+ widget,
23
+ onRemove,
24
+ }: Payable30dKpiProps) {
25
+ const t = useTranslations('finance.DashboardPage');
26
+
27
+ const { data, isLoading, isAccessDenied, isError } =
28
+ useWidgetData<FinanceData>({
29
+ endpoint: '/finance/data',
30
+ queryKey: 'finance-kpi-payable-30d',
31
+ });
32
+
33
+ const value = data?.kpis?.aPagar30dias ?? 0;
34
+ const sevenDays = data?.kpis?.aPagar7dias ?? 0;
35
+ const formatted = new Intl.NumberFormat('pt-BR', {
36
+ style: 'currency',
37
+ currency: 'BRL',
38
+ }).format(value);
39
+
40
+ return (
41
+ <WidgetWrapper
42
+ isLoading={isLoading}
43
+ isAccessDenied={isAccessDenied}
44
+ isError={isError}
45
+ widgetName={widget?.name || t('kpis.payable30.title')}
46
+ onRemove={onRemove}
47
+ >
48
+ <Card className="h-full overflow-hidden transition-all duration-300 hover:shadow-md">
49
+ <CardContent className="flex h-full items-center gap-3 p-4">
50
+ <div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-red-50">
51
+ <TrendingDown className="h-5 w-5 text-red-600" />
52
+ </div>
53
+ <div className="flex min-w-0 flex-col">
54
+ <span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">
55
+ {t('kpis.payable30.title')}
56
+ </span>
57
+ <span className="truncate text-lg font-bold tracking-tight text-foreground">
58
+ {formatted}
59
+ </span>
60
+ <span className="text-[10px] text-muted-foreground">
61
+ {t('kpis.payable30.sevenDays', {
62
+ value: new Intl.NumberFormat('pt-BR', {
63
+ style: 'currency',
64
+ currency: 'BRL',
65
+ }).format(sevenDays),
66
+ })}
67
+ </span>
68
+ </div>
69
+ </CardContent>
70
+ </Card>
71
+ </WidgetWrapper>
72
+ );
73
+ }
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+
3
+ import { Card, CardContent } from '@/components/ui/card';
4
+ import { useWidgetData } from '@/hooks/use-widget-data';
5
+ import { TrendingUp } from 'lucide-react';
6
+ import { useTranslations } from 'next-intl';
7
+ import { WidgetWrapper } from '../widget-wrapper';
8
+
9
+ interface Receivable30dKpiProps {
10
+ widget?: { name?: string };
11
+ onRemove?: () => void;
12
+ }
13
+
14
+ interface FinanceData {
15
+ kpis?: {
16
+ aReceber30dias: number;
17
+ aReceber7dias: number;
18
+ };
19
+ }
20
+
21
+ export default function Receivable30dKpi({
22
+ widget,
23
+ onRemove,
24
+ }: Receivable30dKpiProps) {
25
+ const t = useTranslations('finance.DashboardPage');
26
+
27
+ const { data, isLoading, isAccessDenied, isError } =
28
+ useWidgetData<FinanceData>({
29
+ endpoint: '/finance/data',
30
+ queryKey: 'finance-kpi-receivable-30d',
31
+ });
32
+
33
+ const value = data?.kpis?.aReceber30dias ?? 0;
34
+ const sevenDays = data?.kpis?.aReceber7dias ?? 0;
35
+ const formatted = new Intl.NumberFormat('pt-BR', {
36
+ style: 'currency',
37
+ currency: 'BRL',
38
+ }).format(value);
39
+
40
+ return (
41
+ <WidgetWrapper
42
+ isLoading={isLoading}
43
+ isAccessDenied={isAccessDenied}
44
+ isError={isError}
45
+ widgetName={widget?.name || t('kpis.receivable30.title')}
46
+ onRemove={onRemove}
47
+ >
48
+ <Card className="h-full overflow-hidden transition-all duration-300 hover:shadow-md">
49
+ <CardContent className="flex h-full items-center gap-3 p-4">
50
+ <div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-green-50">
51
+ <TrendingUp className="h-5 w-5 text-green-600" />
52
+ </div>
53
+ <div className="flex min-w-0 flex-col">
54
+ <span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">
55
+ {t('kpis.receivable30.title')}
56
+ </span>
57
+ <span className="truncate text-lg font-bold tracking-tight text-foreground">
58
+ {formatted}
59
+ </span>
60
+ <span className="text-[10px] text-muted-foreground">
61
+ {t('kpis.receivable30.sevenDays', {
62
+ value: new Intl.NumberFormat('pt-BR', {
63
+ style: 'currency',
64
+ currency: 'BRL',
65
+ }).format(sevenDays),
66
+ })}
67
+ </span>
68
+ </div>
69
+ </CardContent>
70
+ </Card>
71
+ </WidgetWrapper>
72
+ );
73
+ }
@@ -0,0 +1,123 @@
1
+ 'use client';
2
+
3
+ import {
4
+ Card,
5
+ CardContent,
6
+ CardDescription,
7
+ CardHeader,
8
+ CardTitle,
9
+ } from '@/components/ui/card';
10
+ import { Money } from '@/components/ui/money';
11
+ import { StatusBadge } from '@/components/ui/status-badge';
12
+ import { useWidgetData } from '@/hooks/use-widget-data';
13
+ import { ArrowDownRight } from 'lucide-react';
14
+ import { useTranslations } from 'next-intl';
15
+ import Link from 'next/link';
16
+ import { WidgetWrapper } from '../widget-wrapper';
17
+
18
+ interface FinanceData {
19
+ titulosPagar?: Array<{
20
+ id: string;
21
+ status: string;
22
+ documento: string;
23
+ fornecedorId?: string;
24
+ parcelas: Array<{
25
+ status: string;
26
+ vencimento: string;
27
+ valor: number;
28
+ }>;
29
+ }>;
30
+ pessoas?: Array<{
31
+ id: string;
32
+ nome: string;
33
+ }>;
34
+ }
35
+
36
+ interface UpcomingPayableProps {
37
+ widget?: { name?: string };
38
+ onRemove?: () => void;
39
+ }
40
+
41
+ function formatDate(value: string) {
42
+ return new Date(value).toLocaleDateString('pt-BR');
43
+ }
44
+
45
+ export default function UpcomingPayable({
46
+ widget,
47
+ onRemove,
48
+ }: UpcomingPayableProps) {
49
+ const t = useTranslations('finance.DashboardPage');
50
+
51
+ const { data, isLoading, isAccessDenied, isError } =
52
+ useWidgetData<FinanceData>({
53
+ endpoint: '/finance/data',
54
+ queryKey: 'finance-upcoming-payable',
55
+ });
56
+
57
+ const getPersonById = (id?: string) =>
58
+ (data?.pessoas || []).find((p) => p.id === id);
59
+
60
+ const approvedPayables = (data?.titulosPagar || []).filter(
61
+ (titulo) => titulo.status !== 'rascunho' && titulo.status !== 'cancelado'
62
+ );
63
+
64
+ const rows = approvedPayables
65
+ .flatMap((titulo) =>
66
+ titulo.parcelas
67
+ .filter((p) => p.status === 'aberto' || p.status === 'vencido')
68
+ .map((parcela) => ({
69
+ tituloId: titulo.id,
70
+ documento: titulo.documento,
71
+ person: getPersonById(titulo.fornecedorId)?.nome || '',
72
+ dueDate: parcela.vencimento,
73
+ value: parcela.valor,
74
+ status: parcela.status,
75
+ }))
76
+ )
77
+ .slice(0, 3);
78
+
79
+ return (
80
+ <WidgetWrapper
81
+ isLoading={isLoading}
82
+ isAccessDenied={isAccessDenied}
83
+ isError={isError}
84
+ widgetName={widget?.name || t('upcoming.payable')}
85
+ onRemove={onRemove}
86
+ >
87
+ <Card className="h-full">
88
+ <CardHeader>
89
+ <CardTitle className="flex items-center gap-2 text-base">
90
+ <ArrowDownRight className="h-4 w-4 text-red-500" />
91
+ {t('upcoming.payable')}
92
+ </CardTitle>
93
+ <CardDescription>{t('upcoming.nextDueDates')}</CardDescription>
94
+ </CardHeader>
95
+ <CardContent>
96
+ <div className="space-y-4">
97
+ {rows.map((item, index) => (
98
+ <Link
99
+ key={index}
100
+ href={`/finance/accounts-payable/installments/${item.tituloId}`}
101
+ className="-m-2 flex cursor-pointer items-center justify-between rounded-md p-2 transition-colors hover:bg-muted/50 active:bg-muted"
102
+ >
103
+ <div className="space-y-1">
104
+ <p className="text-sm font-medium">{item.documento}</p>
105
+ <p className="text-xs text-muted-foreground">{item.person}</p>
106
+ </div>
107
+ <div className="text-right">
108
+ <p className="text-sm font-medium">
109
+ <Money value={item.value} />
110
+ </p>
111
+ <p className="text-xs text-muted-foreground">
112
+ {formatDate(item.dueDate)}
113
+ </p>
114
+ </div>
115
+ <StatusBadge status={item.status as any} />
116
+ </Link>
117
+ ))}
118
+ </div>
119
+ </CardContent>
120
+ </Card>
121
+ </WidgetWrapper>
122
+ );
123
+ }
@@ -0,0 +1,118 @@
1
+ 'use client';
2
+
3
+ import {
4
+ Card,
5
+ CardContent,
6
+ CardDescription,
7
+ CardHeader,
8
+ CardTitle,
9
+ } from '@/components/ui/card';
10
+ import { Money } from '@/components/ui/money';
11
+ import { StatusBadge } from '@/components/ui/status-badge';
12
+ import { useWidgetData } from '@/hooks/use-widget-data';
13
+ import { ArrowUpRight } from 'lucide-react';
14
+ import { useTranslations } from 'next-intl';
15
+ import Link from 'next/link';
16
+ import { WidgetWrapper } from '../widget-wrapper';
17
+
18
+ interface FinanceData {
19
+ titulosReceber?: Array<{
20
+ id: string;
21
+ documento: string;
22
+ clienteId?: string;
23
+ parcelas: Array<{
24
+ status: string;
25
+ vencimento: string;
26
+ valor: number;
27
+ }>;
28
+ }>;
29
+ pessoas?: Array<{
30
+ id: string;
31
+ nome: string;
32
+ }>;
33
+ }
34
+
35
+ interface UpcomingReceivableProps {
36
+ widget?: { name?: string };
37
+ onRemove?: () => void;
38
+ }
39
+
40
+ function formatDate(value: string) {
41
+ return new Date(value).toLocaleDateString('pt-BR');
42
+ }
43
+
44
+ export default function UpcomingReceivable({
45
+ widget,
46
+ onRemove,
47
+ }: UpcomingReceivableProps) {
48
+ const t = useTranslations('finance.DashboardPage');
49
+
50
+ const { data, isLoading, isAccessDenied, isError } =
51
+ useWidgetData<FinanceData>({
52
+ endpoint: '/finance/data',
53
+ queryKey: 'finance-upcoming-receivable',
54
+ });
55
+
56
+ const getPersonById = (id?: string) =>
57
+ (data?.pessoas || []).find((p) => p.id === id);
58
+
59
+ const rows = (data?.titulosReceber || [])
60
+ .flatMap((titulo) =>
61
+ titulo.parcelas
62
+ .filter((p) => p.status === 'aberto' || p.status === 'vencido')
63
+ .map((parcela) => ({
64
+ tituloId: titulo.id,
65
+ documento: titulo.documento,
66
+ person: getPersonById(titulo.clienteId)?.nome || '',
67
+ dueDate: parcela.vencimento,
68
+ value: parcela.valor,
69
+ status: parcela.status,
70
+ }))
71
+ )
72
+ .slice(0, 3);
73
+
74
+ return (
75
+ <WidgetWrapper
76
+ isLoading={isLoading}
77
+ isAccessDenied={isAccessDenied}
78
+ isError={isError}
79
+ widgetName={widget?.name || t('upcoming.receivable')}
80
+ onRemove={onRemove}
81
+ >
82
+ <Card className="h-full">
83
+ <CardHeader>
84
+ <CardTitle className="flex items-center gap-2 text-base">
85
+ <ArrowUpRight className="h-4 w-4 text-green-500" />
86
+ {t('upcoming.receivable')}
87
+ </CardTitle>
88
+ <CardDescription>{t('upcoming.nextDueDates')}</CardDescription>
89
+ </CardHeader>
90
+ <CardContent>
91
+ <div className="space-y-4">
92
+ {rows.map((item, index) => (
93
+ <Link
94
+ key={index}
95
+ href={`/finance/accounts-receivable/installments/${item.tituloId}`}
96
+ className="-m-2 flex cursor-pointer items-center justify-between rounded-md p-2 transition-colors hover:bg-muted/50 active:bg-muted"
97
+ >
98
+ <div className="space-y-1">
99
+ <p className="text-sm font-medium">{item.documento}</p>
100
+ <p className="text-xs text-muted-foreground">{item.person}</p>
101
+ </div>
102
+ <div className="text-right">
103
+ <p className="text-sm font-medium">
104
+ <Money value={item.value} />
105
+ </p>
106
+ <p className="text-xs text-muted-foreground">
107
+ {formatDate(item.dueDate)}
108
+ </p>
109
+ </div>
110
+ <StatusBadge status={item.status as any} />
111
+ </Link>
112
+ ))}
113
+ </div>
114
+ </CardContent>
115
+ </Card>
116
+ </WidgetWrapper>
117
+ );
118
+ }