@hed-hog/core 0.0.297 → 0.0.298
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.
- package/dist/auth/auth.controller.d.ts +10 -10
- package/dist/auth/auth.service.d.ts +10 -10
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +14 -0
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.controller.js +9 -0
- package/dist/dashboard/dashboard-core/dashboard-core.controller.js.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.module.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.module.js +6 -1
- package/dist/dashboard/dashboard-core/dashboard-core.module.js.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +173 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.js +531 -5
- package/dist/dashboard/dashboard-core/dashboard-core.service.js.map +1 -1
- package/dist/file/file.controller.d.ts.map +1 -1
- package/dist/file/file.controller.js +16 -0
- package/dist/file/file.controller.js.map +1 -1
- package/dist/file/file.service.d.ts +7 -1
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +38 -1
- package/dist/file/file.service.js.map +1 -1
- package/dist/file/provider/s3.provider.d.ts +1 -0
- package/dist/file/provider/s3.provider.d.ts.map +1 -1
- package/dist/file/provider/s3.provider.js +38 -29
- package/dist/file/provider/s3.provider.js.map +1 -1
- package/dist/oauth/oauth.service.d.ts.map +1 -1
- package/dist/oauth/oauth.service.js +2 -1
- package/dist/oauth/oauth.service.js.map +1 -1
- package/dist/user/constants/user.constants.d.ts +1 -0
- package/dist/user/constants/user.constants.d.ts.map +1 -1
- package/dist/user/constants/user.constants.js +2 -1
- package/dist/user/constants/user.constants.js.map +1 -1
- package/dist/user/user.controller.d.ts +10 -10
- package/dist/user/user.service.d.ts +30 -30
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +2 -1
- package/dist/user/user.service.js.map +1 -1
- package/hedhog/data/dashboard_item.yaml +11 -11
- package/hedhog/data/route.yaml +8 -0
- package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +76 -15
- package/hedhog/frontend/app/dashboard/components/widgets/email-notifications.tsx.ejs +85 -61
- package/hedhog/frontend/app/dashboard/components/widgets/locale-config.tsx.ejs +139 -280
- package/hedhog/frontend/app/dashboard/components/widgets/mail-config.tsx.ejs +161 -407
- package/hedhog/frontend/app/dashboard/components/widgets/oauth-config.tsx.ejs +150 -271
- package/hedhog/frontend/app/dashboard/components/widgets/profile-card.tsx.ejs +3 -3
- package/hedhog/frontend/app/dashboard/components/widgets/storage-config.tsx.ejs +161 -305
- package/hedhog/frontend/app/dashboard/components/widgets/theme-config.tsx.ejs +184 -246
- package/hedhog/frontend/app/dashboard/components/widgets/user-roles.tsx.ejs +12 -14
- package/hedhog/frontend/messages/en.json +90 -0
- package/hedhog/frontend/messages/pt.json +90 -0
- package/hedhog/table/mail_sent_user.yaml +75 -0
- package/package.json +5 -5
- package/src/dashboard/dashboard-core/dashboard-core.controller.ts +5 -0
- package/src/dashboard/dashboard-core/dashboard-core.module.ts +6 -1
- package/src/dashboard/dashboard-core/dashboard-core.service.ts +766 -3
- package/src/file/file.controller.ts +37 -13
- package/src/file/file.service.ts +47 -5
- package/src/file/provider/s3.provider.ts +39 -29
- package/src/oauth/oauth.service.ts +8 -7
- package/src/user/constants/user.constants.ts +1 -0
- package/src/user/user.service.ts +2 -1
|
@@ -12,66 +12,26 @@ import {
|
|
|
12
12
|
ChartTooltip,
|
|
13
13
|
ChartTooltipContent,
|
|
14
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';
|
|
15
20
|
import { Mail, MailCheck, MailWarning, MailX } from 'lucide-react';
|
|
21
|
+
import { useTranslations } from 'next-intl';
|
|
16
22
|
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';
|
|
17
23
|
import { WidgetWrapper } from '../widget-wrapper';
|
|
18
24
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
{ date: '11 Fev', recebidos: 2, lidos: 2 },
|
|
26
|
-
{ date: '13 Fev', recebidos: 7, lidos: 5 },
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
const chartConfig = {
|
|
30
|
-
recebidos: {
|
|
31
|
-
label: 'Recebidos',
|
|
32
|
-
color: 'hsl(221, 83%, 53%)',
|
|
33
|
-
},
|
|
34
|
-
lidos: {
|
|
35
|
-
label: 'Lidos',
|
|
36
|
-
color: 'hsl(160, 84%, 39%)',
|
|
25
|
+
const defaultEmailNotificationsData: EmailNotificationsData = {
|
|
26
|
+
cards: {
|
|
27
|
+
received: 0,
|
|
28
|
+
read: 0,
|
|
29
|
+
unread: 0,
|
|
30
|
+
error: 0,
|
|
37
31
|
},
|
|
32
|
+
chart: [],
|
|
38
33
|
};
|
|
39
34
|
|
|
40
|
-
const emailStats = [
|
|
41
|
-
{
|
|
42
|
-
label: 'Recebidos',
|
|
43
|
-
shortLabel: 'Rec.',
|
|
44
|
-
value: '35',
|
|
45
|
-
icon: Mail,
|
|
46
|
-
color: 'text-blue-600 dark:text-blue-400',
|
|
47
|
-
bg: 'bg-blue-50 dark:bg-blue-950/40',
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
label: 'Lidos',
|
|
51
|
-
shortLabel: 'Lid.',
|
|
52
|
-
value: '26',
|
|
53
|
-
icon: MailCheck,
|
|
54
|
-
color: 'text-emerald-600 dark:text-emerald-400',
|
|
55
|
-
bg: 'bg-emerald-50 dark:bg-emerald-950/40',
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
label: 'Nao lidos',
|
|
59
|
-
shortLabel: 'N. lid.',
|
|
60
|
-
value: '9',
|
|
61
|
-
icon: MailWarning,
|
|
62
|
-
color: 'text-amber-600 dark:text-amber-400',
|
|
63
|
-
bg: 'bg-amber-50 dark:bg-amber-950/40',
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
label: 'Com erro',
|
|
67
|
-
shortLabel: 'Erro',
|
|
68
|
-
value: '2',
|
|
69
|
-
icon: MailX,
|
|
70
|
-
color: 'text-red-600 dark:text-red-400',
|
|
71
|
-
bg: 'bg-red-50 dark:bg-red-950/40',
|
|
72
|
-
},
|
|
73
|
-
];
|
|
74
|
-
|
|
75
35
|
interface EmailNotificationsProps {
|
|
76
36
|
widget?: { name?: string };
|
|
77
37
|
onRemove?: () => void;
|
|
@@ -81,12 +41,76 @@ export default function EmailNotifications({
|
|
|
81
41
|
widget,
|
|
82
42
|
onRemove,
|
|
83
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
|
+
|
|
84
108
|
return (
|
|
85
109
|
<WidgetWrapper
|
|
86
|
-
isLoading={
|
|
87
|
-
isError={
|
|
88
|
-
isAccessDenied={
|
|
89
|
-
widgetName={widget?.name ?? '
|
|
110
|
+
isLoading={isLoading}
|
|
111
|
+
isError={isError}
|
|
112
|
+
isAccessDenied={isAccessDenied}
|
|
113
|
+
widgetName={widget?.name ?? t('title')}
|
|
90
114
|
onRemove={onRemove}
|
|
91
115
|
>
|
|
92
116
|
<Card className="flex h-full min-h-0 flex-col overflow-hidden">
|
|
@@ -95,10 +119,10 @@ export default function EmailNotifications({
|
|
|
95
119
|
<Mail className="h-4 w-4 text-rose-600 dark:text-rose-400 sm:h-5 sm:w-5" />
|
|
96
120
|
<div>
|
|
97
121
|
<CardTitle className="text-sm font-semibold sm:text-base">
|
|
98
|
-
|
|
122
|
+
{t('title')}
|
|
99
123
|
</CardTitle>
|
|
100
124
|
<CardDescription className="text-xs sm:text-sm">
|
|
101
|
-
|
|
125
|
+
{t('description')}
|
|
102
126
|
</CardDescription>
|
|
103
127
|
</div>
|
|
104
128
|
</div>
|
|
@@ -133,9 +157,9 @@ export default function EmailNotifications({
|
|
|
133
157
|
|
|
134
158
|
<ChartContainer
|
|
135
159
|
config={chartConfig}
|
|
136
|
-
className="min-h-
|
|
160
|
+
className="min-h-42.5 w-full flex-1 overflow-hidden sm:min-h-55"
|
|
137
161
|
>
|
|
138
|
-
<AreaChart data={
|
|
162
|
+
<AreaChart data={chartData}>
|
|
139
163
|
<CartesianGrid vertical={false} strokeDasharray="3 3" />
|
|
140
164
|
<XAxis
|
|
141
165
|
dataKey="date"
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { Badge } from '@/components/ui/badge';
|
|
4
|
-
import { Button } from '@/components/ui/button';
|
|
5
4
|
import {
|
|
6
5
|
Card,
|
|
7
6
|
CardContent,
|
|
@@ -9,301 +8,161 @@ import {
|
|
|
9
8
|
CardHeader,
|
|
10
9
|
CardTitle,
|
|
11
10
|
} from '@/components/ui/card';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} from '@/components/ui/select';
|
|
21
|
-
import { Switch } from '@/components/ui/switch';
|
|
22
|
-
import { Calendar, CheckCircle2, Clock, Globe, Type } from 'lucide-react';
|
|
23
|
-
import { useState } from 'react';
|
|
24
|
-
|
|
25
|
-
interface Language {
|
|
26
|
-
code: string;
|
|
27
|
-
label: string;
|
|
28
|
-
flag: string;
|
|
29
|
-
enabled: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const availableLanguages: Language[] = [
|
|
33
|
-
{ code: 'pt-BR', label: 'Portugues (Brasil)', flag: '🇧🇷', enabled: true },
|
|
34
|
-
{ code: 'en-US', label: 'Ingles (EUA)', flag: '🇺🇸', enabled: true },
|
|
35
|
-
{ code: 'es-ES', label: 'Espanhol (Espanha)', flag: '🇪🇸', enabled: false },
|
|
36
|
-
{ code: 'fr-FR', label: 'Frances (Franca)', flag: '🇫🇷', enabled: false },
|
|
37
|
-
{ code: 'de-DE', label: 'Alemao (Alemanha)', flag: '🇩🇪', enabled: false },
|
|
38
|
-
{ code: 'it-IT', label: 'Italiano (Italia)', flag: '🇮🇹', enabled: false },
|
|
39
|
-
{ code: 'ja-JP', label: 'Japones (Japao)', flag: '🇯🇵', enabled: false },
|
|
40
|
-
{ code: 'zh-CN', label: 'Chines (Simplificado)', flag: '🇨🇳', enabled: false },
|
|
41
|
-
];
|
|
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';
|
|
42
19
|
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
{ value: 'Asia/Shanghai', label: 'Asia/Shanghai (GMT+8)' },
|
|
54
|
-
{ value: 'Australia/Sydney', label: 'Australia/Sydney (GMT+11)' },
|
|
55
|
-
];
|
|
56
|
-
|
|
57
|
-
const dateFormats = [
|
|
58
|
-
{ value: 'DD/MM/YYYY', label: 'DD/MM/YYYY', example: '14/02/2026' },
|
|
59
|
-
{ value: 'MM/DD/YYYY', label: 'MM/DD/YYYY', example: '02/14/2026' },
|
|
60
|
-
{ value: 'YYYY-MM-DD', label: 'YYYY-MM-DD', example: '2026-02-14' },
|
|
61
|
-
{ value: 'DD.MM.YYYY', label: 'DD.MM.YYYY', example: '14.02.2026' },
|
|
62
|
-
{ value: 'DD-MM-YYYY', label: 'DD-MM-YYYY', example: '14-02-2026' },
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
const timeFormats = [
|
|
66
|
-
{ value: 'HH:mm', label: '24 horas', example: '14:30' },
|
|
67
|
-
{ value: 'hh:mm A', label: '12 horas', example: '02:30 PM' },
|
|
68
|
-
{ value: 'HH:mm:ss', label: '24 horas com segundos', example: '14:30:45' },
|
|
69
|
-
{
|
|
70
|
-
value: 'hh:mm:ss A',
|
|
71
|
-
label: '12 horas com segundos',
|
|
72
|
-
example: '02:30:45 PM',
|
|
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,
|
|
73
30
|
},
|
|
74
|
-
]
|
|
31
|
+
locales: [],
|
|
32
|
+
};
|
|
75
33
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
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');
|
|
83
41
|
|
|
84
|
-
const
|
|
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
|
+
});
|
|
85
50
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
prev.map((l) => {
|
|
89
|
-
if (l.code === code) {
|
|
90
|
-
if (l.enabled && l.code === defaultLang) return l;
|
|
91
|
-
return { ...l, enabled: !l.enabled };
|
|
92
|
-
}
|
|
93
|
-
return l;
|
|
94
|
-
})
|
|
95
|
-
);
|
|
96
|
-
}
|
|
51
|
+
const localeData = data ?? defaultLocaleConfigData;
|
|
52
|
+
const enabledLocales = localeData.locales.filter((locale) => locale.enabled);
|
|
97
53
|
|
|
98
54
|
return (
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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>
|
|
105
73
|
</div>
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
</Badge>
|
|
117
|
-
</div>
|
|
118
|
-
</CardHeader>
|
|
119
|
-
<CardContent className="space-y-6">
|
|
120
|
-
{/* Languages */}
|
|
121
|
-
<div className="space-y-3">
|
|
122
|
-
<div className="flex items-center gap-2">
|
|
123
|
-
<Type className="h-4 w-4 text-muted-foreground" />
|
|
124
|
-
<Label className="text-sm font-medium">Idiomas habilitados</Label>
|
|
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>
|
|
125
84
|
</div>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
>
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
{
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
</Badge>
|
|
152
|
-
)}
|
|
153
|
-
</label>
|
|
154
|
-
))}
|
|
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>
|
|
155
110
|
</div>
|
|
156
|
-
</div>
|
|
157
111
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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>
|
|
186
140
|
</div>
|
|
187
|
-
<Select value={timezone} onValueChange={setTimezone}>
|
|
188
|
-
<SelectTrigger>
|
|
189
|
-
<SelectValue />
|
|
190
|
-
</SelectTrigger>
|
|
191
|
-
<SelectContent>
|
|
192
|
-
{timezones.map((tz) => (
|
|
193
|
-
<SelectItem key={tz.value} value={tz.value}>
|
|
194
|
-
{tz.label}
|
|
195
|
-
</SelectItem>
|
|
196
|
-
))}
|
|
197
|
-
</SelectContent>
|
|
198
|
-
</Select>
|
|
199
|
-
</div>
|
|
200
141
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
<Calendar className="h-4 w-4 text-muted-foreground" />
|
|
206
|
-
<Label>Formato de data</Label>
|
|
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>
|
|
207
146
|
</div>
|
|
208
|
-
<
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
<span className="flex items-center gap-2">
|
|
216
|
-
<span className="font-mono text-xs">{df.value}</span>
|
|
217
|
-
<span className="text-muted-foreground">
|
|
218
|
-
{'('}
|
|
219
|
-
{df.example}
|
|
220
|
-
{')'}
|
|
221
|
-
</span>
|
|
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}
|
|
222
154
|
</span>
|
|
223
|
-
</
|
|
224
|
-
))
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
<Clock className="h-4 w-4 text-muted-foreground" />
|
|
231
|
-
<Label>Formato de hora</Label>
|
|
155
|
+
</Badge>
|
|
156
|
+
))
|
|
157
|
+
) : (
|
|
158
|
+
<span className="text-xs text-muted-foreground">
|
|
159
|
+
{t('noneEnabled')}
|
|
160
|
+
</span>
|
|
161
|
+
)}
|
|
232
162
|
</div>
|
|
233
|
-
<Select value={timeFormat} onValueChange={setTimeFormat}>
|
|
234
|
-
<SelectTrigger>
|
|
235
|
-
<SelectValue />
|
|
236
|
-
</SelectTrigger>
|
|
237
|
-
<SelectContent>
|
|
238
|
-
{timeFormats.map((tf) => (
|
|
239
|
-
<SelectItem key={tf.value} value={tf.value}>
|
|
240
|
-
<span className="flex items-center gap-2">
|
|
241
|
-
<span>{tf.label}</span>
|
|
242
|
-
<span className="text-muted-foreground font-mono text-xs">
|
|
243
|
-
{'('}
|
|
244
|
-
{tf.example}
|
|
245
|
-
{')'}
|
|
246
|
-
</span>
|
|
247
|
-
</span>
|
|
248
|
-
</SelectItem>
|
|
249
|
-
))}
|
|
250
|
-
</SelectContent>
|
|
251
|
-
</Select>
|
|
252
|
-
</div>
|
|
253
|
-
</div>
|
|
254
|
-
|
|
255
|
-
{/* Preview */}
|
|
256
|
-
<div className="rounded-lg border bg-muted/50 p-4">
|
|
257
|
-
<p className="mb-2 text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
|
258
|
-
Pre-visualizacao
|
|
259
|
-
</p>
|
|
260
|
-
<div className="flex flex-wrap gap-x-6 gap-y-1 text-sm">
|
|
261
|
-
<span>
|
|
262
|
-
<span className="text-muted-foreground">Data: </span>
|
|
263
|
-
<span className="font-medium font-mono">
|
|
264
|
-
{dateFormats.find((d) => d.value === dateFormat)?.example}
|
|
265
|
-
</span>
|
|
266
|
-
</span>
|
|
267
|
-
<span>
|
|
268
|
-
<span className="text-muted-foreground">Hora: </span>
|
|
269
|
-
<span className="font-medium font-mono">
|
|
270
|
-
{timeFormats.find((t) => t.value === timeFormat)?.example}
|
|
271
|
-
</span>
|
|
272
|
-
</span>
|
|
273
|
-
<span>
|
|
274
|
-
<span className="text-muted-foreground">Fuso: </span>
|
|
275
|
-
<span className="font-medium font-mono">
|
|
276
|
-
{
|
|
277
|
-
timezones
|
|
278
|
-
.find((t) => t.value === timezone)
|
|
279
|
-
?.label.split(' ')[0]
|
|
280
|
-
}
|
|
281
|
-
</span>
|
|
282
|
-
</span>
|
|
283
|
-
</div>
|
|
284
|
-
</div>
|
|
285
|
-
|
|
286
|
-
{/* Actions */}
|
|
287
|
-
<div className="flex items-center justify-between border-t pt-4">
|
|
288
|
-
<div className="flex items-center gap-2">
|
|
289
|
-
<Switch
|
|
290
|
-
id="auto-detect-lang"
|
|
291
|
-
checked={autoDetect}
|
|
292
|
-
onCheckedChange={setAutoDetect}
|
|
293
|
-
/>
|
|
294
|
-
<Label
|
|
295
|
-
htmlFor="auto-detect-lang"
|
|
296
|
-
className="text-sm text-muted-foreground"
|
|
297
|
-
>
|
|
298
|
-
Detectar idioma do navegador
|
|
299
|
-
</Label>
|
|
300
163
|
</div>
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
</Button>
|
|
305
|
-
</div>
|
|
306
|
-
</CardContent>
|
|
307
|
-
</Card>
|
|
164
|
+
</CardContent>
|
|
165
|
+
</Card>
|
|
166
|
+
</WidgetWrapper>
|
|
308
167
|
);
|
|
309
168
|
}
|