@movalib/movalib-commons 1.1.62 → 1.1.64

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,30 @@ 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"));
33
+ var Validator_1 = require("./helpers/Validator");
32
34
  var initialFormState = {
33
35
  password: { value: '', isValid: true },
34
36
  confirmation: { value: '', isValid: true },
35
37
  securityCode: { value: '', isValid: true },
38
+ phoneNumber: { value: '', isValid: true },
36
39
  };
37
40
  var AccountValidation = function (_a) {
38
41
  var _b, _c, _d, _e;
39
- var movaAppType = _a.movaAppType, smsValidation = _a.smsValidation, onSubmit = _a.onSubmit;
42
+ var movaAppType = _a.movaAppType, smsValidation = _a.smsValidation, onSubmit = _a.onSubmit, onResendSecurityCode = _a.onResendSecurityCode;
40
43
  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];
44
+ var _g = (0, react_1.useState)(initialFormState), validationForm = _g[0], setValidationForm = _g[1];
42
45
  var location = (0, react_router_dom_1.useLocation)();
43
46
  var history = (0, react_router_dom_1.useHistory)();
44
47
  var theme = (0, material_1.useTheme)();
45
48
  var _h = (0, react_1.useState)(false), emptyPwd = _h[0], setEmptyPwd = _h[1];
46
49
  var _j = (0, react_1.useState)(false), showPassword = _j[0], setShowPassword = _j[1];
50
+ var _k = (0, react_1.useState)(false), openPhoneNumberInput = _k[0], setOpenPhoneNumberInput = _k[1];
47
51
  var isMobile = (0, material_1.useMediaQuery)(theme.breakpoints.down('sm'));
48
52
  (0, react_1.useEffect)(function () {
49
53
  var params = new URLSearchParams(location.search);
50
54
  var token = params.get('token');
51
55
  // 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
56
  var localEmptyPwd = Boolean(params.get('emptyPwd'));
55
57
  setEmptyPwd(localEmptyPwd);
56
58
  if (token) {
@@ -92,24 +94,28 @@ var AccountValidation = function (_a) {
92
94
  var fieldName = e.target.name;
93
95
  var fieldValue = e.target.value;
94
96
  var newField = (_a = {}, _a[fieldName] = { value: fieldValue, isValid: true }, _a);
95
- setPasswordForm(__assign(__assign({}, passwordForm), newField));
97
+ if (fieldName == "phoneNumber") {
98
+ if (!(0, Validator_1.validatePhoneNumber)(fieldValue))
99
+ return;
100
+ }
101
+ setValidationForm(__assign(__assign({}, validationForm), newField));
96
102
  }
97
103
  };
98
104
  var validateForm = function () {
99
- var newForm = __assign({}, passwordForm);
105
+ var newForm = __assign({}, validationForm);
100
106
  // 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');
107
+ newForm.password = (0, Tools_1.validateField)(validationForm.password, function (value) { return !!value; }, 'Champ obligatoire');
108
+ newForm.confirmation = (0, Tools_1.validateField)(validationForm.confirmation, function (value) { return !!value; }, 'Champ obligatoire');
103
109
  if (smsValidation)
104
- newForm.securityCode = (0, Tools_1.validateField)(passwordForm.securityCode, function (value) { return !!value; }, 'Champ obligatoire');
110
+ newForm.securityCode = (0, Tools_1.validateField)(validationForm.securityCode, function (value) { return !!value; }, 'Champ obligatoire');
105
111
  // 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');
112
+ 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
113
  // 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");
114
+ newForm.confirmation = (0, Tools_1.validateField)(validationForm.confirmation, function (value) { return value === validationForm.password.value; }, "Les mots de passe doivent être identiques");
109
115
  // Validator pour le code de sécurité
110
116
  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);
117
+ newForm.securityCode = (0, Tools_1.validateField)(validationForm.securityCode, function (value) { return value.length === 6; }, "Le code doit contenir 6 chiffres");
118
+ setValidationForm(newForm);
113
119
  return newForm.password.isValid && newForm.confirmation.isValid && (smsValidation ? newForm.securityCode.isValid : true);
114
120
  };
115
121
  var handleValidateAccount = function () {
@@ -118,8 +124,8 @@ var AccountValidation = function (_a) {
118
124
  var params = new URLSearchParams(location.search);
119
125
  var req = {
120
126
  token: !smsValidation ? params.get('token') : null,
121
- securityCode: smsValidation ? passwordForm.securityCode.value : null,
122
- password: passwordForm.password.value,
127
+ securityCode: smsValidation ? validationForm.securityCode.value : null,
128
+ password: validationForm.password.value,
123
129
  demoGarage: Boolean(params.get('demoGarage'))
124
130
  };
125
131
  activateAccount(req);
@@ -137,6 +143,54 @@ var AccountValidation = function (_a) {
137
143
  movaAppType === Enums_1.MovaAppType.INDIVIDUAL ? logo_large_png_1.default :
138
144
  movaAppType === Enums_1.MovaAppType.ADMIN ? logo_large_png_1.default : logo_large_png_1.default;
139
145
  };
146
+ var handleOpenResendCode = function () {
147
+ setOpenPhoneNumberInput(true);
148
+ };
149
+ var controlPhoneNumber = function () {
150
+ var _a, _b, _c, _d, _e;
151
+ var newForm = validationForm;
152
+ var newField;
153
+ // Validator 'phoneNumber'
154
+ if ((_a = newForm.phoneNumber) === null || _a === void 0 ? void 0 : _a.value) {
155
+ if (((_b = newForm.phoneNumber) === null || _b === void 0 ? void 0 : _b.value.length) < 10) {
156
+ newField = { value: (_c = validationForm.phoneNumber) === null || _c === void 0 ? void 0 : _c.value, error: "Le n° de téléphone est invalide." };
157
+ }
158
+ else {
159
+ newField = { value: (_d = validationForm.phoneNumber) === null || _d === void 0 ? void 0 : _d.value, error: '' };
160
+ }
161
+ newForm = __assign(__assign({}, newForm), { phoneNumber: newField });
162
+ }
163
+ setValidationForm(newForm);
164
+ return !Boolean((_e = newForm.phoneNumber) === null || _e === void 0 ? void 0 : _e.error);
165
+ };
166
+ var resendCode = function () {
167
+ var _a;
168
+ if (controlPhoneNumber()) {
169
+ var req = {
170
+ phoneNumber: (_a = validationForm.phoneNumber) === null || _a === void 0 ? void 0 : _a.value
171
+ };
172
+ UserService_1.default.resendSecurityCode(req)
173
+ .then(function (response) {
174
+ var _a, _b;
175
+ Logger_1.default.info(response);
176
+ if (response.success) {
177
+ if (onResendSecurityCode) {
178
+ onResendSecurityCode(response.success, (_a = response.data) !== null && _a !== void 0 ? _a : '');
179
+ }
180
+ }
181
+ else {
182
+ if (onResendSecurityCode) {
183
+ onResendSecurityCode(response.success, (_b = response.error) !== null && _b !== void 0 ? _b : '');
184
+ }
185
+ }
186
+ }).catch(function (error) {
187
+ Logger_1.default.error(error);
188
+ if (onSubmit) {
189
+ onSubmit(false, error);
190
+ }
191
+ });
192
+ }
193
+ };
140
194
  return ((0, jsx_runtime_1.jsxs)("div", { children: [(emptyPwd || smsValidation) &&
141
195
  (0, jsx_runtime_1.jsx)(MovaDialog_1.default, __assign({ leafImageColor: 'pink', titleStyle: getTitleStyle(), fullScreen: isMobile, open: emptyPwd || smsValidation, closable: false, onClose: function () {
142
196
  throw new Error('Function not implemented.');
@@ -144,18 +198,18 @@ var AccountValidation = function (_a) {
144
198
  display: 'flex',
145
199
  flexDirection: 'column',
146
200
  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 ?
201
+ } }, { 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
202
  "Pour commencer, définis ton mot de passe et active ton compte 😉"
149
203
  :
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: {
204
+ "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: {
205
+ maxLength: 6,
206
+ inputMode: 'numeric',
207
+ pattern: '[0-9]*' // Permet seulement la saisie de chiffres
208
+ } }) })), (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
209
  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: {
210
+ } }) })), (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
211
  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
212
  } }) }))] })) })), 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, {}) }))] }));
213
+ (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
214
  };
161
215
  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.62",
3
+ "version": "1.1.64",
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,46 @@
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';
18
+ import { validatePhoneNumber } from './helpers/Validator';
17
19
 
18
20
  const initialFormState = {
19
21
  password: { value: '', isValid: true },
20
22
  confirmation: { value: '', isValid: true },
21
23
  securityCode: { value: '', isValid: true },
24
+ phoneNumber: { value: '', isValid: true },
22
25
  }
23
26
 
24
27
  interface AccountValidationProps {
25
28
  movaAppType: MovaAppType,
26
29
  smsValidation: boolean,
27
30
  onSubmit: (success:boolean, message:string) => void,
31
+ onResendSecurityCode: (success:boolean, message:string) => void,
28
32
  }
29
33
 
30
- const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppType, smsValidation, onSubmit }) => {
34
+ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppType, smsValidation, onSubmit, onResendSecurityCode }) => {
31
35
 
32
36
  const [loading, setLoading] = useState(true);
33
- const [passwordForm, setPasswordForm] = useState<MovaPasswordForm>(initialFormState);
37
+ const [validationForm, setValidationForm] = useState<MovaValidationForm>(initialFormState);
34
38
  const location = useLocation();
35
39
  const history = useHistory();
36
40
  const theme = useTheme();
37
41
  const [emptyPwd, setEmptyPwd] = useState<boolean>(false);
38
42
  const [showPassword, setShowPassword] = useState(false);
43
+ const [openPhoneNumberInput, setOpenPhoneNumberInput] = useState<boolean>(false);
39
44
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
40
45
 
41
46
  useEffect(() => {
@@ -44,8 +49,6 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
44
49
  const token = params.get('token');
45
50
 
46
51
  // 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
52
  let localEmptyPwd = Boolean(params.get('emptyPwd'));
50
53
  setEmptyPwd(localEmptyPwd);
51
54
 
@@ -96,33 +99,38 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
96
99
  const fieldValue: string = e.target.value;
97
100
  const newField: MovaFormField = { [fieldName]: { value: fieldValue, isValid: true } };
98
101
 
99
- setPasswordForm({ ...passwordForm, ...newField});
102
+ if (fieldName == "phoneNumber"){
103
+ if(!validatePhoneNumber(fieldValue))
104
+ return;
105
+ }
106
+
107
+ setValidationForm({ ...validationForm, ...newField});
100
108
  }
101
109
  }
102
110
 
103
111
  const validateForm = () => {
104
- let newForm: MovaPasswordForm = { ...passwordForm };
112
+ let newForm: MovaValidationForm = { ...validationForm };
105
113
 
106
114
  // 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');
115
+ newForm.password = validateField(validationForm.password, value => !!value, 'Champ obligatoire');
116
+ newForm.confirmation = validateField(validationForm.confirmation, value => !!value, 'Champ obligatoire');
109
117
  if(smsValidation)
110
- newForm.securityCode = validateField(passwordForm.securityCode, value => !!value, 'Champ obligatoire');
118
+ newForm.securityCode = validateField(validationForm.securityCode, value => !!value, 'Champ obligatoire');
111
119
 
112
120
  // Validator pour le mot de passe
113
- newForm.password = validateField(passwordForm.password,
121
+ newForm.password = validateField(validationForm.password,
114
122
  value => value.length >= 10 && /[a-z]/.test(value) && /[A-Z]/.test(value),
115
123
  'Votre mot de passe doit faire au moins 10 caractères et contenir une majuscule et une minuscule minimum');
116
124
 
117
125
  // Second validator pour le mot de passe (confirmation)
118
- newForm.confirmation = validateField(passwordForm.confirmation, value => value === passwordForm.password.value,
126
+ newForm.confirmation = validateField(validationForm.confirmation, value => value === validationForm.password.value,
119
127
  "Les mots de passe doivent être identiques");
120
128
 
121
129
  // Validator pour le code de sécurité
122
130
  if(smsValidation)
123
- newForm.securityCode = validateField(passwordForm.securityCode, value => value.length === 6, "Le code doit contenir 6 chiffres");
131
+ newForm.securityCode = validateField(validationForm.securityCode, value => value.length === 6, "Le code doit contenir 6 chiffres");
124
132
 
125
- setPasswordForm(newForm);
133
+ setValidationForm(newForm);
126
134
 
127
135
  return newForm.password.isValid && newForm.confirmation.isValid && (smsValidation ? newForm.securityCode.isValid : true);
128
136
  }
@@ -135,8 +143,8 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
135
143
 
136
144
  let req = {
137
145
  token: !smsValidation ? params.get('token') : null,
138
- securityCode : smsValidation ? passwordForm.securityCode.value : null,
139
- password: passwordForm.password.value,
146
+ securityCode : smsValidation ? validationForm.securityCode.value : null,
147
+ password: validationForm.password.value,
140
148
  demoGarage: Boolean(params.get('demoGarage'))
141
149
  }
142
150
 
@@ -159,6 +167,62 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
159
167
  movaAppType === MovaAppType.ADMIN ? LogoLarge : LogoLarge;
160
168
  }
161
169
 
170
+ const handleOpenResendCode = () => {
171
+ setOpenPhoneNumberInput(true);
172
+ }
173
+
174
+ const controlPhoneNumber = ():boolean => {
175
+
176
+ let newForm: MovaValidationForm = validationForm;
177
+ let newField: MovaFormField;
178
+
179
+ // Validator 'phoneNumber'
180
+ if(newForm.phoneNumber?.value){
181
+ if(newForm.phoneNumber?.value.length < 10){
182
+ newField = { value: validationForm.phoneNumber?.value, error: "Le n° de téléphone est invalide."};
183
+ } else {
184
+ newField ={ value: validationForm.phoneNumber?.value, error: ''};
185
+ }
186
+ newForm = { ...newForm, ...{ phoneNumber: newField } };
187
+ }
188
+
189
+ setValidationForm(newForm);
190
+
191
+ return !Boolean(newForm.phoneNumber?.error);
192
+ }
193
+
194
+ const resendCode = () => {
195
+
196
+ if(controlPhoneNumber()){
197
+
198
+ let req = {
199
+ phoneNumber : validationForm.phoneNumber?.value
200
+ }
201
+
202
+ UserService.resendSecurityCode(req)
203
+ .then(response => {
204
+
205
+ Logger.info(response);
206
+
207
+ if(response.success){
208
+ if(onResendSecurityCode){
209
+ onResendSecurityCode(response.success, response.data ?? '');
210
+ }
211
+ }else{
212
+ if(onResendSecurityCode){
213
+ onResendSecurityCode(response.success, response.error ?? '');
214
+ }
215
+ }
216
+
217
+ }).catch(error => {
218
+ Logger.error(error);
219
+ if(onSubmit){
220
+ onSubmit(false, error);
221
+ }
222
+ });
223
+ }
224
+ }
225
+
162
226
  return (
163
227
  <div>
164
228
  {(emptyPwd || smsValidation) &&
@@ -195,7 +259,7 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
195
259
  </Box>
196
260
  </Grid>
197
261
  <Grid item xs={12}>
198
- <Typography sx={{ mt: 2, mb: 2 }}>
262
+ <Typography sx={{ mt: 2, mb: 3 }}>
199
263
  {movaAppType === MovaAppType.INDIVIDUAL ?
200
264
  "Pour commencer, définis ton mot de passe et active ton compte 😉"
201
265
  :
@@ -203,24 +267,37 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
203
267
  }
204
268
  </Typography>
205
269
  </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>}
270
+ {smsValidation && <>
271
+ <Grid item xs={12}>
272
+ <TextField
273
+ label="Code reçu par SMS"
274
+ required
275
+ fullWidth
276
+ name="securityCode"
277
+ variant="outlined"
278
+ value={validationForm.securityCode?.value}
279
+ error={!validationForm.securityCode?.isValid}
280
+ helperText={Boolean(validationForm.securityCode?.error) ? validationForm.securityCode?.error : null}
281
+ onChange={e => handleInputChange(e)}
282
+ inputProps={{
283
+ maxLength: 6,
284
+ inputMode: 'numeric', // Affiche un clavier numérique sur les appareils mobiles
285
+ pattern: '[0-9]*' // Permet seulement la saisie de chiffres
286
+ }}
287
+ />
288
+ </Grid>
289
+ <Grid item xs={12}>
290
+ <Link
291
+ component="button"
292
+ variant="body2"
293
+ onClick={handleOpenResendCode}
294
+ sx={{ cursor: 'pointer', textAlign: 'center', width: '100%' }}
295
+ >
296
+ Renvoyer le code
297
+ </Link>
298
+ </Grid>
299
+ </>
300
+ }
224
301
  <Grid item xs={12}>
225
302
  <TextField
226
303
  margin="normal"
@@ -232,9 +309,9 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
232
309
  id="password"
233
310
  autoComplete="current-password"
234
311
  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"}
312
+ value={validationForm.password.value}
313
+ error={!validationForm.password.isValid}
314
+ helperText={Boolean(validationForm.password.error) ? validationForm.password.error : "10 caractères minimum, 1 majuscule, 1 minuscule"}
238
315
  InputProps={{
239
316
  endAdornment: (
240
317
  <InputAdornment position="end">
@@ -255,13 +332,13 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
255
332
  required
256
333
  fullWidth
257
334
  name="confirmation"
258
- label="Confirmation"
335
+ label="Confirmation mot de passe"
259
336
  type={showPassword ? 'text' : 'password'}
260
337
  id="confirmation"
261
338
  onChange={e => handleInputChange(e)}
262
- value={passwordForm.confirmation.value}
263
- error={!passwordForm.confirmation.isValid}
264
- helperText={Boolean(passwordForm.confirmation.error) ? passwordForm.confirmation.error : ""}
339
+ value={validationForm.confirmation.value}
340
+ error={!validationForm.confirmation.isValid}
341
+ helperText={Boolean(validationForm.confirmation.error) ? validationForm.confirmation.error : ""}
265
342
  InputProps={{
266
343
  endAdornment: (
267
344
  <InputAdornment position="end">
@@ -284,6 +361,32 @@ const AccountValidation: FunctionComponent<AccountValidationProps> = ({ movaAppT
284
361
  <CircularProgress />
285
362
  </Box>
286
363
  }
364
+
365
+ {openPhoneNumberInput && <ConfirmationDialog
366
+ open={openPhoneNumberInput}
367
+ confirmLabel="Envoyer"
368
+ closeLabel="Annuler"
369
+ onClose={() => setOpenPhoneNumberInput(false)}
370
+ onConfirm={resendCode}
371
+ message={<>
372
+ <Typography><b>Indique nous ton numéro de téléphone</b><br /></Typography>
373
+ <Grid item xs={6}>
374
+ <TextField
375
+ margin="normal"
376
+ fullWidth
377
+ required
378
+ id="phoneNumber"
379
+ label="N° de téléphone"
380
+ name="phoneNumber"
381
+ autoComplete="tel"
382
+ onChange={e => handleInputChange(e)}
383
+ value={validationForm.phoneNumber.value}
384
+ error={Boolean(validationForm.phoneNumber.error)}
385
+ helperText={validationForm.phoneNumber.error}
386
+ />
387
+ </Grid>
388
+ </>}
389
+ /> }
287
390
  </div>
288
391
  );
289
392
  };
@@ -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`,