UNPKG

@krowdy/kds-auth

Version:

React components that implement Google's Material Design.

617 lines (548 loc) 20.8 kB
import _regeneratorRuntime from "@babel/runtime/regenerator"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _extends from "@babel/runtime/helpers/esm/extends"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useState } from 'react'; import clsx from 'clsx'; import { Button, Checkbox, makeStyles, TextField, FormControlLabel, IconButton, Typography, CircularProgress } from '@krowdy/kds-core'; import { Visibility as VisibilityIcon, VisibilityOff as VisibilityOffIcon } from '@material-ui/icons'; import GoogleButton from './GoogleButton'; import MicrosoftButton from './MicrosoftButton'; import { useAuth } from '../utils'; import { ViewType } from '../AuthContext/utils'; var inputLabels = { login: 'Correo o celular', newPassword: 'Nueva contraseña', 'only-email': 'Correo electrónico', 'only-phone': 'Número de celular', password: 'Contraseña', 'phone-and-email': 'Correo o celular', verify: 'Código de verificación' }; var errorMessages = { login: 'Error al verificar cuenta, comunícate con soporte.', newCode: 'Código caducado. Enviamos un nuevo código a tu correo.', newPassword: 'Debe tener mínimo 8 caracteres.', password: 'Contraseña incorrecta. Vuelve a intentarlo o haz click en “¿Olvidaste tu contraseña?”', verify: 'Código de verificación erróneo.' }; var _ref6 = /*#__PURE__*/React.createElement(VisibilityIcon, { color: "inherit", fontSize: "inherit" }); var _ref7 = /*#__PURE__*/React.createElement(VisibilityOffIcon, { color: "inherit", fontSize: "inherit" }); var _ref8 = /*#__PURE__*/React.createElement(GoogleButton, null); var _ref9 = /*#__PURE__*/React.createElement(MicrosoftButton, null); var _ref10 = /*#__PURE__*/React.createElement(CircularProgress, { disableShrink: true, size: 18 }); var KrowdyOneTap = forwardRef(function (_ref, ref) { var _ref$onChangeUserLogi = _ref.onChangeUserLogin, onChangeUserLogin = _ref$onChangeUserLogi === void 0 ? function () {} : _ref$onChangeUserLogi, typeView = _ref.typeView, currentUser = _ref.currentUser; var _useAuth = useAuth(), verifyAccount = _useAuth.verifyAccount, loginByPassword = _useAuth.loginByPassword, loginByCode = _useAuth.loginByCode, typeCode = _useAuth.typeCode, onSuccessLogin = _useAuth.onSuccessLogin, updateAccount = _useAuth.updateAccount, loading = _useAuth.loading, loginWith = _useAuth.loginWith, onUpdatePassword = _useAuth.onUpdatePassword, onUpdateState = _useAuth.onUpdateState, onChangeView = _useAuth.onChangeView, onError = _useAuth.onError, logout = _useAuth.logout; var classes = useStyles(); var _useState = useState(null), _useState2 = _slicedToArray(_useState, 2), loginkey = _useState2[0], setLoginKey = _useState2[1]; var _useState3 = useState(typeView === ViewType.Login ? currentUser : ''), _useState4 = _slicedToArray(_useState3, 2), valueInput = _useState4[0], setValueInput = _useState4[1]; var _useState5 = useState(''), _useState6 = _slicedToArray(_useState5, 2), passwordValue = _useState6[0], setPasswordValue = _useState6[1]; var _useState7 = useState(false), _useState8 = _slicedToArray(_useState7, 2), isErrorLogin = _useState8[0], setErrorLogin = _useState8[1]; var _useState9 = useState(false), _useState10 = _slicedToArray(_useState9, 2), isCodeValidationExpired = _useState10[0], setIsCodeValidationExpired = _useState10[1]; var _useState11 = useState(false), _useState12 = _slicedToArray(_useState11, 2), showPassword = _useState12[0], setShowPassword = _useState12[1]; var _useState13 = useState(true), _useState14 = _slicedToArray(_useState13, 2), keepSession = _useState14[0], setKeepSession = _useState14[1]; var _useState15 = useState({}), _useState16 = _slicedToArray(_useState15, 2), register = _useState16[0], setRegister = _useState16[1]; var isNextDisabled = useMemo(function () { switch (typeView) { case ViewType.NewPassword: return passwordValue.length < 8; case ViewType.Register: { var firstName = register.firstName, lastName = register.lastName; return !(firstName && lastName); } case ViewType.Login: if (loginWith === 'only-email') { var emailRegex = /^[-\w.%+]{1,64}@(?:[A-Z0-9-]{1,63}\.){1,125}[A-Z]{2,63}$/i; return !valueInput || !emailRegex.test(valueInput); } else { return !valueInput; } case ViewType.Password: case ViewType.Recovery: return !passwordValue; default: return false; } }, [typeView, valueInput, register, loginWith, passwordValue]); var _handleChangeInput = useCallback(function (_ref2) { var _ref2$target = _ref2.target, value = _ref2$target.value, name = _ref2$target.name; setValueInput(value); if (name === 'login' && value) { var res = value.split(new RegExp('[ @ | . ]')); var domain = res ? res[res.length - 2] : null; if (domain && 'gmail'.indexOf(domain) !== -1) setLoginKey('google');else if (domain && ('outlook'.indexOf(domain) !== -1 || 'hotmail'.indexOf(domain) !== -1)) setLoginKey('microsoft');else setLoginKey(null); } }, []); var _handleChangePassword = useCallback(function (_ref3) { var value = _ref3.target.value; setPasswordValue(value); }, []); var _handleChangeRegister = useCallback(function (_ref4) { var _ref4$target = _ref4.target, value = _ref4$target.value, name = _ref4$target.name; setRegister(function (prev) { return _extends({}, prev, _defineProperty({}, name, value)); }); }, []); var _handleSubmitSetEmail = useCallback(function _callee(valueInput, nextView) { var _await$verifyAccount, hasPassword, success, value, type; return _regeneratorRuntime.async(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: if (!(nextView && ![ViewType.Password, ViewType.Verify].includes(nextView))) { _context.next = 2; break; } throw new Error('nextView is no valid'); case 2: _context.next = 4; return _regeneratorRuntime.awrap(verifyAccount(valueInput, Boolean(nextView))); case 4: _await$verifyAccount = _context.sent; hasPassword = _await$verifyAccount.hasPassword; success = _await$verifyAccount.success; value = _await$verifyAccount.value; type = _await$verifyAccount.type; setErrorLogin(!success); if (success) { onChangeUserLogin(type === 'phone' ? value : valueInput); onChangeView(nextView !== null && nextView !== void 0 ? nextView : hasPassword ? ViewType.Password : ViewType.Verify); setLoginKey(null); } case 11: case "end": return _context.stop(); } } }, null, null, null, Promise); }, [onChangeUserLogin, onChangeView, verifyAccount]); var _handleNext = useCallback(function _callee2(e) { var _await$loginByPasswor, isPasswordValid, _await$loginByCode, isCodeValid, isFirstTime, error, _ref5, successRegister, _await$onUpdatePasswo, successPasswword, _await$loginByCode2, isRecoveryValid; return _regeneratorRuntime.async(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: if (!(e.charCode && e.charCode !== 13 || isNextDisabled || loading)) { _context2.next = 2; break; } return _context2.abrupt("return"); case 2: setIsCodeValidationExpired(false); _context2.prev = 3; _context2.t0 = typeView; _context2.next = _context2.t0 === ViewType.Login ? 7 : _context2.t0 === ViewType.Password ? 9 : _context2.t0 === ViewType.Verify ? 15 : _context2.t0 === ViewType.Register ? 25 : _context2.t0 === ViewType.NewPassword ? 34 : _context2.t0 === ViewType.Recovery ? 40 : 47; break; case 7: _handleSubmitSetEmail(valueInput); return _context2.abrupt("break", 48); case 9: _context2.next = 11; return _regeneratorRuntime.awrap(loginByPassword({ email: currentUser, keepSession: keepSession, password: passwordValue })); case 11: _await$loginByPasswor = _context2.sent; isPasswordValid = _await$loginByPasswor.success; setErrorLogin(!isPasswordValid); return _context2.abrupt("break", 48); case 15: _context2.next = 17; return _regeneratorRuntime.awrap(loginByCode({ code: passwordValue, keepSession: keepSession, type: typeCode, value: currentUser })); case 17: _await$loginByCode = _context2.sent; isCodeValid = _await$loginByCode.success; isFirstTime = _await$loginByCode.isNew; error = _await$loginByCode.error; setErrorLogin(!isCodeValid); if (error === 'Validation code expired') setIsCodeValidationExpired(!isCodeValid); if (isCodeValid) if (isFirstTime) onChangeView(ViewType.Register);else onSuccessLogin(true); return _context2.abrupt("break", 48); case 25: _context2.next = 27; return _regeneratorRuntime.awrap(updateAccount(register)); case 27: _context2.t1 = _context2.sent; if (_context2.t1) { _context2.next = 30; break; } _context2.t1 = {}; case 30: _ref5 = _context2.t1; successRegister = _ref5.success; if (successRegister) { setValueInput(''); setPasswordValue(''); } return _context2.abrupt("break", 48); case 34: _context2.next = 36; return _regeneratorRuntime.awrap(onUpdatePassword(passwordValue)); case 36: _await$onUpdatePasswo = _context2.sent; successPasswword = _await$onUpdatePasswo.success; if (!successPasswword) setErrorLogin(true); return _context2.abrupt("break", 48); case 40: _context2.next = 42; return _regeneratorRuntime.awrap(loginByCode({ code: passwordValue, keepSession: keepSession, type: typeCode, value: currentUser })); case 42: _await$loginByCode2 = _context2.sent; isRecoveryValid = _await$loginByCode2.success; setErrorLogin(!isRecoveryValid); if (isRecoveryValid) { setPasswordValue(''); onChangeView(ViewType.NewPassword); } return _context2.abrupt("break", 48); case 47: return _context2.abrupt("break", 48); case 48: _context2.next = 53; break; case 50: _context2.prev = 50; _context2.t2 = _context2["catch"](3); onError(_context2.t2, typeView); case 53: case "end": return _context2.stop(); } } }, null, null, [[3, 50]], Promise); }, [isNextDisabled, loading, typeView, _handleSubmitSetEmail, valueInput, loginByPassword, currentUser, keepSession, passwordValue, loginByCode, typeCode, onChangeView, onSuccessLogin, updateAccount, register, onUpdatePassword, onError]); var _handleClickShowPassword = useCallback(function () { setShowPassword(function (prev) { return !prev; }); }, []); var _handleKeepSession = useCallback(function () { setKeepSession(function (prev) { onUpdateState({ keepSession: !prev }); return !prev; }); }, [onUpdateState]); var _handleResendPassword = useCallback(function _callee3() { var _await$verifyAccount2, success; return _regeneratorRuntime.async(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: _context3.next = 2; return _regeneratorRuntime.awrap(verifyAccount(currentUser, true)); case 2: _await$verifyAccount2 = _context3.sent; success = _await$verifyAccount2.success; if (success) setErrorLogin(false); case 5: case "end": return _context3.stop(); } } }, null, null, null, Promise); }, [currentUser, verifyAccount]); var _handleForgotPassword = useCallback(function () { setPasswordValue(''); onChangeView(ViewType.Recovery); verifyAccount(valueInput, true); // eslint-disable-next-line react-hooks/exhaustive-deps }, [verifyAccount, valueInput]); useImperativeHandle(ref, function () { return { submitEmail: function submitEmail(email, nextView) { logout(); _handleChangeInput({ target: { name: 'email', value: email } }); _handleSubmitSetEmail(email, nextView); } }; }); return /*#__PURE__*/React.createElement(React.Fragment, null, [ViewType.Password, ViewType.Verify, ViewType.Recovery, ViewType.NewPassword].includes(typeView) && /*#__PURE__*/React.createElement(TextField, { autoFocus: true, className: clsx(classes.labelOutlined), error: isErrorLogin || isCodeValidationExpired, FormHelperTextProps: { classes: { contained: classes.helperText } }, fullWidth: true, helperText: isCodeValidationExpired ? errorMessages.newCode : (isErrorLogin || [ViewType.Recovery, ViewType.NewPassword].includes(typeView)) && errorMessages[typeView], InputProps: { className: classes.inputStyle, classes: { input: classes.emailInput, root: clsx(isErrorLogin && classes.colorError) }, endAdornment: [ViewType.Password, ViewType.NewPassword].includes(typeView) && /*#__PURE__*/React.createElement(IconButton, { className: classes.iconShowPassword, onClick: _handleClickShowPassword, size: "small" }, showPassword ? _ref6 : _ref7) }, label: [ViewType.Verify, ViewType.Recovery].includes(typeView) ? 'Código de verificación' : inputLabels[typeView], onChange: _handleChangePassword, onKeyPress: _handleNext, required: true, type: showPassword || [ViewType.Verify, ViewType.Recovery].includes(typeView) ? 'text' : 'password', value: passwordValue, variant: "outlined" }), typeView === ViewType.Login && /*#__PURE__*/React.createElement(TextField, { autoFocus: true, className: clsx(classes.fieldEmail, classes.labelOutlined), error: isErrorLogin, fullWidth: true, helperText: isErrorLogin && errorMessages[typeView], InputProps: { classes: { input: classes.emailInput, root: classes.textfield } }, label: inputLabels[loginWith], name: "login", onChange: _handleChangeInput, onKeyPress: _handleNext, type: "email", value: valueInput, variant: "outlined" }), typeView === ViewType.Register && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TextField, { autoFocus: true, className: clsx(classes.labelOutlined), fullWidth: true // InputLabelProps={{ // classes: { // root: classes.labelOutlined // } // }} , InputProps: { classes: { input: classes.emailInput, root: classes.textfield } }, label: "Nombres", name: "firstName", onChange: _handleChangeRegister, required: true, value: register.firstName || '', variant: "outlined" }), /*#__PURE__*/React.createElement(TextField, { className: clsx(classes.fieldEmail, classes.labelOutlined), fullWidth: true // InputLabelProps={{ // classes: { // root: classes.labelOutlined // } // }} , InputProps: { classes: { input: classes.emailInput, root: classes.textfield } }, label: "Apellidos", name: "lastName", onChange: _handleChangeRegister, required: true, value: register.lastName || '', variant: "outlined" }), /*#__PURE__*/React.createElement(TextField, { className: clsx(classes.fieldEmail, classes.labelOutlined), fullWidth: true // InputLabelProps={{ // classes: { // root: classes.labelOutlined // } // }} , InputProps: { classes: { input: classes.emailInput, root: classes.textfield } }, label: currentUser.indexOf('@') !== -1 ? 'Celular (opcional)' : 'Correo electrónico (opcional)', name: currentUser.indexOf('@') !== -1 ? 'phone' : 'email', onChange: _handleChangeRegister, value: register[currentUser.indexOf('@') !== -1 ? 'phone' : 'email'] || '', variant: "outlined" })), loginkey && /*#__PURE__*/React.createElement("div", { className: classes.margintop }, loginkey === 'google' && _ref8, loginkey === 'microsoft' && _ref9), [ViewType.Password, ViewType.Verify, ViewType.NewPassword].includes(typeView) && /*#__PURE__*/React.createElement(FormControlLabel, { className: classes.labelCheckbox, control: /*#__PURE__*/React.createElement(Checkbox, { checked: keepSession, color: "primary", onChange: _handleKeepSession }), label: "Mantener mi sesi\xF3n abierta" }), typeView === ViewType.NewPassword && /*#__PURE__*/React.createElement(Typography, { align: "center", className: clsx(classes.textfield, classes.textEnd, classes.nextButton2), color: "disabled" }, "No olvides revisar tu contrase\xF1a antes de establecerla para evitar cualquier inconveniente m\xE1s adelante."), /*#__PURE__*/React.createElement(Button, { className: clsx(classes.nextButton, loginkey && classes.nextButton2), color: "primary", disabled: isNextDisabled || loading, fullWidth: true, onClick: _handleNext, startIcon: loading && _ref10, variant: "contained" }, "Continuar"), [ViewType.Password, ViewType.Verify, ViewType.Recovery].includes(typeView) && /*#__PURE__*/React.createElement("div", { className: classes.endContent }, typeView === ViewType.Password ? /*#__PURE__*/React.createElement(Button, { color: "primary", onClick: _handleForgotPassword, size: "small" }, "\xBFOlvidaste tu contrase\xF1a?") : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Typography, { className: clsx(classes.textfield, classes.textEnd), color: "disabled" }, "\xBFNo lo encuentras?"), /*#__PURE__*/React.createElement(Button, { className: classes.capitalizeText, color: "primary", onClick: _handleResendPassword, size: "small" }, "Reenviar")))); }); var useStyles = makeStyles(function (_ref11) { var spacing = _ref11.spacing, palette = _ref11.palette; return { capitalizeText: { textTransform: 'capitalize' }, colorError: { color: palette.error.main }, emailInput: { color: palette.common.black, // fontSize: 14, padding: spacing(1.5) }, endContent: { alignItems: 'center', display: 'flex', justifyContent: 'center', marginTop: spacing(3) }, fieldEmail: { marginTop: spacing(1.5) }, helperText: { marginLeft: 0 }, inputStyle: { fontSize: 14 }, labelCheckbox: { '& > span': { fontSize: 14, padding: spacing(1, 1, 1, 0) }, margin: spacing(2, 0, 0, 0) }, labelOutlined: { '& .MuiInputLabel-outlined': { transform: 'translate(8px, 13px) scale(1)' }, '& .MuiInputLabel-outlined.MuiInputLabel-shrink': { transform: 'translate(8px, -5px) scale(0.9)' } }, margintop: { marginTop: spacing(4) }, nextButton: { marginTop: spacing(4) }, nextButton2: { marginTop: spacing(2) }, outlinedLabel: { top: -8 }, textEnd: { color: palette.grey[600] }, textfield: { fontSize: 14 } }; }, { name: 'KrowdyOneTap' }); export default React.memo(KrowdyOneTap);