@joelbarron/react-web-dev-kit 0.1.3 → 0.1.4

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 (56) hide show
  1. package/dist/auth/client.d.ts +2 -1
  2. package/dist/auth/client.d.ts.map +1 -1
  3. package/dist/auth/client.js +14 -1
  4. package/dist/auth/forms/account/AuthAccountConfirmationForm.d.ts.map +1 -1
  5. package/dist/auth/forms/account/AuthAccountConfirmationForm.js +3 -2
  6. package/dist/auth/forms/password/AuthForgotPasswordForm.d.ts +4 -0
  7. package/dist/auth/forms/password/AuthForgotPasswordForm.d.ts.map +1 -1
  8. package/dist/auth/forms/password/AuthForgotPasswordForm.js +43 -5
  9. package/dist/auth/forms/password/AuthPasswordResetConfirmForm.d.ts +2 -0
  10. package/dist/auth/forms/password/AuthPasswordResetConfirmForm.d.ts.map +1 -1
  11. package/dist/auth/forms/password/AuthPasswordResetConfirmForm.js +84 -9
  12. package/dist/auth/forms/password/AuthResetPasswordForm.d.ts.map +1 -1
  13. package/dist/auth/forms/password/AuthResetPasswordForm.js +5 -1
  14. package/dist/auth/forms/password/passwordValidation.d.ts +3 -0
  15. package/dist/auth/forms/password/passwordValidation.d.ts.map +1 -0
  16. package/dist/auth/forms/password/passwordValidation.js +45 -0
  17. package/dist/auth/forms/sign-in/AuthOtpSignInForm.d.ts.map +1 -1
  18. package/dist/auth/forms/sign-in/AuthOtpSignInForm.js +2 -1
  19. package/dist/auth/forms/sign-in/AuthPasswordSignInForm.d.ts +1 -0
  20. package/dist/auth/forms/sign-in/AuthPasswordSignInForm.d.ts.map +1 -1
  21. package/dist/auth/forms/sign-in/AuthPasswordSignInForm.js +36 -8
  22. package/dist/auth/forms/sign-up/AuthSignUpForm.d.ts +1 -0
  23. package/dist/auth/forms/sign-up/AuthSignUpForm.d.ts.map +1 -1
  24. package/dist/auth/forms/sign-up/AuthSignUpForm.js +33 -7
  25. package/dist/auth/fuse/createFuseAuthViews.d.ts.map +1 -1
  26. package/dist/auth/fuse/createFuseAuthViews.js +121 -60
  27. package/dist/auth/fuse/fuseAdapter.d.ts +2 -1
  28. package/dist/auth/fuse/fuseAdapter.d.ts.map +1 -1
  29. package/dist/auth/fuse/fuseAdapter.js +6 -0
  30. package/dist/auth/social/providerAuth.d.ts +9 -1
  31. package/dist/auth/social/providerAuth.d.ts.map +1 -1
  32. package/dist/auth/social/providerAuth.js +19 -1
  33. package/dist/auth/types.d.ts +18 -0
  34. package/dist/auth/types.d.ts.map +1 -1
  35. package/dist/auth/ui/AuthPageTitle.d.ts +7 -0
  36. package/dist/auth/ui/AuthPageTitle.d.ts.map +1 -0
  37. package/dist/auth/ui/AuthPageTitle.js +7 -0
  38. package/dist/auth/ui/AuthPrimaryButton.js +3 -3
  39. package/dist/auth/ui/AuthRoutePageWrapper.d.ts.map +1 -1
  40. package/dist/auth/ui/AuthRoutePageWrapper.js +17 -12
  41. package/dist/auth/ui/AuthSocialProviderButton.d.ts +1 -1
  42. package/dist/auth/ui/AuthSocialProviderButton.d.ts.map +1 -1
  43. package/dist/auth/ui/AuthSocialProviderButton.js +5 -2
  44. package/dist/auth/ui/SignInPageTitle.js +1 -1
  45. package/dist/auth/ui/index.d.ts +1 -3
  46. package/dist/auth/ui/index.d.ts.map +1 -1
  47. package/dist/auth/ui/index.js +1 -3
  48. package/dist/forms/JBDatePickerField.d.ts.map +1 -1
  49. package/dist/forms/JBDatePickerField.js +4 -2
  50. package/dist/forms/JBSelectField.d.ts.map +1 -1
  51. package/dist/forms/JBSelectField.js +2 -2
  52. package/dist/forms/JBTextField.d.ts.map +1 -1
  53. package/dist/forms/JBTextField.js +2 -2
  54. package/dist/forms/JBTimePickerField.d.ts.map +1 -1
  55. package/dist/forms/JBTimePickerField.js +4 -2
  56. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { AxiosInstance } from 'axios';
2
2
  import { JBAppConfig } from '../config';
3
- import { AccountUpdatePayload, AccountConfirmationPayload, AccountConfirmationResendPayload, ApiDetailResponse, CreateAdminUserPayload, CreateProfilePayload, CreateAuthenticatedAxiosOptions, DeleteAccountPayload, JbDrfAuthConfig, JbDrfAuthEndpoints, JbDrfWebAuthResponse, LinkSocialPayload, LoginBasicPayload, LoginSocialPayload, PasswordChangePayload, PasswordResetConfirmPayload, PasswordResetRequestPayload, ProfilePicturePayload, ProfilesResponse, RegisterPayload, RefreshPayload, RequestOtpPayload, SwitchProfilePayload, TokenPair, TokenStorage, UnlinkSocialPayload, UpdateProfilePayload, VerifyOtpPayload } from './types';
3
+ import { AccountUpdatePayload, AccountConfirmationPayload, AccountConfirmationResendPayload, ApiDetailResponse, CreateAdminUserPayload, CreateProfilePayload, CreateAuthenticatedAxiosOptions, DeleteAccountPayload, JbDrfAuthConfig, JbDrfAuthEndpoints, JbDrfWebAuthResponse, LinkSocialPayload, LoginBasicPayload, LoginSocialPrecheckResponse, LoginSocialPayload, PasswordChangePayload, PasswordResetConfirmPayload, PasswordResetRequestPayload, ProfilePicturePayload, ProfilesResponse, RegisterPayload, RefreshPayload, RequestOtpPayload, SwitchProfilePayload, TokenPair, TokenStorage, UnlinkSocialPayload, UpdateProfilePayload, VerifyOtpPayload } from './types';
4
4
  export declare const createAuthEndpoints: (basePath?: string) => JbDrfAuthEndpoints;
5
5
  export declare const defaultAuthEndpoints: JbDrfAuthEndpoints;
6
6
  export type AuthClient = {
@@ -14,6 +14,7 @@ export type AuthClient = {
14
14
  createAuthenticatedAxiosWithRefresh: (options?: CreateAuthenticatedAxiosOptions) => AxiosInstance;
15
15
  loginBasic: (payload: LoginBasicPayload) => Promise<JbDrfWebAuthResponse>;
16
16
  loginSocial: (payload: LoginSocialPayload) => Promise<JbDrfWebAuthResponse>;
17
+ loginSocialPrecheck: (payload: LoginSocialPayload) => Promise<LoginSocialPrecheckResponse>;
17
18
  linkSocial: (payload: LinkSocialPayload) => Promise<Record<string, unknown>>;
18
19
  unlinkSocial: (payload: UnlinkSocialPayload) => Promise<Record<string, unknown>>;
19
20
  requestOtp: (payload: RequestOtpPayload) => Promise<Record<string, unknown>>;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/auth/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/auth/client.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ export const createAuthEndpoints = (basePath) => {
14
14
  return {
15
15
  loginBasic: `${root}/login/basic/`,
16
16
  loginSocial: `${root}/login/social/`,
17
+ loginSocialPrecheck: `${root}/login/social/precheck/`,
17
18
  loginSocialLink: `${root}/login/social/link/`,
18
19
  loginSocialUnlink: `${root}/login/social/unlink/`,
19
20
  loginOtpVerify: `${root}/otp/verify/`,
@@ -180,6 +181,10 @@ export const createAuthClient = (config) => {
180
181
  saveRefreshToken(refreshTokenValue);
181
182
  return response.data;
182
183
  };
184
+ const loginSocialPrecheck = async (payload) => {
185
+ const response = await createPublicAxios().post(withBaseUrl(endpoints.loginSocialPrecheck), withClientPayload(payload, defaultClient));
186
+ return response.data;
187
+ };
183
188
  const linkSocial = async (payload) => {
184
189
  const response = await createAuthenticatedAxiosWithRefresh().post(withBaseUrl(endpoints.loginSocialLink), payload);
185
190
  return response.data;
@@ -268,8 +273,15 @@ export const createAuthClient = (config) => {
268
273
  return response.data;
269
274
  };
270
275
  const refreshToken = async (payload) => {
276
+ const refreshTokenValue = payload?.refreshToken ?? getStoredRefreshToken();
277
+ if (!refreshTokenValue) {
278
+ return {
279
+ accessToken: '',
280
+ refreshToken: ''
281
+ };
282
+ }
271
283
  const response = await createPublicAxios().post(withBaseUrl(endpoints.refresh), {
272
- refresh: payload?.refreshToken
284
+ refresh: refreshTokenValue
273
285
  });
274
286
  const nextTokens = getRefreshTokenFromResponse(response);
275
287
  if (nextTokens.accessToken) {
@@ -319,6 +331,7 @@ export const createAuthClient = (config) => {
319
331
  createAuthenticatedAxiosWithRefresh,
320
332
  loginBasic,
321
333
  loginSocial,
334
+ loginSocialPrecheck,
322
335
  linkSocial,
323
336
  unlinkSocial,
324
337
  requestOtp,
@@ -1 +1 @@
1
- {"version":3,"file":"AuthAccountConfirmationForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/account/AuthAccountConfirmationForm.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,iCAAiC,GAAG;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,aAAa,CAAC,EAAE,OAAO,CAAC,iCAAiC,CAAC,CAAC;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,CAAC,MAAM,EAAE,iCAAiC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtE,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,gCAAgC,2CA4QlF"}
1
+ {"version":3,"file":"AuthAccountConfirmationForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/account/AuthAccountConfirmationForm.tsx"],"names":[],"mappings":"AAUA,MAAM,MAAM,iCAAiC,GAAG;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,aAAa,CAAC,EAAE,OAAO,CAAC,iCAAiC,CAAC,CAAC;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,CAAC,MAAM,EAAE,iCAAiC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtE,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,gCAAgC,2CA8QlF"}
@@ -4,6 +4,7 @@ import Button from '@mui/material/Button';
4
4
  import CircularProgress from '@mui/material/CircularProgress';
5
5
  import Stack from '@mui/material/Stack';
6
6
  import Typography from '@mui/material/Typography';
7
+ import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined';
7
8
  import { useEffect, useRef, useState } from 'react';
8
9
  import { AuthPrimaryButton, AuthSecondaryButton } from '../../ui';
9
10
  import { parseAuthError } from '../errorParser';
@@ -148,7 +149,7 @@ export function AuthAccountConfirmationForm(props) {
148
149
  }, [uid, token, email, hasValues, canResendFromSignup, resendCooldownSeconds]);
149
150
  return (_jsxs(Stack, { spacing: 2, children: [!hasValues && email ? (_jsx(Alert, { severity: "info", children: "Tu cuenta fue creada. Revisa tu correo para verificar tu cuenta." })) : null, !hasValues && !email ? (_jsx(Alert, { severity: "warning", children: "Falta informaci\u00F3n del enlace de verificaci\u00F3n." })) : null, loading ? (_jsx(Alert, { severity: "info", children: _jsxs(Stack, { direction: "row", spacing: 1, alignItems: "center", children: [_jsx(CircularProgress, { size: 16, color: "inherit" }), _jsx(Typography, { variant: "body2", children: "Verificando tu cuenta..." })] }) })) : null, isSuccess ? _jsx(Alert, { severity: "success", children: "Tu cuenta fue verificada correctamente." }) : null, resendMessage ? _jsx(Alert, { severity: "success", children: resendMessage }) : null, errorMessage ? _jsx(Alert, { severity: "error", children: errorMessage }) : null, !isSuccess && hasValues && !canResendFromExpiredLink ? (_jsx(Button, { variant: "contained", onClick: () => {
150
151
  void submit();
151
- }, disabled: loading, children: "Reintentar verificaci\u00F3n" })) : null, canResendFromSignup ? (_jsxs(Stack, { sx: { mt: 1.5 }, children: [_jsx(AuthPrimaryButton, { type: "button", onClick: onGoToSignIn, children: "Ir a iniciar sesi\u00F3n" }), _jsx(AuthSecondaryButton, { sx: { mt: 1.5 }, type: "button", onClick: () => {
152
+ }, disabled: loading, children: "Reintentar verificaci\u00F3n" })) : null, canResendFromSignup ? (_jsxs(Stack, { sx: { mt: 1.5 }, children: [_jsx(AuthPrimaryButton, { type: "button", startIcon: _jsx(EmailOutlinedIcon, { fontSize: "small" }), onClick: onGoToSignIn, children: "Ir a iniciar sesi\u00F3n" }), _jsx(AuthSecondaryButton, { sx: { mt: 1.5 }, type: "button", onClick: () => {
152
153
  void resend();
153
154
  }, disabled: resending || resendCooldown > 0, children: resending
154
155
  ? 'Reenviando...'
@@ -160,7 +161,7 @@ export function AuthAccountConfirmationForm(props) {
160
161
  ? 'Reenviando...'
161
162
  : resendCooldown > 0
162
163
  ? `Reenviar verificación (${formatCooldown(resendCooldown)})`
163
- : 'Reenviar verificación' }) })) : null, isSuccess && !canResendFromSignup && !canResendFromExpiredLink ? (_jsx(Stack, { sx: { mt: 1.5 }, children: _jsx(AuthPrimaryButton, { type: "button", onClick: onGoToSignIn, children: `Ir a iniciar sesión${typeof signInRedirectCountdown === 'number' && signInRedirectCountdown > 0
164
+ : 'Reenviar verificación' }) })) : null, isSuccess && !canResendFromSignup && !canResendFromExpiredLink ? (_jsx(Stack, { sx: { mt: 1.5 }, children: _jsx(AuthPrimaryButton, { type: "button", startIcon: _jsx(EmailOutlinedIcon, { fontSize: "small" }), onClick: onGoToSignIn, children: `Ir a iniciar sesión${typeof signInRedirectCountdown === 'number' && signInRedirectCountdown > 0
164
165
  ? ` (${signInRedirectCountdown}s)`
165
166
  : ''}` }) })) : null] }));
166
167
  }
@@ -5,7 +5,11 @@ export type AuthForgotPasswordFormProps = {
5
5
  defaultValues?: Partial<AuthForgotPasswordFormValues>;
6
6
  loading?: boolean;
7
7
  submitLabel?: string;
8
+ resendLabel?: string;
8
9
  successMessage?: string;
10
+ notSentMessage?: string;
11
+ resendCooldownSeconds?: number;
12
+ onEmailSentSuccess?: () => void;
9
13
  onSubmit: (values: AuthForgotPasswordFormValues) => unknown | Promise<unknown>;
10
14
  };
11
15
  export declare function AuthForgotPasswordForm(props: AuthForgotPasswordFormProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"AuthForgotPasswordForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/password/AuthForgotPasswordForm.tsx"],"names":[],"mappings":"AAWA,MAAM,MAAM,4BAA4B,GAAG;IACzC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,CAAC,MAAM,EAAE,4BAA4B,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChF,CAAC;AAMF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,2CAkHxE"}
1
+ {"version":3,"file":"AuthForgotPasswordForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/password/AuthForgotPasswordForm.tsx"],"names":[],"mappings":"AAYA,MAAM,MAAM,4BAA4B,GAAG;IACzC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,QAAQ,EAAE,CAAC,MAAM,EAAE,4BAA4B,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChF,CAAC;AAgBF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,2CA+JxE"}
@@ -1,19 +1,31 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { zodResolver } from '@hookform/resolvers/zod';
3
+ import LinkOutlinedIcon from '@mui/icons-material/LinkOutlined';
3
4
  import Alert from '@mui/material/Alert';
4
- import Button from '@mui/material/Button';
5
5
  import _ from 'lodash';
6
6
  import { useEffect, useState } from 'react';
7
7
  import { useForm } from 'react-hook-form';
8
8
  import { z } from 'zod';
9
9
  import { JBTextField } from '../../../forms';
10
+ import { AuthPrimaryButton } from '../../ui';
10
11
  import { parseAuthError } from '../errorParser';
12
+ function getEmailSentFlag(response) {
13
+ if (!response || typeof response !== 'object') {
14
+ return undefined;
15
+ }
16
+ const data = response;
17
+ const emailSent = data.emailSent ?? data.email_sent;
18
+ return typeof emailSent === 'boolean' ? emailSent : undefined;
19
+ }
11
20
  const forgotSchema = z.object({
12
21
  email: z.string().email('Debes ingresar un correo válido').nonempty('Debes ingresar un correo')
13
22
  });
14
23
  export function AuthForgotPasswordForm(props) {
15
- const { defaultValues, loading = false, submitLabel = 'Enviar enlace de recuperación', successMessage = 'Si la cuenta existe, enviamos un enlace de recuperación a tu correo.', onSubmit } = props;
24
+ const { defaultValues, loading = false, submitLabel = 'Enviar enlace de recuperación', resendLabel = 'Reenviar enlace de recuperación', successMessage = 'Si la cuenta existe, enviamos un enlace de recuperación a tu correo.', notSentMessage = 'Solicitud recibida, pero no se pudo enviar el correo de recuperación.', resendCooldownSeconds = 30, onEmailSentSuccess, onSubmit } = props;
16
25
  const [success, setSuccess] = useState(null);
26
+ const [successSeverity, setSuccessSeverity] = useState('success');
27
+ const [isEmailSentSuccessfully, setIsEmailSentSuccessfully] = useState(false);
28
+ const [resendSecondsLeft, setResendSecondsLeft] = useState(0);
17
29
  const { control, formState, handleSubmit, setError, clearErrors, watch } = useForm({
18
30
  mode: 'onChange',
19
31
  defaultValues: {
@@ -22,6 +34,25 @@ export function AuthForgotPasswordForm(props) {
22
34
  resolver: zodResolver(forgotSchema)
23
35
  });
24
36
  const { errors, dirtyFields, isSubmitting, isValid } = formState;
37
+ const emailValue = watch('email');
38
+ const isResendCooldownActive = isEmailSentSuccessfully && resendSecondsLeft > 0;
39
+ useEffect(() => {
40
+ if (!isResendCooldownActive) {
41
+ return;
42
+ }
43
+ const timer = window.setInterval(() => {
44
+ setResendSecondsLeft((current) => {
45
+ if (current <= 1) {
46
+ window.clearInterval(timer);
47
+ return 0;
48
+ }
49
+ return current - 1;
50
+ });
51
+ }, 1000);
52
+ return () => {
53
+ window.clearInterval(timer);
54
+ };
55
+ }, [isResendCooldownActive]);
25
56
  useEffect(() => {
26
57
  const subscription = watch((_value, { name }) => {
27
58
  if (name) {
@@ -36,8 +67,15 @@ export function AuthForgotPasswordForm(props) {
36
67
  async function onSubmitForm(values) {
37
68
  try {
38
69
  setSuccess(null);
39
- await onSubmit(values);
40
- setSuccess(successMessage);
70
+ const response = await onSubmit(values);
71
+ const emailSent = getEmailSentFlag(response);
72
+ setSuccessSeverity(emailSent === false ? 'warning' : 'success');
73
+ setSuccess(emailSent === false ? notSentMessage : successMessage);
74
+ setIsEmailSentSuccessfully(emailSent === true);
75
+ if (emailSent === true) {
76
+ setResendSecondsLeft(resendCooldownSeconds);
77
+ onEmailSentSuccess?.();
78
+ }
41
79
  }
42
80
  catch (error) {
43
81
  const parsed = parseAuthError(error);
@@ -67,5 +105,5 @@ export function AuthForgotPasswordForm(props) {
67
105
  });
68
106
  }
69
107
  }
70
- return (_jsxs("form", { name: "forgotPasswordForm", noValidate: true, style: { display: 'flex', width: '100%', flexDirection: 'column', justifyContent: 'center', paddingTop: 4 }, onSubmit: handleSubmit(onSubmitForm), children: [_jsx(JBTextField, { control: control, name: "email", sx: { mb: 3 }, label: "Correo electr\u00F3nico", autoFocus: true, type: "email", variant: "outlined", required: true, fullWidth: true }), errors.root?.message && (_jsx(Alert, { sx: { mb: 2 }, severity: "error", children: errors.root.message })), success && (_jsx(Alert, { sx: { mb: 2 }, severity: "success", children: success })), _jsx(Button, { variant: "contained", color: "secondary", sx: { width: '100%' }, "aria-label": submitLabel, type: "submit", size: "large", disabled: loading || isSubmitting || _.isEmpty(dirtyFields) || !isValid, children: submitLabel })] }));
108
+ return (_jsxs("form", { name: "forgotPasswordForm", noValidate: true, style: { display: 'flex', width: '100%', flexDirection: 'column', justifyContent: 'center', paddingTop: 4 }, onSubmit: handleSubmit(onSubmitForm), children: [!isEmailSentSuccessfully ? (_jsx(JBTextField, { control: control, name: "email", sx: { mb: 3 }, label: "Correo electr\u00F3nico", autoFocus: true, type: "email", variant: "outlined", required: true, fullWidth: true })) : null, errors.root?.message && (_jsx(Alert, { sx: { mb: 2 }, severity: "error", children: errors.root.message })), success && (_jsx(Alert, { sx: { mb: 2 }, severity: successSeverity, children: success })), !isEmailSentSuccessfully ? (_jsx(AuthPrimaryButton, { "aria-label": submitLabel, type: "submit", startIcon: _jsx(LinkOutlinedIcon, { fontSize: "small" }), disabled: loading || isSubmitting || _.isEmpty(dirtyFields) || !isValid, children: submitLabel })) : (_jsx(AuthPrimaryButton, { "aria-label": resendLabel, type: "submit", startIcon: _jsx(LinkOutlinedIcon, { fontSize: "small" }), disabled: loading || isSubmitting || isResendCooldownActive || !isValid || !emailValue?.trim(), children: isResendCooldownActive ? `${resendLabel} (${resendSecondsLeft}s)` : resendLabel }))] }));
71
109
  }
@@ -9,6 +9,8 @@ export type AuthPasswordResetConfirmFormProps = {
9
9
  loading?: boolean;
10
10
  submitLabel?: string;
11
11
  successMessage?: string;
12
+ successRedirectSeconds?: number;
13
+ onGoToSignIn?: () => void;
12
14
  onSubmit: (values: AuthPasswordResetConfirmFormValues) => unknown | Promise<unknown>;
13
15
  };
14
16
  export declare function AuthPasswordResetConfirmForm(props: AuthPasswordResetConfirmFormProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"AuthPasswordResetConfirmForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/password/AuthPasswordResetConfirmForm.tsx"],"names":[],"mappings":"AAWA,MAAM,MAAM,kCAAkC,GAAG;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,aAAa,CAAC,EAAE,OAAO,CAAC,kCAAkC,CAAC,CAAC;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,CAAC,MAAM,EAAE,kCAAkC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtF,CAAC;AAiBF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,iCAAiC,2CAuJpF"}
1
+ {"version":3,"file":"AuthPasswordResetConfirmForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/password/AuthPasswordResetConfirmForm.tsx"],"names":[],"mappings":"AAkBA,MAAM,MAAM,kCAAkC,GAAG;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,aAAa,CAAC,EAAE,OAAO,CAAC,kCAAkC,CAAC,CAAC;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,kCAAkC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtF,CAAC;AA8BF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,iCAAiC,2CA6OpF"}
@@ -1,21 +1,40 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { zodResolver } from '@hookform/resolvers/zod';
3
+ import ArrowBackOutlinedIcon from '@mui/icons-material/ArrowBackOutlined';
4
+ import LockResetOutlinedIcon from '@mui/icons-material/LockResetOutlined';
5
+ import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
6
+ import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
3
7
  import Alert from '@mui/material/Alert';
4
- import Button from '@mui/material/Button';
8
+ import IconButton from '@mui/material/IconButton';
9
+ import InputAdornment from '@mui/material/InputAdornment';
5
10
  import _ from 'lodash';
6
- import { useEffect } from 'react';
11
+ import { useEffect, useMemo, useState } from 'react';
7
12
  import { useForm } from 'react-hook-form';
8
13
  import { z } from 'zod';
9
14
  import { JBTextField } from '../../../forms';
15
+ import { AuthPrimaryButton, AuthSecondaryButton } from '../../ui';
10
16
  import { parseAuthError } from '../errorParser';
17
+ import { getDjangoLikePasswordError } from './passwordValidation';
11
18
  const resetSchema = z
12
19
  .object({
13
20
  uid: z.string().nonempty('El uid es obligatorio'),
14
21
  token: z.string().nonempty('El token es obligatorio'),
15
- newPassword: z
16
- .string()
17
- .nonempty('Debes ingresar tu nueva contraseña')
18
- .min(8, 'La contraseña es muy corta - mínimo 8 caracteres.'),
22
+ newPassword: z.string().superRefine((value, ctx) => {
23
+ if (!value) {
24
+ ctx.addIssue({
25
+ code: z.ZodIssueCode.custom,
26
+ message: 'Debes ingresar tu nueva contraseña'
27
+ });
28
+ return;
29
+ }
30
+ const passwordError = getDjangoLikePasswordError(value);
31
+ if (passwordError) {
32
+ ctx.addIssue({
33
+ code: z.ZodIssueCode.custom,
34
+ message: passwordError
35
+ });
36
+ }
37
+ }),
19
38
  newPasswordConfirm: z.string().nonempty('La confirmación de contraseña es obligatoria')
20
39
  })
21
40
  .refine((data) => data.newPassword === data.newPasswordConfirm, {
@@ -23,7 +42,10 @@ const resetSchema = z
23
42
  path: ['newPasswordConfirm']
24
43
  });
25
44
  export function AuthPasswordResetConfirmForm(props) {
26
- const { defaultValues, loading = false, submitLabel = 'Restablecer contraseña', successMessage = 'Contraseña restablecida correctamente. Ya puedes iniciar sesión.', onSubmit } = props;
45
+ const { defaultValues, loading = false, submitLabel = 'Restablecer contraseña', successMessage = 'Contraseña restablecida correctamente. Ya puedes iniciar sesión.', successRedirectSeconds = 5, onGoToSignIn, onSubmit } = props;
46
+ const [redirectSecondsLeft, setRedirectSecondsLeft] = useState(null);
47
+ const [showNewPassword, setShowNewPassword] = useState(false);
48
+ const [showNewPasswordConfirm, setShowNewPasswordConfirm] = useState(false);
27
49
  const { control, formState, handleSubmit, setError, clearErrors, watch } = useForm({
28
50
  mode: 'onChange',
29
51
  defaultValues: {
@@ -35,6 +57,18 @@ export function AuthPasswordResetConfirmForm(props) {
35
57
  resolver: zodResolver(resetSchema)
36
58
  });
37
59
  const { errors, dirtyFields, isSubmitting, isValid, isSubmitSuccessful } = formState;
60
+ const uidValue = watch('uid');
61
+ const tokenValue = watch('token');
62
+ const hasValidRecoveryLink = Boolean(uidValue?.trim() && tokenValue?.trim());
63
+ const goToSignInLabel = useMemo(() => {
64
+ if (!isSubmitSuccessful) {
65
+ return 'Ir a iniciar sesión';
66
+ }
67
+ if (!redirectSecondsLeft || redirectSecondsLeft <= 0) {
68
+ return 'Ir a iniciar sesión';
69
+ }
70
+ return `Ir a iniciar sesión (${redirectSecondsLeft}s)`;
71
+ }, [isSubmitSuccessful, redirectSecondsLeft]);
38
72
  useEffect(() => {
39
73
  const subscription = watch((_value, { name }) => {
40
74
  if (name) {
@@ -46,6 +80,26 @@ export function AuthPasswordResetConfirmForm(props) {
46
80
  subscription.unsubscribe();
47
81
  };
48
82
  }, [watch, clearErrors]);
83
+ useEffect(() => {
84
+ if (!isSubmitSuccessful || !onGoToSignIn) {
85
+ setRedirectSecondsLeft(null);
86
+ return;
87
+ }
88
+ setRedirectSecondsLeft(successRedirectSeconds);
89
+ const timer = window.setInterval(() => {
90
+ setRedirectSecondsLeft((current) => {
91
+ if (!current || current <= 1) {
92
+ window.clearInterval(timer);
93
+ onGoToSignIn();
94
+ return 0;
95
+ }
96
+ return current - 1;
97
+ });
98
+ }, 1000);
99
+ return () => {
100
+ window.clearInterval(timer);
101
+ };
102
+ }, [isSubmitSuccessful, onGoToSignIn, successRedirectSeconds]);
49
103
  async function onSubmitForm(values) {
50
104
  try {
51
105
  await onSubmit(values);
@@ -59,6 +113,13 @@ export function AuthPasswordResetConfirmForm(props) {
59
113
  'newPasswordConfirm'
60
114
  ];
61
115
  Object.entries(parsed.fieldErrors).forEach(([field, message]) => {
116
+ if (field === 'uid' || field === 'token') {
117
+ setError('root', {
118
+ type: 'manual',
119
+ message
120
+ });
121
+ return;
122
+ }
62
123
  if (allowedFields.includes(field)) {
63
124
  setError(field, {
64
125
  type: 'manual',
@@ -78,11 +139,25 @@ export function AuthPasswordResetConfirmForm(props) {
78
139
  });
79
140
  return;
80
141
  }
142
+ if (Object.keys(parsed.fieldErrors).length > 0) {
143
+ const firstFieldError = Object.values(parsed.fieldErrors)[0];
144
+ if (firstFieldError) {
145
+ setError('root', {
146
+ type: 'manual',
147
+ message: firstFieldError
148
+ });
149
+ return;
150
+ }
151
+ }
81
152
  setError('root', {
82
153
  type: 'manual',
83
154
  message: 'No se pudo restablecer la contraseña. Inténtalo de nuevo.'
84
155
  });
85
156
  }
86
157
  }
87
- return (_jsxs("form", { name: "resetPasswordForm", noValidate: true, style: { display: 'flex', width: '100%', flexDirection: 'column', justifyContent: 'center', paddingTop: 4 }, onSubmit: handleSubmit(onSubmitForm), children: [_jsx(JBTextField, { control: control, name: "uid", sx: { mb: 3 }, label: "UID", type: "text", variant: "outlined", required: true, fullWidth: true }), _jsx(JBTextField, { control: control, name: "token", sx: { mb: 3 }, label: "Token", type: "text", variant: "outlined", required: true, fullWidth: true }), _jsx(JBTextField, { control: control, name: "newPassword", sx: { mb: 3 }, label: "Nueva contrase\u00F1a", type: "password", variant: "outlined", required: true, fullWidth: true }), _jsx(JBTextField, { control: control, name: "newPasswordConfirm", sx: { mb: 3 }, label: "Confirmar nueva contrase\u00F1a", type: "password", variant: "outlined", required: true, fullWidth: true }), errors.root?.message && (_jsx(Alert, { sx: { mb: 2 }, severity: "error", children: errors.root.message })), isSubmitSuccessful && (_jsx(Alert, { sx: { mb: 2 }, severity: "success", children: successMessage })), _jsx(Button, { variant: "contained", color: "secondary", sx: { width: '100%' }, "aria-label": submitLabel, disabled: loading || isSubmitting || _.isEmpty(dirtyFields) || !isValid, type: "submit", size: "large", children: submitLabel })] }));
158
+ return (_jsxs("form", { name: "resetPasswordForm", noValidate: true, style: { display: 'flex', width: '100%', flexDirection: 'column', justifyContent: 'center', paddingTop: 4 }, onSubmit: handleSubmit(onSubmitForm), children: [!isSubmitSuccessful && !hasValidRecoveryLink ? (_jsx(Alert, { sx: { mb: 3 }, severity: "warning", children: "El enlace de recuperaci\u00F3n es inv\u00E1lido o incompleto." })) : null, !isSubmitSuccessful ? (_jsxs(_Fragment, { children: [_jsx(JBTextField, { control: control, name: "newPassword", sx: { mb: 3 }, label: "Nueva contrase\u00F1a", type: showNewPassword ? 'text' : 'password', InputProps: {
159
+ endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { edge: "end", "aria-label": showNewPassword ? 'Ocultar contraseña' : 'Mostrar contraseña', onClick: () => setShowNewPassword((prev) => !prev), children: showNewPassword ? _jsx(VisibilityOffOutlinedIcon, {}) : _jsx(VisibilityOutlinedIcon, {}) }) }))
160
+ }, variant: "outlined", required: true, fullWidth: true }), _jsx(JBTextField, { control: control, name: "newPasswordConfirm", sx: { mb: 3 }, label: "Confirmar nueva contrase\u00F1a", type: showNewPasswordConfirm ? 'text' : 'password', InputProps: {
161
+ endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { edge: "end", "aria-label": showNewPasswordConfirm ? 'Ocultar confirmación de contraseña' : 'Mostrar confirmación de contraseña', onClick: () => setShowNewPasswordConfirm((prev) => !prev), children: showNewPasswordConfirm ? _jsx(VisibilityOffOutlinedIcon, {}) : _jsx(VisibilityOutlinedIcon, {}) }) }))
162
+ }, variant: "outlined", required: true, fullWidth: true })] })) : null, errors.root?.message && (_jsx(Alert, { sx: { mb: 2 }, severity: "error", children: errors.root.message })), isSubmitSuccessful && (_jsx(Alert, { sx: { mb: 2 }, severity: "success", children: successMessage })), !isSubmitSuccessful ? (_jsx(AuthPrimaryButton, { "aria-label": submitLabel, startIcon: _jsx(LockResetOutlinedIcon, { fontSize: "small" }), disabled: loading || isSubmitting || _.isEmpty(dirtyFields) || !isValid || !hasValidRecoveryLink, type: "submit", size: "large", children: submitLabel })) : null, isSubmitSuccessful && onGoToSignIn ? (_jsx(AuthSecondaryButton, { sx: { mt: 2 }, startIcon: _jsx(ArrowBackOutlinedIcon, { fontSize: "small" }), onClick: onGoToSignIn, children: goToSignInLabel })) : null] }));
88
163
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AuthResetPasswordForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/password/AuthResetPasswordForm.tsx"],"names":[],"mappings":"AAKA,MAAM,MAAM,2BAA2B,GAAG;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,CAAC,MAAM,EAAE,2BAA2B,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzE,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,2CA4CtE"}
1
+ {"version":3,"file":"AuthResetPasswordForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/password/AuthResetPasswordForm.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,2BAA2B,GAAG;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,CAAC,MAAM,EAAE,2BAA2B,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzE,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,2CA+CtE"}
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button, Stack } from '@mui/material';
3
3
  import { useForm } from 'react-hook-form';
4
4
  import { JBTextField } from '../../../forms';
5
+ import { getDjangoLikePasswordError } from './passwordValidation';
5
6
  export function AuthResetPasswordForm(props) {
6
7
  const { defaultValues, loading = false, submitLabel = 'Restablecer contraseña', onSubmit } = props;
7
8
  const { control, handleSubmit, watch } = useForm({
@@ -11,7 +12,10 @@ export function AuthResetPasswordForm(props) {
11
12
  }
12
13
  });
13
14
  const newPasswordValue = watch('newPassword');
14
- return (_jsx("form", { style: { paddingTop: 4 }, onSubmit: handleSubmit((values) => onSubmit(values)), children: _jsxs(Stack, { spacing: 2, children: [_jsx(JBTextField, { control: control, name: "newPassword", label: "Nueva contrase\u00F1a", type: "password", fullWidth: true, rules: { required: 'El password es requerido' } }), _jsx(JBTextField, { control: control, name: "confirmPassword", label: "Confirmar contrase\u00F1a", type: "password", fullWidth: true, rules: {
15
+ return (_jsx("form", { style: { paddingTop: 4 }, onSubmit: handleSubmit((values) => onSubmit(values)), children: _jsxs(Stack, { spacing: 2, children: [_jsx(JBTextField, { control: control, name: "newPassword", label: "Nueva contrase\u00F1a", type: "password", fullWidth: true, rules: {
16
+ required: 'El password es requerido',
17
+ validate: (value) => getDjangoLikePasswordError(value) ?? true
18
+ } }), _jsx(JBTextField, { control: control, name: "confirmPassword", label: "Confirmar contrase\u00F1a", type: "password", fullWidth: true, rules: {
15
19
  required: 'La confirmacion es requerida',
16
20
  validate: (value) => value === newPasswordValue || 'Las contraseñas no coinciden'
17
21
  } }), _jsx(Button, { variant: "contained", type: "submit", disabled: loading, children: submitLabel })] }) }));
@@ -0,0 +1,3 @@
1
+ export declare function getDjangoLikePasswordError(password: string): string | null;
2
+ export declare function isPasswordTooSimilar(password: string, candidates: Array<string | undefined | null>): boolean;
3
+ //# sourceMappingURL=passwordValidation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passwordValidation.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/password/passwordValidation.ts"],"names":[],"mappings":"AAqBA,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe1E;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,CAa5G"}
@@ -0,0 +1,45 @@
1
+ const COMMON_PASSWORDS = new Set([
2
+ '12345678',
3
+ '123456789',
4
+ 'password',
5
+ 'password123',
6
+ 'qwerty123',
7
+ 'abc12345',
8
+ 'letmein123',
9
+ 'admin1234',
10
+ 'welcome123',
11
+ 'iloveyou123'
12
+ ]);
13
+ function normalize(value) {
14
+ return value
15
+ .normalize('NFD')
16
+ .replace(/[\u0300-\u036f]/g, '')
17
+ .toLowerCase()
18
+ .trim();
19
+ }
20
+ export function getDjangoLikePasswordError(password) {
21
+ if (!password || password.length < 8) {
22
+ return 'La contraseña debe tener al menos 8 caracteres.';
23
+ }
24
+ if (/^\d+$/.test(password)) {
25
+ return 'La contraseña no puede ser completamente numérica.';
26
+ }
27
+ const normalized = normalize(password);
28
+ if (COMMON_PASSWORDS.has(normalized)) {
29
+ return 'La contraseña es demasiado común.';
30
+ }
31
+ return null;
32
+ }
33
+ export function isPasswordTooSimilar(password, candidates) {
34
+ const normalizedPassword = normalize(password);
35
+ if (!normalizedPassword) {
36
+ return false;
37
+ }
38
+ return candidates.some((candidate) => {
39
+ const normalizedCandidate = normalize(candidate ?? '');
40
+ if (normalizedCandidate.length < 3) {
41
+ return false;
42
+ }
43
+ return normalizedPassword.includes(normalizedCandidate);
44
+ });
45
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"AuthOtpSignInForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/sign-in/AuthOtpSignInForm.tsx"],"names":[],"mappings":"AAYA,OAAO,EAA8B,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAK1E,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACjD,kBAAkB,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACzD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxE,WAAW,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpG,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B,CAAC;AAQF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,2CAsX9D"}
1
+ {"version":3,"file":"AuthOtpSignInForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/sign-in/AuthOtpSignInForm.tsx"],"names":[],"mappings":"AAaA,OAAO,EAA8B,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAK1E,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACjD,kBAAkB,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACzD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxE,WAAW,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpG,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B,CAAC;AAQF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,2CAuX9D"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { zodResolver } from '@hookform/resolvers/zod';
3
+ import ArrowBackOutlinedIcon from '@mui/icons-material/ArrowBackOutlined';
3
4
  import Alert from '@mui/material/Alert';
4
5
  import Dialog from '@mui/material/Dialog';
5
6
  import DialogActions from '@mui/material/DialogActions';
@@ -213,7 +214,7 @@ export function AuthOtpSignInForm(props) {
213
214
  setIsConfirmDialogOpen(false);
214
215
  setShouldSelectRoleOnVerify(false);
215
216
  }
216
- return (_jsxs(_Fragment, { children: [_jsxs("form", { name: "loginFormOtp", noValidate: true, style: { display: 'flex', width: '100%', flexDirection: 'column', justifyContent: 'center', paddingTop: 4 }, onSubmit: handleSubmit(onSubmit), children: [_jsxs(Stack, { direction: "row", spacing: 2, sx: { mb: 3 }, children: [_jsx(JBSelectField, { control: control, name: "countryCode", label: "Lada", variant: "outlined", sx: { width: 184 }, options: resolvedCountryCodeOptions, required: true, disabled: otpRequested }), _jsx(JBTextField, { control: control, name: "phone", label: "Tel\u00E9fono", autoFocus: true, type: "tel", variant: "outlined", required: true, fullWidth: true, disabled: otpRequested })] }), otpRequested ? (_jsx(JBTextField, { control: control, name: "code", sx: { mb: 3 }, label: "C\u00F3digo OTP", type: "text", variant: "outlined", required: true, fullWidth: true })) : null, infoMessage ? (_jsx(Alert, { sx: { mb: 2 }, severity: "info", children: infoMessage })) : null, errors.root?.message ? (_jsx(Alert, { sx: { mb: 2 }, severity: "error", children: errors.root.message })) : null, !otpRequested ? (_jsx(AuthPrimaryButton, { sx: { mt: 2 }, "aria-label": "Solicitar c\u00F3digo OTP", disabled: isRequestOtpButtonDisabled, loading: isLoading, loadingLabel: "Solicitando OTP...", type: "submit", size: "large", children: "Solicitar OTP" })) : null, otpRequested ? (_jsxs(_Fragment, { children: [_jsx(AuthPrimaryButton, { sx: { mt: 2 }, "aria-label": "Verificar c\u00F3digo OTP", disabled: isVerifyButtonDisabled, loading: isLoading, loadingLabel: "Verificando OTP...", type: "submit", size: "large", children: "Verificar OTP" }), _jsx(AuthSecondaryButton, { sx: { mt: 2 }, type: "button", onClick: onChangePhoneNumber, children: "Cambiar n\u00FAmero" })] })) : null, _jsx(AuthSecondaryButton, { sx: { mt: 2 }, type: "button", onClick: onBackToPassword, children: "Usar contrase\u00F1a" })] }), _jsxs(Dialog, { open: isConfirmDialogOpen, onClose: () => {
217
+ return (_jsxs(_Fragment, { children: [_jsxs("form", { name: "loginFormOtp", noValidate: true, style: { display: 'flex', width: '100%', flexDirection: 'column', justifyContent: 'center', paddingTop: 4 }, onSubmit: handleSubmit(onSubmit), children: [_jsxs(Stack, { direction: "row", spacing: 2, sx: { mb: 3 }, children: [_jsx(JBSelectField, { control: control, name: "countryCode", label: "Lada", variant: "outlined", sx: { width: 184 }, options: resolvedCountryCodeOptions, required: true, disabled: otpRequested }), _jsx(JBTextField, { control: control, name: "phone", label: "Tel\u00E9fono", autoFocus: true, type: "tel", variant: "outlined", required: true, fullWidth: true, disabled: otpRequested })] }), otpRequested ? (_jsx(JBTextField, { control: control, name: "code", sx: { mb: 3 }, label: "C\u00F3digo OTP", type: "text", variant: "outlined", required: true, fullWidth: true })) : null, infoMessage ? (_jsx(Alert, { sx: { mb: 2 }, severity: "info", children: infoMessage })) : null, errors.root?.message ? (_jsx(Alert, { sx: { mb: 2 }, severity: "error", children: errors.root.message })) : null, !otpRequested ? (_jsx(AuthPrimaryButton, { sx: { mt: 2 }, "aria-label": "Solicitar c\u00F3digo OTP", disabled: isRequestOtpButtonDisabled, loading: isLoading, loadingLabel: "Solicitando OTP...", type: "submit", size: "large", children: "Solicitar OTP" })) : null, otpRequested ? (_jsxs(_Fragment, { children: [_jsx(AuthPrimaryButton, { sx: { mt: 2 }, "aria-label": "Verificar c\u00F3digo OTP", disabled: isVerifyButtonDisabled, loading: isLoading, loadingLabel: "Verificando OTP...", type: "submit", size: "large", children: "Verificar OTP" }), _jsx(AuthSecondaryButton, { sx: { mt: 2 }, type: "button", onClick: onChangePhoneNumber, children: "Cambiar n\u00FAmero" })] })) : null, _jsx(AuthSecondaryButton, { sx: { mt: 2 }, type: "button", startIcon: _jsx(ArrowBackOutlinedIcon, { fontSize: "small" }), onClick: onBackToPassword, children: "Regresar a iniciar sesi\u00F3n" })] }), _jsxs(Dialog, { open: isConfirmDialogOpen, onClose: () => {
217
218
  setIsConfirmDialogOpen(false);
218
219
  }, fullWidth: true, maxWidth: "xs", children: [_jsx(DialogTitle, { children: "Confirmar n\u00FAmero" }), _jsx(DialogContent, { children: _jsx(DialogContentText, { children: `¿Es correcto este número? ${pendingOtpRequestValues
219
220
  ? `${pendingOtpRequestValues.countryCode}${pendingOtpRequestValues.phone}`.replace(/\s+/g, '')
@@ -7,6 +7,7 @@ export type AuthPasswordSignInFormValues = {
7
7
  export type AuthPasswordSignInFormProps = {
8
8
  defaultValues?: Partial<AuthPasswordSignInFormValues>;
9
9
  loading?: boolean;
10
+ disabled?: boolean;
10
11
  submitLabel?: string;
11
12
  forgotPasswordPath?: string;
12
13
  rememberLabel?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"AuthPasswordSignInForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/sign-in/AuthPasswordSignInForm.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,MAAM,MAAM,4BAA4B,GAAG;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,QAAQ,EAAE,CAAC,MAAM,EAAE,4BAA4B,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChF,CAAC;AAWF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,2CAkMxE"}
1
+ {"version":3,"file":"AuthPasswordSignInForm.d.ts","sourceRoot":"","sources":["../../../../src/auth/forms/sign-in/AuthPasswordSignInForm.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAKlD,MAAM,MAAM,4BAA4B,GAAG;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,QAAQ,EAAE,CAAC,MAAM,EAAE,4BAA4B,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChF,CAAC;AAwBF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,2CA0OxE"}
@@ -1,23 +1,41 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { zodResolver } from '@hookform/resolvers/zod';
3
+ import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined';
4
+ import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
5
+ import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
3
6
  import Alert from '@mui/material/Alert';
4
7
  import Box from '@mui/material/Box';
5
- import { useEffect } from 'react';
8
+ import IconButton from '@mui/material/IconButton';
9
+ import InputAdornment from '@mui/material/InputAdornment';
10
+ import { useEffect, useState } from 'react';
6
11
  import { useForm } from 'react-hook-form';
7
12
  import { z } from 'zod';
8
13
  import { JBCheckboxField, JBTextField } from '../../../forms';
9
14
  import { AuthPrimaryButton, AuthSecondaryButton } from '../../ui';
15
+ import { getDjangoLikePasswordError } from '../password/passwordValidation';
10
16
  import { parseAuthError } from '../errorParser';
11
17
  const signInSchema = z.object({
12
18
  login: z.string().nonempty('Debes ingresar tu usuario o correo'),
13
- password: z
14
- .string()
15
- .min(4, 'La contraseña es muy corta - mínimo 4 caracteres.')
16
- .nonempty('Debes ingresar tu contraseña.'),
19
+ password: z.string().superRefine((value, ctx) => {
20
+ if (!value) {
21
+ ctx.addIssue({
22
+ code: z.ZodIssueCode.custom,
23
+ message: 'Debes ingresar tu contraseña.'
24
+ });
25
+ return;
26
+ }
27
+ const passwordError = getDjangoLikePasswordError(value);
28
+ if (passwordError) {
29
+ ctx.addIssue({
30
+ code: z.ZodIssueCode.custom,
31
+ message: passwordError
32
+ });
33
+ }
34
+ }),
17
35
  remember: z.boolean().optional()
18
36
  });
19
37
  export function AuthPasswordSignInForm(props) {
20
- const { defaultValues, loading = false, submitLabel = 'Iniciar sesión', forgotPasswordPath = '/forgot-password', rememberLabel = 'Recuérdame', loginLabel = 'Usuario o correo', passwordLabel = 'Contraseña', accountConfirmationPath = '/verify-email', verifyAccountLabel = 'Ir a verificar cuenta', LinkComponent, onSubmit } = props;
38
+ const { defaultValues, loading = false, disabled = false, submitLabel = 'Iniciar sesión', forgotPasswordPath = '/forgot-password', rememberLabel = 'Recuérdame', loginLabel = 'Usuario o correo', passwordLabel = 'Contraseña', accountConfirmationPath = '/verify-email', verifyAccountLabel = 'Ir a verificar cuenta', LinkComponent, onSubmit } = props;
21
39
  const { control, formState, handleSubmit, setError, clearErrors, watch } = useForm({
22
40
  mode: 'onChange',
23
41
  defaultValues: {
@@ -31,6 +49,7 @@ export function AuthPasswordSignInForm(props) {
31
49
  const loginValue = watch('login');
32
50
  const passwordValue = watch('password');
33
51
  const isLoading = loading || isSubmitting;
52
+ const [showPassword, setShowPassword] = useState(false);
34
53
  useEffect(() => {
35
54
  const subscription = watch((_value, { name }) => {
36
55
  if (name) {
@@ -96,7 +115,9 @@ export function AuthPasswordSignInForm(props) {
96
115
  });
97
116
  }
98
117
  }
99
- return (_jsxs("form", { name: "loginForm", noValidate: true, style: { display: 'flex', width: '100%', flexDirection: 'column', justifyContent: 'center', paddingTop: 4 }, onSubmit: handleSubmit(onSubmitForm), children: [_jsx(JBTextField, { control: control, name: "login", sx: { mb: 3 }, label: loginLabel, autoFocus: true, type: "text", variant: "outlined", required: true, fullWidth: true }), _jsx(JBTextField, { control: control, name: "password", sx: { mb: 3 }, label: passwordLabel, type: "password", variant: "outlined", required: true, fullWidth: true }), _jsxs(Box, { sx: {
118
+ return (_jsxs("form", { name: "loginForm", noValidate: true, style: { display: 'flex', width: '100%', flexDirection: 'column', justifyContent: 'center', paddingTop: 4 }, onSubmit: handleSubmit(onSubmitForm), children: [_jsx(JBTextField, { control: control, name: "login", sx: { mb: 3 }, label: loginLabel, autoFocus: true, type: "text", variant: "outlined", required: true, fullWidth: true, disabled: disabled }), _jsx(JBTextField, { control: control, name: "password", sx: { mb: 3 }, label: passwordLabel, type: showPassword ? 'text' : 'password', InputProps: {
119
+ endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { edge: "end", "aria-label": showPassword ? 'Ocultar contraseña' : 'Mostrar contraseña', onClick: () => setShowPassword((prev) => !prev), children: showPassword ? _jsx(VisibilityOffOutlinedIcon, {}) : _jsx(VisibilityOutlinedIcon, {}) }) }))
120
+ }, variant: "outlined", required: true, fullWidth: true, disabled: disabled }), _jsxs(Box, { sx: {
100
121
  display: 'flex',
101
122
  flexDirection: { xs: 'column', sm: 'row' },
102
123
  alignItems: 'center',
@@ -116,5 +137,12 @@ export function AuthPasswordSignInForm(props) {
116
137
  '&.Mui-checked .MuiSvgIcon-root': {
117
138
  color: 'secondary.main'
118
139
  }
119
- } }), LinkComponent ? _jsx(LinkComponent, { to: forgotPasswordPath, children: "\u00BFOlvidaste tu contrase\u00F1a?" }) : null] }), _jsx(AuthPrimaryButton, { sx: { mt: 2 }, "aria-label": submitLabel, disabled: isLoading || !loginValue?.trim() || !passwordValue, loading: isLoading, loadingLabel: "Iniciando sesi\u00F3n...", type: "submit", size: "large", children: submitLabel }), LinkComponent && shouldShowVerifyAccountCta(errors.root?.message) ? (_jsx(AuthSecondaryButton, { sx: { mt: 1.5 }, component: LinkComponent, to: getAccountConfirmationTo(), children: verifyAccountLabel })) : null, errors.root?.message && (_jsx(Alert, { sx: { mt: 2 }, severity: "error", children: errors.root.message }))] }));
140
+ }, disabled: disabled }), LinkComponent ? (disabled ? (_jsx(Box, { component: 'span', sx: { color: 'text.disabled' }, children: "\u00BFOlvidaste tu contrase\u00F1a?" })) : (_jsx(Box, { component: LinkComponent, to: forgotPasswordPath, sx: {
141
+ color: 'primary.main',
142
+ fontWeight: 500,
143
+ textDecoration: 'none',
144
+ '&:hover': {
145
+ textDecoration: 'underline'
146
+ }
147
+ }, children: "\u00BFOlvidaste tu contrase\u00F1a?" }))) : null] }), _jsx(AuthPrimaryButton, { sx: { mt: 2 }, "aria-label": submitLabel, disabled: disabled || isLoading || !loginValue?.trim() || !passwordValue, loading: isLoading, loadingLabel: "Iniciando sesi\u00F3n...", startIcon: _jsx(EmailOutlinedIcon, { fontSize: "small" }), type: "submit", size: "large", children: submitLabel }), LinkComponent && shouldShowVerifyAccountCta(errors.root?.message) ? (_jsx(AuthSecondaryButton, { sx: { mt: 1.5 }, component: LinkComponent, to: getAccountConfirmationTo(), children: verifyAccountLabel })) : null, errors.root?.message && (_jsx(Alert, { sx: { mt: 2 }, severity: "error", children: errors.root.message }))] }));
120
148
  }