@movalib/movalib-commons 1.1.61 → 1.1.63

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/devIndex.tsx CHANGED
@@ -195,9 +195,11 @@ const App = () => {
195
195
 
196
196
 
197
197
  {openAccountValidation && <AccountValidation smsValidation={true} movaAppType={MovaAppType.GARAGE}
198
- onSubmit={function (success: boolean, message: string): void {
199
- throw new Error('Function not implemented.');
200
- } } /> }
198
+ onSubmit={function (success: boolean, message: string): void {
199
+ throw new Error('Function not implemented.');
200
+ } } onResendSecurityCode={function (success: boolean, message: string): void {
201
+ throw new Error('Function not implemented.');
202
+ } } /> }
201
203
 
202
204
  </ThemeProvider>
203
205
  </LocalizationProvider>
package/dist/devIndex.js CHANGED
@@ -157,6 +157,8 @@ var App = function () {
157
157
  throw new Error('Function not implemented.');
158
158
  } })] }))] })), (0, jsx_runtime_1.jsx)(material_1.Box, __assign({ style: Tools_1.flexCenter }, { children: (0, jsx_runtime_1.jsx)(material_1.Button, __assign({ onClick: function () { return setOpenAccountValidation(!openAccountValidation); } }, { children: "Validation de compte" })) })), openAccountValidation && (0, jsx_runtime_1.jsx)(AccountValidation_1.default, { smsValidation: true, movaAppType: Enums_1.MovaAppType.GARAGE, onSubmit: function (success, message) {
159
159
  throw new Error('Function not implemented.');
160
+ }, onResendSecurityCode: function (success, message) {
161
+ throw new Error('Function not implemented.');
160
162
  } })] })) })) }));
161
163
  };
162
164
  var root = (0, client_1.createRoot)(document.getElementById('root'));
@@ -4,6 +4,7 @@ interface AccountValidationProps {
4
4
  movaAppType: MovaAppType;
5
5
  smsValidation: boolean;
6
6
  onSubmit: (success: boolean, message: string) => void;
7
+ onResendSecurityCode: (success: boolean, message: string) => void;
7
8
  }
8
9
  declare const AccountValidation: FunctionComponent<AccountValidationProps>;
9
10
  export default AccountValidation;
@@ -29,28 +29,29 @@ var Tools_1 = require("./helpers/Tools");
29
29
  var MovaDialog_1 = __importDefault(require("./MovaDialog"));
30
30
  var logo_large_png_1 = __importDefault(require("./assets/images/logo/logo_large.png"));
31
31
  var logo_pro_large_png_1 = __importDefault(require("./assets/images/logo/logo_pro_large.png"));
32
+ var ConfirmationDialog_1 = __importDefault(require("./ConfirmationDialog"));
32
33
  var initialFormState = {
33
34
  password: { value: '', isValid: true },
34
35
  confirmation: { value: '', isValid: true },
35
36
  securityCode: { value: '', isValid: true },
37
+ phoneNumber: { value: '', isValid: true },
36
38
  };
37
39
  var AccountValidation = function (_a) {
38
40
  var _b, _c, _d, _e;
39
- var movaAppType = _a.movaAppType, smsValidation = _a.smsValidation, onSubmit = _a.onSubmit;
41
+ var movaAppType = _a.movaAppType, smsValidation = _a.smsValidation, onSubmit = _a.onSubmit, onResendSecurityCode = _a.onResendSecurityCode;
40
42
  var _f = (0, react_1.useState)(true), loading = _f[0], setLoading = _f[1];
41
- var _g = (0, react_1.useState)(initialFormState), passwordForm = _g[0], setPasswordForm = _g[1];
43
+ var _g = (0, react_1.useState)(initialFormState), validationForm = _g[0], setValidationForm = _g[1];
42
44
  var location = (0, react_router_dom_1.useLocation)();
43
45
  var history = (0, react_router_dom_1.useHistory)();
44
46
  var theme = (0, material_1.useTheme)();
45
47
  var _h = (0, react_1.useState)(false), emptyPwd = _h[0], setEmptyPwd = _h[1];
46
48
  var _j = (0, react_1.useState)(false), showPassword = _j[0], setShowPassword = _j[1];
49
+ var _k = (0, react_1.useState)(false), openPhoneNumberInput = _k[0], setOpenPhoneNumberInput = _k[1];
47
50
  var isMobile = (0, material_1.useMediaQuery)(theme.breakpoints.down('sm'));
48
51
  (0, react_1.useEffect)(function () {
49
52
  var params = new URLSearchParams(location.search);
50
53
  var token = params.get('token');
51
54
  // Si cette variable est transmise, cela signifie que le compte a été créé sans mot de passe
52
- Logger_1.default.info(params);
53
- Logger_1.default.info(Boolean(params.get('emptyPwd')));
54
55
  var localEmptyPwd = Boolean(params.get('emptyPwd'));
55
56
  setEmptyPwd(localEmptyPwd);
56
57
  if (token) {
@@ -92,24 +93,24 @@ var AccountValidation = function (_a) {
92
93
  var fieldName = e.target.name;
93
94
  var fieldValue = e.target.value;
94
95
  var newField = (_a = {}, _a[fieldName] = { value: fieldValue, isValid: true }, _a);
95
- setPasswordForm(__assign(__assign({}, passwordForm), newField));
96
+ setValidationForm(__assign(__assign({}, validationForm), newField));
96
97
  }
97
98
  };
98
99
  var validateForm = function () {
99
- var newForm = __assign({}, passwordForm);
100
+ var newForm = __assign({}, validationForm);
100
101
  // Validator pour les champs obligatoires
101
- newForm.password = (0, Tools_1.validateField)(passwordForm.password, function (value) { return !!value; }, 'Champ obligatoire');
102
- newForm.confirmation = (0, Tools_1.validateField)(passwordForm.confirmation, function (value) { return !!value; }, 'Champ obligatoire');
102
+ newForm.password = (0, Tools_1.validateField)(validationForm.password, function (value) { return !!value; }, 'Champ obligatoire');
103
+ newForm.confirmation = (0, Tools_1.validateField)(validationForm.confirmation, function (value) { return !!value; }, 'Champ obligatoire');
103
104
  if (smsValidation)
104
- newForm.securityCode = (0, Tools_1.validateField)(passwordForm.securityCode, function (value) { return !!value; }, 'Champ obligatoire');
105
+ newForm.securityCode = (0, Tools_1.validateField)(validationForm.securityCode, function (value) { return !!value; }, 'Champ obligatoire');
105
106
  // Validator pour le mot de passe
106
- newForm.password = (0, Tools_1.validateField)(passwordForm.password, function (value) { return value.length >= 10 && /[a-z]/.test(value) && /[A-Z]/.test(value); }, 'Votre mot de passe doit faire au moins 10 caractères et contenir une majuscule et une minuscule minimum');
107
+ newForm.password = (0, Tools_1.validateField)(validationForm.password, function (value) { return value.length >= 10 && /[a-z]/.test(value) && /[A-Z]/.test(value); }, 'Votre mot de passe doit faire au moins 10 caractères et contenir une majuscule et une minuscule minimum');
107
108
  // Second validator pour le mot de passe (confirmation)
108
- newForm.confirmation = (0, Tools_1.validateField)(passwordForm.confirmation, function (value) { return value === passwordForm.password.value; }, "Les mots de passe doivent être identiques");
109
+ newForm.confirmation = (0, Tools_1.validateField)(validationForm.confirmation, function (value) { return value === validationForm.password.value; }, "Les mots de passe doivent être identiques");
109
110
  // Validator pour le code de sécurité
110
111
  if (smsValidation)
111
- newForm.securityCode = (0, Tools_1.validateField)(passwordForm.securityCode, function (value) { return value.length === 6; }, "Le code doit contenir 6 chiffres");
112
- setPasswordForm(newForm);
112
+ newForm.securityCode = (0, Tools_1.validateField)(validationForm.securityCode, function (value) { return value.length === 6; }, "Le code doit contenir 6 chiffres");
113
+ setValidationForm(newForm);
113
114
  return newForm.password.isValid && newForm.confirmation.isValid && (smsValidation ? newForm.securityCode.isValid : true);
114
115
  };
115
116
  var handleValidateAccount = function () {
@@ -118,8 +119,8 @@ var AccountValidation = function (_a) {
118
119
  var params = new URLSearchParams(location.search);
119
120
  var req = {
120
121
  token: !smsValidation ? params.get('token') : null,
121
- securityCode: smsValidation ? passwordForm.securityCode.value : null,
122
- password: passwordForm.password.value,
122
+ securityCode: smsValidation ? validationForm.securityCode.value : null,
123
+ password: validationForm.password.value,
123
124
  demoGarage: Boolean(params.get('demoGarage'))
124
125
  };
125
126
  activateAccount(req);
@@ -137,25 +138,73 @@ var AccountValidation = function (_a) {
137
138
  movaAppType === Enums_1.MovaAppType.INDIVIDUAL ? logo_large_png_1.default :
138
139
  movaAppType === Enums_1.MovaAppType.ADMIN ? logo_large_png_1.default : logo_large_png_1.default;
139
140
  };
141
+ var handleOpenResendCode = function () {
142
+ setOpenPhoneNumberInput(true);
143
+ };
144
+ var validatePhoneNumber = function () {
145
+ var _a, _b, _c, _d, _e;
146
+ var newForm = validationForm;
147
+ var newField;
148
+ // Validator 'phoneNumber'
149
+ if ((_a = newForm.phoneNumber) === null || _a === void 0 ? void 0 : _a.value) {
150
+ if (((_b = newForm.phoneNumber) === null || _b === void 0 ? void 0 : _b.value.length) < 10) {
151
+ newField = { value: (_c = validationForm.phoneNumber) === null || _c === void 0 ? void 0 : _c.value, error: "Le n° de téléphone est invalide." };
152
+ }
153
+ else {
154
+ newField = { value: (_d = validationForm.phoneNumber) === null || _d === void 0 ? void 0 : _d.value, error: '' };
155
+ }
156
+ newForm = __assign(__assign({}, newForm), { phoneNumber: newField });
157
+ }
158
+ setValidationForm(newForm);
159
+ return !Boolean((_e = newForm.phoneNumber) === null || _e === void 0 ? void 0 : _e.error);
160
+ };
161
+ var resendCode = function () {
162
+ var _a;
163
+ if (validatePhoneNumber()) {
164
+ var req = {
165
+ phoneNumber: (_a = validationForm.phoneNumber) === null || _a === void 0 ? void 0 : _a.value
166
+ };
167
+ UserService_1.default.resendSecurityCode(req)
168
+ .then(function (response) {
169
+ var _a, _b;
170
+ Logger_1.default.info(response);
171
+ if (response.success) {
172
+ if (onResendSecurityCode) {
173
+ onResendSecurityCode(response.success, (_a = response.data) !== null && _a !== void 0 ? _a : '');
174
+ }
175
+ }
176
+ else {
177
+ if (onResendSecurityCode) {
178
+ onResendSecurityCode(response.success, (_b = response.error) !== null && _b !== void 0 ? _b : '');
179
+ }
180
+ }
181
+ }).catch(function (error) {
182
+ Logger_1.default.error(error);
183
+ if (onSubmit) {
184
+ onSubmit(false, error);
185
+ }
186
+ });
187
+ }
188
+ };
140
189
  return ((0, jsx_runtime_1.jsxs)("div", { children: [(emptyPwd || smsValidation) &&
141
- (0, jsx_runtime_1.jsx)(MovaDialog_1.default, __assign({ leafImageColor: 'pink', titleStyle: getTitleStyle(), fullScreen: isMobile, open: emptyPwd, closable: false, onClose: function () {
190
+ (0, jsx_runtime_1.jsx)(MovaDialog_1.default, __assign({ leafImageColor: 'pink', titleStyle: getTitleStyle(), fullScreen: isMobile, open: emptyPwd || smsValidation, closable: false, onClose: function () {
142
191
  throw new Error('Function not implemented.');
143
192
  }, actions: (0, jsx_runtime_1.jsx)(lab_1.LoadingButton, __assign({ type: "submit", onClick: handleValidateAccount, fullWidth: true, variant: "contained", sx: { mt: 4, mb: 0 } }, { children: (0, jsx_runtime_1.jsx)("span", { children: "Activer mon compte" }) })) }, { children: (0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true }, { children: [(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 12 }, { children: (0, jsx_runtime_1.jsxs)(material_1.Box, __assign({ sx: {
144
193
  display: 'flex',
145
194
  flexDirection: 'column',
146
195
  alignItems: 'center',
147
- } }, { children: [(0, jsx_runtime_1.jsx)("img", { src: getMovaLogo(), style: { width: '50%' } }), (0, jsx_runtime_1.jsx)("br", {})] })) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 12 }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, __assign({ sx: { mt: 2, mb: 2 } }, { children: movaAppType === Enums_1.MovaAppType.INDIVIDUAL ?
196
+ } }, { children: [(0, jsx_runtime_1.jsx)("img", { src: getMovaLogo(), style: { width: '50%' } }), (0, jsx_runtime_1.jsx)("br", {})] })) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 12 }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, __assign({ sx: { mt: 2, mb: 3 } }, { children: movaAppType === Enums_1.MovaAppType.INDIVIDUAL ?
148
197
  "Pour commencer, définis ton mot de passe et active ton compte 😉"
149
198
  :
150
- "Pour commencer, définissez votre mot de passe et activez votre compte 😉" })) })), smsValidation && (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 12 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { label: "Code re\u00E7u par SMS", required: true, fullWidth: true, name: "securityCode", variant: "outlined", value: (_b = passwordForm.securityCode) === null || _b === void 0 ? void 0 : _b.value, error: !((_c = passwordForm.securityCode) === null || _c === void 0 ? void 0 : _c.isValid), helperText: Boolean((_d = passwordForm.securityCode) === null || _d === void 0 ? void 0 : _d.error) ? (_e = passwordForm.securityCode) === null || _e === void 0 ? void 0 : _e.error : "Code à 6 chiffres", onChange: function (e) { return handleInputChange(e); }, inputProps: {
151
- maxLength: 6,
152
- inputMode: 'numeric',
153
- pattern: '[0-9]*' // Permet seulement la saisie de chiffres
154
- } }) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 12 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { margin: "normal", required: true, fullWidth: true, name: "password", label: "Mot de passe", type: showPassword ? 'text' : 'password', id: "password", autoComplete: "current-password", onChange: function (e) { return handleInputChange(e); }, value: passwordForm.password.value, error: !passwordForm.password.isValid, helperText: Boolean(passwordForm.password.error) ? passwordForm.password.error : "10 caractères minimum, 1 majuscule, 1 minuscule", InputProps: {
199
+ "Pour commencer, définissez votre mot de passe et activez votre compte 😉" })) })), smsValidation && (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 12 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { label: "Code re\u00E7u par SMS", required: true, fullWidth: true, name: "securityCode", variant: "outlined", value: (_b = validationForm.securityCode) === null || _b === void 0 ? void 0 : _b.value, error: !((_c = validationForm.securityCode) === null || _c === void 0 ? void 0 : _c.isValid), helperText: Boolean((_d = validationForm.securityCode) === null || _d === void 0 ? void 0 : _d.error) ? (_e = validationForm.securityCode) === null || _e === void 0 ? void 0 : _e.error : null, onChange: function (e) { return handleInputChange(e); }, inputProps: {
200
+ maxLength: 6,
201
+ inputMode: 'numeric',
202
+ pattern: '[0-9]*' // Permet seulement la saisie de chiffres
203
+ } }) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 12 }, { children: (0, jsx_runtime_1.jsx)(material_1.Link, __assign({ component: "button", variant: "body2", onClick: handleOpenResendCode, sx: { cursor: 'pointer', textAlign: 'center', width: '100%' } }, { children: "Renvoyer le code" })) }))] }), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 12 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { margin: "normal", required: true, fullWidth: true, name: "password", label: "Mot de passe", type: showPassword ? 'text' : 'password', id: "password", autoComplete: "current-password", onChange: function (e) { return handleInputChange(e); }, value: validationForm.password.value, error: !validationForm.password.isValid, helperText: Boolean(validationForm.password.error) ? validationForm.password.error : "10 caractères minimum, 1 majuscule, 1 minuscule", InputProps: {
155
204
  endAdornment: ((0, jsx_runtime_1.jsx)(InputAdornment_1.default, __assign({ position: "end" }, { children: (0, jsx_runtime_1.jsx)(material_1.IconButton, __assign({ edge: "end", onClick: function (e) { return setShowPassword(function (prev) { return !prev; }); } }, { children: showPassword ? (0, jsx_runtime_1.jsx)(VisibilityOff_1.default, {}) : (0, jsx_runtime_1.jsx)(Visibility_1.default, {}) })) }))),
156
- } }) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 12 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { margin: "normal", required: true, fullWidth: true, name: "confirmation", label: "Confirmation", type: showPassword ? 'text' : 'password', id: "confirmation", onChange: function (e) { return handleInputChange(e); }, value: passwordForm.confirmation.value, error: !passwordForm.confirmation.isValid, helperText: Boolean(passwordForm.confirmation.error) ? passwordForm.confirmation.error : "", InputProps: {
205
+ } }) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 12 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { margin: "normal", required: true, fullWidth: true, name: "confirmation", label: "Confirmation mot de passe", type: showPassword ? 'text' : 'password', id: "confirmation", onChange: function (e) { return handleInputChange(e); }, value: validationForm.confirmation.value, error: !validationForm.confirmation.isValid, helperText: Boolean(validationForm.confirmation.error) ? validationForm.confirmation.error : "", InputProps: {
157
206
  endAdornment: ((0, jsx_runtime_1.jsx)(InputAdornment_1.default, __assign({ position: "end" }, { children: (0, jsx_runtime_1.jsx)(material_1.IconButton, __assign({ edge: "end", onClick: function (e) { return setShowPassword(function (prev) { return !prev; }); } }, { children: showPassword ? (0, jsx_runtime_1.jsx)(VisibilityOff_1.default, {}) : (0, jsx_runtime_1.jsx)(Visibility_1.default, {}) })) }))),
158
207
  } }) }))] })) })), loading &&
159
- (0, jsx_runtime_1.jsx)(material_1.Box, __assign({ display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh" }, { children: (0, jsx_runtime_1.jsx)(material_1.CircularProgress, {}) }))] }));
208
+ (0, jsx_runtime_1.jsx)(material_1.Box, __assign({ display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh" }, { children: (0, jsx_runtime_1.jsx)(material_1.CircularProgress, {}) })), openPhoneNumberInput && (0, jsx_runtime_1.jsx)(ConfirmationDialog_1.default, { open: openPhoneNumberInput, confirmLabel: "Envoyer", closeLabel: "Annuler", onClose: function () { return setOpenPhoneNumberInput(false); }, onConfirm: resendCode, message: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.Typography, { children: [(0, jsx_runtime_1.jsx)("b", { children: "Indique nous ton num\u00E9ro de t\u00E9l\u00E9phone" }), (0, jsx_runtime_1.jsx)("br", {})] }), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 6 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { margin: "normal", fullWidth: true, required: true, id: "phoneNumber", label: "N\u00B0 de t\u00E9l\u00E9phone", name: "phoneNumber", autoComplete: "tel", onChange: function (e) { return handleInputChange(e); }, value: validationForm.phoneNumber.value, error: Boolean(validationForm.phoneNumber.error), helperText: validationForm.phoneNumber.error }) }))] }) })] }));
160
209
  };
161
210
  exports.default = AccountValidation;
@@ -1,7 +1,8 @@
1
- export type MovaPasswordForm = {
1
+ export type MovaValidationForm = {
2
2
  password: MovaFormField;
3
3
  confirmation: MovaFormField;
4
4
  securityCode: MovaFormField;
5
+ phoneNumber: MovaFormField;
5
6
  };
6
7
  export type AddressFieldName = 'streetName' | 'additional' | 'postalCode' | 'cityName';
7
8
  export type MovaVehicleForm = {
@@ -3,6 +3,7 @@ import { MovaAppType } from "../helpers/Enums";
3
3
  import Garage from "../models/Garage";
4
4
  import User from "../models/User";
5
5
  export default class UserService {
6
+ static resendSecurityCode(req: any): Promise<APIResponse<string>>;
6
7
  static getSalesGarages(salesId: string): Promise<APIResponse<Garage[]>>;
7
8
  static validateAccount(req: any): Promise<APIResponse<string>>;
8
9
  /**
@@ -45,6 +45,14 @@ var Logger_1 = __importDefault(require("../helpers/Logger"));
45
45
  var UserService = /** @class */ (function () {
46
46
  function UserService() {
47
47
  }
48
+ UserService.resendSecurityCode = function (req) {
49
+ return (0, ApiHelper_1.request)({
50
+ url: "".concat(ApiHelper_1.API_BASE_URL, "/user/resend-security-code"),
51
+ method: Enums_1.APIMethod.POST,
52
+ appType: Enums_1.MovaAppType.INDIVIDUAL,
53
+ body: JSON.stringify(req)
54
+ });
55
+ };
48
56
  UserService.getSalesGarages = function (salesId) {
49
57
  return (0, ApiHelper_1.request)({
50
58
  url: "".concat(ApiHelper_1.API_BASE_URL, "/sales/").concat(salesId, "/garages"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@movalib/movalib-commons",
3
- "version": "1.1.61",
3
+ "version": "1.1.63",
4
4
  "description": "Bibliothèque d'objets communs à l'ensemble des projets React de Movalib",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,41 +1,45 @@
1
1
  import { CSSProperties, FunctionComponent, useEffect, useState } from 'react';
2
2
  import { useHistory, useLocation } from 'react-router-dom';
3
3
  import UserService from './services/UserService';
4
- import { Box, CircularProgress, Grid, IconButton, TextField, Typography, darken, useMediaQuery, useTheme } from '@mui/material';
4
+ import { Box, CircularProgress, Grid, IconButton, Link, TextField, Typography, darken, useMediaQuery, useTheme } from '@mui/material';
5
5
  import Logger from './helpers/Logger';
6
6
  import InputAdornment from '@mui/material/InputAdornment';
7
7
  import Visibility from '@mui/icons-material/Visibility';
8
8
  import VisibilityOff from '@mui/icons-material/VisibilityOff';
9
9
  import { LoadingButton } from '@mui/lab';
10
10
  import { MovaAppType } from './helpers/Enums';
11
- import { MovaFormField, MovaPasswordForm } from './helpers/Types';
11
+ import { MovaFormField, MovaValidationForm } from './helpers/Types';
12
12
  import { validateField } from './helpers/Tools';
13
13
  import MovaDialog from './MovaDialog';
14
14
 
15
15
  import LogoLarge from './assets/images/logo/logo_large.png';
16
16
  import LogoProLarge from './assets/images/logo/logo_pro_large.png';
17
+ import ConfirmationDialog from './ConfirmationDialog';
17
18
 
18
19
  const initialFormState = {
19
20
  password: { value: '', isValid: true },
20
21
  confirmation: { value: '', isValid: true },
21
22
  securityCode: { value: '', isValid: true },
23
+ phoneNumber: { value: '', isValid: true },
22
24
  }
23
25
 
24
26
  interface AccountValidationProps {
25
27
  movaAppType: MovaAppType,
26
28
  smsValidation: boolean,
27
29
  onSubmit: (success:boolean, message:string) => void,
30
+ onResendSecurityCode: (success:boolean, message:string) => void,
28
31
  }
29
32
 
30
- const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppType, smsValidation, onSubmit }) => {
33
+ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppType, smsValidation, onSubmit, onResendSecurityCode }) => {
31
34
 
32
35
  const [loading, setLoading] = useState(true);
33
- const [passwordForm, setPasswordForm] = useState<MovaPasswordForm>(initialFormState);
36
+ const [validationForm, setValidationForm] = useState<MovaValidationForm>(initialFormState);
34
37
  const location = useLocation();
35
38
  const history = useHistory();
36
39
  const theme = useTheme();
37
40
  const [emptyPwd, setEmptyPwd] = useState<boolean>(false);
38
41
  const [showPassword, setShowPassword] = useState(false);
42
+ const [openPhoneNumberInput, setOpenPhoneNumberInput] = useState<boolean>(false);
39
43
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
40
44
 
41
45
  useEffect(() => {
@@ -44,8 +48,6 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
44
48
  const token = params.get('token');
45
49
 
46
50
  // Si cette variable est transmise, cela signifie que le compte a été créé sans mot de passe
47
- Logger.info(params);
48
- Logger.info(Boolean(params.get('emptyPwd')));
49
51
  let localEmptyPwd = Boolean(params.get('emptyPwd'));
50
52
  setEmptyPwd(localEmptyPwd);
51
53
 
@@ -96,33 +98,33 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
96
98
  const fieldValue: string = e.target.value;
97
99
  const newField: MovaFormField = { [fieldName]: { value: fieldValue, isValid: true } };
98
100
 
99
- setPasswordForm({ ...passwordForm, ...newField});
101
+ setValidationForm({ ...validationForm, ...newField});
100
102
  }
101
103
  }
102
104
 
103
105
  const validateForm = () => {
104
- let newForm: MovaPasswordForm = { ...passwordForm };
106
+ let newForm: MovaValidationForm = { ...validationForm };
105
107
 
106
108
  // Validator pour les champs obligatoires
107
- newForm.password = validateField(passwordForm.password, value => !!value, 'Champ obligatoire');
108
- newForm.confirmation = validateField(passwordForm.confirmation, value => !!value, 'Champ obligatoire');
109
+ newForm.password = validateField(validationForm.password, value => !!value, 'Champ obligatoire');
110
+ newForm.confirmation = validateField(validationForm.confirmation, value => !!value, 'Champ obligatoire');
109
111
  if(smsValidation)
110
- newForm.securityCode = validateField(passwordForm.securityCode, value => !!value, 'Champ obligatoire');
112
+ newForm.securityCode = validateField(validationForm.securityCode, value => !!value, 'Champ obligatoire');
111
113
 
112
114
  // Validator pour le mot de passe
113
- newForm.password = validateField(passwordForm.password,
115
+ newForm.password = validateField(validationForm.password,
114
116
  value => value.length >= 10 && /[a-z]/.test(value) && /[A-Z]/.test(value),
115
117
  'Votre mot de passe doit faire au moins 10 caractères et contenir une majuscule et une minuscule minimum');
116
118
 
117
119
  // Second validator pour le mot de passe (confirmation)
118
- newForm.confirmation = validateField(passwordForm.confirmation, value => value === passwordForm.password.value,
120
+ newForm.confirmation = validateField(validationForm.confirmation, value => value === validationForm.password.value,
119
121
  "Les mots de passe doivent être identiques");
120
122
 
121
123
  // Validator pour le code de sécurité
122
124
  if(smsValidation)
123
- newForm.securityCode = validateField(passwordForm.securityCode, value => value.length === 6, "Le code doit contenir 6 chiffres");
125
+ newForm.securityCode = validateField(validationForm.securityCode, value => value.length === 6, "Le code doit contenir 6 chiffres");
124
126
 
125
- setPasswordForm(newForm);
127
+ setValidationForm(newForm);
126
128
 
127
129
  return newForm.password.isValid && newForm.confirmation.isValid && (smsValidation ? newForm.securityCode.isValid : true);
128
130
  }
@@ -135,8 +137,8 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
135
137
 
136
138
  let req = {
137
139
  token: !smsValidation ? params.get('token') : null,
138
- securityCode : smsValidation ? passwordForm.securityCode.value : null,
139
- password: passwordForm.password.value,
140
+ securityCode : smsValidation ? validationForm.securityCode.value : null,
141
+ password: validationForm.password.value,
140
142
  demoGarage: Boolean(params.get('demoGarage'))
141
143
  }
142
144
 
@@ -159,6 +161,62 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
159
161
  movaAppType === MovaAppType.ADMIN ? LogoLarge : LogoLarge;
160
162
  }
161
163
 
164
+ const handleOpenResendCode = () => {
165
+ setOpenPhoneNumberInput(true);
166
+ }
167
+
168
+ const validatePhoneNumber = ():boolean => {
169
+
170
+ let newForm: MovaValidationForm = validationForm;
171
+ let newField: MovaFormField;
172
+
173
+ // Validator 'phoneNumber'
174
+ if(newForm.phoneNumber?.value){
175
+ if(newForm.phoneNumber?.value.length < 10){
176
+ newField = { value: validationForm.phoneNumber?.value, error: "Le n° de téléphone est invalide."};
177
+ } else {
178
+ newField ={ value: validationForm.phoneNumber?.value, error: ''};
179
+ }
180
+ newForm = { ...newForm, ...{ phoneNumber: newField } };
181
+ }
182
+
183
+ setValidationForm(newForm);
184
+
185
+ return !Boolean(newForm.phoneNumber?.error);
186
+ }
187
+
188
+ const resendCode = () => {
189
+
190
+ if(validatePhoneNumber()){
191
+
192
+ let req = {
193
+ phoneNumber : validationForm.phoneNumber?.value
194
+ }
195
+
196
+ UserService.resendSecurityCode(req)
197
+ .then(response => {
198
+
199
+ Logger.info(response);
200
+
201
+ if(response.success){
202
+ if(onResendSecurityCode){
203
+ onResendSecurityCode(response.success, response.data ?? '');
204
+ }
205
+ }else{
206
+ if(onResendSecurityCode){
207
+ onResendSecurityCode(response.success, response.error ?? '');
208
+ }
209
+ }
210
+
211
+ }).catch(error => {
212
+ Logger.error(error);
213
+ if(onSubmit){
214
+ onSubmit(false, error);
215
+ }
216
+ });
217
+ }
218
+ }
219
+
162
220
  return (
163
221
  <div>
164
222
  {(emptyPwd || smsValidation) &&
@@ -166,7 +224,7 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
166
224
  leafImageColor='pink'
167
225
  titleStyle={getTitleStyle()}
168
226
  fullScreen={isMobile}
169
- open={emptyPwd}
227
+ open={emptyPwd || smsValidation}
170
228
  closable={false}
171
229
  onClose={function (): void {
172
230
  throw new Error('Function not implemented.');
@@ -195,7 +253,7 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
195
253
  </Box>
196
254
  </Grid>
197
255
  <Grid item xs={12}>
198
- <Typography sx={{ mt: 2, mb: 2 }}>
256
+ <Typography sx={{ mt: 2, mb: 3 }}>
199
257
  {movaAppType === MovaAppType.INDIVIDUAL ?
200
258
  "Pour commencer, définis ton mot de passe et active ton compte 😉"
201
259
  :
@@ -203,24 +261,37 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
203
261
  }
204
262
  </Typography>
205
263
  </Grid>
206
- {smsValidation && <Grid item xs={12}>
207
- <TextField
208
- label="Code reçu par SMS"
209
- required
210
- fullWidth
211
- name="securityCode"
212
- variant="outlined"
213
- value={passwordForm.securityCode?.value}
214
- error={!passwordForm.securityCode?.isValid}
215
- helperText={Boolean(passwordForm.securityCode?.error) ? passwordForm.securityCode?.error : "Code à 6 chiffres"}
216
- onChange={e => handleInputChange(e)}
217
- inputProps={{
218
- maxLength: 6,
219
- inputMode: 'numeric', // Affiche un clavier numérique sur les appareils mobiles
220
- pattern: '[0-9]*' // Permet seulement la saisie de chiffres
221
- }}
222
- />
223
- </Grid>}
264
+ {smsValidation && <>
265
+ <Grid item xs={12}>
266
+ <TextField
267
+ label="Code reçu par SMS"
268
+ required
269
+ fullWidth
270
+ name="securityCode"
271
+ variant="outlined"
272
+ value={validationForm.securityCode?.value}
273
+ error={!validationForm.securityCode?.isValid}
274
+ helperText={Boolean(validationForm.securityCode?.error) ? validationForm.securityCode?.error : null}
275
+ onChange={e => handleInputChange(e)}
276
+ inputProps={{
277
+ maxLength: 6,
278
+ inputMode: 'numeric', // Affiche un clavier numérique sur les appareils mobiles
279
+ pattern: '[0-9]*' // Permet seulement la saisie de chiffres
280
+ }}
281
+ />
282
+ </Grid>
283
+ <Grid item xs={12}>
284
+ <Link
285
+ component="button"
286
+ variant="body2"
287
+ onClick={handleOpenResendCode}
288
+ sx={{ cursor: 'pointer', textAlign: 'center', width: '100%' }}
289
+ >
290
+ Renvoyer le code
291
+ </Link>
292
+ </Grid>
293
+ </>
294
+ }
224
295
  <Grid item xs={12}>
225
296
  <TextField
226
297
  margin="normal"
@@ -232,9 +303,9 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
232
303
  id="password"
233
304
  autoComplete="current-password"
234
305
  onChange={e => handleInputChange(e)}
235
- value={passwordForm.password.value}
236
- error={!passwordForm.password.isValid}
237
- helperText={Boolean(passwordForm.password.error) ? passwordForm.password.error : "10 caractères minimum, 1 majuscule, 1 minuscule"}
306
+ value={validationForm.password.value}
307
+ error={!validationForm.password.isValid}
308
+ helperText={Boolean(validationForm.password.error) ? validationForm.password.error : "10 caractères minimum, 1 majuscule, 1 minuscule"}
238
309
  InputProps={{
239
310
  endAdornment: (
240
311
  <InputAdornment position="end">
@@ -255,13 +326,13 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
255
326
  required
256
327
  fullWidth
257
328
  name="confirmation"
258
- label="Confirmation"
329
+ label="Confirmation mot de passe"
259
330
  type={showPassword ? 'text' : 'password'}
260
331
  id="confirmation"
261
332
  onChange={e => handleInputChange(e)}
262
- value={passwordForm.confirmation.value}
263
- error={!passwordForm.confirmation.isValid}
264
- helperText={Boolean(passwordForm.confirmation.error) ? passwordForm.confirmation.error : ""}
333
+ value={validationForm.confirmation.value}
334
+ error={!validationForm.confirmation.isValid}
335
+ helperText={Boolean(validationForm.confirmation.error) ? validationForm.confirmation.error : ""}
265
336
  InputProps={{
266
337
  endAdornment: (
267
338
  <InputAdornment position="end">
@@ -284,6 +355,32 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
284
355
  <CircularProgress />
285
356
  </Box>
286
357
  }
358
+
359
+ {openPhoneNumberInput && <ConfirmationDialog
360
+ open={openPhoneNumberInput}
361
+ confirmLabel="Envoyer"
362
+ closeLabel="Annuler"
363
+ onClose={() => setOpenPhoneNumberInput(false)}
364
+ onConfirm={resendCode}
365
+ message={<>
366
+ <Typography><b>Indique nous ton numéro de téléphone</b><br /></Typography>
367
+ <Grid item xs={6}>
368
+ <TextField
369
+ margin="normal"
370
+ fullWidth
371
+ required
372
+ id="phoneNumber"
373
+ label="N° de téléphone"
374
+ name="phoneNumber"
375
+ autoComplete="tel"
376
+ onChange={e => handleInputChange(e)}
377
+ value={validationForm.phoneNumber.value}
378
+ error={Boolean(validationForm.phoneNumber.error)}
379
+ helperText={validationForm.phoneNumber.error}
380
+ />
381
+ </Grid>
382
+ </>}
383
+ /> }
287
384
  </div>
288
385
  );
289
386
  };
@@ -1,8 +1,9 @@
1
1
 
2
- export type MovaPasswordForm = {
2
+ export type MovaValidationForm = {
3
3
  password: MovaFormField,
4
4
  confirmation: MovaFormField,
5
- securityCode: MovaFormField
5
+ securityCode: MovaFormField,
6
+ phoneNumber: MovaFormField
6
7
  }
7
8
 
8
9
  export type AddressFieldName = 'streetName' | 'additional' | 'postalCode' | 'cityName';
@@ -6,6 +6,15 @@ import User from "../models/User";
6
6
 
7
7
  export default class UserService {
8
8
 
9
+ static resendSecurityCode(req: any): Promise<APIResponse<string>> {
10
+ return request({
11
+ url: `${API_BASE_URL}/user/resend-security-code`,
12
+ method: APIMethod.POST,
13
+ appType: MovaAppType.INDIVIDUAL,
14
+ body: JSON.stringify(req)
15
+ });
16
+ }
17
+
9
18
  static getSalesGarages(salesId: string,): Promise<APIResponse<Garage[]>> {
10
19
  return request({
11
20
  url: `${API_BASE_URL}/sales/${salesId}/garages`,