@hed-hog/core 0.0.299 → 0.0.300

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 (112) hide show
  1. package/dist/dashboard/dashboard/dashboard.controller.d.ts +6 -0
  2. package/dist/dashboard/dashboard/dashboard.controller.d.ts.map +1 -1
  3. package/dist/dashboard/dashboard/dashboard.service.d.ts +6 -0
  4. package/dist/dashboard/dashboard/dashboard.service.d.ts.map +1 -1
  5. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +2 -1
  6. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts.map +1 -1
  7. package/dist/dashboard/dashboard-component/dashboard-component.controller.js +6 -3
  8. package/dist/dashboard/dashboard-component/dashboard-component.controller.js.map +1 -1
  9. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +7 -1
  10. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts.map +1 -1
  11. package/dist/dashboard/dashboard-component/dashboard-component.service.js +76 -33
  12. package/dist/dashboard/dashboard-component/dashboard-component.service.js.map +1 -1
  13. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +65 -0
  14. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts.map +1 -1
  15. package/dist/dashboard/dashboard-core/dashboard-core.controller.js +111 -0
  16. package/dist/dashboard/dashboard-core/dashboard-core.controller.js.map +1 -1
  17. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +69 -0
  18. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts.map +1 -1
  19. package/dist/dashboard/dashboard-core/dashboard-core.service.js +526 -19
  20. package/dist/dashboard/dashboard-core/dashboard-core.service.js.map +1 -1
  21. package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts +2 -0
  22. package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts.map +1 -1
  23. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts +2 -0
  24. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
  25. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +2 -0
  26. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts.map +1 -1
  27. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +2 -0
  28. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts.map +1 -1
  29. package/hedhog/data/dashboard.yaml +12 -6
  30. package/hedhog/data/dashboard_component_role.yaml +66 -0
  31. package/hedhog/data/dashboard_role.yaml +2 -8
  32. package/hedhog/data/route.yaml +72 -0
  33. package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +333 -128
  34. package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +277 -53
  35. package/hedhog/frontend/app/dashboard/components/add-widget-selector-dialog.tsx.ejs +179 -231
  36. package/hedhog/frontend/app/dashboard/components/draggable-grid.tsx.ejs +64 -18
  37. package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +1389 -0
  38. package/hedhog/frontend/app/dashboard/dashboard.css.ejs +37 -0
  39. package/hedhog/frontend/app/dashboard/management/page.tsx.ejs +1 -1
  40. package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +6 -6
  41. package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +8 -8
  42. package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +3 -3
  43. package/hedhog/frontend/app/dashboard/page.tsx.ejs +3 -25
  44. package/hedhog/frontend/messages/en.json +112 -2
  45. package/hedhog/frontend/messages/pt.json +111 -1
  46. package/hedhog/frontend/widgets/account-security.tsx.ejs +1 -1
  47. package/hedhog/frontend/widgets/active-users-card.tsx.ejs +2 -2
  48. package/hedhog/frontend/widgets/activity-timeline.tsx.ejs +1 -1
  49. package/hedhog/frontend/widgets/email-notifications.tsx.ejs +1 -1
  50. package/hedhog/frontend/widgets/locale-config.tsx.ejs +1 -1
  51. package/hedhog/frontend/widgets/login-history-chart.tsx.ejs +1 -1
  52. package/hedhog/frontend/widgets/mail-config.tsx.ejs +1 -1
  53. package/hedhog/frontend/widgets/mail-sent-card.tsx.ejs +2 -2
  54. package/hedhog/frontend/widgets/mail-sent-chart.tsx.ejs +1 -1
  55. package/hedhog/frontend/widgets/menus-card.tsx.ejs +2 -2
  56. package/hedhog/frontend/widgets/oauth-config.tsx.ejs +1 -1
  57. package/hedhog/frontend/widgets/permissions-card.tsx.ejs +2 -2
  58. package/hedhog/frontend/widgets/permissions-chart.tsx.ejs +1 -1
  59. package/hedhog/frontend/widgets/profile-card.tsx.ejs +1 -1
  60. package/hedhog/frontend/widgets/routes-card.tsx.ejs +2 -2
  61. package/hedhog/frontend/widgets/session-activity-chart.tsx.ejs +1 -1
  62. package/hedhog/frontend/widgets/sessions-today-card.tsx.ejs +2 -2
  63. package/hedhog/frontend/widgets/stat-access-level.tsx.ejs +1 -1
  64. package/hedhog/frontend/widgets/stat-actions-today.tsx.ejs +1 -1
  65. package/hedhog/frontend/widgets/stat-consecutive-days.tsx.ejs +1 -1
  66. package/hedhog/frontend/widgets/stat-online-time.tsx.ejs +1 -1
  67. package/hedhog/frontend/widgets/storage-config.tsx.ejs +1 -1
  68. package/hedhog/frontend/widgets/theme-config.tsx.ejs +1 -1
  69. package/hedhog/frontend/widgets/user-growth-chart.tsx.ejs +1 -1
  70. package/hedhog/frontend/widgets/user-roles.tsx.ejs +1 -1
  71. package/hedhog/frontend/widgets/user-sessions.tsx.ejs +1 -1
  72. package/hedhog/table/dashboard.yaml +6 -0
  73. package/package.json +5 -5
  74. package/src/dashboard/dashboard-component/dashboard-component.controller.ts +15 -2
  75. package/src/dashboard/dashboard-component/dashboard-component.service.ts +107 -43
  76. package/src/dashboard/dashboard-core/dashboard-core.controller.ts +112 -1
  77. package/src/dashboard/dashboard-core/dashboard-core.service.ts +674 -19
  78. package/hedhog/frontend/app/dashboard/components/widgets/core..gitkeep.ejs +0 -11
  79. package/hedhog/frontend/app/dashboard/components/widgets/core.account-security.tsx.ejs +0 -192
  80. package/hedhog/frontend/app/dashboard/components/widgets/core.active-users-card.tsx.ejs +0 -58
  81. package/hedhog/frontend/app/dashboard/components/widgets/core.activity-timeline.tsx.ejs +0 -223
  82. package/hedhog/frontend/app/dashboard/components/widgets/core.email-notifications.tsx.ejs +0 -226
  83. package/hedhog/frontend/app/dashboard/components/widgets/core.locale-config.tsx.ejs +0 -168
  84. package/hedhog/frontend/app/dashboard/components/widgets/core.login-history-chart.tsx.ejs +0 -115
  85. package/hedhog/frontend/app/dashboard/components/widgets/core.mail-config.tsx.ejs +0 -199
  86. package/hedhog/frontend/app/dashboard/components/widgets/core.mail-sent-card.tsx.ejs +0 -58
  87. package/hedhog/frontend/app/dashboard/components/widgets/core.mail-sent-chart.tsx.ejs +0 -149
  88. package/hedhog/frontend/app/dashboard/components/widgets/core.menus-card.tsx.ejs +0 -58
  89. package/hedhog/frontend/app/dashboard/components/widgets/core.oauth-config.tsx.ejs +0 -175
  90. package/hedhog/frontend/app/dashboard/components/widgets/core.permissions-card.tsx.ejs +0 -61
  91. package/hedhog/frontend/app/dashboard/components/widgets/core.permissions-chart.tsx.ejs +0 -156
  92. package/hedhog/frontend/app/dashboard/components/widgets/core.profile-card.tsx.ejs +0 -186
  93. package/hedhog/frontend/app/dashboard/components/widgets/core.routes-card.tsx.ejs +0 -58
  94. package/hedhog/frontend/app/dashboard/components/widgets/core.session-activity-chart.tsx.ejs +0 -183
  95. package/hedhog/frontend/app/dashboard/components/widgets/core.sessions-today-card.tsx.ejs +0 -62
  96. package/hedhog/frontend/app/dashboard/components/widgets/core.stat-access-level.tsx.ejs +0 -57
  97. package/hedhog/frontend/app/dashboard/components/widgets/core.stat-actions-today.tsx.ejs +0 -57
  98. package/hedhog/frontend/app/dashboard/components/widgets/core.stat-consecutive-days.tsx.ejs +0 -57
  99. package/hedhog/frontend/app/dashboard/components/widgets/core.stat-online-time.tsx.ejs +0 -57
  100. package/hedhog/frontend/app/dashboard/components/widgets/core.storage-config.tsx.ejs +0 -196
  101. package/hedhog/frontend/app/dashboard/components/widgets/core.theme-config.tsx.ejs +0 -213
  102. package/hedhog/frontend/app/dashboard/components/widgets/core.user-growth-chart.tsx.ejs +0 -210
  103. package/hedhog/frontend/app/dashboard/components/widgets/core.user-roles.tsx.ejs +0 -132
  104. package/hedhog/frontend/app/dashboard/components/widgets/core.user-sessions.tsx.ejs +0 -236
  105. package/hedhog/frontend/app/dashboard/components/widgets/finance.alerts.tsx.ejs +0 -108
  106. package/hedhog/frontend/app/dashboard/components/widgets/finance.cash-balance-kpi.tsx.ejs +0 -66
  107. package/hedhog/frontend/app/dashboard/components/widgets/finance.cash-flow-chart.tsx.ejs +0 -122
  108. package/hedhog/frontend/app/dashboard/components/widgets/finance.default-kpi.tsx.ejs +0 -63
  109. package/hedhog/frontend/app/dashboard/components/widgets/finance.payable-30d-kpi.tsx.ejs +0 -73
  110. package/hedhog/frontend/app/dashboard/components/widgets/finance.receivable-30d-kpi.tsx.ejs +0 -73
  111. package/hedhog/frontend/app/dashboard/components/widgets/finance.upcoming-payable.tsx.ejs +0 -123
  112. package/hedhog/frontend/app/dashboard/components/widgets/finance.upcoming-receivable.tsx.ejs +0 -118
@@ -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
- }
@@ -1,58 +0,0 @@
1
- import { useWidgetData } from '@/hooks/use-widget-data';
2
- import { LayoutList } from 'lucide-react';
3
- import { useTranslations } from 'next-intl';
4
- import StatCard from '../stats';
5
- import { WidgetWrapper } from '../widget-wrapper';
6
-
7
- interface MenusCardProps {
8
- widget?: any;
9
- onRemove?: () => void;
10
- }
11
-
12
- interface SystemStatsData {
13
- cards?: {
14
- menus?: {
15
- value: number;
16
- change: number | null;
17
- };
18
- };
19
- }
20
-
21
- export default function MenusCard({ widget, onRemove }: MenusCardProps) {
22
- const t = useTranslations('core.Dashboard');
23
-
24
- const { data, isLoading, isAccessDenied, isError } =
25
- useWidgetData<SystemStatsData>({
26
- endpoint: '/dashboard-core/stats/overview/system',
27
- queryKey: 'dashboard-stats-system',
28
- });
29
-
30
- const value = data?.cards?.menus?.value?.toLocaleString('pt-BR') || '0';
31
- const change = data?.cards?.menus?.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('menus')}
41
- onRemove={onRemove}
42
- >
43
- <StatCard
44
- title={t('menus')}
45
- value={value}
46
- change={
47
- change !== null && change !== undefined
48
- ? `${change > 0 ? '+' : ''}${change}%`
49
- : undefined
50
- }
51
- changeType={changeType}
52
- icon={<LayoutList className="h-6 w-6 text-green-500" />}
53
- iconBg="bg-green-500/10"
54
- delay={50}
55
- />
56
- </WidgetWrapper>
57
- );
58
- }
@@ -1,175 +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
- OAuthConfigWidgetData,
15
- } from '@/types/widget-data';
16
- import { CheckCircle2, KeyRound, XCircle } from 'lucide-react';
17
- import { useTranslations } from 'next-intl';
18
- import { WidgetWrapper } from '../widget-wrapper';
19
-
20
- const defaultOAuthConfigData: OAuthConfigWidgetData = {
21
- status: {
22
- isConfigured: false,
23
- enabledProviderCount: 0,
24
- configuredProviderCount: 0,
25
- connectedAccountCount: 0,
26
- },
27
- providers: [],
28
- };
29
-
30
- interface OAuthConfigProps {
31
- widget?: { name?: string };
32
- onRemove?: () => void;
33
- }
34
-
35
- export default function OAuthConfig({ widget, onRemove }: OAuthConfigProps) {
36
- const t = useTranslations('core.DashboardPage.oauthConfig');
37
-
38
- const { data, isLoading, isError, isAccessDenied } = useWidgetData<
39
- DashboardCoreConfigOverviewData,
40
- OAuthConfigWidgetData
41
- >({
42
- endpoint: '/dashboard-core/config/overview',
43
- queryKey: 'dashboard-core-config-overview',
44
- select: (d) => d.oauthConfig,
45
- });
46
-
47
- const oauthData = data ?? defaultOAuthConfigData;
48
-
49
- return (
50
- <WidgetWrapper
51
- isLoading={isLoading}
52
- isError={isError}
53
- isAccessDenied={isAccessDenied}
54
- widgetName={widget?.name ?? t('title')}
55
- onRemove={onRemove}
56
- >
57
- <Card className="flex h-full min-h-0 flex-col overflow-hidden">
58
- <CardHeader className="shrink-0">
59
- <div className="flex items-center justify-between gap-3">
60
- <div className="flex items-center gap-3">
61
- <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-amber-50">
62
- <KeyRound className="h-5 w-5 text-amber-600" />
63
- </div>
64
- <div>
65
- <CardTitle className="text-base">{t('title')}</CardTitle>
66
- <CardDescription>{t('description')}</CardDescription>
67
- </div>
68
- </div>
69
- <Badge
70
- variant="secondary"
71
- className={
72
- oauthData.status.isConfigured
73
- ? 'bg-emerald-50 text-emerald-700'
74
- : 'bg-amber-50 text-amber-700'
75
- }
76
- >
77
- {oauthData.status.isConfigured ? t('configured') : t('pending')}
78
- </Badge>
79
- </div>
80
- </CardHeader>
81
- <CardContent className="flex min-h-0 flex-1 flex-col gap-4 overflow-hidden pt-0">
82
- <div className="grid grid-cols-3 gap-2">
83
- <div className="rounded-lg border bg-muted/30 p-3 text-center">
84
- <p className="text-[11px] text-muted-foreground">
85
- {t('enabled')}
86
- </p>
87
- <p className="mt-1 text-lg font-semibold">
88
- {oauthData.status.enabledProviderCount}
89
- </p>
90
- </div>
91
- <div className="rounded-lg border bg-muted/30 p-3 text-center">
92
- <p className="text-[11px] text-muted-foreground">
93
- {t('configuredProviders')}
94
- </p>
95
- <p className="mt-1 text-lg font-semibold">
96
- {oauthData.status.configuredProviderCount}
97
- </p>
98
- </div>
99
- <div className="rounded-lg border bg-muted/30 p-3 text-center">
100
- <p className="text-[11px] text-muted-foreground">
101
- {t('connectedAccounts')}
102
- </p>
103
- <p className="mt-1 text-lg font-semibold">
104
- {oauthData.status.connectedAccountCount}
105
- </p>
106
- </div>
107
- </div>
108
-
109
- <div className="min-h-0 flex-1 space-y-2 overflow-auto">
110
- {oauthData.providers.length > 0 ? (
111
- oauthData.providers.map((provider) => (
112
- <div key={provider.id} className="rounded-lg border p-3">
113
- <div className="flex items-center justify-between gap-2">
114
- <p className="text-sm font-medium">{provider.label}</p>
115
- <div className="flex items-center gap-1.5">
116
- <Badge
117
- variant="secondary"
118
- className={
119
- provider.enabled
120
- ? 'bg-emerald-50 text-emerald-700'
121
- : 'bg-muted text-muted-foreground'
122
- }
123
- >
124
- {provider.enabled ? (
125
- <>
126
- <CheckCircle2 className="mr-1 h-3 w-3" />
127
- {t('enabled')}
128
- </>
129
- ) : (
130
- <>
131
- <XCircle className="mr-1 h-3 w-3" />
132
- {t('disabled')}
133
- </>
134
- )}
135
- </Badge>
136
- <Badge
137
- variant="outline"
138
- className={
139
- provider.configured
140
- ? 'border-emerald-200 text-emerald-700'
141
- : 'text-muted-foreground'
142
- }
143
- >
144
- {provider.configured ? t('configured') : t('pending')}
145
- </Badge>
146
- </div>
147
- </div>
148
- <div className="mt-2 flex flex-wrap gap-3 text-[11px] text-muted-foreground">
149
- <span>
150
- {t('scopesCount', { count: provider.scopesCount })}
151
- </span>
152
- <span>
153
- {t('connectedUsers', { count: provider.connectedUsers })}
154
- </span>
155
- <span>
156
- {provider.missingKeys.length > 0
157
- ? t('missingKeys', {
158
- count: provider.missingKeys.length,
159
- })
160
- : t('allKeysPresent')}
161
- </span>
162
- </div>
163
- </div>
164
- ))
165
- ) : (
166
- <p className="text-xs text-muted-foreground">
167
- {t('noProviders')}
168
- </p>
169
- )}
170
- </div>
171
- </CardContent>
172
- </Card>
173
- </WidgetWrapper>
174
- );
175
- }