@greatapps/common 1.1.676 → 1.1.677
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/components/account/ConfigurationsMyAccountModal.mjs +8 -6
- package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
- package/dist/components/account/ConfirmDeleteAccountModal.mjs +20 -19
- package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/ConfirmGlobalPreferencesModal.mjs +10 -11
- package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -1
- package/dist/components/account/DeleteAccountModal.mjs +34 -28
- package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/DisableTwoFactorAuthModal.mjs +7 -5
- package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
- package/dist/components/account/IsntPossibleDeleteAccountModal.mjs +8 -9
- package/dist/components/account/IsntPossibleDeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/TwoFactorAuthModal.mjs +22 -23
- package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
- package/dist/components/account/constants.mjs +4 -4
- package/dist/components/account/constants.mjs.map +1 -1
- package/dist/components/account/hooks/useChangeEmailForm.mjs +5 -3
- package/dist/components/account/hooks/useChangeEmailForm.mjs.map +1 -1
- package/dist/components/account/hooks/useChangePasswordForm.mjs +26 -3
- package/dist/components/account/hooks/useChangePasswordForm.mjs.map +1 -1
- package/dist/components/account/hooks/useChangePhoneForm.mjs +18 -9
- package/dist/components/account/hooks/useChangePhoneForm.mjs.map +1 -1
- package/dist/components/account/hooks/useDisableTwoFactorAuthForm.mjs +26 -3
- package/dist/components/account/hooks/useDisableTwoFactorAuthForm.mjs.map +1 -1
- package/dist/components/account/hooks/useOtpVerification.mjs +19 -3
- package/dist/components/account/hooks/useOtpVerification.mjs.map +1 -1
- package/dist/components/account/hooks/useTwoFactorAuthForm.mjs +27 -4
- package/dist/components/account/hooks/useTwoFactorAuthForm.mjs.map +1 -1
- package/dist/components/account/sections/ChangeEmailModal.mjs +25 -28
- package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
- package/dist/components/account/sections/ChangePasswordSection.mjs +8 -6
- package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -1
- package/dist/components/account/sections/ChangePhoneModal.mjs +24 -27
- package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
- package/dist/components/account/sections/MyProfileSection.mjs +37 -22
- package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
- package/dist/components/account/sections/PreferencesSection.mjs +48 -24
- package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
- package/dist/components/account/sections/SecuritySection.mjs +11 -9
- package/dist/components/account/sections/SecuritySection.mjs.map +1 -1
- package/dist/components/account/sections/TokenSection.mjs +24 -8
- package/dist/components/account/sections/TokenSection.mjs.map +1 -1
- package/dist/components/layouts/AppMobileNavBar.mjs +2 -148
- package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
- package/dist/components/layouts/NavBar.mjs +5 -3
- package/dist/components/layouts/NavBar.mjs.map +1 -1
- package/dist/components/layouts/NotificationsPopover.mjs +5 -3
- package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
- package/dist/components/layouts/ProfilePopover.mjs +6 -4
- package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
- package/dist/components/layouts/UsersSelectorPopover.mjs +9 -7
- package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
- package/dist/components/modals/BuyCreditsModal.mjs +17 -18
- package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
- package/dist/components/modals/CreditsDisabledModal.mjs +6 -4
- package/dist/components/modals/CreditsDisabledModal.mjs.map +1 -1
- package/dist/components/modals/PaidPlanRequiredModal.mjs +5 -3
- package/dist/components/modals/PaidPlanRequiredModal.mjs.map +1 -1
- package/dist/components/modals/cards/AddCardModal.mjs +64 -46
- package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
- package/dist/components/modals/cards/CannotDeleteCardModal.mjs +9 -7
- package/dist/components/modals/cards/CannotDeleteCardModal.mjs.map +1 -1
- package/dist/components/modals/cards/CardFormFields.mjs +65 -51
- package/dist/components/modals/cards/CardFormFields.mjs.map +1 -1
- package/dist/components/modals/cards/DeleteCardModal.mjs +10 -8
- package/dist/components/modals/cards/DeleteCardModal.mjs.map +1 -1
- package/dist/components/navigation/CancelledSubscriptionBanner.mjs +4 -2
- package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
- package/dist/components/navigation/OverdueInvoiceBanner.mjs +4 -2
- package/dist/components/navigation/OverdueInvoiceBanner.mjs.map +1 -1
- package/dist/components/navigation/PendingCancellationBanner.mjs +4 -6
- package/dist/components/navigation/PendingCancellationBanner.mjs.map +1 -1
- package/dist/components/navigation/ProjectSelectorPopover.mjs +8 -6
- package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
- package/dist/components/navigation/UpcomingInvoiceBanner.mjs +4 -6
- package/dist/components/navigation/UpcomingInvoiceBanner.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/BottomLinks.mjs +5 -3
- package/dist/components/navigation/subcomponents/BottomLinks.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/CreditsCard.mjs +3 -1
- package/dist/components/navigation/subcomponents/CreditsCard.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/PlanCard.mjs +3 -1
- package/dist/components/navigation/subcomponents/PlanCard.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/ProjectSelector.mjs +5 -3
- package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
- package/dist/components/pages/NotFoundPage.mjs +5 -3
- package/dist/components/pages/NotFoundPage.mjs.map +1 -1
- package/dist/components/pages/notifications/Notifications.mjs +13 -10
- package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
- package/dist/components/ui/buttons/CopyButton.mjs +9 -5
- package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
- package/dist/components/ui/data-display/CardItem.mjs +7 -5
- package/dist/components/ui/data-display/CardItem.mjs.map +1 -1
- package/dist/components/ui/data-display/PaymentInfoCard.mjs +10 -8
- package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
- package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
- package/dist/components/ui/feedback/DefaultCircularProgress.mjs +3 -1
- package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
- package/dist/components/ui/form/ComboboxField.mjs +11 -6
- package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
- package/dist/components/ui/form/DatePicker.mjs +5 -2
- package/dist/components/ui/form/DatePicker.mjs.map +1 -1
- package/dist/components/ui/form/DateRangePicker.mjs +5 -2
- package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
- package/dist/components/ui/form/PhoneInput.mjs +5 -3
- package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
- package/dist/components/ui/form/SelectField.mjs +6 -3
- package/dist/components/ui/form/SelectField.mjs.map +1 -1
- package/dist/components/widgets/ImageUpload/ImageCropModal.mjs +11 -18
- package/dist/components/widgets/ImageUpload/ImageCropModal.mjs.map +1 -1
- package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs +6 -15
- package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs.map +1 -1
- package/dist/i18n/config.mjs +13 -0
- package/dist/i18n/config.mjs.map +1 -0
- package/dist/i18n/country-language.mjs +74 -0
- package/dist/i18n/country-language.mjs.map +1 -0
- package/dist/i18n/messages/en-us.mjs +494 -0
- package/dist/i18n/messages/en-us.mjs.map +1 -0
- package/dist/i18n/messages/es-es.mjs +494 -0
- package/dist/i18n/messages/es-es.mjs.map +1 -0
- package/dist/i18n/messages/index.mjs +16 -0
- package/dist/i18n/messages/index.mjs.map +1 -0
- package/dist/i18n/messages/pt-br.mjs +507 -0
- package/dist/i18n/messages/pt-br.mjs.map +1 -0
- package/dist/i18n/normalize.mjs +12 -0
- package/dist/i18n/normalize.mjs.map +1 -0
- package/dist/i18n/resolve-locale.mjs +42 -0
- package/dist/i18n/resolve-locale.mjs.map +1 -0
- package/dist/i18n.mjs +14 -0
- package/dist/i18n.mjs.map +1 -0
- package/dist/index.mjs +19 -3
- package/dist/index.mjs.map +1 -1
- package/dist/modules/accounts/hooks/use-currency-formatter.hook.mjs +20 -0
- package/dist/modules/accounts/hooks/use-currency-formatter.hook.mjs.map +1 -0
- package/dist/modules/cards/hooks/handle-delete-card.hook.mjs +2 -1
- package/dist/modules/cards/hooks/handle-delete-card.hook.mjs.map +1 -1
- package/dist/modules/images/utils/validate-image.mjs +8 -8
- package/dist/modules/images/utils/validate-image.mjs.map +1 -1
- package/dist/modules/plans/hooks/list-plans.hook.mjs +2 -2
- package/dist/modules/plans/hooks/list-plans.hook.mjs.map +1 -1
- package/dist/modules/plans/services/plans.service.mjs +1 -1
- package/dist/modules/plans/services/plans.service.mjs.map +1 -1
- package/dist/modules/plans/types/plan.type.mjs +5 -1
- package/dist/modules/plans/types/plan.type.mjs.map +1 -1
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs +61 -35
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
- package/dist/modules/projects/services/projects.service.mjs +9 -0
- package/dist/modules/projects/services/projects.service.mjs.map +1 -1
- package/dist/modules/subscriptions/utils/periodicity.mjs +20 -14
- package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
- package/dist/providers/auth.provider.mjs +9 -1
- package/dist/providers/auth.provider.mjs.map +1 -1
- package/dist/server.mjs +2 -0
- package/dist/server.mjs.map +1 -1
- package/dist/utils/format/currency.mjs +32 -4
- package/dist/utils/format/currency.mjs.map +1 -1
- package/dist/utils/intl/cookie-domain.mjs +17 -0
- package/dist/utils/intl/cookie-domain.mjs.map +1 -0
- package/dist/utils/intl/locale-cookie.mjs +13 -0
- package/dist/utils/intl/locale-cookie.mjs.map +1 -0
- package/dist/utils/intl/locales.mjs +3 -2
- package/dist/utils/intl/locales.mjs.map +1 -1
- package/package.json +7 -1
- package/src/components/account/ConfigurationsMyAccountModal.tsx +10 -6
- package/src/components/account/ConfirmDeleteAccountModal.tsx +22 -13
- package/src/components/account/ConfirmGlobalPreferencesModal.tsx +12 -10
- package/src/components/account/DeleteAccountModal.tsx +34 -24
- package/src/components/account/DisableTwoFactorAuthModal.tsx +11 -6
- package/src/components/account/IsntPossibleDeleteAccountModal.tsx +8 -6
- package/src/components/account/TwoFactorAuthModal.tsx +33 -29
- package/src/components/account/constants.ts +8 -5
- package/src/components/account/hooks/useChangeEmailForm.tsx +5 -3
- package/src/components/account/hooks/useChangePasswordForm.tsx +20 -6
- package/src/components/account/hooks/useChangePhoneForm.tsx +16 -10
- package/src/components/account/hooks/useDisableTwoFactorAuthForm.tsx +20 -6
- package/src/components/account/hooks/useOtpVerification.tsx +16 -4
- package/src/components/account/hooks/useTwoFactorAuthForm.tsx +21 -7
- package/src/components/account/sections/ChangeEmailModal.tsx +35 -21
- package/src/components/account/sections/ChangePasswordSection.tsx +10 -6
- package/src/components/account/sections/ChangePhoneModal.tsx +50 -22
- package/src/components/account/sections/MyProfileSection.tsx +37 -23
- package/src/components/account/sections/PreferencesSection.tsx +52 -25
- package/src/components/account/sections/SecuritySection.tsx +19 -10
- package/src/components/account/sections/TokenSection.tsx +22 -10
- package/src/components/layouts/AppMobileNavBar.tsx +1 -154
- package/src/components/layouts/NavBar.tsx +5 -3
- package/src/components/layouts/NotificationsPopover.tsx +5 -3
- package/src/components/layouts/ProfilePopover.tsx +6 -4
- package/src/components/layouts/UsersSelectorPopover.tsx +9 -7
- package/src/components/modals/BuyCreditsModal.tsx +18 -16
- package/src/components/modals/CreditsDisabledModal.tsx +6 -6
- package/src/components/modals/PaidPlanRequiredModal.tsx +5 -3
- package/src/components/modals/cards/AddCardModal.tsx +89 -62
- package/src/components/modals/cards/CannotDeleteCardModal.tsx +9 -8
- package/src/components/modals/cards/CardFormFields.tsx +93 -75
- package/src/components/modals/cards/DeleteCardModal.tsx +10 -8
- package/src/components/navigation/CancelledSubscriptionBanner.tsx +4 -2
- package/src/components/navigation/OverdueInvoiceBanner.tsx +4 -2
- package/src/components/navigation/PendingCancellationBanner.tsx +4 -2
- package/src/components/navigation/ProjectSelectorPopover.tsx +8 -6
- package/src/components/navigation/UpcomingInvoiceBanner.tsx +4 -2
- package/src/components/navigation/subcomponents/BottomLinks.tsx +5 -3
- package/src/components/navigation/subcomponents/CreditsCard.tsx +3 -1
- package/src/components/navigation/subcomponents/PlanCard.tsx +3 -1
- package/src/components/navigation/subcomponents/ProjectSelector.tsx +5 -3
- package/src/components/pages/NotFoundPage.tsx +5 -3
- package/src/components/pages/notifications/Notifications.tsx +13 -10
- package/src/components/ui/buttons/CopyButton.tsx +10 -5
- package/src/components/ui/data-display/CardItem.tsx +7 -5
- package/src/components/ui/data-display/PaymentInfoCard.tsx +10 -8
- package/src/components/ui/feedback/CircularProgress.tsx +4 -0
- package/src/components/ui/feedback/DefaultCircularProgress.tsx +3 -1
- package/src/components/ui/form/ComboboxField.tsx +11 -6
- package/src/components/ui/form/DatePicker.tsx +5 -2
- package/src/components/ui/form/DateRangePicker.tsx +5 -2
- package/src/components/ui/form/PhoneInput.tsx +5 -3
- package/src/components/ui/form/SelectField.tsx +6 -3
- package/src/components/widgets/ImageUpload/ImageCropModal.tsx +19 -11
- package/src/components/widgets/ImageUpload/ImageTooSmallModal.tsx +6 -5
- package/src/i18n/config.ts +17 -0
- package/src/i18n/country-language.ts +60 -0
- package/src/i18n/messages/en-us.ts +514 -0
- package/src/i18n/messages/es-es.ts +515 -0
- package/src/i18n/messages/index.ts +24 -0
- package/src/i18n/messages/pt-br.ts +538 -0
- package/src/i18n/normalize.ts +15 -0
- package/src/i18n/resolve-locale.ts +77 -0
- package/src/i18n.ts +10 -0
- package/src/index.ts +13 -2
- package/src/modules/accounts/hooks/use-currency-formatter.hook.tsx +32 -0
- package/src/modules/cards/hooks/handle-delete-card.hook.ts +8 -3
- package/src/modules/images/utils/validate-image.ts +23 -8
- package/src/modules/plans/hooks/list-plans.hook.ts +2 -2
- package/src/modules/plans/services/plans.service.ts +1 -1
- package/src/modules/plans/types/plan.type.ts +4 -0
- package/src/modules/plans/utils/map-api-plan-to-ui.ts +109 -47
- package/src/modules/projects/services/projects.service.ts +12 -0
- package/src/modules/subscriptions/utils/periodicity.ts +29 -12
- package/src/providers/auth.provider.tsx +13 -1
- package/src/server.ts +2 -0
- package/src/utils/format/currency.ts +62 -7
- package/src/utils/intl/cookie-domain.ts +29 -0
- package/src/utils/intl/locale-cookie.ts +18 -0
- package/src/utils/intl/locales.ts +3 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { Button, Progress } from '../../../index';
|
|
4
|
+
import { useTranslations } from 'next-intl';
|
|
4
5
|
|
|
5
6
|
export interface PlanCardProps {
|
|
6
7
|
planName: string;
|
|
@@ -10,6 +11,7 @@ export interface PlanCardProps {
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export function PlanCard({ planName, trialLabel, progressValue, onKnowPlans }: PlanCardProps) {
|
|
14
|
+
const translate = useTranslations();
|
|
13
15
|
return (
|
|
14
16
|
<div className="flex flex-col rounded-md p-4 gap-4 bg-gray-50">
|
|
15
17
|
<div className="flex flex-col gap-1">
|
|
@@ -22,7 +24,7 @@ export function PlanCard({ planName, trialLabel, progressValue, onKnowPlans }: P
|
|
|
22
24
|
className="paragraph-small-semibold text-gray-950"
|
|
23
25
|
onClick={onKnowPlans}
|
|
24
26
|
>
|
|
25
|
-
|
|
27
|
+
{translate('common.navigation.planCard.knowPlans')}
|
|
26
28
|
</Button>
|
|
27
29
|
</div>
|
|
28
30
|
);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useState, useRef, useEffect, useMemo, RefObject } from 'react';
|
|
4
|
+
import { useTranslations } from 'next-intl';
|
|
4
5
|
import { useMobileNavbarSheet } from '../../../store/useMobileNavbarSheet';
|
|
5
6
|
import { useAppNavigationContext } from '../AppNavigationContext';
|
|
6
7
|
import { ProjectSelectorPopover } from '../ProjectSelectorPopover';
|
|
@@ -30,6 +31,7 @@ export function ProjectSelector({
|
|
|
30
31
|
onSelectProject,
|
|
31
32
|
onManageProjects,
|
|
32
33
|
}: ProjectSelectorProps) {
|
|
34
|
+
const translate = useTranslations();
|
|
33
35
|
const isMainWhitelabel = useIsDefaultWhitelabel();
|
|
34
36
|
const { breakpoint } = useAppNavigationContext();
|
|
35
37
|
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
|
@@ -124,10 +126,10 @@ export function ProjectSelector({
|
|
|
124
126
|
{activeSection === 'projects' && (
|
|
125
127
|
<div className="flex flex-col p-3 gap-2 border border-gray-200 rounded-lg animate-in fade-in duration-400">
|
|
126
128
|
<div className="flex items-center justify-between">
|
|
127
|
-
<span className="paragraph-small-semibold">
|
|
129
|
+
<span className="paragraph-small-semibold">{translate('common.navigation.projectSelector.title')}</span>
|
|
128
130
|
</div>
|
|
129
131
|
<Command className="gap-2" shouldFilter={false}>
|
|
130
|
-
<CommandInput placeholder=
|
|
132
|
+
<CommandInput placeholder={translate('common.navigation.projectSelector.searchPlaceholder')} value={search} onValueChange={setSearch} />
|
|
131
133
|
<CommandList
|
|
132
134
|
className="custom-scrollbar paragraph-small-medium text-gray-600 h-[227px]"
|
|
133
135
|
onScroll={(event) => {
|
|
@@ -141,7 +143,7 @@ export function ProjectSelector({
|
|
|
141
143
|
}
|
|
142
144
|
}}
|
|
143
145
|
>
|
|
144
|
-
<CommandEmpty>
|
|
146
|
+
<CommandEmpty>{translate('common.navigation.projectSelector.noResults')}</CommandEmpty>
|
|
145
147
|
{showListSkeleton ? (
|
|
146
148
|
<>
|
|
147
149
|
<ProjectItemSkeleton />
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import Image from "next/image";
|
|
4
4
|
import { useEffect } from "react";
|
|
5
|
+
import { useTranslations } from "next-intl";
|
|
5
6
|
import { useRouter } from "next/navigation";
|
|
6
7
|
import { useWhitelabel, useIsDefaultWhitelabel } from "../../providers/whitelabel.provider";
|
|
7
8
|
import { Button } from "../ui/buttons/Button";
|
|
@@ -18,6 +19,7 @@ function GreatAppsLogo() {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export function NotFoundPage() {
|
|
22
|
+
const translate = useTranslations();
|
|
21
23
|
const router = useRouter();
|
|
22
24
|
|
|
23
25
|
useEffect(() => {
|
|
@@ -47,11 +49,11 @@ export function NotFoundPage() {
|
|
|
47
49
|
</div>
|
|
48
50
|
|
|
49
51
|
<h1 className="max-w-[554px] px-6 font-[family-name:var(--font-outfit)] text-[32px] leading-[36px] font-semibold text-zinc-950 sm:px-0 sm:text-[56px] sm:leading-[56px]">
|
|
50
|
-
|
|
52
|
+
{translate('common.notFound.title')}
|
|
51
53
|
</h1>
|
|
52
54
|
|
|
53
55
|
<p className="max-w-[496px] px-6 paragraph-medium-medium text-zinc-950 sm:px-0">
|
|
54
|
-
|
|
56
|
+
{translate('common.notFound.description')}
|
|
55
57
|
</p>
|
|
56
58
|
|
|
57
59
|
<Button
|
|
@@ -65,7 +67,7 @@ export function NotFoundPage() {
|
|
|
65
67
|
}
|
|
66
68
|
}}
|
|
67
69
|
>
|
|
68
|
-
|
|
70
|
+
{translate('common.notFound.backToHome')}
|
|
69
71
|
</Button>
|
|
70
72
|
</div>
|
|
71
73
|
</div>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { IconBell, IconCheck, IconLoader2 } from '@tabler/icons-react';
|
|
4
|
+
import { useTranslations } from 'next-intl';
|
|
4
5
|
import { Button } from "../../ui/buttons/Button";
|
|
5
6
|
import {
|
|
6
7
|
Tabs,
|
|
@@ -34,6 +35,7 @@ function NotificationsList({
|
|
|
34
35
|
hasNextPage: boolean;
|
|
35
36
|
fetchNextPage: () => void;
|
|
36
37
|
}) {
|
|
38
|
+
const translate = useTranslations();
|
|
37
39
|
const notifications = pages?.pages.flatMap((p) => p.data) ?? [];
|
|
38
40
|
|
|
39
41
|
const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
|
|
@@ -50,7 +52,7 @@ function NotificationsList({
|
|
|
50
52
|
return (
|
|
51
53
|
<div className="rounded-lg border border-zinc-200 bg-white">
|
|
52
54
|
<div className="flex flex-col items-center justify-center py-16 gap-2">
|
|
53
|
-
<span className="paragraph-medium-regular text-zinc-500">
|
|
55
|
+
<span className="paragraph-medium-regular text-zinc-500">{translate('common.notifications.page.empty')}</span>
|
|
54
56
|
</div>
|
|
55
57
|
</div>
|
|
56
58
|
);
|
|
@@ -80,7 +82,7 @@ function NotificationsList({
|
|
|
80
82
|
actions={
|
|
81
83
|
detailsUrl ? (
|
|
82
84
|
<Button asChild variant="secondary" className="h-8! px-3! paragraph-small-semibold">
|
|
83
|
-
<Link href={detailsUrl}>
|
|
85
|
+
<Link href={detailsUrl}>{translate('common.notifications.page.details')}</Link>
|
|
84
86
|
</Button>
|
|
85
87
|
) : undefined
|
|
86
88
|
}
|
|
@@ -97,6 +99,7 @@ function NotificationsList({
|
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
export function NotificationPageContent() {
|
|
102
|
+
const translate = useTranslations();
|
|
100
103
|
const unreadNotifications = useInfiniteMessages({
|
|
101
104
|
readed: false,
|
|
102
105
|
type: "notification",
|
|
@@ -116,12 +119,12 @@ export function NotificationPageContent() {
|
|
|
116
119
|
markAllAsRead(undefined, {
|
|
117
120
|
onSuccess: () => {
|
|
118
121
|
toast.custom((t) => (
|
|
119
|
-
<Toast variant="success" message=
|
|
122
|
+
<Toast variant="success" message={translate('common.notifications.page.markAllSuccess')} toastId={t} />
|
|
120
123
|
));
|
|
121
124
|
},
|
|
122
125
|
onError: () => {
|
|
123
126
|
toast.custom((t) => (
|
|
124
|
-
<Toast variant="error" message=
|
|
127
|
+
<Toast variant="error" message={translate('common.notifications.page.markAllError')} toastId={t} />
|
|
125
128
|
));
|
|
126
129
|
},
|
|
127
130
|
});
|
|
@@ -132,10 +135,10 @@ export function NotificationPageContent() {
|
|
|
132
135
|
<div className="flex items-center justify-between gap-4">
|
|
133
136
|
<div className="flex flex-col gap-2">
|
|
134
137
|
<h1 className="title-large-semibold text-gray-950">
|
|
135
|
-
|
|
138
|
+
{translate('common.notifications.page.title')}
|
|
136
139
|
</h1>
|
|
137
140
|
<p className="paragraph-small-regular text-gray-600 hidden lg:block">
|
|
138
|
-
|
|
141
|
+
{translate('common.notifications.page.subtitle')}
|
|
139
142
|
</p>
|
|
140
143
|
</div>
|
|
141
144
|
<Button
|
|
@@ -145,8 +148,8 @@ export function NotificationPageContent() {
|
|
|
145
148
|
disabled={isMarkingAll || totalUnread === 0}
|
|
146
149
|
>
|
|
147
150
|
{isMarkingAll ? <IconLoader2 size={20} className="animate-spin" /> : <IconCheck size={20} />}
|
|
148
|
-
<span className="lg:block hidden">
|
|
149
|
-
<span className="lg:hidden">
|
|
151
|
+
<span className="lg:block hidden">{translate('common.notifications.page.markAllReadDesktop')}</span>
|
|
152
|
+
<span className="lg:hidden">{translate('common.notifications.page.markAllReadMobile')}</span>
|
|
150
153
|
</Button>
|
|
151
154
|
</div>
|
|
152
155
|
<Tabs
|
|
@@ -155,11 +158,11 @@ export function NotificationPageContent() {
|
|
|
155
158
|
>
|
|
156
159
|
<TabsList className="h-auto pb-0 bg-transparent">
|
|
157
160
|
<TabsTrigger className="gap-2" value="all">
|
|
158
|
-
|
|
161
|
+
{translate('common.notifications.page.tabAll')}{" "}
|
|
159
162
|
<span className="text-gray-500">({totalAll})</span>
|
|
160
163
|
</TabsTrigger>
|
|
161
164
|
<TabsTrigger className="gap-2" value="unreads" disabled={totalUnread === 0}>
|
|
162
|
-
|
|
165
|
+
{translate('common.notifications.page.tabUnread')}{" "}
|
|
163
166
|
<span className="text-gray-500">({totalUnread})</span>
|
|
164
167
|
</TabsTrigger>
|
|
165
168
|
</TabsList>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { useTranslations } from 'next-intl';
|
|
3
4
|
import { IconCheck, IconCopy } from '@tabler/icons-react';
|
|
4
5
|
import { toast } from "sonner";
|
|
5
6
|
import { Toast } from "../feedback/Toast";
|
|
@@ -19,18 +20,22 @@ export function CopyButton({
|
|
|
19
20
|
textToCopy,
|
|
20
21
|
size = 14,
|
|
21
22
|
className,
|
|
22
|
-
tooltipText
|
|
23
|
-
successMessage
|
|
23
|
+
tooltipText,
|
|
24
|
+
successMessage,
|
|
24
25
|
}: CopyButtonProps) {
|
|
26
|
+
const translate = useTranslations();
|
|
27
|
+
const resolvedTooltipText = tooltipText ?? translate('common.forms.copyButton.tooltipDefault');
|
|
28
|
+
const resolvedSuccessMessage = successMessage ?? translate('common.forms.copyButton.successDefault');
|
|
29
|
+
|
|
25
30
|
const { isCopied, copy } = useCopyToClipboard({
|
|
26
31
|
onSuccess: () => {
|
|
27
32
|
toast.custom((t) => (
|
|
28
|
-
<Toast variant="success" message={
|
|
33
|
+
<Toast variant="success" message={resolvedSuccessMessage} toastId={t} />
|
|
29
34
|
));
|
|
30
35
|
},
|
|
31
36
|
onError: () => {
|
|
32
37
|
toast.custom((t) => (
|
|
33
|
-
<Toast variant="error" message=
|
|
38
|
+
<Toast variant="error" message={translate('common.forms.copyButton.errorMessage')} toastId={t} />
|
|
34
39
|
));
|
|
35
40
|
},
|
|
36
41
|
});
|
|
@@ -48,7 +53,7 @@ export function CopyButton({
|
|
|
48
53
|
{isCopied ? <IconCheck size={size} /> : <IconCopy size={size} />}
|
|
49
54
|
</span>
|
|
50
55
|
</TooltipTrigger>
|
|
51
|
-
<TooltipContent>{isCopied ?
|
|
56
|
+
<TooltipContent>{isCopied ? translate('common.actions.copied') : resolvedTooltipText}</TooltipContent>
|
|
52
57
|
</Tooltip>
|
|
53
58
|
);
|
|
54
59
|
}
|
|
@@ -10,6 +10,7 @@ import { CardBrandIcon } from './CardBrandIcons';
|
|
|
10
10
|
import { useSetDefaultCard } from '../../../modules/cards/hooks/set-default-card.hook';
|
|
11
11
|
import { useHandleDeleteCard } from '../../../modules/cards/hooks/handle-delete-card.hook';
|
|
12
12
|
import type { Card } from '../../../modules/cards/types';
|
|
13
|
+
import { useTranslations } from 'next-intl';
|
|
13
14
|
|
|
14
15
|
type CardItemProps = {
|
|
15
16
|
card: Card;
|
|
@@ -32,6 +33,7 @@ export function CardItem({
|
|
|
32
33
|
onAfterDelete,
|
|
33
34
|
onAfterSetDefault,
|
|
34
35
|
}: CardItemProps) {
|
|
36
|
+
const translate = useTranslations();
|
|
35
37
|
const [popoverOpen, setPopoverOpen] = useState(false);
|
|
36
38
|
|
|
37
39
|
const setDefaultCardMutation = useSetDefaultCard();
|
|
@@ -44,7 +46,7 @@ export function CardItem({
|
|
|
44
46
|
toast.custom((t) => (
|
|
45
47
|
<Toast
|
|
46
48
|
variant="success"
|
|
47
|
-
message=
|
|
49
|
+
message={translate('common.cards.item.setDefaultSuccess')}
|
|
48
50
|
toastId={t}
|
|
49
51
|
/>
|
|
50
52
|
));
|
|
@@ -54,7 +56,7 @@ export function CardItem({
|
|
|
54
56
|
toast.custom((t) => (
|
|
55
57
|
<Toast
|
|
56
58
|
variant="error"
|
|
57
|
-
message=
|
|
59
|
+
message={translate('common.cards.item.setDefaultError')}
|
|
58
60
|
toastId={t}
|
|
59
61
|
/>
|
|
60
62
|
));
|
|
@@ -86,7 +88,7 @@ export function CardItem({
|
|
|
86
88
|
</div>
|
|
87
89
|
{card.is_default && (
|
|
88
90
|
<span className="paragraph-xsmall-semibold text-zinc-600 bg-zinc-100 px-2 py-0.5 rounded-lg whitespace-nowrap">
|
|
89
|
-
|
|
91
|
+
{translate('common.cards.item.defaultBadge')}
|
|
90
92
|
</span>
|
|
91
93
|
)}
|
|
92
94
|
<CardBrandIcon brand={card.brand} />
|
|
@@ -108,7 +110,7 @@ export function CardItem({
|
|
|
108
110
|
{menuHasSetDefault && (
|
|
109
111
|
<NavBarItem
|
|
110
112
|
icon={<IconStar size={18} className="text-zinc-400" />}
|
|
111
|
-
label=
|
|
113
|
+
label={translate('common.cards.item.makeDefault')}
|
|
112
114
|
onClick={() => {
|
|
113
115
|
setPopoverOpen(false);
|
|
114
116
|
handleSetDefault();
|
|
@@ -118,7 +120,7 @@ export function CardItem({
|
|
|
118
120
|
{menuHasDelete && (
|
|
119
121
|
<NavBarItem
|
|
120
122
|
icon={<IconTrash size={18} className="text-zinc-400" />}
|
|
121
|
-
label=
|
|
123
|
+
label={translate('common.actions.delete')}
|
|
122
124
|
onClick={() => {
|
|
123
125
|
setPopoverOpen(false);
|
|
124
126
|
handleDeleteCard(card);
|
|
@@ -9,6 +9,7 @@ import { useCards } from '../../../modules/cards/hooks/cards.hook';
|
|
|
9
9
|
import { useModalManager } from '../../../store/useModalManager';
|
|
10
10
|
import { useIsDefaultWhitelabel } from '../../../providers/whitelabel.provider';
|
|
11
11
|
import type { Card } from '../../../modules/cards/types';
|
|
12
|
+
import { useTranslations } from 'next-intl';
|
|
12
13
|
|
|
13
14
|
type PaymentInfoCardProps = {
|
|
14
15
|
email?: string;
|
|
@@ -29,6 +30,7 @@ export function PaymentInfoCard({
|
|
|
29
30
|
hideDelete,
|
|
30
31
|
hideSetDefault,
|
|
31
32
|
}: PaymentInfoCardProps) {
|
|
33
|
+
const translate = useTranslations();
|
|
32
34
|
const isMobile = useIsMobile();
|
|
33
35
|
const { openModal } = useModalManager();
|
|
34
36
|
const isDefaultWl = useIsDefaultWhitelabel();
|
|
@@ -83,19 +85,19 @@ export function PaymentInfoCard({
|
|
|
83
85
|
<div className="border border-zinc-200 rounded-lg overflow-hidden">
|
|
84
86
|
{email && (
|
|
85
87
|
<div className="flex items-center h-[60px] px-4 border-b border-zinc-200 gap-3">
|
|
86
|
-
<span className="paragraph-small-medium text-zinc-500 w-[100px]">
|
|
88
|
+
<span className="paragraph-small-medium text-zinc-500 w-[100px]">{translate('common.cards.paymentInfo.email')}</span>
|
|
87
89
|
<span className="paragraph-small-medium text-zinc-950 flex-1">{email}</span>
|
|
88
90
|
</div>
|
|
89
91
|
)}
|
|
90
92
|
<div className="flex items-center h-[60px] px-4 gap-3">
|
|
91
|
-
<span className="paragraph-small-medium text-zinc-500 w-[100px]">
|
|
93
|
+
<span className="paragraph-small-medium text-zinc-500 w-[100px]">{translate('common.cards.paymentInfo.payment')}</span>
|
|
92
94
|
<button
|
|
93
95
|
type="button"
|
|
94
96
|
onClick={handleOpenAddCardModal}
|
|
95
97
|
className="flex items-center h-8 px-2 paragraph-small-semibold text-zinc-950 border border-zinc-200 rounded-md hover:border-zinc-400 transition-colors cursor-pointer w-fit"
|
|
96
98
|
>
|
|
97
99
|
<IconPlus className="size-[18px]" />
|
|
98
|
-
<span className="px-1.5">
|
|
100
|
+
<span className="px-1.5">{translate('common.cards.paymentInfo.addCard')}</span>
|
|
99
101
|
</button>
|
|
100
102
|
</div>
|
|
101
103
|
</div>
|
|
@@ -107,7 +109,7 @@ export function PaymentInfoCard({
|
|
|
107
109
|
<div className="border border-zinc-200 rounded-lg overflow-hidden">
|
|
108
110
|
{email && (
|
|
109
111
|
<div className="flex items-center h-[60px] px-4 border-b border-zinc-200 gap-3">
|
|
110
|
-
<span className="paragraph-small-medium text-zinc-500 w-[100px]">
|
|
112
|
+
<span className="paragraph-small-medium text-zinc-500 w-[100px]">{translate('common.cards.paymentInfo.email')}</span>
|
|
111
113
|
<span className="paragraph-small-medium text-zinc-950 flex-1">{email}</span>
|
|
112
114
|
</div>
|
|
113
115
|
)}
|
|
@@ -118,7 +120,7 @@ export function PaymentInfoCard({
|
|
|
118
120
|
>
|
|
119
121
|
{!isExpanded ? (
|
|
120
122
|
<>
|
|
121
|
-
<span className="paragraph-small-medium text-zinc-500 w-[100px]">
|
|
123
|
+
<span className="paragraph-small-medium text-zinc-500 w-[100px]">{translate('common.cards.paymentInfo.payment')}</span>
|
|
122
124
|
<div className="flex flex-col gap-0.5 flex-1 min-w-0">
|
|
123
125
|
<span className="paragraph-small-semibold text-zinc-950 truncate">
|
|
124
126
|
{selectedCard?.name}
|
|
@@ -135,7 +137,7 @@ export function PaymentInfoCard({
|
|
|
135
137
|
) : (
|
|
136
138
|
<>
|
|
137
139
|
<span className="paragraph-small-semibold text-zinc-950 flex-1">
|
|
138
|
-
|
|
140
|
+
{translate('common.cards.paymentInfo.selectPaymentMethod')}
|
|
139
141
|
</span>
|
|
140
142
|
<div className="size-8 flex items-center justify-center rounded-lg">
|
|
141
143
|
<IconChevronDown className="size-[18px] text-zinc-500 rotate-180" />
|
|
@@ -170,7 +172,7 @@ export function PaymentInfoCard({
|
|
|
170
172
|
: 'text-zinc-600 border border-zinc-200 hover:bg-zinc-50'
|
|
171
173
|
}`}
|
|
172
174
|
>
|
|
173
|
-
|
|
175
|
+
{translate('common.cards.paymentInfo.manageCards')}
|
|
174
176
|
</button>
|
|
175
177
|
)}
|
|
176
178
|
</div>
|
|
@@ -183,7 +185,7 @@ export function PaymentInfoCard({
|
|
|
183
185
|
>
|
|
184
186
|
<IconPlus className="size-[18px]" />
|
|
185
187
|
<span className="px-1.5">
|
|
186
|
-
{isExpanded ? '
|
|
188
|
+
{isExpanded ? translate('common.cards.paymentInfo.addCard') : translate('common.cards.paymentInfo.newPaymentMethod')}
|
|
187
189
|
</span>
|
|
188
190
|
</button>
|
|
189
191
|
</div>
|
|
@@ -34,6 +34,10 @@ export default function CircularProgress({
|
|
|
34
34
|
aria-valuenow={current}
|
|
35
35
|
aria-valuemin={0}
|
|
36
36
|
aria-valuemax={total}
|
|
37
|
+
// i18n-TODO: aria-label hardcoded — CircularProgress has no 'use client' directive and
|
|
38
|
+
// receives no translate prop, so useTranslations() cannot be called here without
|
|
39
|
+
// converting it to a client component. Key to use: common.forms.progressAriaLabel ('Progresso').
|
|
40
|
+
// Either add 'use client' + useTranslations(), or accept a translate prop from the caller.
|
|
37
41
|
aria-label="Progresso"
|
|
38
42
|
>
|
|
39
43
|
<svg width={size} height={size} className="absolute">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { useTranslations } from 'next-intl';
|
|
3
4
|
import {
|
|
4
5
|
calculateRadius,
|
|
5
6
|
calculateCircumference,
|
|
@@ -21,6 +22,7 @@ export default function DefaultCircularProgress({
|
|
|
21
22
|
size = 62,
|
|
22
23
|
strokeWidth = 3,
|
|
23
24
|
}: CircularProgressProps) {
|
|
25
|
+
const translate = useTranslations();
|
|
24
26
|
const isDefaultWl = useIsDefaultWhitelabel();
|
|
25
27
|
const radius = calculateRadius(size, strokeWidth);
|
|
26
28
|
const circumference = calculateCircumference(radius);
|
|
@@ -35,7 +37,7 @@ export default function DefaultCircularProgress({
|
|
|
35
37
|
aria-valuenow={current}
|
|
36
38
|
aria-valuemin={0}
|
|
37
39
|
aria-valuemax={total}
|
|
38
|
-
aria-label=
|
|
40
|
+
aria-label={translate('common.forms.circularProgress.ariaLabel')}
|
|
39
41
|
>
|
|
40
42
|
<svg width={size} height={size} className="absolute">
|
|
41
43
|
<circle
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useState, useMemo } from 'react';
|
|
4
|
+
import { useTranslations } from 'next-intl';
|
|
4
5
|
import { IconCheck, IconChevronDown, IconSearch } from '@tabler/icons-react';
|
|
5
6
|
import { Popover, PopoverContent, PopoverTrigger } from '../overlay/Popover';
|
|
6
7
|
import { cn } from '../../../infra/utils/clsx';
|
|
@@ -28,9 +29,9 @@ interface ComboboxFieldProps {
|
|
|
28
29
|
export function ComboboxField({
|
|
29
30
|
options,
|
|
30
31
|
label,
|
|
31
|
-
placeholder
|
|
32
|
-
searchPlaceholder
|
|
33
|
-
emptyMessage
|
|
32
|
+
placeholder,
|
|
33
|
+
searchPlaceholder,
|
|
34
|
+
emptyMessage,
|
|
34
35
|
value,
|
|
35
36
|
onChange,
|
|
36
37
|
disabled = false,
|
|
@@ -38,6 +39,10 @@ export function ComboboxField({
|
|
|
38
39
|
className,
|
|
39
40
|
containerClassName,
|
|
40
41
|
}: ComboboxFieldProps) {
|
|
42
|
+
const translate = useTranslations();
|
|
43
|
+
const resolvedPlaceholder = placeholder ?? translate('common.forms.combobox.placeholder');
|
|
44
|
+
const resolvedSearchPlaceholder = searchPlaceholder ?? translate('common.forms.combobox.searchPlaceholder');
|
|
45
|
+
const resolvedEmptyMessage = emptyMessage ?? translate('common.forms.combobox.emptyMessage');
|
|
41
46
|
const [open, setOpen] = useState(false);
|
|
42
47
|
const [search, setSearch] = useState('');
|
|
43
48
|
|
|
@@ -90,7 +95,7 @@ export function ComboboxField({
|
|
|
90
95
|
<span className={cn('truncate text-left', !selectedOption && 'text-gray-400')}>
|
|
91
96
|
{selectedOption
|
|
92
97
|
? (selectedOption.displayValue ?? selectedOption.label)
|
|
93
|
-
:
|
|
98
|
+
: resolvedPlaceholder}
|
|
94
99
|
</span>
|
|
95
100
|
{icon ?? (
|
|
96
101
|
<IconChevronDown
|
|
@@ -114,7 +119,7 @@ export function ComboboxField({
|
|
|
114
119
|
<IconSearch className="size-4 shrink-0 opacity-50 text-gray-500" />
|
|
115
120
|
<input
|
|
116
121
|
autoFocus
|
|
117
|
-
placeholder={
|
|
122
|
+
placeholder={resolvedSearchPlaceholder}
|
|
118
123
|
value={search}
|
|
119
124
|
onChange={(e) => setSearch(e.target.value)}
|
|
120
125
|
className="flex h-full w-full bg-transparent text-sm outline-none placeholder:text-gray-400 paragraph-small-medium text-gray-950"
|
|
@@ -123,7 +128,7 @@ export function ComboboxField({
|
|
|
123
128
|
|
|
124
129
|
<div className="overflow-y-auto max-h-[280px] p-1">
|
|
125
130
|
{filteredOptions.length === 0 ? (
|
|
126
|
-
<p className="py-6 text-center paragraph-small-medium text-gray-500">{
|
|
131
|
+
<p className="py-6 text-center paragraph-small-medium text-gray-500">{resolvedEmptyMessage}</p>
|
|
127
132
|
) : (
|
|
128
133
|
filteredOptions.map((option) => {
|
|
129
134
|
const isSelected = value === option.value;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useState, forwardRef, useEffect } from "react";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
4
5
|
import { format } from "date-fns";
|
|
5
6
|
import { Calendar } from "./Calendar";
|
|
6
7
|
import { Popover, PopoverContent, PopoverTrigger } from "../overlay/Popover";
|
|
@@ -23,9 +24,11 @@ interface DatePickerProps {
|
|
|
23
24
|
|
|
24
25
|
export const DatePicker = forwardRef<HTMLButtonElement, DatePickerProps>(
|
|
25
26
|
(
|
|
26
|
-
{ value, onChange, placeholder
|
|
27
|
+
{ value, onChange, placeholder, className, disabled },
|
|
27
28
|
ref,
|
|
28
29
|
) => {
|
|
30
|
+
const translate = useTranslations();
|
|
31
|
+
const resolvedPlaceholder = placeholder ?? translate('common.forms.datePicker.placeholder');
|
|
29
32
|
const [open, setOpen] = useState(false);
|
|
30
33
|
const [date, setDate] = useState<Date | undefined>(() => {
|
|
31
34
|
return value ? isoParaDataLocal(value) : undefined;
|
|
@@ -51,7 +54,7 @@ export const DatePicker = forwardRef<HTMLButtonElement, DatePickerProps>(
|
|
|
51
54
|
}
|
|
52
55
|
};
|
|
53
56
|
|
|
54
|
-
const displayText = date ? format(date, "dd/MM/yyyy") :
|
|
57
|
+
const displayText = date ? format(date, "dd/MM/yyyy") : resolvedPlaceholder;
|
|
55
58
|
|
|
56
59
|
return (
|
|
57
60
|
<Popover open={open} onOpenChange={setOpen}>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useState, forwardRef, useEffect } from "react";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
4
5
|
import { format } from "date-fns";
|
|
5
6
|
import { IconCalendar } from '@tabler/icons-react';
|
|
6
7
|
import { DateRange } from "react-day-picker";
|
|
@@ -24,7 +25,9 @@ interface DateRangePickerProps {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export const DateRangePicker = forwardRef<HTMLButtonElement, DateRangePickerProps>(
|
|
27
|
-
({ value, onChange, placeholder
|
|
28
|
+
({ value, onChange, placeholder, className, disabled }, ref) => {
|
|
29
|
+
const translate = useTranslations();
|
|
30
|
+
const resolvedPlaceholder = placeholder ?? translate('common.forms.dateRangePicker.placeholder');
|
|
28
31
|
const [open, setOpen] = useState(false);
|
|
29
32
|
const [range, setRange] = useState<DateRange | undefined>(() => {
|
|
30
33
|
if (value?.from && value?.to) {
|
|
@@ -62,7 +65,7 @@ export const DateRangePicker = forwardRef<HTMLButtonElement, DateRangePickerProp
|
|
|
62
65
|
|
|
63
66
|
const displayText = range?.from && range?.to
|
|
64
67
|
? `${format(range.from, "dd/MM/yyyy")} - ${format(range.to, "dd/MM/yyyy")}`
|
|
65
|
-
:
|
|
68
|
+
: resolvedPlaceholder;
|
|
66
69
|
|
|
67
70
|
return (
|
|
68
71
|
<Popover open={open} onOpenChange={setOpen}>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useRef } from 'react';
|
|
4
|
+
import { useTranslations } from 'next-intl';
|
|
4
5
|
import { AsYouType, CountryCode } from 'libphonenumber-js';
|
|
5
6
|
import { Input, Separator, Popover, PopoverTrigger, PopoverContent, cn } from '@greatapps/common';
|
|
6
7
|
import { IconChevronDown, IconSearch } from '@tabler/icons-react';
|
|
@@ -41,6 +42,7 @@ export default function PhoneInput({
|
|
|
41
42
|
classnameContainer,
|
|
42
43
|
className,
|
|
43
44
|
}: PhoneInputProps) {
|
|
45
|
+
const translate = useTranslations();
|
|
44
46
|
const parsed = parsePhoneValue(value ?? '');
|
|
45
47
|
const [selectedCountry, setSelectedCountry] = useState<Country>(parsed.country);
|
|
46
48
|
const [phoneNumber, setPhoneNumber] = useState(parsed.number);
|
|
@@ -115,7 +117,7 @@ export default function PhoneInput({
|
|
|
115
117
|
{label && (
|
|
116
118
|
<div className="flex items-center gap-1 paragraph-xsmall-semibold">
|
|
117
119
|
<span className="text-zinc-600">{label}</span>
|
|
118
|
-
{optional && <span className="text-zinc-500">(
|
|
120
|
+
{optional && <span className="text-zinc-500">{translate('common.forms.phoneInput.optional')}</span>}
|
|
119
121
|
{required && <span className="text-red-600">*</span>}
|
|
120
122
|
</div>
|
|
121
123
|
)}
|
|
@@ -148,7 +150,7 @@ export default function PhoneInput({
|
|
|
148
150
|
<input
|
|
149
151
|
type="text"
|
|
150
152
|
className="flex-1 text-sm outline-none placeholder:text-zinc-400"
|
|
151
|
-
placeholder=
|
|
153
|
+
placeholder={translate('common.forms.phoneInput.searchPlaceholder')}
|
|
152
154
|
value={search}
|
|
153
155
|
onChange={(e) => setSearch(e.target.value)}
|
|
154
156
|
autoFocus
|
|
@@ -175,7 +177,7 @@ export default function PhoneInput({
|
|
|
175
177
|
</button>
|
|
176
178
|
))}
|
|
177
179
|
{filtered.length === 0 && (
|
|
178
|
-
<p className="text-sm text-zinc-500 p-3 text-center">
|
|
180
|
+
<p className="text-sm text-zinc-500 p-3 text-center">{translate('common.forms.phoneInput.emptyMessage')}</p>
|
|
179
181
|
)}
|
|
180
182
|
</div>
|
|
181
183
|
</PopoverContent>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import React from 'react';
|
|
4
|
+
import { useTranslations } from 'next-intl';
|
|
4
5
|
import {
|
|
5
6
|
Select,
|
|
6
7
|
SelectContent,
|
|
@@ -41,7 +42,7 @@ export function SelectField({
|
|
|
41
42
|
hintMessage,
|
|
42
43
|
error = false,
|
|
43
44
|
errorMessage,
|
|
44
|
-
placeholder
|
|
45
|
+
placeholder,
|
|
45
46
|
options,
|
|
46
47
|
value,
|
|
47
48
|
defaultValue,
|
|
@@ -51,6 +52,8 @@ export function SelectField({
|
|
|
51
52
|
className,
|
|
52
53
|
containerClassName,
|
|
53
54
|
}: SelectFieldProps) {
|
|
55
|
+
const translate = useTranslations();
|
|
56
|
+
const resolvedPlaceholder = placeholder ?? translate('common.forms.select.placeholder');
|
|
54
57
|
const handleValueChange = (selectedValue: string) => {
|
|
55
58
|
if (!onChange) return;
|
|
56
59
|
const selectedOption = options.find((option) => String(option.value) === selectedValue);
|
|
@@ -67,7 +70,7 @@ export function SelectField({
|
|
|
67
70
|
{label && (
|
|
68
71
|
<div className="flex items-center gap-1 paragraph-xsmall-semibold">
|
|
69
72
|
<span className="text-gray-600">{label}</span>
|
|
70
|
-
{optional && <span className="text-gray-500">(
|
|
73
|
+
{optional && <span className="text-gray-500">{translate('common.forms.select.optional')}</span>}
|
|
71
74
|
{required && <span className="text-red-600">*</span>}
|
|
72
75
|
</div>
|
|
73
76
|
)}
|
|
@@ -89,7 +92,7 @@ export function SelectField({
|
|
|
89
92
|
)}
|
|
90
93
|
icon={icon}
|
|
91
94
|
>
|
|
92
|
-
<SelectValue placeholder={
|
|
95
|
+
<SelectValue placeholder={resolvedPlaceholder}>
|
|
93
96
|
{value !== undefined &&
|
|
94
97
|
(() => {
|
|
95
98
|
const selectedOption = options.find((opt) => String(opt.value) === String(value));
|