@umituz/web-dashboard 5.0.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/package.json +2 -12
  2. package/src/index.ts +0 -10
  3. package/src/styles/dashboard.css +0 -460
  4. package/src/domains/auth/components/AuthLayout.tsx +0 -99
  5. package/src/domains/auth/components/ForgotPasswordForm.tsx +0 -167
  6. package/src/domains/auth/components/LoginForm.tsx +0 -222
  7. package/src/domains/auth/components/RegisterForm.tsx +0 -281
  8. package/src/domains/auth/components/ResetPasswordForm.tsx +0 -173
  9. package/src/domains/auth/components/index.ts +0 -11
  10. package/src/domains/auth/components/shared/AuthErrorBanner.tsx +0 -25
  11. package/src/domains/auth/components/shared/EmailInput.tsx +0 -73
  12. package/src/domains/auth/components/shared/PasswordInput.tsx +0 -100
  13. package/src/domains/auth/components/shared/PasswordStrengthIndicator.tsx +0 -63
  14. package/src/domains/auth/components/shared/SocialLoginButtons.tsx +0 -44
  15. package/src/domains/auth/components/shared/SocialProviderIcons.tsx +0 -48
  16. package/src/domains/auth/components/shared/index.ts +0 -20
  17. package/src/domains/auth/hooks/index.ts +0 -8
  18. package/src/domains/auth/hooks/useAuth.ts +0 -230
  19. package/src/domains/auth/index.ts +0 -62
  20. package/src/domains/auth/types/auth.ts +0 -302
  21. package/src/domains/auth/types/index.ts +0 -25
  22. package/src/domains/auth/utils/auth.test.ts +0 -188
  23. package/src/domains/auth/utils/auth.ts +0 -221
  24. package/src/domains/auth/utils/i18nKeys.ts +0 -109
  25. package/src/domains/auth/utils/index.ts +0 -29
  26. package/src/domains/auth/utils/secureToken.ts +0 -33
  27. package/src/domains/auth/utils/validationKeys.ts +0 -23
  28. package/src/domains/session/DemoLogin.tsx +0 -42
  29. package/src/domains/session/OrgSwitcher.tsx +0 -102
  30. package/src/domains/session/SessionContext.tsx +0 -150
  31. package/src/domains/session/inMemoryAuthAdapter.ts +0 -53
  32. package/src/domains/session/index.ts +0 -18
  33. package/src/domains/session/types.ts +0 -47
  34. package/src/domains/session/utils/i18nKeys.ts +0 -12
@@ -1,167 +0,0 @@
1
- import { useState } from "react";
2
- import { useNavigate } from "react-router-dom";
3
- import { useT } from "@umituz/web-localization/react";
4
- import { ArrowLeft, Loader2, CheckCircle2, Check } from "lucide-react";
5
- import { Button } from "@umituz/web-design-system/atoms";
6
- import type { ForgotPasswordFormProps, Translate } from "../types/auth";
7
- import { validateForgotPassword } from "../utils/auth";
8
- import { AUTH_KEYS } from "../utils/i18nKeys";
9
- import { AUTH_VALIDATION_KEYS } from "../utils/validationKeys";
10
- import { AuthErrorBanner, EmailInput } from "./shared";
11
-
12
- const KEYS = {
13
- title: 'auth.forgotPassword.title',
14
- description: 'auth.forgotPassword.description',
15
- emailLabel: AUTH_KEYS.fields.email,
16
- emailPlaceholder: AUTH_KEYS.placeholders.emailExample,
17
- submitting: 'auth.forgotPassword.submitting',
18
- submit: 'auth.forgotPassword.submit',
19
- backToSignIn: 'auth.forgotPassword.backToSignIn',
20
- successTitle: 'auth.forgotPassword.successTitle',
21
- successMessage: 'auth.forgotPassword.successMessage',
22
- sentTo: 'auth.forgotPassword.sentTo',
23
- step1: 'auth.forgotPassword.steps.step1',
24
- step2: 'auth.forgotPassword.steps.step2',
25
- step3: 'auth.forgotPassword.steps.step3',
26
- invalidEmail: AUTH_VALIDATION_KEYS.emailInvalid,
27
- sendResetFailed: 'auth.errors.sendResetFailed',
28
- } as const;
29
-
30
- export const ForgotPasswordForm = ({
31
- config,
32
- onSuccess,
33
- onError,
34
- showBackLink = true,
35
- }: ForgotPasswordFormProps) => {
36
- const navigate = useNavigate();
37
- const t = useT();
38
- const translate: Translate = t;
39
-
40
- const [email, setEmail] = useState("");
41
- const [isLoading, setIsLoading] = useState(false);
42
- const [error, setError] = useState<string | null>(null);
43
- const [success, setSuccess] = useState(false);
44
-
45
- const handleSubmit = async (e: React.FormEvent) => {
46
- e.preventDefault();
47
- setError(null);
48
-
49
- const validation = validateForgotPassword({ email });
50
- if (!validation.valid) {
51
- const message = validation.error ?? KEYS.invalidEmail;
52
- setError(message);
53
- onError?.(message);
54
- return;
55
- }
56
-
57
- setIsLoading(true);
58
- try {
59
- await onSuccess?.({ email });
60
- setSuccess(true);
61
- } catch (err) {
62
- const message = err instanceof Error ? err.message : KEYS.sendResetFailed;
63
- setError(message);
64
- onError?.(message);
65
- } finally {
66
- setIsLoading(false);
67
- }
68
- };
69
-
70
- if (success) {
71
- return (
72
- <div className="udb-form" role="status" aria-live="polite">
73
- <div className="udb-form__header">
74
- <div className="udb-success-badge">
75
- <CheckCircle2 className="udb-success-badge__icon" aria-hidden="true" />
76
- </div>
77
- <h1 className="udb-form__title">
78
- {translate(KEYS.successTitle)}
79
- </h1>
80
- <p className="udb-form__subtitle">
81
- {translate(KEYS.sentTo)}{' '}
82
- <span className="udb-form__subtitle-strong">{email}</span>
83
- </p>
84
- </div>
85
-
86
- <ol className="udb-steps-list">
87
- <li className="udb-steps-list__item">
88
- <Check className="udb-steps-list__icon" aria-hidden="true" />
89
- {translate(KEYS.step1)}
90
- </li>
91
- <li className="udb-steps-list__item">
92
- <Check className="udb-steps-list__icon" aria-hidden="true" />
93
- {translate(KEYS.step2)}
94
- </li>
95
- <li className="udb-steps-list__item">
96
- <Check className="udb-steps-list__icon" aria-hidden="true" />
97
- {translate(KEYS.step3)}
98
- </li>
99
- </ol>
100
-
101
- {showBackLink && config.loginRoute && (
102
- <Button
103
- type="button"
104
- variant="ghost"
105
- onClick={() => navigate(config.loginRoute)}
106
- className="udb-submit-btn"
107
- >
108
- <ArrowLeft className="udb-btn__spinner" aria-hidden="true" />
109
- {translate(KEYS.backToSignIn)}
110
- </Button>
111
- )}
112
- </div>
113
- );
114
- }
115
-
116
- return (
117
- <form onSubmit={handleSubmit} className="udb-form" noValidate>
118
- <div className="udb-form__header">
119
- <h1 className="udb-form__title udb-form__title--lg">
120
- {translate(KEYS.title)}
121
- </h1>
122
- <p className="udb-form__subtitle">{translate(KEYS.description)}</p>
123
- </div>
124
-
125
- <AuthErrorBanner message={error} translate={translate} />
126
-
127
- <EmailInput
128
- id="forgot-email"
129
- labelKey={KEYS.emailLabel}
130
- placeholderKey={KEYS.emailPlaceholder}
131
- value={email}
132
- onChange={setEmail}
133
- translate={translate}
134
- disabled={isLoading}
135
- required
136
- />
137
-
138
- <Button
139
- type="submit"
140
- className="udb-submit-btn udb-submit-btn--pill"
141
- disabled={isLoading}
142
- >
143
- {isLoading ? (
144
- <>
145
- <Loader2 className="udb-btn__spinner" aria-hidden="true" />
146
- {translate(KEYS.submitting)}
147
- </>
148
- ) : (
149
- translate(KEYS.submit)
150
- )}
151
- </Button>
152
-
153
- {showBackLink && config.loginRoute && (
154
- <button
155
- type="button"
156
- onClick={() => navigate(config.loginRoute)}
157
- className="udb-back-link"
158
- >
159
- <ArrowLeft className="udb-back-link__icon" aria-hidden="true" />
160
- {translate(KEYS.backToSignIn)}
161
- </button>
162
- )}
163
- </form>
164
- );
165
- };
166
-
167
- export default ForgotPasswordForm;
@@ -1,222 +0,0 @@
1
- import { useState, useCallback } from "react";
2
- import { useNavigate } from "react-router-dom";
3
- import { useT } from "@umituz/web-localization/react";
4
- import { Button, Checkbox } from "@umituz/web-design-system/atoms";
5
- import { Loader2 } from "lucide-react";
6
- import { validateLogin } from "../utils/auth";
7
- import type {
8
- LoginFormProps,
9
- LoginCredentials,
10
- User,
11
- Translate,
12
- } from "../types/auth";
13
- import {
14
- AuthErrorBanner,
15
- EmailInput,
16
- PasswordInput,
17
- SocialLoginButtons,
18
- } from "./shared";
19
-
20
- const KEYS = {
21
- welcomeBack: 'auth.login.welcomeBack',
22
- signInTo: 'auth.login.signInTo',
23
- emailLabel: 'auth.fields.email',
24
- emailPlaceholder: 'auth.placeholders.emailExample',
25
- passwordLabel: 'auth.fields.password',
26
- passwordPlaceholder: 'auth.placeholders.password',
27
- rememberMe: 'auth.login.rememberMe',
28
- forgotPassword: 'auth.login.forgotPassword',
29
- submit: 'auth.login.submit',
30
- submitting: 'auth.login.submitting',
31
- noAccount: 'auth.login.noAccount',
32
- signUp: 'auth.login.signUp',
33
- orContinueWith: 'auth.login.orContinueWith',
34
- invalidCredentials: 'auth.errors.invalidCredentials',
35
- loginFailed: 'auth.errors.loginFailed',
36
- noAuthProvider: 'auth.errors.noAuthProvider',
37
- } as const;
38
-
39
- export const LoginForm = ({
40
- config,
41
- defaultCredentials,
42
- showRememberMe = true,
43
- showForgotPassword = true,
44
- showRegisterLink = true,
45
- showSocialLogin = true,
46
- enableMockAuth = false,
47
- onLoginAttempt,
48
- onLoginSuccess,
49
- onLoginError,
50
- onGoogleLogin,
51
- onAppleLogin,
52
- }: LoginFormProps) => {
53
- const navigate = useNavigate();
54
- const t = useT();
55
- const translate: Translate = t;
56
-
57
- const [email, setEmail] = useState<string>(defaultCredentials?.email ?? "");
58
- const [password, setPassword] = useState<string>(defaultCredentials?.password ?? "");
59
- const [remember, setRemember] = useState<boolean>(false);
60
- const [loading, setLoading] = useState<boolean>(false);
61
- const [error, setError] = useState<string | null>(null);
62
-
63
- const performLogin = useCallback(
64
- async (credentials: LoginCredentials): Promise<User> => {
65
- if (onLoginAttempt) {
66
- return onLoginAttempt(credentials);
67
- }
68
- if (!enableMockAuth) {
69
- throw new Error(KEYS.noAuthProvider);
70
- }
71
- await new Promise((resolve) => setTimeout(resolve, 1000));
72
- return {
73
- id: "1",
74
- email: credentials.email,
75
- name: credentials.email.split("@")[0],
76
- };
77
- },
78
- [onLoginAttempt, enableMockAuth],
79
- );
80
-
81
- const handleSubmit = useCallback(
82
- async (e: React.FormEvent) => {
83
- e.preventDefault();
84
- setError(null);
85
-
86
- const validation = validateLogin({ email, password });
87
- if (!validation.valid) {
88
- const message = validation.error ?? KEYS.invalidCredentials;
89
- setError(message);
90
- onLoginError?.(message);
91
- return;
92
- }
93
-
94
- setLoading(true);
95
- try {
96
- const user = await performLogin({ email, password });
97
- await onLoginSuccess?.(user);
98
- navigate(config.afterLoginRoute);
99
- } catch (err) {
100
- const message = err instanceof Error ? err.message : KEYS.loginFailed;
101
- setError(message);
102
- onLoginError?.(message);
103
- } finally {
104
- setLoading(false);
105
- }
106
- },
107
- [email, password, performLogin, navigate, config.afterLoginRoute, onLoginSuccess, onLoginError],
108
- );
109
-
110
- const handleSocial = useCallback(
111
- (provider: 'google' | 'apple') => {
112
- if (provider === 'google') onGoogleLogin?.();
113
- if (provider === 'apple') onAppleLogin?.();
114
- },
115
- [onGoogleLogin, onAppleLogin],
116
- );
117
-
118
- return (
119
- <form onSubmit={handleSubmit} className="udb-form" noValidate>
120
- <div className="udb-form__header">
121
- <h1 className="udb-form__title">
122
- {translate(KEYS.welcomeBack)}
123
- </h1>
124
- <p className="udb-form__subtitle">
125
- {translate(KEYS.signInTo, { brand: config.brandName })}
126
- </p>
127
- </div>
128
-
129
- <AuthErrorBanner message={error} translate={translate} />
130
-
131
- <EmailInput
132
- id="login-email"
133
- labelKey={KEYS.emailLabel}
134
- placeholderKey={KEYS.emailPlaceholder}
135
- value={email}
136
- onChange={setEmail}
137
- translate={translate}
138
- disabled={loading}
139
- required
140
- />
141
-
142
- <PasswordInput
143
- id="login-password"
144
- labelKey={KEYS.passwordLabel}
145
- placeholderKey={KEYS.passwordPlaceholder}
146
- value={password}
147
- onChange={setPassword}
148
- translate={translate}
149
- autoComplete="current-password"
150
- disabled={loading}
151
- required
152
- />
153
-
154
- {(showRememberMe || showForgotPassword) && (
155
- <div className="udb-form__row">
156
- {showRememberMe && (
157
- <label className="udb-check-label">
158
- <Checkbox
159
- checked={remember}
160
- onCheckedChange={(checked) => setRemember(Boolean(checked))}
161
- disabled={loading}
162
- />
163
- {translate(KEYS.rememberMe)}
164
- </label>
165
- )}
166
- {showForgotPassword && (
167
- <button
168
- type="button"
169
- onClick={() => navigate(config.forgotPasswordRoute ?? '/forgot-password')}
170
- className="udb-link-btn"
171
- disabled={loading}
172
- >
173
- {translate(KEYS.forgotPassword)}
174
- </button>
175
- )}
176
- </div>
177
- )}
178
-
179
- <Button type="submit" disabled={loading} className="udb-submit-btn">
180
- {loading ? (
181
- <>
182
- <Loader2 className="udb-btn__spinner" aria-hidden="true" />
183
- {translate(KEYS.submitting)}
184
- </>
185
- ) : (
186
- translate(KEYS.submit)
187
- )}
188
- </Button>
189
-
190
- {showRegisterLink && (
191
- <p className="udb-form__footer-text">
192
- {translate(KEYS.noAccount)}{' '}
193
- <button
194
- type="button"
195
- onClick={() => navigate(config.registerRoute)}
196
- className="udb-link-btn udb-link-btn--strong"
197
- disabled={loading}
198
- >
199
- {translate(KEYS.signUp)}
200
- </button>
201
- </p>
202
- )}
203
-
204
- {showSocialLogin && (
205
- <>
206
- <div className="udb-divider-row">
207
- <span className="udb-divider-row__label">
208
- {translate(KEYS.orContinueWith)}
209
- </span>
210
- </div>
211
- <SocialLoginButtons
212
- onProvider={handleSocial}
213
- translate={translate}
214
- disabled={loading}
215
- />
216
- </>
217
- )}
218
- </form>
219
- );
220
- };
221
-
222
- export default LoginForm;
@@ -1,281 +0,0 @@
1
- import { useState, useCallback } from "react";
2
- import { useNavigate } from "react-router-dom";
3
- import { useT } from "@umituz/web-localization/react";
4
- import { Loader2 } from "lucide-react";
5
- import { Button, Checkbox, Input } from "@umituz/web-design-system/atoms";
6
- import { cn } from "@umituz/web-design-system/utils/cn";
7
- import type { RegisterFormProps, RegisterData, Translate } from "../types/auth";
8
- import { validateRegister } from "../utils/auth";
9
- import { AUTH_KEYS } from "../utils/i18nKeys";
10
- import { AUTH_VALIDATION_KEYS } from "../utils/validationKeys";
11
- import {
12
- AuthErrorBanner,
13
- EmailInput,
14
- PasswordInput,
15
- PasswordStrengthIndicator,
16
- SocialLoginButtons,
17
- } from "./shared";
18
-
19
- const KEYS = {
20
- title: 'auth.register.createAccount',
21
- join: 'auth.register.join',
22
- nameLabel: 'auth.fields.name',
23
- namePlaceholder: 'auth.placeholders.fullName',
24
- emailLabel: AUTH_KEYS.fields.email,
25
- emailPlaceholder: AUTH_KEYS.placeholders.emailExample,
26
- passwordLabel: AUTH_KEYS.fields.password,
27
- passwordPlaceholder: AUTH_KEYS.placeholders.password,
28
- confirmPassword: 'auth.register.confirmPassword',
29
- submit: 'auth.register.submit',
30
- submitting: 'auth.register.submitting',
31
- acceptTerms: 'auth.register.acceptTerms',
32
- termsOfService: 'auth.register.termsOfService',
33
- privacyPolicy: 'auth.register.privacyPolicy',
34
- haveAccount: 'auth.register.haveAccount',
35
- signIn: 'auth.register.signIn',
36
- orContinueWith: 'auth.login.orContinueWith',
37
- invalidData: 'auth.errors.registrationFailed',
38
- mustAcceptTerms: 'auth.register.mustAcceptTerms',
39
- passwordsDoNotMatch: AUTH_VALIDATION_KEYS.passwordsDoNotMatch,
40
- } as const;
41
-
42
- export const RegisterForm = ({
43
- config,
44
- defaultData = {},
45
- showTerms = true,
46
- showLoginLink = true,
47
- requirePasswordConfirm = true,
48
- showSocialLogin = true,
49
- onRegisterAttempt,
50
- onRegisterSuccess,
51
- onRegisterError,
52
- onGoogleLogin,
53
- onAppleLogin,
54
- }: RegisterFormProps) => {
55
- const navigate = useNavigate();
56
- const t = useT();
57
- const translate: Translate = t;
58
-
59
- const [name, setName] = useState<string>(defaultData.name ?? '');
60
- const [email, setEmail] = useState<string>(defaultData.email ?? '');
61
- const [password, setPassword] = useState<string>(defaultData.password ?? '');
62
- const [confirmPassword, setConfirmPassword] = useState<string>('');
63
- const [agreeToTerms, setAgreeToTerms] = useState<boolean>(false);
64
- const [isLoading, setIsLoading] = useState<boolean>(false);
65
- const [error, setError] = useState<string | null>(null);
66
-
67
- const passwordsMatch = !requirePasswordConfirm || password === confirmPassword;
68
-
69
- const handleSubmit = useCallback(
70
- async (e: React.FormEvent) => {
71
- e.preventDefault();
72
- setError(null);
73
-
74
- const validation = validateRegister(
75
- { email, password, name, confirmPassword },
76
- false,
77
- requirePasswordConfirm,
78
- );
79
- if (!validation.valid) {
80
- const message = validation.error ?? KEYS.invalidData;
81
- setError(message);
82
- onRegisterError?.(message);
83
- return;
84
- }
85
-
86
- if (showTerms && !agreeToTerms) {
87
- setError(KEYS.mustAcceptTerms);
88
- onRegisterError?.(KEYS.mustAcceptTerms);
89
- return;
90
- }
91
-
92
- setIsLoading(true);
93
- try {
94
- if (!onRegisterAttempt) {
95
- throw new Error('No register handler configured');
96
- }
97
- const registerData: RegisterData = { email, password, name };
98
- const user = await onRegisterAttempt(registerData);
99
- await onRegisterSuccess?.(user);
100
- navigate(config.afterLoginRoute);
101
- } catch (err) {
102
- const message = err instanceof Error ? err.message : KEYS.invalidData;
103
- setError(message);
104
- onRegisterError?.(message);
105
- } finally {
106
- setIsLoading(false);
107
- }
108
- },
109
- [
110
- agreeToTerms,
111
- config.afterLoginRoute,
112
- confirmPassword,
113
- email,
114
- name,
115
- navigate,
116
- onRegisterAttempt,
117
- onRegisterError,
118
- onRegisterSuccess,
119
- password,
120
- requirePasswordConfirm,
121
- showTerms,
122
- ],
123
- );
124
-
125
- const handleSocial = useCallback(
126
- (provider: 'google' | 'apple') => {
127
- if (provider === 'google') onGoogleLogin?.();
128
- if (provider === 'apple') onAppleLogin?.();
129
- },
130
- [onGoogleLogin, onAppleLogin],
131
- );
132
-
133
- return (
134
- <form onSubmit={handleSubmit} className="udb-form" noValidate>
135
- <div className="udb-form__header">
136
- <h1 className="udb-form__title udb-form__title--lg">
137
- {translate(KEYS.title)}
138
- </h1>
139
- <p className="udb-form__subtitle">
140
- {translate(KEYS.join, { brand: config.brandName })}
141
- </p>
142
- </div>
143
-
144
- <AuthErrorBanner message={error} translate={translate} />
145
-
146
- <div className="udb-field">
147
- <label htmlFor="register-name" className="udb-field__label">
148
- {translate(KEYS.nameLabel)}
149
- </label>
150
- <Input
151
- id="register-name"
152
- type="text"
153
- autoComplete="name"
154
- disabled={isLoading}
155
- value={name}
156
- placeholder={translate(KEYS.namePlaceholder)}
157
- onChange={(e) => setName(e.target.value)}
158
- />
159
- </div>
160
-
161
- <EmailInput
162
- id="register-email"
163
- labelKey={KEYS.emailLabel}
164
- placeholderKey={KEYS.emailPlaceholder}
165
- value={email}
166
- onChange={setEmail}
167
- translate={translate}
168
- disabled={isLoading}
169
- required
170
- />
171
-
172
- <div className="udb-form__group">
173
- <PasswordInput
174
- id="register-password"
175
- labelKey={KEYS.passwordLabel}
176
- placeholderKey={KEYS.passwordPlaceholder}
177
- value={password}
178
- onChange={setPassword}
179
- translate={translate}
180
- autoComplete="new-password"
181
- disabled={isLoading}
182
- required
183
- />
184
- <PasswordStrengthIndicator password={password} translate={translate} />
185
- </div>
186
-
187
- {requirePasswordConfirm && (
188
- <div className="udb-field">
189
- <label htmlFor="register-confirm" className="udb-field__label">
190
- {translate(KEYS.confirmPassword)}
191
- <span className="udb-field__required" aria-hidden="true">*</span>
192
- </label>
193
- <Input
194
- id="register-confirm"
195
- type="password"
196
- autoComplete="new-password"
197
- required
198
- disabled={isLoading}
199
- value={confirmPassword}
200
- placeholder={translate(KEYS.passwordPlaceholder)}
201
- onChange={(e) => setConfirmPassword(e.target.value)}
202
- aria-invalid={Boolean(confirmPassword) && !passwordsMatch}
203
- className={cn(confirmPassword && !passwordsMatch && 'udb-input--error')}
204
- />
205
- {confirmPassword && !passwordsMatch && (
206
- <p className="udb-field__error" role="alert">
207
- {translate(KEYS.passwordsDoNotMatch)}
208
- </p>
209
- )}
210
- </div>
211
- )}
212
-
213
- {showTerms && (
214
- <label className="udb-check-label udb-check-label--multiline">
215
- <Checkbox
216
- checked={agreeToTerms}
217
- onCheckedChange={(checked) => setAgreeToTerms(Boolean(checked))}
218
- disabled={isLoading}
219
- aria-label={translate(KEYS.acceptTerms)}
220
- />
221
- <span className="udb-check-label__text">
222
- {translate(KEYS.acceptTerms)}{' '}
223
- <a href="/terms" className="udb-text-link">
224
- {translate(KEYS.termsOfService)}
225
- </a>{' '}
226
- and{' '}
227
- <a href="/privacy" className="udb-text-link">
228
- {translate(KEYS.privacyPolicy)}
229
- </a>
230
- </span>
231
- </label>
232
- )}
233
-
234
- <Button
235
- type="submit"
236
- className="udb-submit-btn udb-submit-btn--pill"
237
- disabled={isLoading || (requirePasswordConfirm && !passwordsMatch)}
238
- >
239
- {isLoading ? (
240
- <>
241
- <Loader2 className="udb-btn__spinner" aria-hidden="true" />
242
- {translate(KEYS.submitting)}
243
- </>
244
- ) : (
245
- translate(KEYS.submit)
246
- )}
247
- </Button>
248
-
249
- {showLoginLink && config.loginRoute && (
250
- <p className="udb-form__footer-text">
251
- {translate(KEYS.haveAccount)}{' '}
252
- <button
253
- type="button"
254
- onClick={() => navigate(config.loginRoute)}
255
- className="udb-link-btn udb-link-btn--strong"
256
- disabled={isLoading}
257
- >
258
- {translate(KEYS.signIn)}
259
- </button>
260
- </p>
261
- )}
262
-
263
- {showSocialLogin && config.showSocialLogin && config.socialProviders && config.socialProviders.length > 0 && (
264
- <>
265
- <div className="udb-divider-row">
266
- <span className="udb-divider-row__label">
267
- {translate(KEYS.orContinueWith)}
268
- </span>
269
- </div>
270
- <SocialLoginButtons
271
- onProvider={handleSocial}
272
- translate={translate}
273
- disabled={isLoading}
274
- />
275
- </>
276
- )}
277
- </form>
278
- );
279
- };
280
-
281
- export default RegisterForm;