@greatapps/common 1.1.24 → 1.1.26
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 +121 -0
- package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -0
- package/dist/components/account/ConfirmGlobalPreferencesModal.mjs +45 -0
- package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -0
- package/dist/components/account/DisableTwoFactorAuthModal.mjs +67 -0
- package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -0
- package/dist/components/account/TwoFactorAuthModal.mjs +190 -0
- package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -0
- package/dist/components/account/constants.mjs +32 -0
- package/dist/components/account/constants.mjs.map +1 -0
- package/dist/components/account/hooks/useChangeEmailForm.mjs +53 -0
- package/dist/components/account/hooks/useChangeEmailForm.mjs.map +1 -0
- package/dist/components/account/hooks/useChangePasswordForm.mjs +47 -0
- package/dist/components/account/hooks/useChangePasswordForm.mjs.map +1 -0
- package/dist/components/account/hooks/useChangePhoneForm.mjs +64 -0
- package/dist/components/account/hooks/useChangePhoneForm.mjs.map +1 -0
- package/dist/components/account/hooks/useConfigurationsModal.mjs +33 -0
- package/dist/components/account/hooks/useConfigurationsModal.mjs.map +1 -0
- package/dist/components/account/hooks/useDisableTwoFactorAuthForm.mjs +54 -0
- package/dist/components/account/hooks/useDisableTwoFactorAuthForm.mjs.map +1 -0
- package/dist/components/account/hooks/useOtpVerification.mjs +94 -0
- package/dist/components/account/hooks/useOtpVerification.mjs.map +1 -0
- package/dist/components/account/hooks/useTwoFactorAuthForm.mjs +88 -0
- package/dist/components/account/hooks/useTwoFactorAuthForm.mjs.map +1 -0
- package/dist/components/account/sections/ChangeEmailModal.mjs +180 -0
- package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -0
- package/dist/components/account/sections/ChangePasswordSection.mjs +64 -0
- package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -0
- package/dist/components/account/sections/ChangePhoneModal.mjs +182 -0
- package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -0
- package/dist/components/account/sections/MyProfileSection.mjs +312 -0
- package/dist/components/account/sections/MyProfileSection.mjs.map +1 -0
- package/dist/components/account/sections/PreferencesSection.mjs +246 -0
- package/dist/components/account/sections/PreferencesSection.mjs.map +1 -0
- package/dist/components/account/sections/SecuritySection.mjs +147 -0
- package/dist/components/account/sections/SecuritySection.mjs.map +1 -0
- package/dist/components/ui/form/ComboboxField.mjs +130 -0
- package/dist/components/ui/form/ComboboxField.mjs.map +1 -0
- package/dist/components/ui/form/FormField.mjs +103 -0
- package/dist/components/ui/form/FormField.mjs.map +1 -0
- package/dist/components/ui/form/PhoneInput.mjs +78 -0
- package/dist/components/ui/form/PhoneInput.mjs.map +1 -0
- package/dist/components/ui/form/SelectField.mjs +80 -0
- package/dist/components/ui/form/SelectField.mjs.map +1 -0
- package/dist/components/ui/form/SwitchOptionFieldWithIcon.mjs +40 -0
- package/dist/components/ui/form/SwitchOptionFieldWithIcon.mjs.map +1 -0
- package/dist/components/ui/form/TextAreaField.mjs +56 -0
- package/dist/components/ui/form/TextAreaField.mjs.map +1 -0
- package/dist/enums/AccountSectionType.mjs +11 -0
- package/dist/enums/AccountSectionType.mjs.map +1 -0
- package/dist/hooks/useCountdownTimer.mjs +29 -0
- package/dist/hooks/useCountdownTimer.mjs.map +1 -0
- package/dist/hooks/useIsMobile.mjs +18 -0
- package/dist/hooks/useIsMobile.mjs.map +1 -0
- package/dist/hooks/usePasswordVisibility.mjs +13 -0
- package/dist/hooks/usePasswordVisibility.mjs.map +1 -0
- package/dist/index.mjs +80 -0
- package/dist/index.mjs.map +1 -1
- package/dist/modules/accounts/actions/account-management.action.mjs +163 -0
- package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -0
- package/dist/modules/accounts/hooks/useAccountManagement.mjs +64 -0
- package/dist/modules/accounts/hooks/useAccountManagement.mjs.map +1 -0
- package/dist/modules/accounts/services/account.service.mjs +162 -25
- package/dist/modules/accounts/services/account.service.mjs.map +1 -1
- package/dist/modules/accounts/services/two-factor.service.mjs +77 -0
- package/dist/modules/accounts/services/two-factor.service.mjs.map +1 -0
- package/dist/modules/auth/services/auth.service.mjs +7 -4
- package/dist/modules/auth/services/auth.service.mjs.map +1 -1
- package/dist/server.mjs +36 -0
- package/dist/server.mjs.map +1 -1
- package/dist/utils/browser/clipboard.mjs +36 -0
- package/dist/utils/browser/clipboard.mjs.map +1 -0
- package/dist/utils/file/index.mjs +9 -0
- package/dist/utils/file/index.mjs.map +1 -0
- package/dist/utils/format/masks.mjs +56 -0
- package/dist/utils/format/masks.mjs.map +1 -0
- package/dist/utils/intl/locales.mjs +12 -0
- package/dist/utils/intl/locales.mjs.map +1 -0
- package/dist/utils/intl/timezones.mjs +41 -0
- package/dist/utils/intl/timezones.mjs.map +1 -0
- package/dist/utils/validators/account.mjs +26 -0
- package/dist/utils/validators/account.mjs.map +1 -0
- package/dist/utils/validators/common.mjs +47 -0
- package/dist/utils/validators/common.mjs.map +1 -0
- package/package.json +5 -1
- package/src/components/account/ConfigurationsMyAccountModal.tsx +147 -0
- package/src/components/account/ConfirmGlobalPreferencesModal.tsx +66 -0
- package/src/components/account/DisableTwoFactorAuthModal.tsx +86 -0
- package/src/components/account/TwoFactorAuthModal.tsx +221 -0
- package/src/components/account/constants.ts +29 -0
- package/src/components/account/hooks/useChangeEmailForm.tsx +56 -0
- package/src/components/account/hooks/useChangePasswordForm.tsx +59 -0
- package/src/components/account/hooks/useChangePhoneForm.tsx +69 -0
- package/src/components/account/hooks/useConfigurationsModal.ts +40 -0
- package/src/components/account/hooks/useDisableTwoFactorAuthForm.tsx +69 -0
- package/src/components/account/hooks/useOtpVerification.tsx +116 -0
- package/src/components/account/hooks/useTwoFactorAuthForm.tsx +114 -0
- package/src/components/account/sections/ChangeEmailModal.tsx +224 -0
- package/src/components/account/sections/ChangePasswordSection.tsx +64 -0
- package/src/components/account/sections/ChangePhoneModal.tsx +229 -0
- package/src/components/account/sections/MyProfileSection.tsx +337 -0
- package/src/components/account/sections/PreferencesSection.tsx +277 -0
- package/src/components/account/sections/SecuritySection.tsx +160 -0
- package/src/components/ui/form/ComboboxField.tsx +154 -0
- package/src/components/ui/form/FormField.tsx +130 -0
- package/src/components/ui/form/PhoneInput.tsx +98 -0
- package/src/components/ui/form/SelectField.tsx +118 -0
- package/src/components/ui/form/SwitchOptionFieldWithIcon.tsx +47 -0
- package/src/components/ui/form/TextAreaField.tsx +70 -0
- package/src/enums/AccountSectionType.ts +6 -0
- package/src/hooks/useCountdownTimer.ts +41 -0
- package/src/hooks/useIsMobile.ts +19 -0
- package/src/hooks/usePasswordVisibility.ts +13 -0
- package/src/index.ts +70 -0
- package/src/modules/accounts/actions/account-management.action.ts +197 -0
- package/src/modules/accounts/hooks/useAccountManagement.ts +79 -0
- package/src/modules/accounts/services/account.service.ts +229 -50
- package/src/modules/accounts/services/two-factor.service.ts +98 -0
- package/src/modules/accounts/types.ts +157 -0
- package/src/modules/auth/services/auth.service.ts +9 -5
- package/src/server.ts +21 -0
- package/src/utils/browser/clipboard.ts +34 -0
- package/src/utils/file/index.ts +5 -0
- package/src/utils/format/masks.ts +52 -0
- package/src/utils/intl/locales.ts +15 -0
- package/src/utils/intl/timezones.ts +53 -0
- package/src/utils/validators/account.ts +36 -0
- package/src/utils/validators/common.ts +43 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { LucideIcon } from 'lucide-react';
|
|
2
|
+
import { Switch } from './Switch';
|
|
3
|
+
|
|
4
|
+
type SwitchOptionFieldWithIconProps = {
|
|
5
|
+
icon: LucideIcon;
|
|
6
|
+
label: string;
|
|
7
|
+
description: string;
|
|
8
|
+
checked: boolean;
|
|
9
|
+
onCheckedChange: (checked: boolean) => void;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
hideBorderBottom?: boolean;
|
|
12
|
+
id?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default function SwitchOptionFieldWithIcon({
|
|
16
|
+
icon: Icon,
|
|
17
|
+
label,
|
|
18
|
+
description,
|
|
19
|
+
checked,
|
|
20
|
+
onCheckedChange,
|
|
21
|
+
disabled = false,
|
|
22
|
+
hideBorderBottom = false,
|
|
23
|
+
id,
|
|
24
|
+
}: SwitchOptionFieldWithIconProps) {
|
|
25
|
+
return (
|
|
26
|
+
<label
|
|
27
|
+
className={`flex justify-between items-center gap-3 p-5 ${
|
|
28
|
+
!hideBorderBottom ? 'border-b border-gray-200' : ''
|
|
29
|
+
} ${disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}`}
|
|
30
|
+
>
|
|
31
|
+
<div className="size-10 rounded-lg bg-gray-50 flex items-center justify-center text-gray-950">
|
|
32
|
+
<Icon size={20} />
|
|
33
|
+
</div>
|
|
34
|
+
<div className="flex flex-col gap-2 flex-1">
|
|
35
|
+
<span className="paragraph-small-semibold text-gray-950">{label}</span>
|
|
36
|
+
<span className="paragraph-small-regular text-gray-600">{description}</span>
|
|
37
|
+
</div>
|
|
38
|
+
<Switch
|
|
39
|
+
id={id}
|
|
40
|
+
checked={disabled ? true : checked}
|
|
41
|
+
onCheckedChange={onCheckedChange}
|
|
42
|
+
disabled={disabled}
|
|
43
|
+
className={disabled ? 'opacity-20!' : ''}
|
|
44
|
+
/>
|
|
45
|
+
</label>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { forwardRef, type ComponentPropsWithoutRef } from 'react';
|
|
4
|
+
import { Textarea } from './Textarea';
|
|
5
|
+
import { cn } from '../../../infra/utils/clsx';
|
|
6
|
+
|
|
7
|
+
interface TextAreaFieldProps extends ComponentPropsWithoutRef<'textarea'> {
|
|
8
|
+
label?: string;
|
|
9
|
+
optional?: boolean;
|
|
10
|
+
required?: boolean;
|
|
11
|
+
hintMessage?: string;
|
|
12
|
+
error?: boolean;
|
|
13
|
+
errorMessage?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const TextAreaField = forwardRef<HTMLTextAreaElement, TextAreaFieldProps>(
|
|
17
|
+
(
|
|
18
|
+
{
|
|
19
|
+
label,
|
|
20
|
+
optional = false,
|
|
21
|
+
required = false,
|
|
22
|
+
hintMessage,
|
|
23
|
+
error = false,
|
|
24
|
+
errorMessage,
|
|
25
|
+
className,
|
|
26
|
+
...textareaProps
|
|
27
|
+
},
|
|
28
|
+
ref
|
|
29
|
+
) => {
|
|
30
|
+
const finalMessage = error && errorMessage ? errorMessage : hintMessage;
|
|
31
|
+
const messageColor = error ? 'text-red-600' : 'text-gray-600';
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div className="flex flex-col gap-1.5">
|
|
35
|
+
<div className="flex items-center gap-1 paragraph-xsmall-semibold">
|
|
36
|
+
{label && <span className="text-gray-600">{label}</span>}
|
|
37
|
+
{optional && <span className="text-gray-500">(Opcional)</span>}
|
|
38
|
+
{required && <span className="text-red-600">*</span>}
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div
|
|
42
|
+
className={cn(
|
|
43
|
+
'flex px-4 py-3 border rounded-lg transition-colors overflow-hidden',
|
|
44
|
+
error
|
|
45
|
+
? 'border-red-600 hover:border-red-700'
|
|
46
|
+
: 'border-gray-200 hover:border-gray-400 focus-within:border-gray-950'
|
|
47
|
+
)}
|
|
48
|
+
>
|
|
49
|
+
<Textarea
|
|
50
|
+
ref={ref}
|
|
51
|
+
className={cn(
|
|
52
|
+
'paragraph-small-medium w-full text-gray-950 border-none shadow-none focus-visible:ring-0 p-0 resize-none overflow-y-auto field-sizing-fixed! min-h-0! break-words',
|
|
53
|
+
error && 'placeholder:text-red-400',
|
|
54
|
+
className
|
|
55
|
+
)}
|
|
56
|
+
{...textareaProps}
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
{finalMessage && (
|
|
61
|
+
<span className={cn('paragraph-xsmall-medium', messageColor)}>{finalMessage}</span>
|
|
62
|
+
)}
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
TextAreaField.displayName = 'TextAreaField';
|
|
69
|
+
|
|
70
|
+
export default TextAreaField;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState, useCallback } from 'react';
|
|
4
|
+
|
|
5
|
+
interface UseCountdownTimerOptions {
|
|
6
|
+
initialSeconds?: number;
|
|
7
|
+
onExpire?: () => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface UseCountdownTimerReturn {
|
|
11
|
+
seconds: number;
|
|
12
|
+
isExpired: boolean;
|
|
13
|
+
reset: () => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default function useCountdownTimer({
|
|
17
|
+
initialSeconds = 59,
|
|
18
|
+
onExpire,
|
|
19
|
+
}: UseCountdownTimerOptions = {}): UseCountdownTimerReturn {
|
|
20
|
+
const [seconds, setSeconds] = useState(initialSeconds);
|
|
21
|
+
const [isExpired, setIsExpired] = useState(false);
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (seconds > 0) {
|
|
25
|
+
const interval = setInterval(() => {
|
|
26
|
+
setSeconds((prev) => prev - 1);
|
|
27
|
+
}, 1000);
|
|
28
|
+
return () => clearInterval(interval);
|
|
29
|
+
} else {
|
|
30
|
+
setIsExpired(true);
|
|
31
|
+
onExpire?.();
|
|
32
|
+
}
|
|
33
|
+
}, [seconds, onExpire]);
|
|
34
|
+
|
|
35
|
+
const reset = useCallback(() => {
|
|
36
|
+
setSeconds(initialSeconds);
|
|
37
|
+
setIsExpired(false);
|
|
38
|
+
}, [initialSeconds]);
|
|
39
|
+
|
|
40
|
+
return { seconds, isExpired, reset };
|
|
41
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
export default function useIsMobile() {
|
|
6
|
+
const [isMobile, setIsMobile] = useState(false);
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const checkMobile = () => {
|
|
10
|
+
setIsMobile(window.innerWidth < 1024);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
checkMobile();
|
|
14
|
+
window.addEventListener('resize', checkMobile);
|
|
15
|
+
return () => window.removeEventListener('resize', checkMobile);
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
return isMobile;
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useCallback } from 'react';
|
|
4
|
+
|
|
5
|
+
export default function usePasswordVisibility() {
|
|
6
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
7
|
+
|
|
8
|
+
const togglePassword = useCallback(() => {
|
|
9
|
+
setShowPassword((prev) => !prev);
|
|
10
|
+
}, []);
|
|
11
|
+
|
|
12
|
+
return { showPassword, togglePassword };
|
|
13
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -96,3 +96,73 @@ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './comp
|
|
|
96
96
|
|
|
97
97
|
// Store
|
|
98
98
|
export { useMdSidebarStore } from './store/useMdSidebarStore';
|
|
99
|
+
|
|
100
|
+
// Enums
|
|
101
|
+
export { AccountSectionType } from './enums/AccountSectionType';
|
|
102
|
+
|
|
103
|
+
// Hooks
|
|
104
|
+
export { default as usePasswordVisibility } from './hooks/usePasswordVisibility';
|
|
105
|
+
export { default as useCountdownTimer } from './hooks/useCountdownTimer';
|
|
106
|
+
export { default as useIsMobile } from './hooks/useIsMobile';
|
|
107
|
+
|
|
108
|
+
// Utils
|
|
109
|
+
export { formatPhone, formatTimer, formatFullName, formatCPF, formatCardNumber } from './utils/format/masks';
|
|
110
|
+
export { buildTimezoneOptions } from './utils/intl/timezones';
|
|
111
|
+
export type { TimezoneOption } from './utils/intl/timezones';
|
|
112
|
+
export { buildLocaleOptions, LANGUAGE_OPTIONS as LOCALE_LANGUAGE_OPTIONS } from './utils/intl/locales';
|
|
113
|
+
export type { LocaleOption } from './utils/intl/locales';
|
|
114
|
+
export { copyToClipboard, readFromClipboard } from './utils/browser/clipboard';
|
|
115
|
+
|
|
116
|
+
// UI - Form (new widgets)
|
|
117
|
+
export { FormField } from './components/ui/form/FormField';
|
|
118
|
+
export { SelectField } from './components/ui/form/SelectField';
|
|
119
|
+
export { ComboboxField } from './components/ui/form/ComboboxField';
|
|
120
|
+
export type { ComboboxOption } from './components/ui/form/ComboboxField';
|
|
121
|
+
export { default as PhoneInput } from './components/ui/form/PhoneInput';
|
|
122
|
+
export { default as SwitchOptionFieldWithIcon } from './components/ui/form/SwitchOptionFieldWithIcon';
|
|
123
|
+
export { TextAreaField } from './components/ui/form/TextAreaField';
|
|
124
|
+
|
|
125
|
+
// Account Module - Hooks
|
|
126
|
+
export {
|
|
127
|
+
useUpdateAccount,
|
|
128
|
+
useUpdateAccountUser,
|
|
129
|
+
useUpdateAccountUserById,
|
|
130
|
+
useDeleteAccountUser,
|
|
131
|
+
useDeleteAccount,
|
|
132
|
+
} from './modules/accounts/hooks/useAccountManagement';
|
|
133
|
+
|
|
134
|
+
// Account Types
|
|
135
|
+
export type {
|
|
136
|
+
UpdateAccountRequest,
|
|
137
|
+
UpdateAccountUserRequest,
|
|
138
|
+
ChangePasswordRequest,
|
|
139
|
+
DeleteAccountActionResult,
|
|
140
|
+
DeleteUserActionResult,
|
|
141
|
+
UpdateAccountActionResult,
|
|
142
|
+
UpdateUserActionResult,
|
|
143
|
+
TwoFactorGenerateResult,
|
|
144
|
+
TwoFactorActionResult,
|
|
145
|
+
ContactResetResult,
|
|
146
|
+
} from './modules/accounts/types';
|
|
147
|
+
|
|
148
|
+
// Account Components
|
|
149
|
+
export { default as ConfigurationsMyAccountModal } from './components/account/ConfigurationsMyAccountModal';
|
|
150
|
+
export { default as TwoFactorAuthModal } from './components/account/TwoFactorAuthModal';
|
|
151
|
+
export { default as DisableTwoFactorAuthModal } from './components/account/DisableTwoFactorAuthModal';
|
|
152
|
+
export { default as ConfirmGlobalPreferencesModal } from './components/account/ConfirmGlobalPreferencesModal';
|
|
153
|
+
export { MyProfileSection } from './components/account/sections/MyProfileSection';
|
|
154
|
+
export { PreferencesSection } from './components/account/sections/PreferencesSection';
|
|
155
|
+
export { SecuritySection } from './components/account/sections/SecuritySection';
|
|
156
|
+
export { ChangePasswordSection } from './components/account/sections/ChangePasswordSection';
|
|
157
|
+
export { ChangeEmailModal } from './components/account/sections/ChangeEmailModal';
|
|
158
|
+
export { ChangePhoneModal } from './components/account/sections/ChangePhoneModal';
|
|
159
|
+
|
|
160
|
+
// Account Constants
|
|
161
|
+
export {
|
|
162
|
+
GENDER_OPTIONS,
|
|
163
|
+
CURRENCY_OPTIONS,
|
|
164
|
+
TIMEZONE_OPTIONS,
|
|
165
|
+
TIME_FORMAT_OPTIONS,
|
|
166
|
+
NOTIFICATION_TYPES,
|
|
167
|
+
LANGUAGE_OPTIONS,
|
|
168
|
+
} from './components/account/constants';
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { accountService } from '../services/account.service';
|
|
4
|
+
import { ApiError } from '../../../infra/api/types';
|
|
5
|
+
import type {
|
|
6
|
+
AccountUsersPaginationParams,
|
|
7
|
+
AccountUsersActionResult,
|
|
8
|
+
ChangePasswordActionResult,
|
|
9
|
+
ChangePasswordRequest,
|
|
10
|
+
ContactResetResult,
|
|
11
|
+
CreateAccountUserRequest,
|
|
12
|
+
DeleteAccountActionResult,
|
|
13
|
+
DeleteUserActionResult,
|
|
14
|
+
TwoFactorActionResult,
|
|
15
|
+
TwoFactorGenerateResult,
|
|
16
|
+
UpdateAccountActionResult,
|
|
17
|
+
UpdateAccountRequest,
|
|
18
|
+
UpdateAccountUserRequest,
|
|
19
|
+
UpdateUserActionResult,
|
|
20
|
+
} from '../types';
|
|
21
|
+
import { twoFactorService } from '../services/two-factor.service';
|
|
22
|
+
|
|
23
|
+
export async function listAccountUsersAction(
|
|
24
|
+
params?: AccountUsersPaginationParams
|
|
25
|
+
): Promise<AccountUsersActionResult> {
|
|
26
|
+
try {
|
|
27
|
+
const { users, total } = await accountService.listAccountUsers(params);
|
|
28
|
+
return { success: true, data: users, total };
|
|
29
|
+
} catch (error) {
|
|
30
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
31
|
+
return { success: false, error: 'Erro ao listar usuários. Tente novamente.' };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function updateUserAction(
|
|
36
|
+
user: UpdateAccountUserRequest
|
|
37
|
+
): Promise<UpdateUserActionResult> {
|
|
38
|
+
try {
|
|
39
|
+
const result = await accountService.updateAccountUser(user);
|
|
40
|
+
return { success: true, data: result };
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
43
|
+
return { success: false, error: 'Erro ao atualizar usuário. Tente novamente.' };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function updateAccountUserByIdAction(
|
|
48
|
+
userId: number,
|
|
49
|
+
user: UpdateAccountUserRequest
|
|
50
|
+
): Promise<UpdateUserActionResult> {
|
|
51
|
+
try {
|
|
52
|
+
const result = await accountService.updateAccountUserById(userId, user);
|
|
53
|
+
return { success: true, data: result };
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
56
|
+
return { success: false, error: 'Erro ao atualizar usuário. Tente novamente.' };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function updateAccountAction(
|
|
61
|
+
data: UpdateAccountRequest
|
|
62
|
+
): Promise<UpdateAccountActionResult> {
|
|
63
|
+
try {
|
|
64
|
+
await accountService.updateAccount(data);
|
|
65
|
+
return { success: true };
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
68
|
+
return { success: false, error: 'Erro ao atualizar conta. Tente novamente.' };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function deleteAccountUserAction(userId: number): Promise<DeleteUserActionResult> {
|
|
73
|
+
try {
|
|
74
|
+
await accountService.deleteAccountUser(userId);
|
|
75
|
+
return { success: true };
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
78
|
+
return { success: false, error: 'Erro ao remover usuário. Tente novamente.' };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function deleteAccountAction(): Promise<DeleteAccountActionResult> {
|
|
83
|
+
try {
|
|
84
|
+
await accountService.deleteAccount();
|
|
85
|
+
return { success: true };
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
88
|
+
return { success: false, error: 'Erro ao excluir conta. Tente novamente.' };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export async function createAccountUserAction(
|
|
93
|
+
user: CreateAccountUserRequest
|
|
94
|
+
): Promise<AccountUsersActionResult> {
|
|
95
|
+
try {
|
|
96
|
+
const result = await accountService.createAccountUser(user);
|
|
97
|
+
return { success: true, data: result.data };
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
100
|
+
return { success: false, error: 'Erro ao criar usuário. Tente novamente.' };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function changePasswordAction(
|
|
105
|
+
data: ChangePasswordRequest
|
|
106
|
+
): Promise<ChangePasswordActionResult> {
|
|
107
|
+
try {
|
|
108
|
+
await accountService.changePassword(data);
|
|
109
|
+
return { success: true };
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
112
|
+
return { success: false, error: 'Erro ao alterar senha. Tente novamente.' };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export async function requestEmailChangeAction(newEmail: string): Promise<ContactResetResult> {
|
|
117
|
+
try {
|
|
118
|
+
await accountService.requestContactReset('email', newEmail);
|
|
119
|
+
return { success: true };
|
|
120
|
+
} catch (error) {
|
|
121
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
122
|
+
return { success: false, error: 'E-mail já existente ou ocorreu um erro. Tente novamente mais tarde.' };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export async function confirmEmailChangeAction(
|
|
127
|
+
token: string,
|
|
128
|
+
newEmail: string
|
|
129
|
+
): Promise<ContactResetResult> {
|
|
130
|
+
try {
|
|
131
|
+
await accountService.confirmContactReset('email', token, newEmail);
|
|
132
|
+
return { success: true };
|
|
133
|
+
} catch (error) {
|
|
134
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
135
|
+
return { success: false, error: 'Código inválido ou expirado. Tente novamente.' };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export async function requestPhoneChangeAction(newPhone: string): Promise<ContactResetResult> {
|
|
140
|
+
try {
|
|
141
|
+
await accountService.requestContactReset('phone', newPhone);
|
|
142
|
+
return { success: true };
|
|
143
|
+
} catch (error) {
|
|
144
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
145
|
+
return { success: false, error: 'Número já existente ou ocorreu um erro. Tente novamente mais tarde.' };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export async function confirmPhoneChangeAction(
|
|
150
|
+
token: string,
|
|
151
|
+
newPhone: string
|
|
152
|
+
): Promise<ContactResetResult> {
|
|
153
|
+
try {
|
|
154
|
+
await accountService.confirmContactReset('phone', token, newPhone);
|
|
155
|
+
return { success: true };
|
|
156
|
+
} catch (error) {
|
|
157
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
158
|
+
return { success: false, error: 'Código inválido ou expirado. Tente novamente.' };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export async function generateTwoFactorAction(): Promise<TwoFactorGenerateResult> {
|
|
163
|
+
try {
|
|
164
|
+
const result = await twoFactorService.generate();
|
|
165
|
+
return { success: true, qrcode: result.data.qrcode, backupCodes: result.data.backup_codes };
|
|
166
|
+
} catch (error) {
|
|
167
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
168
|
+
return { success: false, error: 'Erro ao gerar QR Code. Tente novamente.' };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export async function confirmTwoFactorAction(code: string): Promise<TwoFactorActionResult> {
|
|
173
|
+
try {
|
|
174
|
+
await twoFactorService.confirm(code);
|
|
175
|
+
return { success: true };
|
|
176
|
+
} catch (error) {
|
|
177
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
178
|
+
return { success: false, error: 'Código inválido. Tente novamente.' };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export async function disableTwoFactorAction(code: string): Promise<TwoFactorActionResult> {
|
|
183
|
+
try {
|
|
184
|
+
await twoFactorService.verify(code);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
187
|
+
return { success: false, error: 'Código inválido. Tente novamente.' };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
await twoFactorService.disable();
|
|
192
|
+
return { success: true };
|
|
193
|
+
} catch (error) {
|
|
194
|
+
if (error instanceof ApiError) return { success: false, error: error.message };
|
|
195
|
+
return { success: false, error: 'Erro ao desabilitar 2FA. Tente novamente.' };
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
4
|
+
import { USER_QUERY_KEY } from '../../auth/hooks/useUserQuery';
|
|
5
|
+
import type {
|
|
6
|
+
UpdateAccountRequest,
|
|
7
|
+
UpdateAccountUserRequest,
|
|
8
|
+
DeleteUserActionResult,
|
|
9
|
+
DeleteAccountActionResult,
|
|
10
|
+
} from '../types';
|
|
11
|
+
import {
|
|
12
|
+
updateUserAction,
|
|
13
|
+
updateAccountAction,
|
|
14
|
+
updateAccountUserByIdAction,
|
|
15
|
+
deleteAccountUserAction,
|
|
16
|
+
deleteAccountAction,
|
|
17
|
+
} from '../actions/account-management.action';
|
|
18
|
+
import type { UseMutationOptions } from '@tanstack/react-query';
|
|
19
|
+
|
|
20
|
+
const ACCOUNT_USERS_QUERY_KEY = ['account-users'];
|
|
21
|
+
|
|
22
|
+
export function useUpdateAccount() {
|
|
23
|
+
const queryClient = useQueryClient();
|
|
24
|
+
|
|
25
|
+
return useMutation({
|
|
26
|
+
mutationFn: (data: UpdateAccountRequest) => updateAccountAction(data),
|
|
27
|
+
onSuccess: () => {
|
|
28
|
+
queryClient.invalidateQueries({ queryKey: ACCOUNT_USERS_QUERY_KEY });
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function useUpdateAccountUser() {
|
|
34
|
+
const queryClient = useQueryClient();
|
|
35
|
+
|
|
36
|
+
return useMutation({
|
|
37
|
+
mutationFn: updateUserAction,
|
|
38
|
+
onSuccess: () => {
|
|
39
|
+
queryClient.invalidateQueries({ queryKey: ACCOUNT_USERS_QUERY_KEY });
|
|
40
|
+
queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function useUpdateAccountUserById() {
|
|
46
|
+
const queryClient = useQueryClient();
|
|
47
|
+
|
|
48
|
+
return useMutation({
|
|
49
|
+
mutationFn: ({ userId, ...user }: UpdateAccountUserRequest & { userId: number }) =>
|
|
50
|
+
updateAccountUserByIdAction(userId, user),
|
|
51
|
+
onSuccess: () => {
|
|
52
|
+
queryClient.invalidateQueries({ queryKey: ACCOUNT_USERS_QUERY_KEY });
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function useDeleteAccountUser(
|
|
58
|
+
options?: UseMutationOptions<DeleteUserActionResult, Error, number>
|
|
59
|
+
) {
|
|
60
|
+
const queryClient = useQueryClient();
|
|
61
|
+
|
|
62
|
+
return useMutation({
|
|
63
|
+
mutationFn: (userId: number) => deleteAccountUserAction(userId),
|
|
64
|
+
...options,
|
|
65
|
+
onSuccess: (...params) => {
|
|
66
|
+
options?.onSuccess?.(...params);
|
|
67
|
+
queryClient.invalidateQueries({ queryKey: ACCOUNT_USERS_QUERY_KEY });
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function useDeleteAccount(
|
|
73
|
+
options?: UseMutationOptions<DeleteAccountActionResult, Error, void>
|
|
74
|
+
) {
|
|
75
|
+
return useMutation({
|
|
76
|
+
mutationFn: () => deleteAccountAction(),
|
|
77
|
+
...options,
|
|
78
|
+
});
|
|
79
|
+
}
|