@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,226 @@
1
+ 'use client';
2
+
3
+ import {
4
+ Card,
5
+ CardContent,
6
+ CardDescription,
7
+ CardHeader,
8
+ CardTitle,
9
+ } from '@/components/ui/card';
10
+ import {
11
+ ChartContainer,
12
+ ChartTooltip,
13
+ ChartTooltipContent,
14
+ } from '@/components/ui/chart';
15
+ import { useWidgetData } from '@/hooks/use-widget-data';
16
+ import type {
17
+ AllWidgetsData,
18
+ EmailNotificationsData,
19
+ } from '@/types/widget-data';
20
+ import { Mail, MailCheck, MailWarning, MailX } from 'lucide-react';
21
+ import { useTranslations } from 'next-intl';
22
+ import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';
23
+ import { WidgetWrapper } from '../widget-wrapper';
24
+
25
+ const defaultEmailNotificationsData: EmailNotificationsData = {
26
+ cards: {
27
+ received: 0,
28
+ read: 0,
29
+ unread: 0,
30
+ error: 0,
31
+ },
32
+ chart: [],
33
+ };
34
+
35
+ interface EmailNotificationsProps {
36
+ widget?: { name?: string };
37
+ onRemove?: () => void;
38
+ }
39
+
40
+ export default function EmailNotifications({
41
+ widget,
42
+ onRemove,
43
+ }: EmailNotificationsProps) {
44
+ const t = useTranslations('core.DashboardPage.emailNotifications');
45
+
46
+ const chartConfig = {
47
+ recebidos: {
48
+ label: t('received'),
49
+ color: 'hsl(221, 83%, 53%)',
50
+ },
51
+ lidos: {
52
+ label: t('read'),
53
+ color: 'hsl(160, 84%, 39%)',
54
+ },
55
+ };
56
+
57
+ const { data, isLoading, isError, isAccessDenied } = useWidgetData<
58
+ AllWidgetsData,
59
+ EmailNotificationsData
60
+ >({
61
+ endpoint: '/dashboard-core/widgets/me',
62
+ queryKey: 'widget-me',
63
+ select: (d) => d.emailNotifications,
64
+ });
65
+
66
+ const widgetData = data ?? defaultEmailNotificationsData;
67
+ const chartData = widgetData.chart.map((point) => ({
68
+ date: point.date,
69
+ recebidos: point.received ?? 0,
70
+ lidos: point.read ?? 0,
71
+ }));
72
+
73
+ const emailStats = [
74
+ {
75
+ label: t('received'),
76
+ shortLabel: t('receivedShort'),
77
+ value: widgetData.cards.received ?? 0,
78
+ icon: Mail,
79
+ color: 'text-blue-600 dark:text-blue-400',
80
+ bg: 'bg-blue-50 dark:bg-blue-950/40',
81
+ },
82
+ {
83
+ label: t('read'),
84
+ shortLabel: t('readShort'),
85
+ value: widgetData.cards.read ?? 0,
86
+ icon: MailCheck,
87
+ color: 'text-emerald-600 dark:text-emerald-400',
88
+ bg: 'bg-emerald-50 dark:bg-emerald-950/40',
89
+ },
90
+ {
91
+ label: t('unread'),
92
+ shortLabel: t('unreadShort'),
93
+ value: widgetData.cards.unread ?? 0,
94
+ icon: MailWarning,
95
+ color: 'text-amber-600 dark:text-amber-400',
96
+ bg: 'bg-amber-50 dark:bg-amber-950/40',
97
+ },
98
+ {
99
+ label: t('error'),
100
+ shortLabel: t('errorShort'),
101
+ value: widgetData.cards.error ?? 0,
102
+ icon: MailX,
103
+ color: 'text-red-600 dark:text-red-400',
104
+ bg: 'bg-red-50 dark:bg-red-950/40',
105
+ },
106
+ ];
107
+
108
+ return (
109
+ <WidgetWrapper
110
+ isLoading={isLoading}
111
+ isError={isError}
112
+ isAccessDenied={isAccessDenied}
113
+ widgetName={widget?.name ?? t('title')}
114
+ onRemove={onRemove}
115
+ >
116
+ <Card className="flex h-full min-h-0 flex-col overflow-hidden">
117
+ <CardHeader className="shrink-0 pb-2">
118
+ <div className="flex items-center gap-2">
119
+ <Mail className="h-4 w-4 text-rose-600 dark:text-rose-400 sm:h-5 sm:w-5" />
120
+ <div>
121
+ <CardTitle className="text-sm font-semibold sm:text-base">
122
+ {t('title')}
123
+ </CardTitle>
124
+ <CardDescription className="text-xs sm:text-sm">
125
+ {t('description')}
126
+ </CardDescription>
127
+ </div>
128
+ </div>
129
+ </CardHeader>
130
+ <CardContent className="flex min-h-0 flex-1 flex-col gap-4 overflow-hidden pt-0">
131
+ <div className="grid grid-cols-2 gap-1.5 sm:gap-2 md:grid-cols-4">
132
+ {emailStats.map((stat) => {
133
+ const Icon = stat.icon;
134
+ return (
135
+ <div
136
+ key={stat.label}
137
+ className="flex min-w-0 flex-col items-center gap-1 rounded-lg border p-2 text-center transition-colors hover:bg-muted/30 sm:p-2.5"
138
+ >
139
+ <div
140
+ className={`flex h-6 w-6 items-center justify-center rounded-md sm:h-7 sm:w-7 ${stat.bg}`}
141
+ >
142
+ <Icon
143
+ className={`h-3 w-3 sm:h-3.5 sm:w-3.5 ${stat.color}`}
144
+ />
145
+ </div>
146
+ <span className="text-base font-bold text-foreground sm:text-lg">
147
+ {stat.value}
148
+ </span>
149
+ <span className="truncate text-[9px] text-muted-foreground sm:text-[10px]">
150
+ <span className="sm:hidden">{stat.shortLabel}</span>
151
+ <span className="hidden sm:inline">{stat.label}</span>
152
+ </span>
153
+ </div>
154
+ );
155
+ })}
156
+ </div>
157
+
158
+ <ChartContainer
159
+ config={chartConfig}
160
+ className="min-h-42.5 w-full flex-1 overflow-hidden sm:min-h-55"
161
+ >
162
+ <AreaChart data={chartData}>
163
+ <CartesianGrid vertical={false} strokeDasharray="3 3" />
164
+ <XAxis
165
+ dataKey="date"
166
+ tickLine={false}
167
+ axisLine={false}
168
+ fontSize={10}
169
+ tickMargin={4}
170
+ minTickGap={20}
171
+ />
172
+ <YAxis
173
+ tickLine={false}
174
+ axisLine={false}
175
+ fontSize={10}
176
+ tickMargin={4}
177
+ allowDecimals={false}
178
+ />
179
+ <ChartTooltip content={<ChartTooltipContent />} />
180
+ <defs>
181
+ <linearGradient id="fillRecebidos" x1="0" y1="0" x2="0" y2="1">
182
+ <stop
183
+ offset="5%"
184
+ stopColor="hsl(221, 83%, 53%)"
185
+ stopOpacity={0.2}
186
+ />
187
+ <stop
188
+ offset="95%"
189
+ stopColor="hsl(221, 83%, 53%)"
190
+ stopOpacity={0}
191
+ />
192
+ </linearGradient>
193
+ <linearGradient id="fillLidos" x1="0" y1="0" x2="0" y2="1">
194
+ <stop
195
+ offset="5%"
196
+ stopColor="hsl(160, 84%, 39%)"
197
+ stopOpacity={0.2}
198
+ />
199
+ <stop
200
+ offset="95%"
201
+ stopColor="hsl(160, 84%, 39%)"
202
+ stopOpacity={0}
203
+ />
204
+ </linearGradient>
205
+ </defs>
206
+ <Area
207
+ type="monotone"
208
+ dataKey="recebidos"
209
+ stroke="hsl(221, 83%, 53%)"
210
+ fill="url(#fillRecebidos)"
211
+ strokeWidth={2}
212
+ />
213
+ <Area
214
+ type="monotone"
215
+ dataKey="lidos"
216
+ stroke="hsl(160, 84%, 39%)"
217
+ fill="url(#fillLidos)"
218
+ strokeWidth={2}
219
+ />
220
+ </AreaChart>
221
+ </ChartContainer>
222
+ </CardContent>
223
+ </Card>
224
+ </WidgetWrapper>
225
+ );
226
+ }
@@ -0,0 +1,168 @@
1
+ 'use client';
2
+
3
+ import { Badge } from '@/components/ui/badge';
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ } from '@/components/ui/card';
11
+ import { useWidgetData } from '@/hooks/use-widget-data';
12
+ import type {
13
+ DashboardCoreConfigOverviewData,
14
+ LocaleConfigWidgetData,
15
+ } from '@/types/widget-data';
16
+ import { Calendar, Clock, Globe, Languages } from 'lucide-react';
17
+ import { useTranslations } from 'next-intl';
18
+ import { WidgetWrapper } from '../widget-wrapper';
19
+
20
+ const defaultLocaleConfigData: LocaleConfigWidgetData = {
21
+ status: {
22
+ isConfigured: false,
23
+ enabledLocaleCount: 0,
24
+ disabledLocaleCount: 0,
25
+ },
26
+ settings: {
27
+ dateFormat: null,
28
+ timeFormat: null,
29
+ timezone: null,
30
+ },
31
+ locales: [],
32
+ };
33
+
34
+ interface LocaleConfigProps {
35
+ widget?: { name?: string };
36
+ onRemove?: () => void;
37
+ }
38
+
39
+ export default function LocaleConfig({ widget, onRemove }: LocaleConfigProps) {
40
+ const t = useTranslations('core.DashboardPage.localeConfig');
41
+
42
+ const { data, isLoading, isError, isAccessDenied } = useWidgetData<
43
+ DashboardCoreConfigOverviewData,
44
+ LocaleConfigWidgetData
45
+ >({
46
+ endpoint: '/dashboard-core/config/overview',
47
+ queryKey: 'dashboard-core-config-overview',
48
+ select: (d) => d.localeConfig,
49
+ });
50
+
51
+ const localeData = data ?? defaultLocaleConfigData;
52
+ const enabledLocales = localeData.locales.filter((locale) => locale.enabled);
53
+
54
+ return (
55
+ <WidgetWrapper
56
+ isLoading={isLoading}
57
+ isError={isError}
58
+ isAccessDenied={isAccessDenied}
59
+ widgetName={widget?.name ?? t('title')}
60
+ onRemove={onRemove}
61
+ >
62
+ <Card className="flex h-full min-h-0 flex-col overflow-hidden">
63
+ <CardHeader className="shrink-0">
64
+ <div className="flex items-center justify-between gap-3">
65
+ <div className="flex items-center gap-3">
66
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-indigo-50">
67
+ <Globe className="h-5 w-5 text-indigo-600" />
68
+ </div>
69
+ <div>
70
+ <CardTitle className="text-base">{t('title')}</CardTitle>
71
+ <CardDescription>{t('description')}</CardDescription>
72
+ </div>
73
+ </div>
74
+ <Badge
75
+ variant="secondary"
76
+ className={
77
+ localeData.status.isConfigured
78
+ ? 'bg-emerald-50 text-emerald-700'
79
+ : 'bg-amber-50 text-amber-700'
80
+ }
81
+ >
82
+ {localeData.status.isConfigured ? t('configured') : t('pending')}
83
+ </Badge>
84
+ </div>
85
+ </CardHeader>
86
+ <CardContent className="flex min-h-0 flex-1 flex-col gap-4 overflow-hidden pt-0">
87
+ <div className="grid grid-cols-3 gap-2">
88
+ <div className="rounded-lg border bg-muted/30 p-3 text-center">
89
+ <p className="text-[11px] text-muted-foreground">
90
+ {t('enabled')}
91
+ </p>
92
+ <p className="mt-1 text-lg font-semibold">
93
+ {localeData.status.enabledLocaleCount}
94
+ </p>
95
+ </div>
96
+ <div className="rounded-lg border bg-muted/30 p-3 text-center">
97
+ <p className="text-[11px] text-muted-foreground">
98
+ {t('disabled')}
99
+ </p>
100
+ <p className="mt-1 text-lg font-semibold">
101
+ {localeData.status.disabledLocaleCount}
102
+ </p>
103
+ </div>
104
+ <div className="rounded-lg border bg-muted/30 p-3 text-center">
105
+ <p className="text-[11px] text-muted-foreground">{t('total')}</p>
106
+ <p className="mt-1 text-lg font-semibold">
107
+ {localeData.locales.length}
108
+ </p>
109
+ </div>
110
+ </div>
111
+
112
+ <div className="grid gap-2 sm:grid-cols-3">
113
+ <div className="rounded-lg border p-3">
114
+ <div className="mb-1 flex items-center gap-1.5 text-xs text-muted-foreground">
115
+ <Clock className="h-3.5 w-3.5" />
116
+ {t('timezone')}
117
+ </div>
118
+ <p className="truncate font-mono text-xs">
119
+ {localeData.settings.timezone || t('notSet')}
120
+ </p>
121
+ </div>
122
+ <div className="rounded-lg border p-3">
123
+ <div className="mb-1 flex items-center gap-1.5 text-xs text-muted-foreground">
124
+ <Calendar className="h-3.5 w-3.5" />
125
+ {t('dateFormat')}
126
+ </div>
127
+ <p className="font-mono text-xs">
128
+ {localeData.settings.dateFormat || t('notSet')}
129
+ </p>
130
+ </div>
131
+ <div className="rounded-lg border p-3">
132
+ <div className="mb-1 flex items-center gap-1.5 text-xs text-muted-foreground">
133
+ <Clock className="h-3.5 w-3.5" />
134
+ {t('timeFormat')}
135
+ </div>
136
+ <p className="font-mono text-xs">
137
+ {localeData.settings.timeFormat || t('notSet')}
138
+ </p>
139
+ </div>
140
+ </div>
141
+
142
+ <div className="min-h-0 flex-1 rounded-lg border p-3">
143
+ <div className="mb-2 flex items-center gap-2 text-xs text-muted-foreground">
144
+ <Languages className="h-3.5 w-3.5" />
145
+ <span>{t('enabledLocales')}</span>
146
+ </div>
147
+ <div className="flex flex-wrap gap-1.5">
148
+ {enabledLocales.length > 0 ? (
149
+ enabledLocales.map((locale) => (
150
+ <Badge key={locale.id} variant="outline" className="gap-1">
151
+ <span className="font-mono text-[10px]">{locale.code}</span>
152
+ <span className="text-[10px] text-muted-foreground">
153
+ {locale.name}
154
+ </span>
155
+ </Badge>
156
+ ))
157
+ ) : (
158
+ <span className="text-xs text-muted-foreground">
159
+ {t('noneEnabled')}
160
+ </span>
161
+ )}
162
+ </div>
163
+ </div>
164
+ </CardContent>
165
+ </Card>
166
+ </WidgetWrapper>
167
+ );
168
+ }
@@ -0,0 +1,199 @@
1
+ 'use client';
2
+
3
+ import { Badge } from '@/components/ui/badge';
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ } from '@/components/ui/card';
11
+ import { useWidgetData } from '@/hooks/use-widget-data';
12
+ import type {
13
+ DashboardCoreConfigOverviewData,
14
+ MailConfigWidgetData,
15
+ } from '@/types/widget-data';
16
+ import { CheckCircle2, Mail, Send, Server } from 'lucide-react';
17
+ import { useTranslations } from 'next-intl';
18
+ import { WidgetWrapper } from '../widget-wrapper';
19
+
20
+ const defaultMailConfigData: MailConfigWidgetData = {
21
+ status: {
22
+ isConfigured: false,
23
+ selectedProvider: null,
24
+ configuredProvider: null,
25
+ },
26
+ sender: {
27
+ from: null,
28
+ },
29
+ metrics: {
30
+ templateCount: 0,
31
+ sentCount: 0,
32
+ sentLast30Days: 0,
33
+ },
34
+ providers: [],
35
+ };
36
+
37
+ interface MailConfigProps {
38
+ widget?: { name?: string };
39
+ onRemove?: () => void;
40
+ }
41
+
42
+ const iconByProvider: Record<string, React.ElementType> = {
43
+ SMTP: Server,
44
+ GMAIL: Mail,
45
+ SES: Send,
46
+ };
47
+
48
+ export default function MailConfig({ widget, onRemove }: MailConfigProps) {
49
+ const t = useTranslations('core.DashboardPage.mailConfig');
50
+
51
+ const { data, isLoading, isError, isAccessDenied } = useWidgetData<
52
+ DashboardCoreConfigOverviewData,
53
+ MailConfigWidgetData
54
+ >({
55
+ endpoint: '/dashboard-core/config/overview',
56
+ queryKey: 'dashboard-core-config-overview',
57
+ select: (d) => d.mailConfig,
58
+ });
59
+
60
+ const mailData = data ?? defaultMailConfigData;
61
+
62
+ return (
63
+ <WidgetWrapper
64
+ isLoading={isLoading}
65
+ isError={isError}
66
+ isAccessDenied={isAccessDenied}
67
+ widgetName={widget?.name ?? t('title')}
68
+ onRemove={onRemove}
69
+ >
70
+ <Card className="flex h-full min-h-0 flex-col overflow-hidden">
71
+ <CardHeader className="shrink-0">
72
+ <div className="flex items-center justify-between gap-3">
73
+ <div className="flex items-center gap-3">
74
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-50">
75
+ <Mail className="h-5 w-5 text-blue-600" />
76
+ </div>
77
+ <div>
78
+ <CardTitle className="text-base">{t('title')}</CardTitle>
79
+ <CardDescription>{t('description')}</CardDescription>
80
+ </div>
81
+ </div>
82
+ <Badge
83
+ variant="secondary"
84
+ className={
85
+ mailData.status.isConfigured
86
+ ? 'bg-emerald-50 text-emerald-700'
87
+ : 'bg-amber-50 text-amber-700'
88
+ }
89
+ >
90
+ {mailData.status.isConfigured ? t('configured') : t('pending')}
91
+ </Badge>
92
+ </div>
93
+ </CardHeader>
94
+ <CardContent className="flex min-h-0 flex-1 flex-col gap-4 overflow-hidden pt-0">
95
+ <div className="grid grid-cols-3 gap-2">
96
+ <div className="rounded-lg border bg-muted/30 p-3 text-center">
97
+ <p className="text-[11px] text-muted-foreground">
98
+ {t('templates')}
99
+ </p>
100
+ <p className="mt-1 text-lg font-semibold">
101
+ {mailData.metrics.templateCount}
102
+ </p>
103
+ </div>
104
+ <div className="rounded-lg border bg-muted/30 p-3 text-center">
105
+ <p className="text-[11px] text-muted-foreground">
106
+ {t('sentTotal')}
107
+ </p>
108
+ <p className="mt-1 text-lg font-semibold">
109
+ {mailData.metrics.sentCount}
110
+ </p>
111
+ </div>
112
+ <div className="rounded-lg border bg-muted/30 p-3 text-center">
113
+ <p className="text-[11px] text-muted-foreground">
114
+ {t('sent30Days')}
115
+ </p>
116
+ <p className="mt-1 text-lg font-semibold">
117
+ {mailData.metrics.sentLast30Days}
118
+ </p>
119
+ </div>
120
+ </div>
121
+
122
+ <div className="rounded-lg border p-3">
123
+ <p className="mb-2 text-xs text-muted-foreground">{t('sender')}</p>
124
+ <p className="truncate text-sm font-medium">
125
+ {mailData.sender.from || t('notSet')}
126
+ </p>
127
+ </div>
128
+
129
+ <div className="min-h-0 flex-1 rounded-lg border p-3">
130
+ <div className="mb-2 flex items-center justify-between">
131
+ <p className="text-xs text-muted-foreground">{t('providers')}</p>
132
+ <Badge variant="outline" className="text-[10px]">
133
+ {t('selectedProvider', {
134
+ provider: mailData.status.selectedProvider || t('none'),
135
+ })}
136
+ </Badge>
137
+ </div>
138
+ <div className="space-y-2">
139
+ {mailData.providers.length > 0 ? (
140
+ mailData.providers.map((provider) => {
141
+ const Icon = iconByProvider[provider.id] ?? Mail;
142
+ const statusClass = provider.configured
143
+ ? 'bg-emerald-50 text-emerald-700'
144
+ : 'bg-muted text-muted-foreground';
145
+
146
+ return (
147
+ <div
148
+ key={provider.id}
149
+ className="flex items-center justify-between rounded-lg border p-2"
150
+ >
151
+ <div className="flex min-w-0 items-center gap-2">
152
+ <div className="flex h-7 w-7 items-center justify-center rounded-md bg-muted/60">
153
+ <Icon className="h-3.5 w-3.5" />
154
+ </div>
155
+ <div className="min-w-0">
156
+ <p className="truncate text-sm font-medium">
157
+ {provider.label}
158
+ </p>
159
+ <p className="truncate text-[11px] text-muted-foreground">
160
+ {provider.missingKeys.length > 0
161
+ ? t('missingKeys', {
162
+ count: provider.missingKeys.length,
163
+ })
164
+ : t('allKeysPresent')}
165
+ </p>
166
+ </div>
167
+ </div>
168
+ <div className="flex items-center gap-1.5">
169
+ {provider.selected && (
170
+ <Badge variant="outline" className="text-[10px]">
171
+ {t('selected')}
172
+ </Badge>
173
+ )}
174
+ <Badge variant="secondary" className={statusClass}>
175
+ {provider.configured ? (
176
+ <>
177
+ <CheckCircle2 className="mr-1 h-3 w-3" />
178
+ {t('configured')}
179
+ </>
180
+ ) : (
181
+ t('pending')
182
+ )}
183
+ </Badge>
184
+ </div>
185
+ </div>
186
+ );
187
+ })
188
+ ) : (
189
+ <p className="text-xs text-muted-foreground">
190
+ {t('noProviders')}
191
+ </p>
192
+ )}
193
+ </div>
194
+ </div>
195
+ </CardContent>
196
+ </Card>
197
+ </WidgetWrapper>
198
+ );
199
+ }