@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,57 @@
1
+ 'use client';
2
+
3
+ import { Card, CardContent } from '@/components/ui/card';
4
+ import { useWidgetData } from '@/hooks/use-widget-data';
5
+ import type { AllWidgetsData } from '@/types/widget-data';
6
+ import { CalendarDays } from 'lucide-react';
7
+ import { useTranslations } from 'next-intl';
8
+ import { WidgetWrapper } from '../widget-wrapper';
9
+
10
+ interface StatConsecutiveDaysProps {
11
+ widget?: { name?: string };
12
+ onRemove?: () => void;
13
+ }
14
+
15
+ export default function StatConsecutiveDays({
16
+ widget,
17
+ onRemove,
18
+ }: StatConsecutiveDaysProps) {
19
+ const t = useTranslations('core.DashboardPage.quickStats');
20
+ const { data, isLoading, isError, isAccessDenied } = useWidgetData<
21
+ AllWidgetsData,
22
+ number
23
+ >({
24
+ endpoint: '/dashboard-core/widgets/me',
25
+ queryKey: 'widget-me',
26
+ select: (d) => d.quickStats.consecutiveDays,
27
+ });
28
+
29
+ return (
30
+ <WidgetWrapper
31
+ isLoading={isLoading}
32
+ isError={isError}
33
+ isAccessDenied={isAccessDenied}
34
+ widgetName={widget?.name ?? 'stat-consecutive-days'}
35
+ onRemove={onRemove}
36
+ >
37
+ <Card className="h-full overflow-hidden transition-all duration-300 hover:shadow-md">
38
+ <CardContent className="flex h-full items-center gap-2.5 p-2.5 sm:gap-3 sm:p-3 md:gap-4 md:p-4">
39
+ <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-xl bg-emerald-50 dark:bg-emerald-950/40 sm:h-9 sm:w-9 md:h-11 md:w-11">
40
+ <CalendarDays className="h-3.5 w-3.5 text-emerald-600 dark:text-emerald-400 sm:h-4 sm:w-4 md:h-5 md:w-5" />
41
+ </div>
42
+ <div className="flex min-w-0 flex-col">
43
+ <span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground sm:text-[11px]">
44
+ {t('consecutiveDays')}
45
+ </span>
46
+ <span className="truncate text-lg font-bold tracking-tight text-foreground sm:text-xl md:text-2xl">
47
+ {data ?? '—'}
48
+ </span>
49
+ <span className="truncate text-[10px] text-muted-foreground sm:text-[11px]">
50
+ {t('consecutiveDaysSubtitle')}
51
+ </span>
52
+ </div>
53
+ </CardContent>
54
+ </Card>
55
+ </WidgetWrapper>
56
+ );
57
+ }
@@ -0,0 +1,57 @@
1
+ 'use client';
2
+
3
+ import { Card, CardContent } from '@/components/ui/card';
4
+ import { useWidgetData } from '@/hooks/use-widget-data';
5
+ import type { AllWidgetsData } from '@/types/widget-data';
6
+ import { Clock } from 'lucide-react';
7
+ import { useTranslations } from 'next-intl';
8
+ import { WidgetWrapper } from '../widget-wrapper';
9
+
10
+ interface StatOnlineTimeProps {
11
+ widget?: { name?: string };
12
+ onRemove?: () => void;
13
+ }
14
+
15
+ export default function StatOnlineTime({
16
+ widget,
17
+ onRemove,
18
+ }: StatOnlineTimeProps) {
19
+ const t = useTranslations('core.DashboardPage.quickStats');
20
+ const { data, isLoading, isError, isAccessDenied } = useWidgetData<
21
+ AllWidgetsData,
22
+ string
23
+ >({
24
+ endpoint: '/dashboard-core/widgets/me',
25
+ queryKey: 'widget-me',
26
+ select: (d) => d.quickStats.onlineTime,
27
+ });
28
+
29
+ return (
30
+ <WidgetWrapper
31
+ isLoading={isLoading}
32
+ isError={isError}
33
+ isAccessDenied={isAccessDenied}
34
+ widgetName={widget?.name ?? 'stat-online-time'}
35
+ onRemove={onRemove}
36
+ >
37
+ <Card className="h-full overflow-hidden transition-all duration-300 hover:shadow-md">
38
+ <CardContent className="flex h-full items-center gap-2.5 p-2.5 sm:gap-3 sm:p-3 md:gap-4 md:p-4">
39
+ <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-xl bg-blue-50 dark:bg-blue-950/40 sm:h-9 sm:w-9 md:h-11 md:w-11">
40
+ <Clock className="h-3.5 w-3.5 text-blue-600 dark:text-blue-400 sm:h-4 sm:w-4 md:h-5 md:w-5" />
41
+ </div>
42
+ <div className="flex min-w-0 flex-col">
43
+ <span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground sm:text-[11px]">
44
+ {t('onlineTime')}
45
+ </span>
46
+ <span className="truncate text-lg font-bold tracking-tight text-foreground sm:text-xl md:text-2xl">
47
+ {data ?? '—'}
48
+ </span>
49
+ <span className="truncate text-[10px] text-muted-foreground sm:text-[11px]">
50
+ {t('onlineTimeSubtitle')}
51
+ </span>
52
+ </div>
53
+ </CardContent>
54
+ </Card>
55
+ </WidgetWrapper>
56
+ );
57
+ }
@@ -0,0 +1,196 @@
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
+ StorageConfigWidgetData,
15
+ } from '@/types/widget-data';
16
+ import { CheckCircle2, HardDrive } from 'lucide-react';
17
+ import { useTranslations } from 'next-intl';
18
+ import { WidgetWrapper } from '../widget-wrapper';
19
+
20
+ const defaultStorageConfigData: StorageConfigWidgetData = {
21
+ status: {
22
+ isConfigured: false,
23
+ totalProfiles: 0,
24
+ activeProfiles: 0,
25
+ defaultProfileId: null,
26
+ },
27
+ providers: [],
28
+ profiles: [],
29
+ };
30
+
31
+ interface StorageConfigProps {
32
+ widget?: { name?: string };
33
+ onRemove?: () => void;
34
+ }
35
+
36
+ export default function StorageConfig({
37
+ widget,
38
+ onRemove,
39
+ }: StorageConfigProps) {
40
+ const t = useTranslations('core.DashboardPage.storageConfig');
41
+
42
+ const { data, isLoading, isError, isAccessDenied } = useWidgetData<
43
+ DashboardCoreConfigOverviewData,
44
+ StorageConfigWidgetData
45
+ >({
46
+ endpoint: '/dashboard-core/config/overview',
47
+ queryKey: 'dashboard-core-config-overview',
48
+ select: (d) => d.storageConfig,
49
+ });
50
+
51
+ const storageData = data ?? defaultStorageConfigData;
52
+ const defaultProfile = storageData.profiles.find(
53
+ (profile) => profile.id === storageData.status.defaultProfileId
54
+ );
55
+
56
+ return (
57
+ <WidgetWrapper
58
+ isLoading={isLoading}
59
+ isError={isError}
60
+ isAccessDenied={isAccessDenied}
61
+ widgetName={widget?.name ?? t('title')}
62
+ onRemove={onRemove}
63
+ >
64
+ <Card className="flex h-full min-h-0 flex-col overflow-hidden">
65
+ <CardHeader className="shrink-0">
66
+ <div className="flex items-center justify-between gap-3">
67
+ <div className="flex items-center gap-3">
68
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-violet-50">
69
+ <HardDrive className="h-5 w-5 text-violet-600" />
70
+ </div>
71
+ <div>
72
+ <CardTitle className="text-base">{t('title')}</CardTitle>
73
+ <CardDescription>{t('description')}</CardDescription>
74
+ </div>
75
+ </div>
76
+ <Badge
77
+ variant="secondary"
78
+ className={
79
+ storageData.status.isConfigured
80
+ ? 'bg-emerald-50 text-emerald-700'
81
+ : 'bg-amber-50 text-amber-700'
82
+ }
83
+ >
84
+ {storageData.status.isConfigured ? t('configured') : t('pending')}
85
+ </Badge>
86
+ </div>
87
+ </CardHeader>
88
+ <CardContent className="flex min-h-0 flex-1 flex-col gap-4 overflow-hidden pt-0">
89
+ <div className="grid grid-cols-3 gap-2">
90
+ <div className="rounded-lg border bg-muted/30 p-3 text-center">
91
+ <p className="text-[11px] text-muted-foreground">
92
+ {t('profiles')}
93
+ </p>
94
+ <p className="mt-1 text-lg font-semibold">
95
+ {storageData.status.totalProfiles}
96
+ </p>
97
+ </div>
98
+ <div className="rounded-lg border bg-muted/30 p-3 text-center">
99
+ <p className="text-[11px] text-muted-foreground">{t('active')}</p>
100
+ <p className="mt-1 text-lg font-semibold">
101
+ {storageData.status.activeProfiles}
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('providers')}
107
+ </p>
108
+ <p className="mt-1 text-lg font-semibold">
109
+ {storageData.providers.length}
110
+ </p>
111
+ </div>
112
+ </div>
113
+
114
+ <div className="rounded-lg border p-3">
115
+ <p className="mb-1 text-xs text-muted-foreground">
116
+ {t('defaultProfile')}
117
+ </p>
118
+ <p className="truncate text-sm font-medium">
119
+ {defaultProfile?.name || t('notSet')}
120
+ </p>
121
+ {defaultProfile && (
122
+ <p className="mt-1 text-[11px] text-muted-foreground">
123
+ {defaultProfile.providerType.toUpperCase()} |{' '}
124
+ {defaultProfile.bucketName}
125
+ </p>
126
+ )}
127
+ </div>
128
+
129
+ <div className="grid gap-2 sm:grid-cols-2">
130
+ {storageData.providers.map((provider) => (
131
+ <div
132
+ key={provider.providerType}
133
+ className="rounded-lg border p-3"
134
+ >
135
+ <div className="flex items-center justify-between">
136
+ <p className="text-sm font-medium">
137
+ {provider.providerType.toUpperCase()}
138
+ </p>
139
+ <Badge variant="outline" className="text-[10px]">
140
+ {provider.defaults} {t('defaults')}
141
+ </Badge>
142
+ </div>
143
+ <p className="mt-1 text-[11px] text-muted-foreground">
144
+ {t('providerSummary', {
145
+ total: provider.total,
146
+ active: provider.active,
147
+ })}
148
+ </p>
149
+ </div>
150
+ ))}
151
+ </div>
152
+
153
+ <div className="min-h-0 flex-1 space-y-2 overflow-auto">
154
+ {storageData.profiles.slice(0, 4).map((profile) => (
155
+ <div key={profile.id} className="rounded-lg border p-3">
156
+ <div className="flex items-center justify-between gap-2">
157
+ <p className="truncate text-sm font-medium">{profile.name}</p>
158
+ <div className="flex items-center gap-1.5">
159
+ {profile.isDefault && (
160
+ <Badge variant="outline" className="text-[10px]">
161
+ {t('defaultTag')}
162
+ </Badge>
163
+ )}
164
+ <Badge
165
+ variant="secondary"
166
+ className={
167
+ profile.isActive
168
+ ? 'bg-emerald-50 text-emerald-700'
169
+ : 'bg-muted text-muted-foreground'
170
+ }
171
+ >
172
+ {profile.isActive ? (
173
+ <>
174
+ <CheckCircle2 className="mr-1 h-3 w-3" />
175
+ {t('active')}
176
+ </>
177
+ ) : (
178
+ t('inactive')
179
+ )}
180
+ </Badge>
181
+ </div>
182
+ </div>
183
+ <p className="mt-1 truncate text-[11px] text-muted-foreground">
184
+ {profile.providerType.toUpperCase()} | {profile.bucketName}
185
+ </p>
186
+ </div>
187
+ ))}
188
+ {storageData.profiles.length === 0 && (
189
+ <p className="text-xs text-muted-foreground">{t('noProfiles')}</p>
190
+ )}
191
+ </div>
192
+ </CardContent>
193
+ </Card>
194
+ </WidgetWrapper>
195
+ );
196
+ }
@@ -0,0 +1,213 @@
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
+ ThemeConfigWidgetData,
15
+ } from '@/types/widget-data';
16
+ import { Palette } from 'lucide-react';
17
+ import { useTranslations } from 'next-intl';
18
+ import { WidgetWrapper } from '../widget-wrapper';
19
+
20
+ const emptyPaletteMode = {
21
+ primary: null,
22
+ primaryForeground: null,
23
+ secondary: null,
24
+ secondaryForeground: null,
25
+ accent: null,
26
+ accentForeground: null,
27
+ muted: null,
28
+ mutedForeground: null,
29
+ background: null,
30
+ backgroundForeground: null,
31
+ card: null,
32
+ cardForeground: null,
33
+ };
34
+
35
+ const defaultThemeConfigData: ThemeConfigWidgetData = {
36
+ status: {
37
+ isConfigured: false,
38
+ configuredTokenCount: 0,
39
+ },
40
+ branding: {
41
+ systemName: null,
42
+ systemSlogan: null,
43
+ iconUrl: null,
44
+ imageUrl: null,
45
+ },
46
+ presentation: {
47
+ mode: null,
48
+ font: null,
49
+ textSize: null,
50
+ radius: null,
51
+ },
52
+ palette: {
53
+ light: emptyPaletteMode,
54
+ dark: emptyPaletteMode,
55
+ },
56
+ };
57
+
58
+ interface ThemeConfigProps {
59
+ widget?: { name?: string };
60
+ onRemove?: () => void;
61
+ }
62
+
63
+ export default function ThemeConfig({ widget, onRemove }: ThemeConfigProps) {
64
+ const t = useTranslations('core.DashboardPage.themeConfig');
65
+
66
+ const { data, isLoading, isError, isAccessDenied } = useWidgetData<
67
+ DashboardCoreConfigOverviewData,
68
+ ThemeConfigWidgetData
69
+ >({
70
+ endpoint: '/dashboard-core/config/overview',
71
+ queryKey: 'dashboard-core-config-overview',
72
+ select: (d) => d.themeConfig,
73
+ });
74
+
75
+ const themeData = data ?? defaultThemeConfigData;
76
+
77
+ return (
78
+ <WidgetWrapper
79
+ isLoading={isLoading}
80
+ isError={isError}
81
+ isAccessDenied={isAccessDenied}
82
+ widgetName={widget?.name ?? t('title')}
83
+ onRemove={onRemove}
84
+ >
85
+ <Card className="flex h-full min-h-0 flex-col overflow-hidden">
86
+ <CardHeader className="shrink-0">
87
+ <div className="flex items-center justify-between gap-3">
88
+ <div className="flex items-center gap-3">
89
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-rose-50">
90
+ <Palette className="h-5 w-5 text-rose-600" />
91
+ </div>
92
+ <div>
93
+ <CardTitle className="text-base">{t('title')}</CardTitle>
94
+ <CardDescription>{t('description')}</CardDescription>
95
+ </div>
96
+ </div>
97
+ <Badge
98
+ variant="secondary"
99
+ className={
100
+ themeData.status.isConfigured
101
+ ? 'bg-emerald-50 text-emerald-700'
102
+ : 'bg-amber-50 text-amber-700'
103
+ }
104
+ >
105
+ {themeData.status.isConfigured ? t('configured') : t('pending')}
106
+ </Badge>
107
+ </div>
108
+ </CardHeader>
109
+ <CardContent className="flex min-h-0 flex-1 flex-col gap-4 overflow-hidden pt-0">
110
+ <div className="rounded-lg border bg-muted/30 p-4">
111
+ <div className="flex items-center gap-3 rounded-lg border bg-background p-3">
112
+ <div
113
+ className="flex h-10 w-10 items-center justify-center rounded-lg text-sm font-bold text-white"
114
+ style={{
115
+ backgroundColor: themeData.palette.light.primary || '#64748b',
116
+ }}
117
+ >
118
+ {(themeData.branding.systemName || 'S').charAt(0).toUpperCase()}
119
+ </div>
120
+ <div className="min-w-0">
121
+ <p className="truncate text-sm font-semibold">
122
+ {themeData.branding.systemName || t('notSet')}
123
+ </p>
124
+ <p className="truncate text-xs text-muted-foreground">
125
+ {themeData.branding.systemSlogan || t('notSet')}
126
+ </p>
127
+ </div>
128
+ <Badge variant="outline" className="ml-auto text-[10px]">
129
+ {themeData.presentation.mode || t('notSet')}
130
+ </Badge>
131
+ </div>
132
+ </div>
133
+
134
+ <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
135
+ <div className="rounded-lg border p-3 text-center">
136
+ <p className="text-[11px] text-muted-foreground">{t('tokens')}</p>
137
+ <p className="mt-1 text-lg font-semibold">
138
+ {themeData.status.configuredTokenCount}
139
+ </p>
140
+ </div>
141
+ <div className="rounded-lg border p-3 text-center">
142
+ <p className="text-[11px] text-muted-foreground">{t('font')}</p>
143
+ <p className="mt-1 truncate text-sm font-medium">
144
+ {themeData.presentation.font || t('notSet')}
145
+ </p>
146
+ </div>
147
+ <div className="rounded-lg border p-3 text-center">
148
+ <p className="text-[11px] text-muted-foreground">
149
+ {t('textSize')}
150
+ </p>
151
+ <p className="mt-1 truncate text-sm font-medium">
152
+ {themeData.presentation.textSize || t('notSet')}
153
+ </p>
154
+ </div>
155
+ <div className="rounded-lg border p-3 text-center">
156
+ <p className="text-[11px] text-muted-foreground">{t('radius')}</p>
157
+ <p className="mt-1 truncate text-sm font-medium">
158
+ {themeData.presentation.radius || t('notSet')}
159
+ </p>
160
+ </div>
161
+ </div>
162
+
163
+ <div className="grid gap-2 sm:grid-cols-2">
164
+ <div className="rounded-lg border p-3">
165
+ <div className="mb-2 flex items-center justify-between">
166
+ <p className="text-xs text-muted-foreground">
167
+ {t('lightPalette')}
168
+ </p>
169
+ <Badge variant="outline" className="text-[10px]">
170
+ {themeData.palette.light.primary || t('notSet')}
171
+ </Badge>
172
+ </div>
173
+ <div className="flex items-center gap-2">
174
+ <span
175
+ className="h-5 w-5 rounded-full border"
176
+ style={{
177
+ backgroundColor:
178
+ themeData.palette.light.primary || 'transparent',
179
+ }}
180
+ />
181
+ <span className="text-xs text-muted-foreground">
182
+ {t('primary')}
183
+ </span>
184
+ </div>
185
+ </div>
186
+ <div className="rounded-lg border p-3">
187
+ <div className="mb-2 flex items-center justify-between">
188
+ <p className="text-xs text-muted-foreground">
189
+ {t('darkPalette')}
190
+ </p>
191
+ <Badge variant="outline" className="text-[10px]">
192
+ {themeData.palette.dark.primary || t('notSet')}
193
+ </Badge>
194
+ </div>
195
+ <div className="flex items-center gap-2">
196
+ <span
197
+ className="h-5 w-5 rounded-full border"
198
+ style={{
199
+ backgroundColor:
200
+ themeData.palette.dark.primary || 'transparent',
201
+ }}
202
+ />
203
+ <span className="text-xs text-muted-foreground">
204
+ {t('primary')}
205
+ </span>
206
+ </div>
207
+ </div>
208
+ </div>
209
+ </CardContent>
210
+ </Card>
211
+ </WidgetWrapper>
212
+ );
213
+ }