@hed-hog/core 0.0.299 → 0.0.301

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 (133) hide show
  1. package/dist/ai/ai.service.d.ts +13 -2
  2. package/dist/ai/ai.service.d.ts.map +1 -1
  3. package/dist/ai/ai.service.js +104 -2
  4. package/dist/ai/ai.service.js.map +1 -1
  5. package/dist/dashboard/dashboard/dashboard.controller.d.ts +6 -0
  6. package/dist/dashboard/dashboard/dashboard.controller.d.ts.map +1 -1
  7. package/dist/dashboard/dashboard/dashboard.service.d.ts +6 -0
  8. package/dist/dashboard/dashboard/dashboard.service.d.ts.map +1 -1
  9. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +2 -1
  10. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts.map +1 -1
  11. package/dist/dashboard/dashboard-component/dashboard-component.controller.js +6 -3
  12. package/dist/dashboard/dashboard-component/dashboard-component.controller.js.map +1 -1
  13. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +7 -1
  14. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts.map +1 -1
  15. package/dist/dashboard/dashboard-component/dashboard-component.service.js +76 -33
  16. package/dist/dashboard/dashboard-component/dashboard-component.service.js.map +1 -1
  17. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +82 -0
  18. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts.map +1 -1
  19. package/dist/dashboard/dashboard-core/dashboard-core.controller.js +117 -0
  20. package/dist/dashboard/dashboard-core/dashboard-core.controller.js.map +1 -1
  21. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +93 -0
  22. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts.map +1 -1
  23. package/dist/dashboard/dashboard-core/dashboard-core.service.js +654 -20
  24. package/dist/dashboard/dashboard-core/dashboard-core.service.js.map +1 -1
  25. package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts +2 -0
  26. package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts.map +1 -1
  27. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts +2 -0
  28. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
  29. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +2 -0
  30. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts.map +1 -1
  31. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +2 -0
  32. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts.map +1 -1
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +1 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/mail/mail.service.d.ts +9 -2
  38. package/dist/mail/mail.service.d.ts.map +1 -1
  39. package/dist/mail/mail.service.js +56 -4
  40. package/dist/mail/mail.service.js.map +1 -1
  41. package/dist/setting/setting.service.d.ts +6 -1
  42. package/dist/setting/setting.service.d.ts.map +1 -1
  43. package/dist/setting/setting.service.js +188 -15
  44. package/dist/setting/setting.service.js.map +1 -1
  45. package/hedhog/data/dashboard.yaml +12 -6
  46. package/hedhog/data/dashboard_component_role.yaml +66 -0
  47. package/hedhog/data/dashboard_role.yaml +2 -8
  48. package/hedhog/data/route.yaml +72 -0
  49. package/hedhog/data/setting_group.yaml +28 -0
  50. package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +333 -128
  51. package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +277 -53
  52. package/hedhog/frontend/app/dashboard/components/add-widget-selector-dialog.tsx.ejs +179 -231
  53. package/hedhog/frontend/app/dashboard/components/draggable-grid.tsx.ejs +64 -18
  54. package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +1619 -0
  55. package/hedhog/frontend/app/dashboard/dashboard.css.ejs +37 -0
  56. package/hedhog/frontend/app/dashboard/management/page.tsx.ejs +1 -1
  57. package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +6 -6
  58. package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +8 -8
  59. package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +3 -3
  60. package/hedhog/frontend/app/dashboard/page.tsx.ejs +3 -25
  61. package/hedhog/frontend/messages/en.json +124 -2
  62. package/hedhog/frontend/messages/pt.json +123 -1
  63. package/hedhog/frontend/widgets/account-security.tsx.ejs +1 -1
  64. package/hedhog/frontend/widgets/active-users-card.tsx.ejs +2 -2
  65. package/hedhog/frontend/widgets/activity-timeline.tsx.ejs +1 -1
  66. package/hedhog/frontend/widgets/email-notifications.tsx.ejs +1 -1
  67. package/hedhog/frontend/widgets/locale-config.tsx.ejs +1 -1
  68. package/hedhog/frontend/widgets/login-history-chart.tsx.ejs +1 -1
  69. package/hedhog/frontend/widgets/mail-config.tsx.ejs +1 -1
  70. package/hedhog/frontend/widgets/mail-sent-card.tsx.ejs +2 -2
  71. package/hedhog/frontend/widgets/mail-sent-chart.tsx.ejs +1 -1
  72. package/hedhog/frontend/widgets/menus-card.tsx.ejs +2 -2
  73. package/hedhog/frontend/widgets/oauth-config.tsx.ejs +1 -1
  74. package/hedhog/frontend/widgets/permissions-card.tsx.ejs +2 -2
  75. package/hedhog/frontend/widgets/permissions-chart.tsx.ejs +1 -1
  76. package/hedhog/frontend/widgets/profile-card.tsx.ejs +1 -1
  77. package/hedhog/frontend/widgets/routes-card.tsx.ejs +2 -2
  78. package/hedhog/frontend/widgets/session-activity-chart.tsx.ejs +1 -1
  79. package/hedhog/frontend/widgets/sessions-today-card.tsx.ejs +2 -2
  80. package/hedhog/frontend/widgets/stat-access-level.tsx.ejs +1 -1
  81. package/hedhog/frontend/widgets/stat-actions-today.tsx.ejs +1 -1
  82. package/hedhog/frontend/widgets/stat-consecutive-days.tsx.ejs +1 -1
  83. package/hedhog/frontend/widgets/stat-online-time.tsx.ejs +1 -1
  84. package/hedhog/frontend/widgets/storage-config.tsx.ejs +1 -1
  85. package/hedhog/frontend/widgets/theme-config.tsx.ejs +1 -1
  86. package/hedhog/frontend/widgets/user-growth-chart.tsx.ejs +1 -1
  87. package/hedhog/frontend/widgets/user-roles.tsx.ejs +1 -1
  88. package/hedhog/frontend/widgets/user-sessions.tsx.ejs +1 -1
  89. package/hedhog/table/dashboard.yaml +6 -0
  90. package/package.json +3 -3
  91. package/src/ai/ai.service.ts +129 -1
  92. package/src/dashboard/dashboard-component/dashboard-component.controller.ts +15 -2
  93. package/src/dashboard/dashboard-component/dashboard-component.service.ts +107 -43
  94. package/src/dashboard/dashboard-core/dashboard-core.controller.ts +119 -1
  95. package/src/dashboard/dashboard-core/dashboard-core.service.ts +876 -20
  96. package/src/index.ts +7 -6
  97. package/src/mail/mail.service.ts +67 -3
  98. package/src/setting/setting.service.ts +222 -15
  99. package/hedhog/frontend/app/dashboard/components/widgets/core..gitkeep.ejs +0 -11
  100. package/hedhog/frontend/app/dashboard/components/widgets/core.account-security.tsx.ejs +0 -192
  101. package/hedhog/frontend/app/dashboard/components/widgets/core.active-users-card.tsx.ejs +0 -58
  102. package/hedhog/frontend/app/dashboard/components/widgets/core.activity-timeline.tsx.ejs +0 -223
  103. package/hedhog/frontend/app/dashboard/components/widgets/core.email-notifications.tsx.ejs +0 -226
  104. package/hedhog/frontend/app/dashboard/components/widgets/core.locale-config.tsx.ejs +0 -168
  105. package/hedhog/frontend/app/dashboard/components/widgets/core.login-history-chart.tsx.ejs +0 -115
  106. package/hedhog/frontend/app/dashboard/components/widgets/core.mail-config.tsx.ejs +0 -199
  107. package/hedhog/frontend/app/dashboard/components/widgets/core.mail-sent-card.tsx.ejs +0 -58
  108. package/hedhog/frontend/app/dashboard/components/widgets/core.mail-sent-chart.tsx.ejs +0 -149
  109. package/hedhog/frontend/app/dashboard/components/widgets/core.menus-card.tsx.ejs +0 -58
  110. package/hedhog/frontend/app/dashboard/components/widgets/core.oauth-config.tsx.ejs +0 -175
  111. package/hedhog/frontend/app/dashboard/components/widgets/core.permissions-card.tsx.ejs +0 -61
  112. package/hedhog/frontend/app/dashboard/components/widgets/core.permissions-chart.tsx.ejs +0 -156
  113. package/hedhog/frontend/app/dashboard/components/widgets/core.profile-card.tsx.ejs +0 -186
  114. package/hedhog/frontend/app/dashboard/components/widgets/core.routes-card.tsx.ejs +0 -58
  115. package/hedhog/frontend/app/dashboard/components/widgets/core.session-activity-chart.tsx.ejs +0 -183
  116. package/hedhog/frontend/app/dashboard/components/widgets/core.sessions-today-card.tsx.ejs +0 -62
  117. package/hedhog/frontend/app/dashboard/components/widgets/core.stat-access-level.tsx.ejs +0 -57
  118. package/hedhog/frontend/app/dashboard/components/widgets/core.stat-actions-today.tsx.ejs +0 -57
  119. package/hedhog/frontend/app/dashboard/components/widgets/core.stat-consecutive-days.tsx.ejs +0 -57
  120. package/hedhog/frontend/app/dashboard/components/widgets/core.stat-online-time.tsx.ejs +0 -57
  121. package/hedhog/frontend/app/dashboard/components/widgets/core.storage-config.tsx.ejs +0 -196
  122. package/hedhog/frontend/app/dashboard/components/widgets/core.theme-config.tsx.ejs +0 -213
  123. package/hedhog/frontend/app/dashboard/components/widgets/core.user-growth-chart.tsx.ejs +0 -210
  124. package/hedhog/frontend/app/dashboard/components/widgets/core.user-roles.tsx.ejs +0 -132
  125. package/hedhog/frontend/app/dashboard/components/widgets/core.user-sessions.tsx.ejs +0 -236
  126. package/hedhog/frontend/app/dashboard/components/widgets/finance.alerts.tsx.ejs +0 -108
  127. package/hedhog/frontend/app/dashboard/components/widgets/finance.cash-balance-kpi.tsx.ejs +0 -66
  128. package/hedhog/frontend/app/dashboard/components/widgets/finance.cash-flow-chart.tsx.ejs +0 -122
  129. package/hedhog/frontend/app/dashboard/components/widgets/finance.default-kpi.tsx.ejs +0 -63
  130. package/hedhog/frontend/app/dashboard/components/widgets/finance.payable-30d-kpi.tsx.ejs +0 -73
  131. package/hedhog/frontend/app/dashboard/components/widgets/finance.receivable-30d-kpi.tsx.ejs +0 -73
  132. package/hedhog/frontend/app/dashboard/components/widgets/finance.upcoming-payable.tsx.ejs +0 -123
  133. package/hedhog/frontend/app/dashboard/components/widgets/finance.upcoming-receivable.tsx.ejs +0 -118
@@ -1,168 +0,0 @@
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
- }
@@ -1,115 +0,0 @@
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 { AllWidgetsData, LoginDay } from '@/types/widget-data';
17
- import { LogIn } from 'lucide-react';
18
- import { useTranslations } from 'next-intl';
19
- import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from 'recharts';
20
- import { WidgetWrapper } from '../widget-wrapper';
21
-
22
- function LoginChart({ data }: { data: LoginDay[] }) {
23
- const t = useTranslations('core.DashboardPage.loginHistory');
24
-
25
- const chartConfig = {
26
- logins: { label: t('logins'), color: 'hsl(221, 83%, 53%)' },
27
- failed: { label: t('failed'), color: 'hsl(0, 84%, 60%)' },
28
- };
29
-
30
- return (
31
- <Card className="flex h-full min-h-0 flex-col overflow-hidden">
32
- <CardHeader className="shrink-0 pb-2">
33
- <div className="flex items-center gap-2">
34
- <LogIn className="h-4 w-4 text-blue-600 sm:h-5 sm:w-5" />
35
- <div>
36
- <CardTitle className="text-sm font-semibold sm:text-base">
37
- {t('title')}
38
- </CardTitle>
39
- <CardDescription className="text-xs sm:text-sm">
40
- {t('description')}
41
- </CardDescription>
42
- </div>
43
- </div>
44
- </CardHeader>
45
- <CardContent className="flex min-h-0 flex-1 flex-col overflow-hidden pt-0">
46
- <ChartContainer
47
- config={chartConfig}
48
- className="h-full min-h-[140px] w-full flex-1 overflow-hidden sm:min-h-40"
49
- >
50
- <BarChart data={data as any} barGap={2}>
51
- <CartesianGrid vertical={false} strokeDasharray="3 3" />
52
- <XAxis
53
- dataKey="day"
54
- tickLine={false}
55
- axisLine={false}
56
- fontSize={10}
57
- tickMargin={4}
58
- minTickGap={20}
59
- interval="preserveStartEnd"
60
- />
61
- <YAxis
62
- tickLine={false}
63
- axisLine={false}
64
- fontSize={10}
65
- tickMargin={4}
66
- allowDecimals={false}
67
- />
68
- <ChartTooltip content={<ChartTooltipContent />} />
69
- <Bar
70
- dataKey="logins"
71
- fill="hsl(221, 83%, 53%)"
72
- radius={[4, 4, 0, 0]}
73
- />
74
- <Bar
75
- dataKey="failed"
76
- fill="hsl(0, 84%, 60%)"
77
- radius={[4, 4, 0, 0]}
78
- />
79
- </BarChart>
80
- </ChartContainer>
81
- </CardContent>
82
- </Card>
83
- );
84
- }
85
-
86
- interface LoginHistoryChartProps {
87
- widget?: { name?: string };
88
- onRemove?: () => void;
89
- }
90
-
91
- export default function LoginHistoryChart({
92
- widget,
93
- onRemove,
94
- }: LoginHistoryChartProps) {
95
- const { data, isLoading, isError, isAccessDenied } = useWidgetData<
96
- AllWidgetsData,
97
- LoginDay[]
98
- >({
99
- endpoint: '/dashboard-core/widgets/me',
100
- queryKey: 'widget-me',
101
- select: (d) => d.loginHistory,
102
- });
103
-
104
- return (
105
- <WidgetWrapper
106
- isLoading={isLoading}
107
- isError={isError}
108
- isAccessDenied={isAccessDenied}
109
- widgetName={widget?.name ?? 'login-history-chart'}
110
- onRemove={onRemove}
111
- >
112
- {data && <LoginChart data={data} />}
113
- </WidgetWrapper>
114
- );
115
- }
@@ -1,199 +0,0 @@
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
- }
@@ -1,58 +0,0 @@
1
- import { useWidgetData } from '@/hooks/use-widget-data';
2
- import { Mail } from 'lucide-react';
3
- import { useTranslations } from 'next-intl';
4
- import StatCard from '../stats';
5
- import { WidgetWrapper } from '../widget-wrapper';
6
-
7
- interface MailSentProps {
8
- widget?: any;
9
- onRemove?: () => void;
10
- }
11
-
12
- interface MailStatsData {
13
- cards?: {
14
- emailsSent?: {
15
- value: number;
16
- change: number | null;
17
- };
18
- };
19
- }
20
-
21
- export default function MailSent({ widget, onRemove }: MailSentProps) {
22
- const t = useTranslations('core.Dashboard');
23
-
24
- const { data, isLoading, isAccessDenied, isError } =
25
- useWidgetData<MailStatsData>({
26
- endpoint: '/dashboard-core/stats/overview/mails',
27
- queryKey: 'dashboard-stats-mails',
28
- });
29
-
30
- const value = data?.cards?.emailsSent?.value?.toLocaleString('pt-BR') || '0';
31
- const change = data?.cards?.emailsSent?.change;
32
- const changeType =
33
- change !== null && change !== undefined && change >= 0 ? 'up' : 'down';
34
-
35
- return (
36
- <WidgetWrapper
37
- isLoading={isLoading}
38
- isAccessDenied={isAccessDenied}
39
- isError={isError}
40
- widgetName={widget?.name || t('emailsSent')}
41
- onRemove={onRemove}
42
- >
43
- <StatCard
44
- title={t('emailsSent')}
45
- value={value}
46
- change={
47
- change !== null && change !== undefined
48
- ? `${change > 0 ? '+' : ''}${change}%`
49
- : undefined
50
- }
51
- changeType={changeType}
52
- icon={<Mail className="h-6 w-6 text-amber-500" />}
53
- iconBg="bg-amber-500/10"
54
- delay={150}
55
- />
56
- </WidgetWrapper>
57
- );
58
- }
@@ -1,149 +0,0 @@
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 { IconGripVertical } from '@tabler/icons-react';
12
- import { useTranslations } from 'next-intl';
13
- import {
14
- Bar,
15
- BarChart,
16
- CartesianGrid,
17
- ResponsiveContainer,
18
- Tooltip,
19
- XAxis,
20
- YAxis,
21
- } from 'recharts';
22
- import { WidgetWrapper } from '../widget-wrapper';
23
-
24
- function CustomTooltip({
25
- active,
26
- payload,
27
- label,
28
- }: {
29
- active?: boolean;
30
- payload?: Array<{ value: number; dataKey: string }>;
31
- label?: string;
32
- }) {
33
- const t = useTranslations('core.Dashboard');
34
- if (!active || !payload?.length) return null;
35
-
36
- return (
37
- <div className="rounded-lg border bg-card px-3 py-2 shadow-xl">
38
- <p className="mb-1 text-xs font-medium text-card-foreground">{label}</p>
39
- {payload.map((entry) => (
40
- <p key={entry.dataKey} className="text-xs text-muted-foreground">
41
- <span
42
- className="mr-1.5 inline-block h-2 w-2 rounded-full"
43
- style={{ backgroundColor: '#3b82f6' }}
44
- />
45
- {t('sent')}: {entry.value.toLocaleString('pt-BR')}
46
- </p>
47
- ))}
48
- </div>
49
- );
50
- }
51
-
52
- interface EmailStatsChartProps {
53
- widget?: any;
54
- onRemove?: () => void;
55
- }
56
-
57
- interface MailStatsData {
58
- charts?: {
59
- emailsPerWeek?: Array<{
60
- day: string;
61
- sent: number;
62
- }>;
63
- };
64
- }
65
-
66
- export default function EmailStatsChart({
67
- widget,
68
- onRemove,
69
- }: EmailStatsChartProps) {
70
- const t = useTranslations('core.Dashboard');
71
-
72
- const { data, isLoading, isAccessDenied, isError } =
73
- useWidgetData<MailStatsData>({
74
- endpoint: '/dashboard-core/stats/overview/mails',
75
- queryKey: 'dashboard-stats-mails',
76
- });
77
-
78
- const chartData = data?.charts?.emailsPerWeek || [];
79
-
80
- return (
81
- <WidgetWrapper
82
- isLoading={isLoading}
83
- isAccessDenied={isAccessDenied}
84
- isError={isError}
85
- widgetName={widget?.name || t('emailSendingTitle')}
86
- onRemove={onRemove}
87
- >
88
- <Card className="h-full flex flex-col group">
89
- <div
90
- className="drag-handle absolute top-3 left-4 z-10"
91
- style={{ cursor: 'grab' }}
92
- >
93
- <IconGripVertical className="text-muted-foreground/50 size-4 shrink-0" />
94
- </div>
95
- <CardHeader className="pb-2 pt-4 pl-10">
96
- <CardTitle className="text-base font-semibold">
97
- {t('emailSendingTitle')}
98
- </CardTitle>
99
- <CardDescription>{t('emailSendingDescription')}</CardDescription>
100
- </CardHeader>
101
- <CardContent className="flex-1 pt-0">
102
- <div className="h-[280px] w-full">
103
- <ResponsiveContainer width="100%" height="100%">
104
- <BarChart
105
- data={chartData}
106
- margin={{ top: 5, right: 10, left: -20, bottom: 0 }}
107
- >
108
- <CartesianGrid
109
- strokeDasharray="3 3"
110
- stroke="currentColor"
111
- opacity={0.1}
112
- />
113
- <XAxis
114
- dataKey="day"
115
- tick={{ fill: 'hsl(var(--muted-foreground))', fontSize: 12 }}
116
- axisLine={false}
117
- tickLine={false}
118
- />
119
- <YAxis
120
- tick={{ fill: 'hsl(var(--muted-foreground))', fontSize: 12 }}
121
- axisLine={false}
122
- tickLine={false}
123
- />
124
- <Tooltip content={<CustomTooltip />} />
125
- <Bar
126
- dataKey="sent"
127
- fill="#3b82f6"
128
- radius={[4, 4, 0, 0]}
129
- animationDuration={1200}
130
- />
131
- </BarChart>
132
- </ResponsiveContainer>
133
- </div>
134
- <div className="mt-3 flex items-center justify-center">
135
- <div className="flex items-center gap-2">
136
- <div
137
- className="h-2.5 w-2.5 rounded-full"
138
- style={{ backgroundColor: '#3b82f6' }}
139
- />
140
- <span className="text-xs text-muted-foreground">
141
- {t('emailsSent')}
142
- </span>
143
- </div>
144
- </div>
145
- </CardContent>
146
- </Card>
147
- </WidgetWrapper>
148
- );
149
- }