valtech-components 2.0.558 → 2.0.559
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/esm2022/lib/components/organisms/login/login.component.mjs +353 -306
- package/esm2022/lib/services/i18n/default-content.mjs +165 -1
- package/esm2022/lib/services/i18n/index.mjs +3 -1
- package/esm2022/lib/services/i18n/input-i18n.helper.mjs +93 -0
- package/fesm2022/valtech-components.mjs +606 -306
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/atoms/rights-footer/rights-footer.component.d.ts +1 -1
- package/lib/components/atoms/text/text.component.d.ts +1 -1
- package/lib/components/organisms/article/article.component.d.ts +3 -3
- package/lib/components/organisms/login/login.component.d.ts +32 -17
- package/lib/services/i18n/index.d.ts +1 -0
- package/lib/services/i18n/input-i18n.helper.d.ts +69 -0
- package/package.json +1 -1
|
@@ -3319,6 +3319,96 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
3319
3319
|
args: [{ providedIn: 'root' }]
|
|
3320
3320
|
}], ctorParameters: () => [] });
|
|
3321
3321
|
|
|
3322
|
+
/**
|
|
3323
|
+
* Helper para resolver traducciones i18n en InputMetadata y FormMetadata.
|
|
3324
|
+
*
|
|
3325
|
+
* @example
|
|
3326
|
+
* ```typescript
|
|
3327
|
+
* helper = inject(InputI18nHelper);
|
|
3328
|
+
*
|
|
3329
|
+
* // Resolver un input
|
|
3330
|
+
* emailInput = this.helper.resolveInput({
|
|
3331
|
+
* ...baseEmailInput,
|
|
3332
|
+
* labelKey: 'email',
|
|
3333
|
+
* placeholderKey: 'emailPlaceholder',
|
|
3334
|
+
* errorKeys: { required: 'emailRequired', email: 'emailInvalid' },
|
|
3335
|
+
* i18nNamespace: '_auth',
|
|
3336
|
+
* });
|
|
3337
|
+
*
|
|
3338
|
+
* // Resolver un form completo
|
|
3339
|
+
* loginForm = this.helper.resolveForm(loginFormConfig);
|
|
3340
|
+
* ```
|
|
3341
|
+
*/
|
|
3342
|
+
class InputI18nHelper {
|
|
3343
|
+
constructor() {
|
|
3344
|
+
this.i18n = inject(I18nService);
|
|
3345
|
+
}
|
|
3346
|
+
/**
|
|
3347
|
+
* Resuelve traducciones para un InputMetadata.
|
|
3348
|
+
* Si hay keys de i18n, las resuelve; sino, usa los valores directos.
|
|
3349
|
+
*/
|
|
3350
|
+
resolveInput(input) {
|
|
3351
|
+
const namespace = input.i18nNamespace || '_global';
|
|
3352
|
+
return {
|
|
3353
|
+
...input,
|
|
3354
|
+
label: input.labelKey
|
|
3355
|
+
? this.i18n.t(input.labelKey, namespace)
|
|
3356
|
+
: input.label || '',
|
|
3357
|
+
placeholder: input.placeholderKey
|
|
3358
|
+
? this.i18n.t(input.placeholderKey, namespace)
|
|
3359
|
+
: input.placeholder || '',
|
|
3360
|
+
hint: input.hintKey ? this.i18n.t(input.hintKey, namespace) : input.hint || '',
|
|
3361
|
+
errors: input.errorKeys
|
|
3362
|
+
? this.resolveErrors(input.errorKeys, namespace)
|
|
3363
|
+
: input.errors || {},
|
|
3364
|
+
};
|
|
3365
|
+
}
|
|
3366
|
+
/**
|
|
3367
|
+
* Resuelve traducciones para un FormMetadata completo.
|
|
3368
|
+
*/
|
|
3369
|
+
resolveForm(form) {
|
|
3370
|
+
const namespace = form.i18nNamespace || '_global';
|
|
3371
|
+
return {
|
|
3372
|
+
...form,
|
|
3373
|
+
name: form.nameKey ? this.i18n.t(form.nameKey, namespace) : form.name || '',
|
|
3374
|
+
sections: form.sections.map((section) => ({
|
|
3375
|
+
...section,
|
|
3376
|
+
name: section.nameKey
|
|
3377
|
+
? this.i18n.t(section.nameKey, namespace)
|
|
3378
|
+
: section.name || '',
|
|
3379
|
+
fields: section.fields.map((field) => this.resolveInput({ ...field, i18nNamespace: namespace })),
|
|
3380
|
+
})),
|
|
3381
|
+
actions: this.resolveButton(form.actions, namespace),
|
|
3382
|
+
};
|
|
3383
|
+
}
|
|
3384
|
+
/**
|
|
3385
|
+
* Resuelve traducciones para un ButtonMetadata.
|
|
3386
|
+
*/
|
|
3387
|
+
resolveButton(button, namespace) {
|
|
3388
|
+
const ns = namespace || button.i18nNamespace || '_global';
|
|
3389
|
+
return {
|
|
3390
|
+
...button,
|
|
3391
|
+
text: button.textKey ? this.i18n.t(button.textKey, ns) : button.text,
|
|
3392
|
+
};
|
|
3393
|
+
}
|
|
3394
|
+
/**
|
|
3395
|
+
* Resuelve un mapa de error keys a mensajes traducidos.
|
|
3396
|
+
*/
|
|
3397
|
+
resolveErrors(errorKeys, namespace) {
|
|
3398
|
+
const resolved = {};
|
|
3399
|
+
for (const [validatorKey, i18nKey] of Object.entries(errorKeys)) {
|
|
3400
|
+
resolved[validatorKey] = this.i18n.t(i18nKey, namespace);
|
|
3401
|
+
}
|
|
3402
|
+
return resolved;
|
|
3403
|
+
}
|
|
3404
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InputI18nHelper, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3405
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InputI18nHelper, providedIn: 'root' }); }
|
|
3406
|
+
}
|
|
3407
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InputI18nHelper, decorators: [{
|
|
3408
|
+
type: Injectable,
|
|
3409
|
+
args: [{ providedIn: 'root' }]
|
|
3410
|
+
}] });
|
|
3411
|
+
|
|
3322
3412
|
/**
|
|
3323
3413
|
* Pipe de traducción para templates.
|
|
3324
3414
|
*
|
|
@@ -3677,6 +3767,170 @@ const VALTECH_DEFAULT_CONTENT = {
|
|
|
3677
3767
|
paymentFailed: 'Failed',
|
|
3678
3768
|
},
|
|
3679
3769
|
},
|
|
3770
|
+
_auth: {
|
|
3771
|
+
es: {
|
|
3772
|
+
// Login
|
|
3773
|
+
loginTitle: 'Iniciar sesión',
|
|
3774
|
+
email: 'Correo electrónico',
|
|
3775
|
+
emailPlaceholder: 'tu@email.com',
|
|
3776
|
+
emailRequired: 'El correo es requerido',
|
|
3777
|
+
emailInvalid: 'Ingresa un correo válido',
|
|
3778
|
+
password: 'Contraseña',
|
|
3779
|
+
passwordPlaceholder: '••••••••',
|
|
3780
|
+
passwordRequired: 'La contraseña es requerida',
|
|
3781
|
+
loginSubmit: 'Iniciar sesión',
|
|
3782
|
+
// OAuth
|
|
3783
|
+
orContinueWith: 'o continúa con',
|
|
3784
|
+
continueWithGoogle: 'Continuar con Google',
|
|
3785
|
+
continueWithApple: 'Continuar con Apple',
|
|
3786
|
+
continueWithMicrosoft: 'Continuar con Microsoft',
|
|
3787
|
+
connecting: 'Conectando...',
|
|
3788
|
+
// Register
|
|
3789
|
+
registerTitle: 'Crear cuenta',
|
|
3790
|
+
fullName: 'Nombre completo',
|
|
3791
|
+
namePlaceholder: 'Tu nombre',
|
|
3792
|
+
nameRequired: 'El nombre es requerido',
|
|
3793
|
+
nameMinLength: 'Mínimo 2 caracteres',
|
|
3794
|
+
passwordMinLength: 'Mínimo 8 caracteres',
|
|
3795
|
+
registerSubmit: 'Registrarse',
|
|
3796
|
+
noAccount: '¿No tienes cuenta?',
|
|
3797
|
+
register: 'Registrarse',
|
|
3798
|
+
hasAccount: '¿Ya tienes cuenta?',
|
|
3799
|
+
signIn: 'Iniciar sesión',
|
|
3800
|
+
// Verify email
|
|
3801
|
+
verifyTitle: 'Verificar correo',
|
|
3802
|
+
verifyDescription: 'Ingresa el código de verificación enviado a tu correo.',
|
|
3803
|
+
verifySubmit: 'Verificar',
|
|
3804
|
+
codeRequired: 'El código es requerido',
|
|
3805
|
+
codeMinLength: 'Ingresa los 6 dígitos',
|
|
3806
|
+
noCodeReceived: '¿No has recibido tu código?',
|
|
3807
|
+
resend: 'Reenviar',
|
|
3808
|
+
resendIn: 'Reenviar en {seconds}s',
|
|
3809
|
+
codeSent: 'Código reenviado. Revisa tu email.',
|
|
3810
|
+
emailVerified: '¡Email verificado! Bienvenido.',
|
|
3811
|
+
// MFA
|
|
3812
|
+
mfaTitle: 'Verificación MFA',
|
|
3813
|
+
mfaTOTP: 'Ingresa el código de tu app de autenticación',
|
|
3814
|
+
mfaEmail: 'Ingresa el código enviado a tu correo',
|
|
3815
|
+
mfaSMS: 'Ingresa el código enviado a tu teléfono',
|
|
3816
|
+
// Forgot/Reset password
|
|
3817
|
+
forgotTitle: 'Recuperar contraseña',
|
|
3818
|
+
forgotDescription: 'Ingresa tu correo electrónico y te enviaremos un código.',
|
|
3819
|
+
forgotSubmit: 'Enviar código',
|
|
3820
|
+
forgotLink: '¿Olvidaste tu contraseña?',
|
|
3821
|
+
recoverPassword: 'Recuperar contraseña',
|
|
3822
|
+
resetTitle: 'Restablecer contraseña',
|
|
3823
|
+
resetDescription: 'Hemos enviado un código de verificación a tu correo.',
|
|
3824
|
+
newPassword: 'Nueva contraseña',
|
|
3825
|
+
newPasswordHint: 'Mínimo 8 caracteres',
|
|
3826
|
+
resetSubmit: 'Cambiar contraseña',
|
|
3827
|
+
passwordUpdated: '¡Contraseña actualizada! Ya puedes iniciar sesión.',
|
|
3828
|
+
// Legal
|
|
3829
|
+
legalPrefix: 'Utilizamos los servicios de',
|
|
3830
|
+
legalSuffix: 'para ofrecerte una experiencia segura. Al iniciar sesión, aceptas nuestros',
|
|
3831
|
+
termsAndConditions: 'Términos y Condiciones',
|
|
3832
|
+
and: 'y',
|
|
3833
|
+
privacyPolicy: 'Política de Privacidad',
|
|
3834
|
+
// Toasts
|
|
3835
|
+
welcome: '¡Bienvenido!',
|
|
3836
|
+
completeAllFields: 'Completa todos los campos.',
|
|
3837
|
+
enterEmail: 'Ingresa tu correo electrónico.',
|
|
3838
|
+
// Errors (mapeados de códigos backend)
|
|
3839
|
+
errorInvalidCredentials: 'Correo o contraseña incorrectos',
|
|
3840
|
+
errorEmailNotVerified: 'Debes verificar tu correo electrónico',
|
|
3841
|
+
errorAccountSuspended: 'Tu cuenta ha sido suspendida',
|
|
3842
|
+
errorEmailExists: 'Este correo ya está registrado',
|
|
3843
|
+
errorWeakPassword: 'La contraseña es muy débil',
|
|
3844
|
+
errorInvalidCode: 'Código incorrecto',
|
|
3845
|
+
errorExpiredCode: 'El código ha expirado. Solicita uno nuevo.',
|
|
3846
|
+
errorTooManyAttempts: 'Demasiados intentos, intenta más tarde',
|
|
3847
|
+
errorMFAInvalidCode: 'Código de verificación incorrecto',
|
|
3848
|
+
errorPopupBlocked: 'Por favor, permite ventanas emergentes',
|
|
3849
|
+
errorOAuthFailed: 'Error de autenticación',
|
|
3850
|
+
errorGeneric: 'Ha ocurrido un error. Intenta de nuevo.',
|
|
3851
|
+
},
|
|
3852
|
+
en: {
|
|
3853
|
+
// Login
|
|
3854
|
+
loginTitle: 'Sign in',
|
|
3855
|
+
email: 'Email',
|
|
3856
|
+
emailPlaceholder: 'you@email.com',
|
|
3857
|
+
emailRequired: 'Email is required',
|
|
3858
|
+
emailInvalid: 'Enter a valid email',
|
|
3859
|
+
password: 'Password',
|
|
3860
|
+
passwordPlaceholder: '••••••••',
|
|
3861
|
+
passwordRequired: 'Password is required',
|
|
3862
|
+
loginSubmit: 'Sign in',
|
|
3863
|
+
// OAuth
|
|
3864
|
+
orContinueWith: 'or continue with',
|
|
3865
|
+
continueWithGoogle: 'Continue with Google',
|
|
3866
|
+
continueWithApple: 'Continue with Apple',
|
|
3867
|
+
continueWithMicrosoft: 'Continue with Microsoft',
|
|
3868
|
+
connecting: 'Connecting...',
|
|
3869
|
+
// Register
|
|
3870
|
+
registerTitle: 'Create account',
|
|
3871
|
+
fullName: 'Full name',
|
|
3872
|
+
namePlaceholder: 'Your name',
|
|
3873
|
+
nameRequired: 'Name is required',
|
|
3874
|
+
nameMinLength: 'Minimum 2 characters',
|
|
3875
|
+
passwordMinLength: 'Minimum 8 characters',
|
|
3876
|
+
registerSubmit: 'Sign up',
|
|
3877
|
+
noAccount: "Don't have an account?",
|
|
3878
|
+
register: 'Sign up',
|
|
3879
|
+
hasAccount: 'Already have an account?',
|
|
3880
|
+
signIn: 'Sign in',
|
|
3881
|
+
// Verify email
|
|
3882
|
+
verifyTitle: 'Verify email',
|
|
3883
|
+
verifyDescription: 'Enter the verification code sent to your email.',
|
|
3884
|
+
verifySubmit: 'Verify',
|
|
3885
|
+
codeRequired: 'Code is required',
|
|
3886
|
+
codeMinLength: 'Enter all 6 digits',
|
|
3887
|
+
noCodeReceived: "Didn't receive your code?",
|
|
3888
|
+
resend: 'Resend',
|
|
3889
|
+
resendIn: 'Resend in {seconds}s',
|
|
3890
|
+
codeSent: 'Code resent. Check your email.',
|
|
3891
|
+
emailVerified: 'Email verified! Welcome.',
|
|
3892
|
+
// MFA
|
|
3893
|
+
mfaTitle: 'MFA Verification',
|
|
3894
|
+
mfaTOTP: 'Enter the code from your authenticator app',
|
|
3895
|
+
mfaEmail: 'Enter the code sent to your email',
|
|
3896
|
+
mfaSMS: 'Enter the code sent to your phone',
|
|
3897
|
+
// Forgot/Reset password
|
|
3898
|
+
forgotTitle: 'Recover password',
|
|
3899
|
+
forgotDescription: 'Enter your email and we will send you a code.',
|
|
3900
|
+
forgotSubmit: 'Send code',
|
|
3901
|
+
forgotLink: 'Forgot your password?',
|
|
3902
|
+
recoverPassword: 'Recover password',
|
|
3903
|
+
resetTitle: 'Reset password',
|
|
3904
|
+
resetDescription: 'We have sent a verification code to your email.',
|
|
3905
|
+
newPassword: 'New password',
|
|
3906
|
+
newPasswordHint: 'Minimum 8 characters',
|
|
3907
|
+
resetSubmit: 'Change password',
|
|
3908
|
+
passwordUpdated: 'Password updated! You can now sign in.',
|
|
3909
|
+
// Legal
|
|
3910
|
+
legalPrefix: 'We use the services of',
|
|
3911
|
+
legalSuffix: 'to offer you a secure experience. By signing in, you accept our',
|
|
3912
|
+
termsAndConditions: 'Terms and Conditions',
|
|
3913
|
+
and: 'and',
|
|
3914
|
+
privacyPolicy: 'Privacy Policy',
|
|
3915
|
+
// Toasts
|
|
3916
|
+
welcome: 'Welcome!',
|
|
3917
|
+
completeAllFields: 'Complete all fields.',
|
|
3918
|
+
enterEmail: 'Enter your email.',
|
|
3919
|
+
// Errors
|
|
3920
|
+
errorInvalidCredentials: 'Incorrect email or password',
|
|
3921
|
+
errorEmailNotVerified: 'You must verify your email',
|
|
3922
|
+
errorAccountSuspended: 'Your account has been suspended',
|
|
3923
|
+
errorEmailExists: 'This email is already registered',
|
|
3924
|
+
errorWeakPassword: 'Password is too weak',
|
|
3925
|
+
errorInvalidCode: 'Incorrect code',
|
|
3926
|
+
errorExpiredCode: 'Code has expired. Request a new one.',
|
|
3927
|
+
errorTooManyAttempts: 'Too many attempts, try again later',
|
|
3928
|
+
errorMFAInvalidCode: 'Incorrect verification code',
|
|
3929
|
+
errorPopupBlocked: 'Please allow pop-ups',
|
|
3930
|
+
errorOAuthFailed: 'Authentication error',
|
|
3931
|
+
errorGeneric: 'An error occurred. Please try again.',
|
|
3932
|
+
},
|
|
3933
|
+
},
|
|
3680
3934
|
};
|
|
3681
3935
|
|
|
3682
3936
|
/**
|
|
@@ -28923,6 +29177,8 @@ class LoginComponent {
|
|
|
28923
29177
|
this.authService = inject(AuthService);
|
|
28924
29178
|
this.toastService = inject(ToastService);
|
|
28925
29179
|
this.router = inject(Router);
|
|
29180
|
+
this.i18n = inject(I18nService);
|
|
29181
|
+
this.i18nHelper = inject(InputI18nHelper);
|
|
28926
29182
|
// Timers
|
|
28927
29183
|
this.resendTimer = null;
|
|
28928
29184
|
this.resetResendTimer = null;
|
|
@@ -28940,283 +29196,351 @@ class LoginComponent {
|
|
|
28940
29196
|
// ==========================================
|
|
28941
29197
|
// LOGIN FORM
|
|
28942
29198
|
// ==========================================
|
|
28943
|
-
this.
|
|
28944
|
-
|
|
28945
|
-
|
|
28946
|
-
|
|
28947
|
-
|
|
28948
|
-
|
|
28949
|
-
|
|
28950
|
-
|
|
28951
|
-
|
|
28952
|
-
|
|
28953
|
-
|
|
28954
|
-
|
|
28955
|
-
|
|
28956
|
-
|
|
28957
|
-
|
|
28958
|
-
|
|
28959
|
-
|
|
28960
|
-
|
|
28961
|
-
|
|
28962
|
-
|
|
28963
|
-
|
|
28964
|
-
|
|
28965
|
-
|
|
28966
|
-
|
|
28967
|
-
|
|
28968
|
-
|
|
28969
|
-
|
|
28970
|
-
|
|
28971
|
-
|
|
28972
|
-
|
|
28973
|
-
|
|
28974
|
-
|
|
28975
|
-
|
|
29199
|
+
this._loginFormState = ComponentStates.ENABLED;
|
|
29200
|
+
// ==========================================
|
|
29201
|
+
// REGISTER FORM
|
|
29202
|
+
// ==========================================
|
|
29203
|
+
this._registerFormState = ComponentStates.ENABLED;
|
|
29204
|
+
// ==========================================
|
|
29205
|
+
// VERIFY EMAIL FORM
|
|
29206
|
+
// ==========================================
|
|
29207
|
+
this._verifyFormState = ComponentStates.ENABLED;
|
|
29208
|
+
this._verifyFormSectionName = '';
|
|
29209
|
+
// ==========================================
|
|
29210
|
+
// MFA VERIFY FORM
|
|
29211
|
+
// ==========================================
|
|
29212
|
+
this._mfaVerifyFormState = ComponentStates.ENABLED;
|
|
29213
|
+
this._mfaMethod = 'TOTP';
|
|
29214
|
+
// ==========================================
|
|
29215
|
+
// FORGOT PASSWORD FORM
|
|
29216
|
+
// ==========================================
|
|
29217
|
+
this._forgotPasswordFormState = ComponentStates.ENABLED;
|
|
29218
|
+
// ==========================================
|
|
29219
|
+
// RESET PASSWORD FORM
|
|
29220
|
+
// ==========================================
|
|
29221
|
+
this._resetPasswordFormState = ComponentStates.ENABLED;
|
|
29222
|
+
this._resetFormSectionName = '';
|
|
29223
|
+
}
|
|
29224
|
+
/**
|
|
29225
|
+
* Helper method for translating auth-related strings.
|
|
29226
|
+
* Exposed to template for dynamic text.
|
|
29227
|
+
*/
|
|
29228
|
+
t(key, data) {
|
|
29229
|
+
return this.i18n.t(key, '_auth', data);
|
|
29230
|
+
}
|
|
29231
|
+
// Resolved props with defaults
|
|
29232
|
+
get config() {
|
|
29233
|
+
return { ...LOGIN_DEFAULTS, ...this.props };
|
|
29234
|
+
}
|
|
29235
|
+
get loginFormProps() {
|
|
29236
|
+
return this.i18nHelper.resolveForm({
|
|
29237
|
+
nameKey: 'loginTitle',
|
|
29238
|
+
i18nNamespace: '_auth',
|
|
28976
29239
|
sections: [
|
|
28977
29240
|
{
|
|
28978
29241
|
name: '',
|
|
28979
29242
|
order: 0,
|
|
28980
|
-
fields: [
|
|
29243
|
+
fields: [
|
|
29244
|
+
{
|
|
29245
|
+
type: InputType.EMAIL,
|
|
29246
|
+
name: 'email',
|
|
29247
|
+
token: 'login-email',
|
|
29248
|
+
hint: '',
|
|
29249
|
+
labelKey: 'email',
|
|
29250
|
+
placeholderKey: 'emailPlaceholder',
|
|
29251
|
+
errorKeys: {
|
|
29252
|
+
required: 'emailRequired',
|
|
29253
|
+
email: 'emailInvalid',
|
|
29254
|
+
},
|
|
29255
|
+
validators: [Validators.required, Validators.email],
|
|
29256
|
+
order: 0,
|
|
29257
|
+
state: ComponentStates.ENABLED,
|
|
29258
|
+
},
|
|
29259
|
+
{
|
|
29260
|
+
type: InputType.PASSWORD,
|
|
29261
|
+
name: 'password',
|
|
29262
|
+
token: 'login-password',
|
|
29263
|
+
hint: '',
|
|
29264
|
+
labelKey: 'password',
|
|
29265
|
+
placeholderKey: 'passwordPlaceholder',
|
|
29266
|
+
errorKeys: {
|
|
29267
|
+
required: 'passwordRequired',
|
|
29268
|
+
},
|
|
29269
|
+
validators: [Validators.required],
|
|
29270
|
+
order: 1,
|
|
29271
|
+
state: ComponentStates.ENABLED,
|
|
29272
|
+
},
|
|
29273
|
+
],
|
|
28981
29274
|
},
|
|
28982
29275
|
],
|
|
28983
29276
|
actions: {
|
|
28984
|
-
...SolidDefaultBlock('
|
|
29277
|
+
...SolidDefaultBlock('', 'submit'),
|
|
28985
29278
|
token: 'login-submit',
|
|
29279
|
+
textKey: 'loginSubmit',
|
|
28986
29280
|
},
|
|
28987
|
-
state:
|
|
28988
|
-
};
|
|
28989
|
-
|
|
28990
|
-
|
|
28991
|
-
|
|
28992
|
-
|
|
28993
|
-
|
|
28994
|
-
|
|
28995
|
-
|
|
28996
|
-
|
|
28997
|
-
hint: '',
|
|
28998
|
-
placeholder: 'Tu nombre',
|
|
28999
|
-
errors: {
|
|
29000
|
-
required: 'El nombre es requerido',
|
|
29001
|
-
minlength: 'Mínimo 2 caracteres',
|
|
29002
|
-
},
|
|
29003
|
-
validators: [Validators.required, Validators.minLength(2)],
|
|
29004
|
-
order: 0,
|
|
29005
|
-
state: ComponentStates.ENABLED,
|
|
29006
|
-
control: undefined,
|
|
29007
|
-
};
|
|
29008
|
-
this.registerEmailInput = {
|
|
29009
|
-
type: InputType.EMAIL,
|
|
29010
|
-
label: 'Correo electrónico',
|
|
29011
|
-
name: 'email',
|
|
29012
|
-
token: 'register-email',
|
|
29013
|
-
hint: '',
|
|
29014
|
-
placeholder: 'tu@email.com',
|
|
29015
|
-
errors: {
|
|
29016
|
-
required: 'El correo es requerido',
|
|
29017
|
-
email: 'Ingresa un correo válido',
|
|
29018
|
-
},
|
|
29019
|
-
validators: [Validators.required, Validators.email],
|
|
29020
|
-
order: 1,
|
|
29021
|
-
state: ComponentStates.ENABLED,
|
|
29022
|
-
control: undefined,
|
|
29023
|
-
};
|
|
29024
|
-
this.registerPasswordInput = {
|
|
29025
|
-
type: InputType.PASSWORD,
|
|
29026
|
-
label: 'Contraseña',
|
|
29027
|
-
name: 'password',
|
|
29028
|
-
token: 'register-password',
|
|
29029
|
-
hint: '',
|
|
29030
|
-
placeholder: '••••••••',
|
|
29031
|
-
errors: {
|
|
29032
|
-
required: 'La contraseña es requerida',
|
|
29033
|
-
minlength: 'Mínimo 8 caracteres',
|
|
29034
|
-
},
|
|
29035
|
-
validators: [Validators.required, Validators.minLength(8)],
|
|
29036
|
-
order: 2,
|
|
29037
|
-
state: ComponentStates.ENABLED,
|
|
29038
|
-
control: undefined,
|
|
29039
|
-
};
|
|
29040
|
-
this.registerFormProps = {
|
|
29041
|
-
name: 'Crear cuenta',
|
|
29281
|
+
state: this._loginFormState,
|
|
29282
|
+
});
|
|
29283
|
+
}
|
|
29284
|
+
set loginFormState(value) {
|
|
29285
|
+
this._loginFormState = value;
|
|
29286
|
+
}
|
|
29287
|
+
get registerFormProps() {
|
|
29288
|
+
return this.i18nHelper.resolveForm({
|
|
29289
|
+
nameKey: 'registerTitle',
|
|
29290
|
+
i18nNamespace: '_auth',
|
|
29042
29291
|
sections: [
|
|
29043
29292
|
{
|
|
29044
29293
|
name: '',
|
|
29045
29294
|
order: 0,
|
|
29046
|
-
fields: [
|
|
29295
|
+
fields: [
|
|
29296
|
+
{
|
|
29297
|
+
type: InputType.TEXT,
|
|
29298
|
+
name: 'name',
|
|
29299
|
+
token: 'register-name',
|
|
29300
|
+
hint: '',
|
|
29301
|
+
labelKey: 'fullName',
|
|
29302
|
+
placeholderKey: 'namePlaceholder',
|
|
29303
|
+
errorKeys: {
|
|
29304
|
+
required: 'nameRequired',
|
|
29305
|
+
minlength: 'nameMinLength',
|
|
29306
|
+
},
|
|
29307
|
+
validators: [Validators.required, Validators.minLength(2)],
|
|
29308
|
+
order: 0,
|
|
29309
|
+
state: ComponentStates.ENABLED,
|
|
29310
|
+
},
|
|
29311
|
+
{
|
|
29312
|
+
type: InputType.EMAIL,
|
|
29313
|
+
name: 'email',
|
|
29314
|
+
token: 'register-email',
|
|
29315
|
+
hint: '',
|
|
29316
|
+
labelKey: 'email',
|
|
29317
|
+
placeholderKey: 'emailPlaceholder',
|
|
29318
|
+
errorKeys: {
|
|
29319
|
+
required: 'emailRequired',
|
|
29320
|
+
email: 'emailInvalid',
|
|
29321
|
+
},
|
|
29322
|
+
validators: [Validators.required, Validators.email],
|
|
29323
|
+
order: 1,
|
|
29324
|
+
state: ComponentStates.ENABLED,
|
|
29325
|
+
},
|
|
29326
|
+
{
|
|
29327
|
+
type: InputType.PASSWORD,
|
|
29328
|
+
name: 'password',
|
|
29329
|
+
token: 'register-password',
|
|
29330
|
+
hint: '',
|
|
29331
|
+
labelKey: 'password',
|
|
29332
|
+
placeholderKey: 'passwordPlaceholder',
|
|
29333
|
+
errorKeys: {
|
|
29334
|
+
required: 'passwordRequired',
|
|
29335
|
+
minlength: 'passwordMinLength',
|
|
29336
|
+
},
|
|
29337
|
+
validators: [Validators.required, Validators.minLength(8)],
|
|
29338
|
+
order: 2,
|
|
29339
|
+
state: ComponentStates.ENABLED,
|
|
29340
|
+
},
|
|
29341
|
+
],
|
|
29047
29342
|
},
|
|
29048
29343
|
],
|
|
29049
29344
|
actions: {
|
|
29050
|
-
...SolidDefaultBlock('
|
|
29345
|
+
...SolidDefaultBlock('', 'submit'),
|
|
29051
29346
|
token: 'register-submit',
|
|
29347
|
+
textKey: 'registerSubmit',
|
|
29052
29348
|
},
|
|
29053
|
-
state:
|
|
29054
|
-
};
|
|
29055
|
-
|
|
29056
|
-
|
|
29057
|
-
|
|
29058
|
-
|
|
29059
|
-
|
|
29060
|
-
|
|
29061
|
-
|
|
29062
|
-
|
|
29063
|
-
hint: '',
|
|
29064
|
-
placeholder: '',
|
|
29065
|
-
errors: {
|
|
29066
|
-
required: 'El código es requerido',
|
|
29067
|
-
minlength: 'Ingresa los 6 dígitos',
|
|
29068
|
-
},
|
|
29069
|
-
validators: [Validators.required, Validators.minLength(6)],
|
|
29070
|
-
order: 0,
|
|
29071
|
-
state: ComponentStates.ENABLED,
|
|
29072
|
-
control: undefined,
|
|
29073
|
-
length: 6,
|
|
29074
|
-
allowNumbersOnly: true,
|
|
29075
|
-
autoFocus: true,
|
|
29076
|
-
};
|
|
29077
|
-
this.verifyFormProps = {
|
|
29078
|
-
name: 'Verificar correo',
|
|
29349
|
+
state: this._registerFormState,
|
|
29350
|
+
});
|
|
29351
|
+
}
|
|
29352
|
+
set registerFormState(value) {
|
|
29353
|
+
this._registerFormState = value;
|
|
29354
|
+
}
|
|
29355
|
+
get verifyFormProps() {
|
|
29356
|
+
return this.i18nHelper.resolveForm({
|
|
29357
|
+
nameKey: 'verifyTitle',
|
|
29358
|
+
i18nNamespace: '_auth',
|
|
29079
29359
|
sections: [
|
|
29080
29360
|
{
|
|
29081
|
-
name:
|
|
29361
|
+
name: this._verifyFormSectionName || this.t('verifyDescription'),
|
|
29082
29362
|
order: 0,
|
|
29083
|
-
fields: [
|
|
29363
|
+
fields: [
|
|
29364
|
+
{
|
|
29365
|
+
type: InputType.PIN_CODE,
|
|
29366
|
+
label: '',
|
|
29367
|
+
name: 'code',
|
|
29368
|
+
token: 'verify-pin',
|
|
29369
|
+
hint: '',
|
|
29370
|
+
placeholder: '',
|
|
29371
|
+
errorKeys: {
|
|
29372
|
+
required: 'codeRequired',
|
|
29373
|
+
minlength: 'codeMinLength',
|
|
29374
|
+
},
|
|
29375
|
+
validators: [Validators.required, Validators.minLength(6)],
|
|
29376
|
+
order: 0,
|
|
29377
|
+
state: ComponentStates.ENABLED,
|
|
29378
|
+
length: 6,
|
|
29379
|
+
allowNumbersOnly: true,
|
|
29380
|
+
autoFocus: true,
|
|
29381
|
+
},
|
|
29382
|
+
],
|
|
29084
29383
|
},
|
|
29085
29384
|
],
|
|
29086
29385
|
actions: {
|
|
29087
|
-
...SolidDefaultBlock('
|
|
29386
|
+
...SolidDefaultBlock('', 'submit'),
|
|
29088
29387
|
token: 'verify-submit',
|
|
29388
|
+
textKey: 'verifySubmit',
|
|
29089
29389
|
},
|
|
29090
|
-
state:
|
|
29091
|
-
};
|
|
29092
|
-
|
|
29093
|
-
|
|
29094
|
-
|
|
29095
|
-
|
|
29096
|
-
|
|
29097
|
-
|
|
29098
|
-
|
|
29099
|
-
|
|
29100
|
-
|
|
29101
|
-
|
|
29102
|
-
|
|
29103
|
-
|
|
29104
|
-
|
|
29105
|
-
|
|
29106
|
-
|
|
29107
|
-
|
|
29108
|
-
state: ComponentStates.ENABLED,
|
|
29109
|
-
control: undefined,
|
|
29110
|
-
length: 6,
|
|
29111
|
-
allowNumbersOnly: true,
|
|
29112
|
-
autoFocus: true,
|
|
29113
|
-
};
|
|
29114
|
-
this.mfaVerifyFormProps = {
|
|
29115
|
-
name: 'Verificación MFA',
|
|
29390
|
+
state: this._verifyFormState,
|
|
29391
|
+
});
|
|
29392
|
+
}
|
|
29393
|
+
set verifyFormState(value) {
|
|
29394
|
+
this._verifyFormState = value;
|
|
29395
|
+
}
|
|
29396
|
+
set verifyFormSectionName(value) {
|
|
29397
|
+
this._verifyFormSectionName = value;
|
|
29398
|
+
}
|
|
29399
|
+
get mfaVerifyFormProps() {
|
|
29400
|
+
const sectionName = this._mfaMethod === 'TOTP'
|
|
29401
|
+
? this.t('mfaTOTP')
|
|
29402
|
+
: this._mfaMethod === 'EMAIL'
|
|
29403
|
+
? this.t('mfaEmail')
|
|
29404
|
+
: this.t('mfaSMS');
|
|
29405
|
+
return this.i18nHelper.resolveForm({
|
|
29406
|
+
nameKey: 'mfaTitle',
|
|
29407
|
+
i18nNamespace: '_auth',
|
|
29116
29408
|
sections: [
|
|
29117
29409
|
{
|
|
29118
|
-
name:
|
|
29410
|
+
name: sectionName,
|
|
29119
29411
|
order: 0,
|
|
29120
|
-
fields: [
|
|
29412
|
+
fields: [
|
|
29413
|
+
{
|
|
29414
|
+
type: InputType.PIN_CODE,
|
|
29415
|
+
label: '',
|
|
29416
|
+
name: 'code',
|
|
29417
|
+
token: 'mfa-pin',
|
|
29418
|
+
hint: '',
|
|
29419
|
+
placeholder: '',
|
|
29420
|
+
errorKeys: {
|
|
29421
|
+
required: 'codeRequired',
|
|
29422
|
+
minlength: 'codeMinLength',
|
|
29423
|
+
},
|
|
29424
|
+
validators: [Validators.required, Validators.minLength(6)],
|
|
29425
|
+
order: 0,
|
|
29426
|
+
state: ComponentStates.ENABLED,
|
|
29427
|
+
length: 6,
|
|
29428
|
+
allowNumbersOnly: true,
|
|
29429
|
+
autoFocus: true,
|
|
29430
|
+
},
|
|
29431
|
+
],
|
|
29121
29432
|
},
|
|
29122
29433
|
],
|
|
29123
29434
|
actions: {
|
|
29124
|
-
...SolidDefaultBlock('
|
|
29435
|
+
...SolidDefaultBlock('', 'submit'),
|
|
29125
29436
|
token: 'mfa-verify-submit',
|
|
29437
|
+
textKey: 'verifySubmit',
|
|
29126
29438
|
},
|
|
29127
|
-
state:
|
|
29128
|
-
};
|
|
29129
|
-
|
|
29130
|
-
|
|
29131
|
-
|
|
29132
|
-
|
|
29133
|
-
|
|
29134
|
-
|
|
29135
|
-
|
|
29136
|
-
|
|
29137
|
-
|
|
29138
|
-
|
|
29139
|
-
|
|
29140
|
-
required: 'El correo es requerido',
|
|
29141
|
-
email: 'Ingresa un correo válido',
|
|
29142
|
-
},
|
|
29143
|
-
validators: [Validators.required, Validators.email],
|
|
29144
|
-
order: 0,
|
|
29145
|
-
state: ComponentStates.ENABLED,
|
|
29146
|
-
control: undefined,
|
|
29147
|
-
};
|
|
29148
|
-
this.forgotPasswordFormProps = {
|
|
29149
|
-
name: 'Recuperar contraseña',
|
|
29439
|
+
state: this._mfaVerifyFormState,
|
|
29440
|
+
});
|
|
29441
|
+
}
|
|
29442
|
+
set mfaVerifyFormState(value) {
|
|
29443
|
+
this._mfaVerifyFormState = value;
|
|
29444
|
+
}
|
|
29445
|
+
set mfaMethod(value) {
|
|
29446
|
+
this._mfaMethod = value;
|
|
29447
|
+
}
|
|
29448
|
+
get forgotPasswordFormProps() {
|
|
29449
|
+
return this.i18nHelper.resolveForm({
|
|
29450
|
+
nameKey: 'forgotTitle',
|
|
29451
|
+
i18nNamespace: '_auth',
|
|
29150
29452
|
sections: [
|
|
29151
29453
|
{
|
|
29152
|
-
name:
|
|
29454
|
+
name: this.t('forgotDescription'),
|
|
29153
29455
|
order: 0,
|
|
29154
|
-
fields: [
|
|
29456
|
+
fields: [
|
|
29457
|
+
{
|
|
29458
|
+
type: InputType.EMAIL,
|
|
29459
|
+
label: '',
|
|
29460
|
+
name: 'email',
|
|
29461
|
+
token: 'forgot-email',
|
|
29462
|
+
hint: '',
|
|
29463
|
+
placeholderKey: 'emailPlaceholder',
|
|
29464
|
+
errorKeys: {
|
|
29465
|
+
required: 'emailRequired',
|
|
29466
|
+
email: 'emailInvalid',
|
|
29467
|
+
},
|
|
29468
|
+
validators: [Validators.required, Validators.email],
|
|
29469
|
+
order: 0,
|
|
29470
|
+
state: ComponentStates.ENABLED,
|
|
29471
|
+
},
|
|
29472
|
+
],
|
|
29155
29473
|
},
|
|
29156
29474
|
],
|
|
29157
29475
|
actions: {
|
|
29158
|
-
...SolidDefaultBlock('
|
|
29476
|
+
...SolidDefaultBlock('', 'submit'),
|
|
29159
29477
|
token: 'forgot-submit',
|
|
29478
|
+
textKey: 'forgotSubmit',
|
|
29160
29479
|
},
|
|
29161
|
-
state:
|
|
29162
|
-
};
|
|
29163
|
-
|
|
29164
|
-
|
|
29165
|
-
|
|
29166
|
-
|
|
29167
|
-
|
|
29168
|
-
|
|
29169
|
-
|
|
29170
|
-
|
|
29171
|
-
hint: '',
|
|
29172
|
-
placeholder: '',
|
|
29173
|
-
errors: {
|
|
29174
|
-
required: 'El código es requerido',
|
|
29175
|
-
minlength: 'Ingresa los 6 dígitos',
|
|
29176
|
-
},
|
|
29177
|
-
validators: [Validators.required, Validators.minLength(6)],
|
|
29178
|
-
order: 0,
|
|
29179
|
-
state: ComponentStates.ENABLED,
|
|
29180
|
-
control: undefined,
|
|
29181
|
-
length: 6,
|
|
29182
|
-
allowNumbersOnly: true,
|
|
29183
|
-
autoFocus: true,
|
|
29184
|
-
};
|
|
29185
|
-
this.newPasswordInput = {
|
|
29186
|
-
type: InputType.PASSWORD,
|
|
29187
|
-
label: 'Nueva contraseña',
|
|
29188
|
-
name: 'newPassword',
|
|
29189
|
-
token: 'reset-new-password',
|
|
29190
|
-
hint: 'Mínimo 8 caracteres',
|
|
29191
|
-
placeholder: '••••••••',
|
|
29192
|
-
errors: {
|
|
29193
|
-
required: 'La contraseña es requerida',
|
|
29194
|
-
minlength: 'Mínimo 8 caracteres',
|
|
29195
|
-
},
|
|
29196
|
-
validators: [Validators.required, Validators.minLength(8)],
|
|
29197
|
-
order: 1,
|
|
29198
|
-
state: ComponentStates.ENABLED,
|
|
29199
|
-
control: undefined,
|
|
29200
|
-
};
|
|
29201
|
-
this.resetPasswordFormProps = {
|
|
29202
|
-
name: 'Restablecer contraseña',
|
|
29480
|
+
state: this._forgotPasswordFormState,
|
|
29481
|
+
});
|
|
29482
|
+
}
|
|
29483
|
+
set forgotPasswordFormState(value) {
|
|
29484
|
+
this._forgotPasswordFormState = value;
|
|
29485
|
+
}
|
|
29486
|
+
get resetPasswordFormProps() {
|
|
29487
|
+
return this.i18nHelper.resolveForm({
|
|
29488
|
+
nameKey: 'resetTitle',
|
|
29489
|
+
i18nNamespace: '_auth',
|
|
29203
29490
|
sections: [
|
|
29204
29491
|
{
|
|
29205
|
-
name:
|
|
29492
|
+
name: this._resetFormSectionName || this.t('resetDescription'),
|
|
29206
29493
|
order: 0,
|
|
29207
|
-
fields: [
|
|
29494
|
+
fields: [
|
|
29495
|
+
{
|
|
29496
|
+
type: InputType.PIN_CODE,
|
|
29497
|
+
label: '',
|
|
29498
|
+
name: 'code',
|
|
29499
|
+
token: 'reset-pin',
|
|
29500
|
+
hint: '',
|
|
29501
|
+
placeholder: '',
|
|
29502
|
+
errorKeys: {
|
|
29503
|
+
required: 'codeRequired',
|
|
29504
|
+
minlength: 'codeMinLength',
|
|
29505
|
+
},
|
|
29506
|
+
validators: [Validators.required, Validators.minLength(6)],
|
|
29507
|
+
order: 0,
|
|
29508
|
+
state: ComponentStates.ENABLED,
|
|
29509
|
+
length: 6,
|
|
29510
|
+
allowNumbersOnly: true,
|
|
29511
|
+
autoFocus: true,
|
|
29512
|
+
},
|
|
29513
|
+
{
|
|
29514
|
+
type: InputType.PASSWORD,
|
|
29515
|
+
name: 'newPassword',
|
|
29516
|
+
token: 'reset-new-password',
|
|
29517
|
+
labelKey: 'newPassword',
|
|
29518
|
+
hintKey: 'newPasswordHint',
|
|
29519
|
+
placeholderKey: 'passwordPlaceholder',
|
|
29520
|
+
errorKeys: {
|
|
29521
|
+
required: 'passwordRequired',
|
|
29522
|
+
minlength: 'passwordMinLength',
|
|
29523
|
+
},
|
|
29524
|
+
validators: [Validators.required, Validators.minLength(8)],
|
|
29525
|
+
order: 1,
|
|
29526
|
+
state: ComponentStates.ENABLED,
|
|
29527
|
+
},
|
|
29528
|
+
],
|
|
29208
29529
|
},
|
|
29209
29530
|
],
|
|
29210
29531
|
actions: {
|
|
29211
|
-
...SolidDefaultBlock('
|
|
29532
|
+
...SolidDefaultBlock('', 'submit'),
|
|
29212
29533
|
token: 'reset-submit',
|
|
29534
|
+
textKey: 'resetSubmit',
|
|
29213
29535
|
},
|
|
29214
|
-
state:
|
|
29215
|
-
};
|
|
29536
|
+
state: this._resetPasswordFormState,
|
|
29537
|
+
});
|
|
29216
29538
|
}
|
|
29217
|
-
|
|
29218
|
-
|
|
29219
|
-
|
|
29539
|
+
set resetPasswordFormState(value) {
|
|
29540
|
+
this._resetPasswordFormState = value;
|
|
29541
|
+
}
|
|
29542
|
+
set resetFormSectionName(value) {
|
|
29543
|
+
this._resetFormSectionName = value;
|
|
29220
29544
|
}
|
|
29221
29545
|
// ==========================================
|
|
29222
29546
|
// HANDLERS
|
|
@@ -29225,13 +29549,13 @@ class LoginComponent {
|
|
|
29225
29549
|
const email = event.fields['email'];
|
|
29226
29550
|
const password = event.fields['password'];
|
|
29227
29551
|
if (!email || !password) {
|
|
29228
|
-
this.showToast(
|
|
29552
|
+
this.showToast(this.t('completeAllFields'));
|
|
29229
29553
|
return;
|
|
29230
29554
|
}
|
|
29231
|
-
this.
|
|
29555
|
+
this._loginFormState = ComponentStates.WORKING;
|
|
29232
29556
|
this.authService.signin({ email, password }).subscribe({
|
|
29233
29557
|
next: () => {
|
|
29234
|
-
this.
|
|
29558
|
+
this._loginFormState = ComponentStates.ENABLED;
|
|
29235
29559
|
if (this.authService.mfaPending().required) {
|
|
29236
29560
|
this.openMFAVerifyModal();
|
|
29237
29561
|
return;
|
|
@@ -29239,7 +29563,7 @@ class LoginComponent {
|
|
|
29239
29563
|
this.handleLoginSuccess();
|
|
29240
29564
|
},
|
|
29241
29565
|
error: (err) => {
|
|
29242
|
-
this.
|
|
29566
|
+
this._loginFormState = ComponentStates.ENABLED;
|
|
29243
29567
|
const errorCode = err?.code;
|
|
29244
29568
|
if (errorCode === 'AUTHV2_EMAIL_NOT_VERIFIED') {
|
|
29245
29569
|
this.openVerifyModal(email);
|
|
@@ -29284,18 +29608,18 @@ class LoginComponent {
|
|
|
29284
29608
|
const email = event.fields['email'];
|
|
29285
29609
|
const password = event.fields['password'];
|
|
29286
29610
|
if (!name || !email || !password) {
|
|
29287
|
-
this.showToast(
|
|
29611
|
+
this.showToast(this.t('completeAllFields'));
|
|
29288
29612
|
return;
|
|
29289
29613
|
}
|
|
29290
|
-
this.
|
|
29614
|
+
this._registerFormState = ComponentStates.WORKING;
|
|
29291
29615
|
this.authService.signup({ name, email, password }).subscribe({
|
|
29292
29616
|
next: () => {
|
|
29293
|
-
this.
|
|
29617
|
+
this._registerFormState = ComponentStates.ENABLED;
|
|
29294
29618
|
this.closeRegisterModal();
|
|
29295
29619
|
this.openVerifyModal(email);
|
|
29296
29620
|
},
|
|
29297
29621
|
error: (err) => {
|
|
29298
|
-
this.
|
|
29622
|
+
this._registerFormState = ComponentStates.ENABLED;
|
|
29299
29623
|
this.handleError(err, 'signup');
|
|
29300
29624
|
},
|
|
29301
29625
|
});
|
|
@@ -29305,19 +29629,20 @@ class LoginComponent {
|
|
|
29305
29629
|
// ==========================================
|
|
29306
29630
|
openVerifyModal(email) {
|
|
29307
29631
|
this.pendingVerificationEmail = email;
|
|
29308
|
-
this.
|
|
29309
|
-
this.
|
|
29632
|
+
this._verifyFormSectionName = `${this.t('verifyDescription').replace('.', '')} (${email})`;
|
|
29633
|
+
this._verifyFormState = ComponentStates.ENABLED;
|
|
29310
29634
|
this.isVerifyModalOpen = true;
|
|
29311
29635
|
this.startResendCooldown();
|
|
29312
29636
|
}
|
|
29313
29637
|
closeVerifyModal() {
|
|
29314
29638
|
this.isVerifyModalOpen = false;
|
|
29315
29639
|
this.pendingVerificationEmail = '';
|
|
29640
|
+
this._verifyFormSectionName = '';
|
|
29316
29641
|
this.stopResendCooldown();
|
|
29317
29642
|
}
|
|
29318
29643
|
verifyHandler(event) {
|
|
29319
29644
|
const code = event.fields['code'];
|
|
29320
|
-
this.
|
|
29645
|
+
this._verifyFormState = ComponentStates.WORKING;
|
|
29321
29646
|
this.authService
|
|
29322
29647
|
.verifyEmail({
|
|
29323
29648
|
email: this.pendingVerificationEmail,
|
|
@@ -29325,13 +29650,13 @@ class LoginComponent {
|
|
|
29325
29650
|
})
|
|
29326
29651
|
.subscribe({
|
|
29327
29652
|
next: () => {
|
|
29328
|
-
this.
|
|
29329
|
-
this.showToast(
|
|
29653
|
+
this._verifyFormState = ComponentStates.ENABLED;
|
|
29654
|
+
this.showToast(this.t('emailVerified'));
|
|
29330
29655
|
this.closeVerifyModal();
|
|
29331
29656
|
this.handleLoginSuccess();
|
|
29332
29657
|
},
|
|
29333
29658
|
error: (err) => {
|
|
29334
|
-
this.
|
|
29659
|
+
this._verifyFormState = ComponentStates.ENABLED;
|
|
29335
29660
|
this.handleError(err, 'verify');
|
|
29336
29661
|
},
|
|
29337
29662
|
});
|
|
@@ -29346,7 +29671,7 @@ class LoginComponent {
|
|
|
29346
29671
|
})
|
|
29347
29672
|
.subscribe({
|
|
29348
29673
|
next: () => {
|
|
29349
|
-
this.showToast(
|
|
29674
|
+
this.showToast(this.t('codeSent'));
|
|
29350
29675
|
this.startResendCooldown();
|
|
29351
29676
|
},
|
|
29352
29677
|
error: (err) => {
|
|
@@ -29359,30 +29684,25 @@ class LoginComponent {
|
|
|
29359
29684
|
// ==========================================
|
|
29360
29685
|
openMFAVerifyModal() {
|
|
29361
29686
|
const method = this.authService.mfaPending().method;
|
|
29362
|
-
this.
|
|
29363
|
-
|
|
29364
|
-
? 'Ingresa el código de tu app de autenticación'
|
|
29365
|
-
: method === 'EMAIL'
|
|
29366
|
-
? 'Ingresa el código enviado a tu correo'
|
|
29367
|
-
: 'Ingresa el código enviado a tu teléfono';
|
|
29368
|
-
this.mfaVerifyFormProps.state = ComponentStates.ENABLED;
|
|
29687
|
+
this._mfaMethod = method;
|
|
29688
|
+
this._mfaVerifyFormState = ComponentStates.ENABLED;
|
|
29369
29689
|
this.isMFAVerifyModalOpen = true;
|
|
29370
|
-
this.onMFARequired.emit({ method
|
|
29690
|
+
this.onMFARequired.emit({ method });
|
|
29371
29691
|
}
|
|
29372
29692
|
closeMFAVerifyModal() {
|
|
29373
29693
|
this.isMFAVerifyModalOpen = false;
|
|
29374
29694
|
}
|
|
29375
29695
|
verifyMFAHandler(event) {
|
|
29376
29696
|
const code = event.fields['code'];
|
|
29377
|
-
this.
|
|
29697
|
+
this._mfaVerifyFormState = ComponentStates.WORKING;
|
|
29378
29698
|
this.authService.verifyMFA(code).subscribe({
|
|
29379
29699
|
next: () => {
|
|
29380
|
-
this.
|
|
29700
|
+
this._mfaVerifyFormState = ComponentStates.ENABLED;
|
|
29381
29701
|
this.closeMFAVerifyModal();
|
|
29382
29702
|
this.handleLoginSuccess(undefined, true);
|
|
29383
29703
|
},
|
|
29384
29704
|
error: (err) => {
|
|
29385
|
-
this.
|
|
29705
|
+
this._mfaVerifyFormState = ComponentStates.ENABLED;
|
|
29386
29706
|
this.handleError(err, 'mfa');
|
|
29387
29707
|
},
|
|
29388
29708
|
});
|
|
@@ -29399,19 +29719,19 @@ class LoginComponent {
|
|
|
29399
29719
|
forgotPasswordHandler(event) {
|
|
29400
29720
|
const email = event.fields['email'];
|
|
29401
29721
|
if (!email) {
|
|
29402
|
-
this.showToast(
|
|
29722
|
+
this.showToast(this.t('enterEmail'));
|
|
29403
29723
|
return;
|
|
29404
29724
|
}
|
|
29405
|
-
this.
|
|
29725
|
+
this._forgotPasswordFormState = ComponentStates.WORKING;
|
|
29406
29726
|
this.authService.forgotPassword({ email }).subscribe({
|
|
29407
29727
|
next: () => {
|
|
29408
|
-
this.
|
|
29728
|
+
this._forgotPasswordFormState = ComponentStates.ENABLED;
|
|
29409
29729
|
this.closeForgotPasswordModal();
|
|
29410
29730
|
this.openResetPasswordModal(email);
|
|
29411
|
-
this.showToast(
|
|
29731
|
+
this.showToast(this.t('codeSent'));
|
|
29412
29732
|
},
|
|
29413
29733
|
error: (err) => {
|
|
29414
|
-
this.
|
|
29734
|
+
this._forgotPasswordFormState = ComponentStates.ENABLED;
|
|
29415
29735
|
this.handleError(err, 'forgot');
|
|
29416
29736
|
},
|
|
29417
29737
|
});
|
|
@@ -29421,20 +29741,21 @@ class LoginComponent {
|
|
|
29421
29741
|
// ==========================================
|
|
29422
29742
|
openResetPasswordModal(email) {
|
|
29423
29743
|
this.pendingResetEmail = email;
|
|
29424
|
-
this.
|
|
29425
|
-
this.
|
|
29744
|
+
this._resetFormSectionName = `${this.t('resetDescription').replace('.', '')} (${email})`;
|
|
29745
|
+
this._resetPasswordFormState = ComponentStates.ENABLED;
|
|
29426
29746
|
this.isResetPasswordModalOpen = true;
|
|
29427
29747
|
this.startResetResendCooldown();
|
|
29428
29748
|
}
|
|
29429
29749
|
closeResetPasswordModal() {
|
|
29430
29750
|
this.isResetPasswordModalOpen = false;
|
|
29431
29751
|
this.pendingResetEmail = '';
|
|
29752
|
+
this._resetFormSectionName = '';
|
|
29432
29753
|
this.stopResetResendCooldown();
|
|
29433
29754
|
}
|
|
29434
29755
|
resetPasswordHandler(event) {
|
|
29435
29756
|
const code = event.fields['code'];
|
|
29436
29757
|
const newPassword = event.fields['newPassword'];
|
|
29437
|
-
this.
|
|
29758
|
+
this._resetPasswordFormState = ComponentStates.WORKING;
|
|
29438
29759
|
this.authService
|
|
29439
29760
|
.resetPassword({
|
|
29440
29761
|
email: this.pendingResetEmail,
|
|
@@ -29443,12 +29764,12 @@ class LoginComponent {
|
|
|
29443
29764
|
})
|
|
29444
29765
|
.subscribe({
|
|
29445
29766
|
next: () => {
|
|
29446
|
-
this.
|
|
29447
|
-
this.showToast(
|
|
29767
|
+
this._resetPasswordFormState = ComponentStates.ENABLED;
|
|
29768
|
+
this.showToast(this.t('passwordUpdated'));
|
|
29448
29769
|
this.closeResetPasswordModal();
|
|
29449
29770
|
},
|
|
29450
29771
|
error: (err) => {
|
|
29451
|
-
this.
|
|
29772
|
+
this._resetPasswordFormState = ComponentStates.ENABLED;
|
|
29452
29773
|
this.handleError(err, 'reset');
|
|
29453
29774
|
},
|
|
29454
29775
|
});
|
|
@@ -29463,7 +29784,7 @@ class LoginComponent {
|
|
|
29463
29784
|
})
|
|
29464
29785
|
.subscribe({
|
|
29465
29786
|
next: () => {
|
|
29466
|
-
this.showToast(
|
|
29787
|
+
this.showToast(this.t('codeSent'));
|
|
29467
29788
|
this.startResetResendCooldown();
|
|
29468
29789
|
},
|
|
29469
29790
|
error: (err) => {
|
|
@@ -29475,7 +29796,7 @@ class LoginComponent {
|
|
|
29475
29796
|
// HELPERS
|
|
29476
29797
|
// ==========================================
|
|
29477
29798
|
handleLoginSuccess(oauthProvider, mfaCompleted) {
|
|
29478
|
-
this.showToast('
|
|
29799
|
+
this.showToast(this.t('welcome'));
|
|
29479
29800
|
this.onSuccess.emit({
|
|
29480
29801
|
user: this.authService.user(),
|
|
29481
29802
|
mfaCompleted,
|
|
@@ -29504,55 +29825,34 @@ class LoginComponent {
|
|
|
29504
29825
|
}
|
|
29505
29826
|
getErrorMessage(err) {
|
|
29506
29827
|
const error = err;
|
|
29507
|
-
|
|
29508
|
-
|
|
29509
|
-
VALIDATION_MISSING_REQUIRED_FIELDS: 'Faltan campos requeridos',
|
|
29510
|
-
VALIDATION_INVALID_REQUEST: 'Solicitud inválida',
|
|
29828
|
+
// Map error codes to i18n keys
|
|
29829
|
+
const errorKeyMap = {
|
|
29511
29830
|
// Signin
|
|
29512
|
-
AUTHV2_INVALID_CREDENTIALS: '
|
|
29513
|
-
AUTHV2_EMAIL_NOT_VERIFIED: '
|
|
29514
|
-
AUTHV2_ACCOUNT_SUSPENDED: '
|
|
29515
|
-
AUTHV2_SIGNIN_FAILED: 'Error al iniciar sesión',
|
|
29831
|
+
AUTHV2_INVALID_CREDENTIALS: 'errorInvalidCredentials',
|
|
29832
|
+
AUTHV2_EMAIL_NOT_VERIFIED: 'errorEmailNotVerified',
|
|
29833
|
+
AUTHV2_ACCOUNT_SUSPENDED: 'errorAccountSuspended',
|
|
29516
29834
|
// Signup
|
|
29517
|
-
AUTHV2_EMAIL_EXISTS: '
|
|
29518
|
-
|
|
29519
|
-
AUTHV2_WEAK_PASSWORD: 'La contraseña es muy débil',
|
|
29520
|
-
AUTHV2_SIGNUP_FAILED: 'Error al crear la cuenta',
|
|
29835
|
+
AUTHV2_EMAIL_EXISTS: 'errorEmailExists',
|
|
29836
|
+
AUTHV2_WEAK_PASSWORD: 'errorWeakPassword',
|
|
29521
29837
|
// Verification codes
|
|
29522
|
-
AUTHV2_INVALID_CODE: '
|
|
29523
|
-
AUTHV2_EXPIRED_CODE: '
|
|
29524
|
-
AUTHV2_CODE_EXPIRED: '
|
|
29525
|
-
|
|
29526
|
-
AUTHV2_TOO_MANY_ATTEMPTS: 'Demasiados intentos, intenta más tarde',
|
|
29527
|
-
AUTHV2_SEND_CODE_FAILED: 'Error al enviar el código',
|
|
29528
|
-
AUTHV2_ALREADY_VERIFIED: 'Este email ya está verificado',
|
|
29838
|
+
AUTHV2_INVALID_CODE: 'errorInvalidCode',
|
|
29839
|
+
AUTHV2_EXPIRED_CODE: 'errorExpiredCode',
|
|
29840
|
+
AUTHV2_CODE_EXPIRED: 'errorExpiredCode',
|
|
29841
|
+
AUTHV2_TOO_MANY_ATTEMPTS: 'errorTooManyAttempts',
|
|
29529
29842
|
// MFA
|
|
29530
|
-
AUTHV2_MFA_INVALID_CODE: '
|
|
29531
|
-
// Password reset
|
|
29532
|
-
AUTHV2_PASSWORD_RESET_FAILED: 'Error al restablecer la contraseña',
|
|
29533
|
-
AUTHV2_INVALID_CURRENT_PASSWORD: 'Contraseña actual incorrecta',
|
|
29534
|
-
AUTHV2_SAME_PASSWORD: 'La nueva contraseña debe ser diferente',
|
|
29535
|
-
// Session/Tokens
|
|
29536
|
-
AUTHV2_INVALID_TOKEN: 'Sesión inválida',
|
|
29537
|
-
AUTHV2_EXPIRED_TOKEN: 'Tu sesión ha expirado',
|
|
29538
|
-
AUTHV2_SESSION_EXPIRED: 'Tu sesión ha expirado',
|
|
29539
|
-
// User
|
|
29540
|
-
AUTHV2_USER_NOT_FOUND: 'Usuario no encontrado',
|
|
29843
|
+
AUTHV2_MFA_INVALID_CODE: 'errorMFAInvalidCode',
|
|
29541
29844
|
// OAuth
|
|
29542
|
-
POPUP_BLOCKED: '
|
|
29543
|
-
|
|
29544
|
-
INVALID_RESPONSE: 'Error en la respuesta del servidor',
|
|
29545
|
-
OAUTH_FAILED: 'Error de autenticación',
|
|
29546
|
-
OAUTH_EMAIL_EXISTS: 'Este correo ya está registrado con otro método',
|
|
29845
|
+
POPUP_BLOCKED: 'errorPopupBlocked',
|
|
29846
|
+
OAUTH_FAILED: 'errorOAuthFailed',
|
|
29547
29847
|
};
|
|
29548
29848
|
const errorCode = error?.error?.code || error?.code;
|
|
29549
|
-
if (errorCode &&
|
|
29550
|
-
return
|
|
29849
|
+
if (errorCode && errorKeyMap[errorCode]) {
|
|
29850
|
+
return this.t(errorKeyMap[errorCode]);
|
|
29551
29851
|
}
|
|
29552
29852
|
if (error?.error?.message) {
|
|
29553
29853
|
return error.error.message;
|
|
29554
29854
|
}
|
|
29555
|
-
return
|
|
29855
|
+
return this.t('errorGeneric');
|
|
29556
29856
|
}
|
|
29557
29857
|
// ==========================================
|
|
29558
29858
|
// COOLDOWN TIMERS
|
|
@@ -29594,7 +29894,7 @@ class LoginComponent {
|
|
|
29594
29894
|
this.stopResetResendCooldown();
|
|
29595
29895
|
}
|
|
29596
29896
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoginComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
29597
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LoginComponent, isStandalone: true, selector: "val-login", inputs: { props: "props" }, outputs: { onSuccess: "onSuccess", onError: "onError", onMFARequired: "onMFARequired" }, ngImport: i0, template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo -->\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n\n <!-- Login Form -->\n <val-form [props]=\"loginFormProps\" (onSubmit)=\"loginHandler($event)\" />\n\n <!-- OAuth Section -->\n @if (config.showOAuth && config.oauthProviders.length > 0) {\n <div class=\"oauth-separator\">\n <span>o contin\u00FAa con</span>\n </div>\n\n <div class=\"oauth-buttons\">\n @for (provider of config.oauthProviders; track provider) {\n <ion-button\n expand=\"block\"\n fill=\"outline\"\n color=\"dark\"\n (click)=\"loginWithOAuth(provider)\"\n [disabled]=\"isOAuthLoading\"\n >\n @switch (provider) {\n @case ('google') {\n <ion-icon slot=\"start\" name=\"logo-google\"></ion-icon>\n {{ isOAuthLoading ? 'Conectando...' : 'Continuar con Google' }}\n }\n @case ('apple') {\n <ion-icon slot=\"start\" name=\"logo-apple\"></ion-icon>\n {{ isOAuthLoading ? 'Conectando...' : 'Continuar con Apple' }}\n }\n @case ('microsoft') {\n <ion-icon slot=\"start\" name=\"logo-microsoft\"></ion-icon>\n {{ isOAuthLoading ? 'Conectando...' : 'Continuar con Microsoft' }}\n }\n }\n </ion-button>\n }\n </div>\n }\n\n <!-- Register Link -->\n @if (config.showRegister) {\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n \u00BFNo tienes cuenta?\n <a (click)=\"openRegisterModal()\">Registrarse</a>\n </ion-text>\n </div>\n }\n\n <!-- Forgot Password Link -->\n @if (config.showForgotPassword) {\n <div class=\"auth-link forgot-password\">\n <ion-text color=\"dark\">\n \u00BFOlvidaste tu contrase\u00F1a?\n <a (click)=\"openForgotPasswordModal()\">Recuperar contrase\u00F1a</a>\n </ion-text>\n </div>\n }\n\n <!-- Legal Notice -->\n @if (props.legal) {\n <div class=\"legal-notice\">\n <ion-text color=\"medium\">\n <p>\n Utilizamos los servicios de\n @if (props.legal.companyLink) {\n <a [href]=\"props.legal.companyLink\"><strong>{{ props.legal.companyName }}</strong></a>\n } @else {\n <strong>{{ props.legal.companyName }}</strong>\n }\n para ofrecerte una experiencia segura. Al iniciar sesi\u00F3n, aceptas\n nuestros\n @if (props.legal.termsLink) {\n <a [href]=\"props.legal.termsLink\">T\u00E9rminos y Condiciones</a>\n } @else {\n <span>T\u00E9rminos y Condiciones</span>\n }\n y\n @if (props.legal.privacyLink) {\n <a [href]=\"props.legal.privacyLink\">Pol\u00EDtica de Privacidad</a>\n } @else {\n <span>Pol\u00EDtica de Privacidad</span>\n }.\n </p>\n </ion-text>\n </div>\n }\n</div>\n\n<!-- Register Modal -->\n<ion-modal [isOpen]=\"isRegisterModalOpen\" (didDismiss)=\"closeRegisterModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeRegisterModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"registerFormProps\" (onSubmit)=\"registerHandler($event)\" />\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n \u00BFYa tienes cuenta?\n <a (click)=\"closeRegisterModal()\">Iniciar sesi\u00F3n</a>\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Verify Email Modal -->\n<ion-modal [isOpen]=\"isVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"verifyFormProps\" (onSubmit)=\"verifyHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n \u00BFNo has recibido tu c\u00F3digo?\n @if (resendCooldown > 0) {\n <span class=\"cooldown\">Reenviar en {{ resendCooldown }}s</span>\n } @else {\n <a (click)=\"resendCode()\">Reenviar</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Forgot Password Modal -->\n<ion-modal [isOpen]=\"isForgotPasswordModalOpen\" (didDismiss)=\"closeForgotPasswordModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeForgotPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"forgotPasswordFormProps\" (onSubmit)=\"forgotPasswordHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Reset Password Modal -->\n<ion-modal [isOpen]=\"isResetPasswordModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeResetPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"resetPasswordFormProps\" (onSubmit)=\"resetPasswordHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n \u00BFNo has recibido tu c\u00F3digo?\n @if (resetResendCooldown > 0) {\n <span class=\"cooldown\">Reenviar en {{ resetResendCooldown }}s</span>\n } @else {\n <a (click)=\"resendResetCode()\">Reenviar</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- MFA Verify Modal -->\n<ion-modal [isOpen]=\"isMFAVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeMFAVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"mfaVerifyFormProps\" (onSubmit)=\"verifyMFAHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n", styles: [".val-login{width:100%}.val-login--card{padding:1rem;background:var(--ion-color-light);border-radius:16px;box-shadow:0 2px 8px #00000014}.logo-container{max-width:130px;margin-bottom:1.5rem}.auth-link{text-align:center;margin-top:1rem;font-size:.9rem}.auth-link a{color:var(--ion-color-primary);text-decoration:none;font-weight:500;cursor:pointer}.auth-link a:hover{text-decoration:underline}.oauth-separator{display:flex;align-items:center;margin:1.5rem 0}.oauth-separator:before,.oauth-separator:after{content:\"\";flex:1;height:1px;background:var(--ion-color-medium-tint)}.oauth-separator span{padding:0 1rem;color:var(--ion-color-dark);font-size:.85rem}.oauth-buttons{margin-bottom:1rem}.oauth-buttons ion-button{--border-radius: 8px;--border-width: 1px}.oauth-buttons ion-icon{font-size:1.2rem;margin-right:.5rem}.legal-notice{margin-top:1.5rem;padding-top:1rem;border-top:1px solid var(--ion-color-medium-tint)}.legal-notice p{font-size:.75rem;line-height:1.5;text-align:center;margin:0}.legal-notice a{color:var(--ion-color-primary);text-decoration:none}.legal-notice a:hover{text-decoration:underline}.modal-form-section{padding:1rem}.resend-link{text-align:center;margin-top:1rem;font-size:.9rem}.resend-link a{color:var(--ion-color-primary);cursor:pointer;font-weight:500}.resend-link a:hover{text-decoration:underline}.resend-link .cooldown{color:var(--ion-color-medium)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonModal, selector: "ion-modal" }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: FormComponent, selector: "val-form", inputs: ["props"], outputs: ["onSubmit", "onInvalid", "onSelectChange"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }] }); }
|
|
29897
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LoginComponent, isStandalone: true, selector: "val-login", inputs: { props: "props" }, outputs: { onSuccess: "onSuccess", onError: "onError", onMFARequired: "onMFARequired" }, ngImport: i0, template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo -->\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n\n <!-- Login Form -->\n <val-form [props]=\"loginFormProps\" (onSubmit)=\"loginHandler($event)\" />\n\n <!-- OAuth Section -->\n @if (config.showOAuth && config.oauthProviders.length > 0) {\n <div class=\"oauth-separator\">\n <span>{{ t('orContinueWith') }}</span>\n </div>\n\n <div class=\"oauth-buttons\">\n @for (provider of config.oauthProviders; track provider) {\n <ion-button\n expand=\"block\"\n fill=\"outline\"\n color=\"dark\"\n (click)=\"loginWithOAuth(provider)\"\n [disabled]=\"isOAuthLoading\"\n >\n @switch (provider) {\n @case ('google') {\n <ion-icon slot=\"start\" name=\"logo-google\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithGoogle') }}\n }\n @case ('apple') {\n <ion-icon slot=\"start\" name=\"logo-apple\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithApple') }}\n }\n @case ('microsoft') {\n <ion-icon slot=\"start\" name=\"logo-microsoft\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithMicrosoft') }}\n }\n }\n </ion-button>\n }\n </div>\n }\n\n <!-- Register Link -->\n @if (config.showRegister) {\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('noAccount') }}\n <a (click)=\"openRegisterModal()\">{{ t('register') }}</a>\n </ion-text>\n </div>\n }\n\n <!-- Forgot Password Link -->\n @if (config.showForgotPassword) {\n <div class=\"auth-link forgot-password\">\n <ion-text color=\"dark\">\n {{ t('forgotLink') }}\n <a (click)=\"openForgotPasswordModal()\">{{ t('recoverPassword') }}</a>\n </ion-text>\n </div>\n }\n\n <!-- Legal Notice -->\n @if (props.legal) {\n <div class=\"legal-notice\">\n <ion-text color=\"medium\">\n <p>\n {{ t('legalPrefix') }}\n @if (props.legal.companyLink) {\n <a [href]=\"props.legal.companyLink\"><strong>{{ props.legal.companyName }}</strong></a>\n } @else {\n <strong>{{ props.legal.companyName }}</strong>\n }\n {{ t('legalSuffix') }}\n @if (props.legal.termsLink) {\n <a [href]=\"props.legal.termsLink\">{{ t('termsAndConditions') }}</a>\n } @else {\n <span>{{ t('termsAndConditions') }}</span>\n }\n {{ t('and') }}\n @if (props.legal.privacyLink) {\n <a [href]=\"props.legal.privacyLink\">{{ t('privacyPolicy') }}</a>\n } @else {\n <span>{{ t('privacyPolicy') }}</span>\n }.\n </p>\n </ion-text>\n </div>\n }\n</div>\n\n<!-- Register Modal -->\n<ion-modal [isOpen]=\"isRegisterModalOpen\" (didDismiss)=\"closeRegisterModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeRegisterModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"registerFormProps\" (onSubmit)=\"registerHandler($event)\" />\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('hasAccount') }}\n <a (click)=\"closeRegisterModal()\">{{ t('signIn') }}</a>\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Verify Email Modal -->\n<ion-modal [isOpen]=\"isVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"verifyFormProps\" (onSubmit)=\"verifyHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('noCodeReceived') }}\n @if (resendCooldown > 0) {\n <span class=\"cooldown\">{{ t('resendIn', { seconds: resendCooldown.toString() }) }}</span>\n } @else {\n <a (click)=\"resendCode()\">{{ t('resend') }}</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Forgot Password Modal -->\n<ion-modal [isOpen]=\"isForgotPasswordModalOpen\" (didDismiss)=\"closeForgotPasswordModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeForgotPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"forgotPasswordFormProps\" (onSubmit)=\"forgotPasswordHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Reset Password Modal -->\n<ion-modal [isOpen]=\"isResetPasswordModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeResetPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"resetPasswordFormProps\" (onSubmit)=\"resetPasswordHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('noCodeReceived') }}\n @if (resetResendCooldown > 0) {\n <span class=\"cooldown\">{{ t('resendIn', { seconds: resetResendCooldown.toString() }) }}</span>\n } @else {\n <a (click)=\"resendResetCode()\">{{ t('resend') }}</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- MFA Verify Modal -->\n<ion-modal [isOpen]=\"isMFAVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeMFAVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"mfaVerifyFormProps\" (onSubmit)=\"verifyMFAHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n", styles: [".val-login{width:100%}.val-login--card{padding:1rem;background:var(--ion-color-light);border-radius:16px;box-shadow:0 2px 8px #00000014}.logo-container{max-width:130px;margin-bottom:1.5rem}.auth-link{text-align:center;margin-top:1rem;font-size:.9rem}.auth-link a{color:var(--ion-color-primary);text-decoration:none;font-weight:500;cursor:pointer}.auth-link a:hover{text-decoration:underline}.oauth-separator{display:flex;align-items:center;margin:1.5rem 0}.oauth-separator:before,.oauth-separator:after{content:\"\";flex:1;height:1px;background:var(--ion-color-medium-tint)}.oauth-separator span{padding:0 1rem;color:var(--ion-color-dark);font-size:.85rem}.oauth-buttons{margin-bottom:1rem}.oauth-buttons ion-button{--border-radius: 8px;--border-width: 1px}.oauth-buttons ion-icon{font-size:1.2rem;margin-right:.5rem}.legal-notice{margin-top:1.5rem;padding-top:1rem;border-top:1px solid var(--ion-color-medium-tint)}.legal-notice p{font-size:.75rem;line-height:1.5;text-align:center;margin:0}.legal-notice a{color:var(--ion-color-primary);text-decoration:none}.legal-notice a:hover{text-decoration:underline}.modal-form-section{padding:1rem}.resend-link{text-align:center;margin-top:1rem;font-size:.9rem}.resend-link a{color:var(--ion-color-primary);cursor:pointer;font-weight:500}.resend-link a:hover{text-decoration:underline}.resend-link .cooldown{color:var(--ion-color-medium)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonModal, selector: "ion-modal" }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: FormComponent, selector: "val-form", inputs: ["props"], outputs: ["onSubmit", "onInvalid", "onSelectChange"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }] }); }
|
|
29598
29898
|
}
|
|
29599
29899
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoginComponent, decorators: [{
|
|
29600
29900
|
type: Component,
|
|
@@ -29610,7 +29910,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
29610
29910
|
IonToolbar,
|
|
29611
29911
|
FormComponent,
|
|
29612
29912
|
ImageComponent,
|
|
29613
|
-
], template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo -->\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n\n <!-- Login Form -->\n <val-form [props]=\"loginFormProps\" (onSubmit)=\"loginHandler($event)\" />\n\n <!-- OAuth Section -->\n @if (config.showOAuth && config.oauthProviders.length > 0) {\n <div class=\"oauth-separator\">\n <span>
|
|
29913
|
+
], template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo -->\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n\n <!-- Login Form -->\n <val-form [props]=\"loginFormProps\" (onSubmit)=\"loginHandler($event)\" />\n\n <!-- OAuth Section -->\n @if (config.showOAuth && config.oauthProviders.length > 0) {\n <div class=\"oauth-separator\">\n <span>{{ t('orContinueWith') }}</span>\n </div>\n\n <div class=\"oauth-buttons\">\n @for (provider of config.oauthProviders; track provider) {\n <ion-button\n expand=\"block\"\n fill=\"outline\"\n color=\"dark\"\n (click)=\"loginWithOAuth(provider)\"\n [disabled]=\"isOAuthLoading\"\n >\n @switch (provider) {\n @case ('google') {\n <ion-icon slot=\"start\" name=\"logo-google\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithGoogle') }}\n }\n @case ('apple') {\n <ion-icon slot=\"start\" name=\"logo-apple\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithApple') }}\n }\n @case ('microsoft') {\n <ion-icon slot=\"start\" name=\"logo-microsoft\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithMicrosoft') }}\n }\n }\n </ion-button>\n }\n </div>\n }\n\n <!-- Register Link -->\n @if (config.showRegister) {\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('noAccount') }}\n <a (click)=\"openRegisterModal()\">{{ t('register') }}</a>\n </ion-text>\n </div>\n }\n\n <!-- Forgot Password Link -->\n @if (config.showForgotPassword) {\n <div class=\"auth-link forgot-password\">\n <ion-text color=\"dark\">\n {{ t('forgotLink') }}\n <a (click)=\"openForgotPasswordModal()\">{{ t('recoverPassword') }}</a>\n </ion-text>\n </div>\n }\n\n <!-- Legal Notice -->\n @if (props.legal) {\n <div class=\"legal-notice\">\n <ion-text color=\"medium\">\n <p>\n {{ t('legalPrefix') }}\n @if (props.legal.companyLink) {\n <a [href]=\"props.legal.companyLink\"><strong>{{ props.legal.companyName }}</strong></a>\n } @else {\n <strong>{{ props.legal.companyName }}</strong>\n }\n {{ t('legalSuffix') }}\n @if (props.legal.termsLink) {\n <a [href]=\"props.legal.termsLink\">{{ t('termsAndConditions') }}</a>\n } @else {\n <span>{{ t('termsAndConditions') }}</span>\n }\n {{ t('and') }}\n @if (props.legal.privacyLink) {\n <a [href]=\"props.legal.privacyLink\">{{ t('privacyPolicy') }}</a>\n } @else {\n <span>{{ t('privacyPolicy') }}</span>\n }.\n </p>\n </ion-text>\n </div>\n }\n</div>\n\n<!-- Register Modal -->\n<ion-modal [isOpen]=\"isRegisterModalOpen\" (didDismiss)=\"closeRegisterModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeRegisterModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"registerFormProps\" (onSubmit)=\"registerHandler($event)\" />\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('hasAccount') }}\n <a (click)=\"closeRegisterModal()\">{{ t('signIn') }}</a>\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Verify Email Modal -->\n<ion-modal [isOpen]=\"isVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"verifyFormProps\" (onSubmit)=\"verifyHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('noCodeReceived') }}\n @if (resendCooldown > 0) {\n <span class=\"cooldown\">{{ t('resendIn', { seconds: resendCooldown.toString() }) }}</span>\n } @else {\n <a (click)=\"resendCode()\">{{ t('resend') }}</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Forgot Password Modal -->\n<ion-modal [isOpen]=\"isForgotPasswordModalOpen\" (didDismiss)=\"closeForgotPasswordModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeForgotPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"forgotPasswordFormProps\" (onSubmit)=\"forgotPasswordHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Reset Password Modal -->\n<ion-modal [isOpen]=\"isResetPasswordModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeResetPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"resetPasswordFormProps\" (onSubmit)=\"resetPasswordHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('noCodeReceived') }}\n @if (resetResendCooldown > 0) {\n <span class=\"cooldown\">{{ t('resendIn', { seconds: resetResendCooldown.toString() }) }}</span>\n } @else {\n <a (click)=\"resendResetCode()\">{{ t('resend') }}</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- MFA Verify Modal -->\n<ion-modal [isOpen]=\"isMFAVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeMFAVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"mfaVerifyFormProps\" (onSubmit)=\"verifyMFAHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n", styles: [".val-login{width:100%}.val-login--card{padding:1rem;background:var(--ion-color-light);border-radius:16px;box-shadow:0 2px 8px #00000014}.logo-container{max-width:130px;margin-bottom:1.5rem}.auth-link{text-align:center;margin-top:1rem;font-size:.9rem}.auth-link a{color:var(--ion-color-primary);text-decoration:none;font-weight:500;cursor:pointer}.auth-link a:hover{text-decoration:underline}.oauth-separator{display:flex;align-items:center;margin:1.5rem 0}.oauth-separator:before,.oauth-separator:after{content:\"\";flex:1;height:1px;background:var(--ion-color-medium-tint)}.oauth-separator span{padding:0 1rem;color:var(--ion-color-dark);font-size:.85rem}.oauth-buttons{margin-bottom:1rem}.oauth-buttons ion-button{--border-radius: 8px;--border-width: 1px}.oauth-buttons ion-icon{font-size:1.2rem;margin-right:.5rem}.legal-notice{margin-top:1.5rem;padding-top:1rem;border-top:1px solid var(--ion-color-medium-tint)}.legal-notice p{font-size:.75rem;line-height:1.5;text-align:center;margin:0}.legal-notice a{color:var(--ion-color-primary);text-decoration:none}.legal-notice a:hover{text-decoration:underline}.modal-form-section{padding:1rem}.resend-link{text-align:center;margin-top:1rem;font-size:.9rem}.resend-link a{color:var(--ion-color-primary);cursor:pointer;font-weight:500}.resend-link a:hover{text-decoration:underline}.resend-link .cooldown{color:var(--ion-color-medium)}\n"] }]
|
|
29614
29914
|
}], propDecorators: { props: [{
|
|
29615
29915
|
type: Input
|
|
29616
29916
|
}], onSuccess: [{
|
|
@@ -34936,5 +35236,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
34936
35236
|
* Generated bundle index. Do not edit.
|
|
34937
35237
|
*/
|
|
34938
35238
|
|
|
34939
|
-
export { AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_SPACING, AccordionComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, ArticleBuilder, ArticleComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, BannerComponent, BaseDefault, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, CheckInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContentLoaderComponent, CountdownComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CANCEL_BUTTON, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_EMPTY_STATE, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_LEGEND_LABELS, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PAYMENT_STATUS_COLORS, DEFAULT_PAYMENT_STATUS_LABELS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_STATUS_COLORS, DEFAULT_STATUS_LABELS, DEFAULT_WINNER_LABELS, DataTableComponent, DateInputComponent, DateRangeInputComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsSearchComponent, DocsSidebarComponent, DocsTocComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FabComponent, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FooterComponent, FooterLinksComponent, FormComponent, FormFooterComponent, FormSkeletonComponent, FunHeaderComponent, GlowCardComponent, GridSkeletonComponent, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, Icon, IconComponent, IconService, ImageComponent, InAppBrowserService, InfiniteListComponent, InfoComponent, InputType, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LOGIN_DEFAULTS, LanguageSelectorComponent, LayeredCardComponent, LayoutComponent, LinkComponent, LinkProcessorService, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginComponent, MODAL_SIZES, MOTION, MenuComponent, MessagingService, ModalService, MultiSelectSearchComponent, NavigationService, NoContentComponent, NotesBoxComponent, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAuthCallbackComponent, OAuthService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PLATFORM_CONFIGS, PageContentComponent, PageTemplateComponent, PageWrapperComponent, PaginationComponent, PaginationService, ParticipantCardComponent, PasswordInputComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, RadioInputComponent, RaffleStatusCardComponent, RangeInputComponent, RatingComponent, RecapCardComponent, RefresherComponent, RightsFooterComponent, SKELETON_PRESETS, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SegmentControlComponent, SelectSearchComponent, SessionService, ShareButtonsComponent, SimpleComponent, SkeletonComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, TabbedContentComponent, TableSkeletonComponent, TabsComponent, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TicketGridComponent, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TranslatePipe, TypedCollection, VALTECH_ADS_CONFIG, VALTECH_AUTH_CONFIG, VALTECH_DEFAULT_CONTENT, VALTECH_FIREBASE_CONFIG, WinnerDisplayComponent, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, buildPath, collections, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createTitleProps, extractPathParams, getCollectionPath, getDocumentId, goToTop, guestGuard, hasEmulators, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, permissionGuard, permissionGuardFromRoute, provideValtechAds, provideValtechAuth, provideValtechAuthInterceptor, provideValtechFirebase, provideValtechI18n, provideValtechPresets, provideValtechSkeleton, query, replaceSpecialChars, resolveColor, resolveInputDefaultValue, roleGuard, storagePaths, superAdminGuard };
|
|
35239
|
+
export { AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_SPACING, AccordionComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, ArticleBuilder, ArticleComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, BannerComponent, BaseDefault, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, CheckInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContentLoaderComponent, CountdownComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CANCEL_BUTTON, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_EMPTY_STATE, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_LEGEND_LABELS, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PAYMENT_STATUS_COLORS, DEFAULT_PAYMENT_STATUS_LABELS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_STATUS_COLORS, DEFAULT_STATUS_LABELS, DEFAULT_WINNER_LABELS, DataTableComponent, DateInputComponent, DateRangeInputComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsSearchComponent, DocsSidebarComponent, DocsTocComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FabComponent, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FooterComponent, FooterLinksComponent, FormComponent, FormFooterComponent, FormSkeletonComponent, FunHeaderComponent, GlowCardComponent, GridSkeletonComponent, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, Icon, IconComponent, IconService, ImageComponent, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LOGIN_DEFAULTS, LanguageSelectorComponent, LayeredCardComponent, LayoutComponent, LinkComponent, LinkProcessorService, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginComponent, MODAL_SIZES, MOTION, MenuComponent, MessagingService, ModalService, MultiSelectSearchComponent, NavigationService, NoContentComponent, NotesBoxComponent, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAuthCallbackComponent, OAuthService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PLATFORM_CONFIGS, PageContentComponent, PageTemplateComponent, PageWrapperComponent, PaginationComponent, PaginationService, ParticipantCardComponent, PasswordInputComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, RadioInputComponent, RaffleStatusCardComponent, RangeInputComponent, RatingComponent, RecapCardComponent, RefresherComponent, RightsFooterComponent, SKELETON_PRESETS, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SegmentControlComponent, SelectSearchComponent, SessionService, ShareButtonsComponent, SimpleComponent, SkeletonComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, TabbedContentComponent, TableSkeletonComponent, TabsComponent, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TicketGridComponent, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TranslatePipe, TypedCollection, VALTECH_ADS_CONFIG, VALTECH_AUTH_CONFIG, VALTECH_DEFAULT_CONTENT, VALTECH_FIREBASE_CONFIG, WinnerDisplayComponent, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, buildPath, collections, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createTitleProps, extractPathParams, getCollectionPath, getDocumentId, goToTop, guestGuard, hasEmulators, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, permissionGuard, permissionGuardFromRoute, provideValtechAds, provideValtechAuth, provideValtechAuthInterceptor, provideValtechFirebase, provideValtechI18n, provideValtechPresets, provideValtechSkeleton, query, replaceSpecialChars, resolveColor, resolveInputDefaultValue, roleGuard, storagePaths, superAdminGuard };
|
|
34940
35240
|
//# sourceMappingURL=valtech-components.mjs.map
|