@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 +5 -3
- package/dist/devIndex.js +2 -0
- package/dist/src/AccountValidation.d.ts +1 -0
- package/dist/src/AccountValidation.js +77 -23
- package/dist/src/helpers/Types.d.ts +2 -1
- package/dist/src/services/UserService.d.ts +1 -0
- package/dist/src/services/UserService.js +8 -0
- package/package.json +1 -1
- package/src/AccountValidation.tsx +146 -43
- package/src/helpers/Types.ts +3 -2
- package/src/services/UserService.ts +9 -0
package/devIndex.tsx
CHANGED
|
@@ -195,9 +195,11 @@ const App = () => {
|
|
|
195
195
|
|
|
196
196
|
|
|
197
197
|
{openAccountValidation && <AccountValidation smsValidation={true} movaAppType={MovaAppType.GARAGE}
|
|
198
|
-
|
|
199
|
-
|
|
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),
|
|
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
|
-
|
|
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({},
|
|
105
|
+
var newForm = __assign({}, validationForm);
|
|
100
106
|
// Validator pour les champs obligatoires
|
|
101
|
-
newForm.password = (0, Tools_1.validateField)(
|
|
102
|
-
newForm.confirmation = (0, Tools_1.validateField)(
|
|
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)(
|
|
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)(
|
|
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)(
|
|
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)(
|
|
112
|
-
|
|
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 ?
|
|
122
|
-
password:
|
|
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:
|
|
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 =
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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:
|
|
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
|
|
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,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,
|
|
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 [
|
|
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
|
-
|
|
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:
|
|
112
|
+
let newForm: MovaValidationForm = { ...validationForm };
|
|
105
113
|
|
|
106
114
|
// Validator pour les champs obligatoires
|
|
107
|
-
newForm.password = validateField(
|
|
108
|
-
newForm.confirmation = validateField(
|
|
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(
|
|
118
|
+
newForm.securityCode = validateField(validationForm.securityCode, value => !!value, 'Champ obligatoire');
|
|
111
119
|
|
|
112
120
|
// Validator pour le mot de passe
|
|
113
|
-
newForm.password = validateField(
|
|
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(
|
|
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(
|
|
131
|
+
newForm.securityCode = validateField(validationForm.securityCode, value => value.length === 6, "Le code doit contenir 6 chiffres");
|
|
124
132
|
|
|
125
|
-
|
|
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 ?
|
|
139
|
-
password:
|
|
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:
|
|
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 &&
|
|
207
|
-
<
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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={
|
|
236
|
-
error={!
|
|
237
|
-
helperText={Boolean(
|
|
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={
|
|
263
|
-
error={!
|
|
264
|
-
helperText={Boolean(
|
|
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
|
};
|
package/src/helpers/Types.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
export type
|
|
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`,
|