@movalib/movalib-commons 1.0.14 → 1.0.15
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/PV_README.md +9 -1
- package/dist/GenderSelector.d.ts +12 -0
- package/dist/GenderSelector.js +20 -0
- package/dist/MovaSignUp.d.ts +21 -0
- package/dist/MovaSignUp.js +175 -0
- package/dist/helpers/Types.d.ts +9 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1 -2
- package/package.json +14 -8
- package/src/GenderSelector.tsx +32 -0
- package/src/MovaLogin.tsx +1 -4
- package/src/MovaSignUp.tsx +274 -0
- package/src/helpers/Types.ts +9 -0
- package/src/index.ts +3 -4
package/PV_README.md
CHANGED
|
@@ -12,4 +12,12 @@
|
|
|
12
12
|
Make shure that "private=true" in your package.json
|
|
13
13
|
|
|
14
14
|
### `npm login`
|
|
15
|
-
### `npm publish --access=restricted`
|
|
15
|
+
### `npm publish --access=restricted`
|
|
16
|
+
|
|
17
|
+
Pour lier la librairie aux projets qui l'utilise, executer la commande suivnte
|
|
18
|
+
|
|
19
|
+
### `npm run link`
|
|
20
|
+
|
|
21
|
+
Les commandes exécutées (ci-dessous) permettent de contourner un problème de double référence vers react et react-dom lorsque les deux appli utilisent des Hook
|
|
22
|
+
|
|
23
|
+
"link": "npm link --only=production && npm link \"/home/dimitri/Projets/5 - MOVALIB/02 - Développement/Front-End/movalib-user-app/node_modules/react\" && npm link \"/home/dimitri/Projets/5 - MOVALIB/02 - Développement/Front-End/movalib-user-app/node_modules/react-dom\"",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SelectChangeEvent } from '@mui/material';
|
|
3
|
+
import { MovaFormField } from './helpers/Types';
|
|
4
|
+
interface GenderSelectorProps {
|
|
5
|
+
handleSelectChange: (event: SelectChangeEvent<string>) => void;
|
|
6
|
+
form: {
|
|
7
|
+
gender: MovaFormField;
|
|
8
|
+
};
|
|
9
|
+
required?: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare const GenderSelector: React.FC<GenderSelectorProps>;
|
|
12
|
+
export default GenderSelector;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
var jsx_runtime_1 = require("react/jsx-runtime");
|
|
15
|
+
var material_1 = require("@mui/material");
|
|
16
|
+
var GenderSelector = function (_a) {
|
|
17
|
+
var handleSelectChange = _a.handleSelectChange, form = _a.form, required = _a.required;
|
|
18
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.FormControl, __assign({ fullWidth: true, margin: "normal", required: required }, { children: [(0, jsx_runtime_1.jsx)(material_1.InputLabel, __assign({ id: "gender-label" }, { children: "Sexe" })), (0, jsx_runtime_1.jsxs)(material_1.Select, __assign({ labelId: "gender-label", id: "gender", name: "gender", value: form.gender.value, onChange: function (e) { return handleSelectChange(e); } }, { children: [(0, jsx_runtime_1.jsx)(material_1.MenuItem, __assign({ value: "MALE" }, { children: "Homme" })), (0, jsx_runtime_1.jsx)(material_1.MenuItem, __assign({ value: "FEMALE" }, { children: "Femme" })), (0, jsx_runtime_1.jsx)(material_1.MenuItem, __assign({ value: "OTHER" }, { children: "Autre" }))] }))] })));
|
|
19
|
+
};
|
|
20
|
+
exports.default = GenderSelector;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { FunctionComponent } from "react";
|
|
2
|
+
import { AlertColor } from "@mui/material";
|
|
3
|
+
import { MovaLoginForm } from "./helpers/Types";
|
|
4
|
+
import { MovaAppType } from "./helpers/Enums";
|
|
5
|
+
/**
|
|
6
|
+
* Propriétés du composant
|
|
7
|
+
* movaAppType : type d'application Movalib au sein de laquelle le composant est injectée
|
|
8
|
+
* onSubmit : callbakc invoquée en cas de formulaire valide
|
|
9
|
+
* alertMessage : éventuel message à afficher
|
|
10
|
+
* alertSeverity : niveau d'alerte pour le message à afficher
|
|
11
|
+
* loading : permet de mettre éventuellement le bouton de soumission en état de chargement
|
|
12
|
+
*/
|
|
13
|
+
interface MovaSignUpProps {
|
|
14
|
+
movaAppType: MovaAppType;
|
|
15
|
+
onSubmit: (form: MovaLoginForm) => void;
|
|
16
|
+
alertMessage?: string;
|
|
17
|
+
alertSeverity?: AlertColor;
|
|
18
|
+
loading?: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare const MovaLogin: FunctionComponent<MovaSignUpProps>;
|
|
21
|
+
export default MovaLogin;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
50
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
51
|
+
};
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
var jsx_runtime_1 = require("react/jsx-runtime");
|
|
54
|
+
var react_1 = require("react");
|
|
55
|
+
var lab_1 = require("@mui/lab");
|
|
56
|
+
var logo_large_png_1 = __importDefault(require("./assets/images/logo/logo_large.png"));
|
|
57
|
+
var logo_pro_large_png_1 = __importDefault(require("./assets/images/logo/logo_pro_large.png"));
|
|
58
|
+
var leaf_green_large_png_1 = __importDefault(require("./assets/images/leaf_green_large.png"));
|
|
59
|
+
var leaf_pink_large_png_1 = __importDefault(require("./assets/images/leaf_pink_large.png"));
|
|
60
|
+
var material_1 = require("@mui/material");
|
|
61
|
+
var MovaCopyright_1 = __importDefault(require("./MovaCopyright"));
|
|
62
|
+
var Enums_1 = require("./helpers/Enums");
|
|
63
|
+
var Validator_1 = require("./helpers/Validator");
|
|
64
|
+
var GenderSelector_1 = __importDefault(require("./GenderSelector"));
|
|
65
|
+
// Permet de centrer le contenu de l'application
|
|
66
|
+
var styles = {
|
|
67
|
+
display: 'flex',
|
|
68
|
+
justifyContent: 'center',
|
|
69
|
+
alignItems: 'center',
|
|
70
|
+
height: '100vh', // Ajustez la hauteur en fonction de vos besoins
|
|
71
|
+
};
|
|
72
|
+
var initialUserFormState = {
|
|
73
|
+
firstname: { value: '', isValid: true },
|
|
74
|
+
lastname: { value: '', isValid: true },
|
|
75
|
+
email: { value: '', isValid: true },
|
|
76
|
+
password: { value: '', isValid: true },
|
|
77
|
+
gender: { value: '', isValid: true },
|
|
78
|
+
birthDate: { value: '', isValid: true },
|
|
79
|
+
acceptsTerms: { value: false, isValid: true },
|
|
80
|
+
};
|
|
81
|
+
var MovaLogin = function (_a) {
|
|
82
|
+
var loading = _a.loading, movaAppType = _a.movaAppType, onSubmit = _a.onSubmit, alertMessage = _a.alertMessage, alertSeverity = _a.alertSeverity;
|
|
83
|
+
var _b = (0, react_1.useState)(initialUserFormState), userForm = _b[0], setUserForm = _b[1];
|
|
84
|
+
var _c = (0, react_1.useState)(""), message = _c[0], setMessage = _c[1];
|
|
85
|
+
//const [loading, setLoading] = useState(false);
|
|
86
|
+
var handleInputChange = function (e) {
|
|
87
|
+
var _a;
|
|
88
|
+
var fieldName = e.target.name;
|
|
89
|
+
var fieldValue = e.target.value;
|
|
90
|
+
var newField = (_a = {}, _a[fieldName] = { value: fieldValue, isValid: true }, _a);
|
|
91
|
+
setUserForm(__assign(__assign({}, userForm), newField));
|
|
92
|
+
};
|
|
93
|
+
var handleCheckboxChange = function (e, checked) {
|
|
94
|
+
var _a;
|
|
95
|
+
var fieldName = e.target.name;
|
|
96
|
+
var fieldValue = checked;
|
|
97
|
+
var newField = (_a = {}, _a[fieldName] = { value: fieldValue, isValid: true }, _a);
|
|
98
|
+
setUserForm(__assign(__assign({}, userForm), newField));
|
|
99
|
+
};
|
|
100
|
+
var handleSelectChange = function (e) {
|
|
101
|
+
var _a;
|
|
102
|
+
var fieldName = e.target.name;
|
|
103
|
+
var fieldValue = e.target.value;
|
|
104
|
+
var newField = (_a = {}, _a[fieldName] = { value: fieldValue, isValid: true }, _a);
|
|
105
|
+
setUserForm(__assign(__assign({}, userForm), newField));
|
|
106
|
+
};
|
|
107
|
+
var handleSubmit = function (e) { return __awaiter(void 0, void 0, void 0, function () {
|
|
108
|
+
return __generator(this, function (_a) {
|
|
109
|
+
e.preventDefault();
|
|
110
|
+
try {
|
|
111
|
+
if (validateForm() && onSubmit) {
|
|
112
|
+
// Si le formulaire est valide, on appel la function callback transmise en props
|
|
113
|
+
onSubmit(userForm);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error('Error occurred during submission:', error);
|
|
118
|
+
}
|
|
119
|
+
return [2 /*return*/];
|
|
120
|
+
});
|
|
121
|
+
}); };
|
|
122
|
+
var validateForm = function () {
|
|
123
|
+
var newForm = userForm;
|
|
124
|
+
// Validator email
|
|
125
|
+
if (!(0, Validator_1.validateEmail)(userForm.email.value)) {
|
|
126
|
+
var errorMsg = 'Adresse email invalide';
|
|
127
|
+
var newField = { value: userForm.email.value, error: errorMsg, isValid: false };
|
|
128
|
+
newForm = __assign(__assign({}, newForm), { email: newField });
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
var newField = { value: userForm.email.value, error: '', isValid: true };
|
|
132
|
+
newForm = __assign(__assign({}, newForm), { email: newField });
|
|
133
|
+
}
|
|
134
|
+
// Validator password
|
|
135
|
+
if (userForm.password.value.length < 8) {
|
|
136
|
+
var errorMsg = 'Votre mot de passe doit faire au moins 8 caractères de long.';
|
|
137
|
+
var newField = { value: userForm.password.value, error: errorMsg, isValid: false };
|
|
138
|
+
newForm = __assign(__assign({}, newForm), { password: newField });
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
var newField = { value: userForm.password.value, error: '', isValid: true };
|
|
142
|
+
newForm = __assign(__assign({}, newForm), { password: newField });
|
|
143
|
+
}
|
|
144
|
+
setUserForm(newForm);
|
|
145
|
+
return newForm.email.isValid && newForm.password.isValid;
|
|
146
|
+
};
|
|
147
|
+
var getMovaLogo = function () {
|
|
148
|
+
return movaAppType === Enums_1.MovaAppType.GARAGE ? logo_pro_large_png_1.default :
|
|
149
|
+
movaAppType === Enums_1.MovaAppType.USER ? logo_large_png_1.default :
|
|
150
|
+
movaAppType === Enums_1.MovaAppType.ADMIN ? logo_large_png_1.default : logo_large_png_1.default;
|
|
151
|
+
};
|
|
152
|
+
return ((0, jsx_runtime_1.jsxs)("div", __assign({ style: styles }, { children: [(0, jsx_runtime_1.jsx)("img", { src: leaf_green_large_png_1.default, style: { position: 'fixed',
|
|
153
|
+
float: 'left',
|
|
154
|
+
width: '250px',
|
|
155
|
+
height: '400px',
|
|
156
|
+
top: '-20%',
|
|
157
|
+
left: '3%',
|
|
158
|
+
opacity: '0.3',
|
|
159
|
+
zIndex: -8 }, alt: 'Feuille Verte Movalib' }), (0, jsx_runtime_1.jsxs)(material_1.Container, __assign({ component: "main", maxWidth: "sm" }, { children: [(0, jsx_runtime_1.jsx)(material_1.CssBaseline, {}), (0, jsx_runtime_1.jsxs)(material_1.Box, __assign({ sx: {
|
|
160
|
+
marginTop: 6,
|
|
161
|
+
display: 'flex',
|
|
162
|
+
flexDirection: 'column',
|
|
163
|
+
alignItems: 'center',
|
|
164
|
+
} }, { 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.Typography, __assign({ variant: "h2" }, { children: "Nouveau compte utilisateur" }))] })), (0, jsx_runtime_1.jsxs)(material_1.Box, __assign({ component: "form", onSubmit: handleSubmit, noValidate: true, sx: { mt: 1 } }, { children: [(0, jsx_runtime_1.jsx)(material_1.TextField, { margin: "normal", required: true, autoFocus: true, fullWidth: true, id: "firstname", label: "Pr\u00E9nom", name: "firstname", autoComplete: "given-name", onChange: function (e) { return handleInputChange(e); }, value: userForm.firstname.value, error: Boolean(userForm.firstname.error), helperText: userForm.firstname.error }), (0, jsx_runtime_1.jsx)(material_1.TextField, { margin: "normal", required: true, fullWidth: true, id: "lastname", label: "Nom", name: "lastname", autoComplete: "family-name", onChange: function (e) { return handleInputChange(e); }, value: userForm.lastname.value, error: Boolean(userForm.lastname.error), helperText: userForm.lastname.error }), (0, jsx_runtime_1.jsx)(material_1.TextField, { margin: "normal", required: true, fullWidth: true, id: "email", label: "Adresse email", name: "email", autoComplete: "email", autoFocus: true, onChange: function (e) { return handleInputChange(e); }, value: userForm.email.value, error: !userForm.email.isValid, helperText: userForm.email.error }), (0, jsx_runtime_1.jsx)(material_1.TextField, { margin: "normal", required: true, fullWidth: true, name: "password", label: "Mot de passe", type: "password", id: "password", autoComplete: "current-password", onChange: function (e) { return handleInputChange(e); }, value: userForm.password.value, error: !userForm.password.isValid, helperText: userForm.password.error }), (0, jsx_runtime_1.jsx)(GenderSelector_1.default, { handleSelectChange: handleSelectChange, form: userForm, required: true }), (0, jsx_runtime_1.jsx)(material_1.TextField, { margin: "normal", required: true, label: "Date de naissance", type: "date", InputLabelProps: {
|
|
165
|
+
shrink: true,
|
|
166
|
+
}, autoComplete: "bday", value: userForm.password.value, error: !userForm.password.isValid, helperText: userForm.password.error, onChange: function (e) { return handleInputChange(e); } }), (0, jsx_runtime_1.jsxs)(material_1.FormControl, __assign({ error: !userForm.acceptsTerms.isValid }, { children: [(0, jsx_runtime_1.jsx)(material_1.FormControlLabel, { control: (0, jsx_runtime_1.jsx)(material_1.Checkbox, { color: "primary", checked: userForm.acceptsTerms.value, onChange: function (e, checked) { return handleCheckboxChange(e, checked); } }), label: (0, jsx_runtime_1.jsxs)("span", { children: ["J'accepte les", ' ', (0, jsx_runtime_1.jsx)(material_1.Link, __assign({ href: "/terms-and-conditions", target: "_blank" }, { children: "Conditions G\u00E9n\u00E9rales d'Utilisation" }))] }) }), (0, jsx_runtime_1.jsx)(material_1.FormHelperText, { children: userForm.acceptsTerms.error })] })), alertMessage && alertSeverity && (0, jsx_runtime_1.jsx)(material_1.Alert, __assign({ severity: alertSeverity, sx: { mb: 2 } }, { children: alertMessage })), (0, jsx_runtime_1.jsx)(lab_1.LoadingButton, __assign({ loading: loading, type: "submit", fullWidth: true, variant: "contained", sx: { mt: 3, mb: 2 } }, { children: (0, jsx_runtime_1.jsx)("span", { children: "Cr\u00E9er mon compte" }) }))] })), (0, jsx_runtime_1.jsx)(MovaCopyright_1.default, { sx: { mt: 8, mb: 4 } })] })), (0, jsx_runtime_1.jsx)("img", { src: leaf_pink_large_png_1.default, style: { position: 'fixed',
|
|
167
|
+
float: 'right',
|
|
168
|
+
width: '250px',
|
|
169
|
+
height: '400px',
|
|
170
|
+
bottom: '-20%',
|
|
171
|
+
right: '3%',
|
|
172
|
+
opacity: '0.3',
|
|
173
|
+
zIndex: '-10' }, alt: 'Feuille Rose Movalib' })] })));
|
|
174
|
+
};
|
|
175
|
+
exports.default = MovaLogin;
|
package/dist/helpers/Types.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
export type MovaUserSignUpForm = {
|
|
2
|
+
firstname: MovaFormField;
|
|
3
|
+
lastname: MovaFormField;
|
|
4
|
+
email: MovaFormField;
|
|
5
|
+
password: MovaFormField;
|
|
6
|
+
gender: MovaFormField;
|
|
7
|
+
birthDate: MovaFormField;
|
|
8
|
+
acceptsTerms: MovaFormField;
|
|
9
|
+
};
|
|
1
10
|
export type MovaLoginForm = {
|
|
2
11
|
email: MovaFormField;
|
|
3
12
|
password: MovaFormField;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,5 @@ export { default as MovaCopyright } from './MovaCopyright';
|
|
|
5
5
|
export { default as User } from './models/User';
|
|
6
6
|
export { default as Role } from './models/Role';
|
|
7
7
|
export { default as Address } from './models/Address';
|
|
8
|
-
export type { MovaFormField } from './helpers/Types';
|
|
9
|
-
export
|
|
10
|
-
export { RoleType } from './helpers/Enums';
|
|
11
|
-
export { MovaAppType } from './helpers/Enums';
|
|
8
|
+
export type { MovaFormField, MovaLoginForm, MovaUserSignUpForm } from './helpers/Types';
|
|
9
|
+
export { RoleType, MovaAppType } from './helpers/Enums';
|
package/dist/index.js
CHANGED
|
@@ -24,5 +24,4 @@ Object.defineProperty(exports, "Address", { enumerable: true, get: function () {
|
|
|
24
24
|
// Export des enums
|
|
25
25
|
var Enums_1 = require("./helpers/Enums");
|
|
26
26
|
Object.defineProperty(exports, "RoleType", { enumerable: true, get: function () { return Enums_1.RoleType; } });
|
|
27
|
-
|
|
28
|
-
Object.defineProperty(exports, "MovaAppType", { enumerable: true, get: function () { return Enums_2.MovaAppType; } });
|
|
27
|
+
Object.defineProperty(exports, "MovaAppType", { enumerable: true, get: function () { return Enums_1.MovaAppType; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@movalib/movalib-commons",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
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",
|
|
@@ -15,11 +15,10 @@
|
|
|
15
15
|
"author": "",
|
|
16
16
|
"license": "ISC",
|
|
17
17
|
"dependencies": {
|
|
18
|
+
"@types/node": "^16.18.53",
|
|
18
19
|
"react": "^18.2.0",
|
|
19
|
-
"react-scripts": "5.0.1",
|
|
20
20
|
"react-dom": "^18.2.0",
|
|
21
|
-
"
|
|
22
|
-
"@types/react": "^18.2.22"
|
|
21
|
+
"react-scripts": "5.0.1"
|
|
23
22
|
},
|
|
24
23
|
"eslintConfig": {
|
|
25
24
|
"extends": [
|
|
@@ -27,13 +26,20 @@
|
|
|
27
26
|
]
|
|
28
27
|
},
|
|
29
28
|
"devDependencies": {
|
|
30
|
-
"@mui/material": "^5.13.5",
|
|
31
|
-
"@mui/icons-material": "^5.11.16",
|
|
32
|
-
"@mui/lab": "^5.0.0-alpha.134",
|
|
33
29
|
"@emotion/react": "^11.11.1",
|
|
34
30
|
"@emotion/styled": "^11.11.0",
|
|
31
|
+
"@mui/icons-material": "^5.11.16",
|
|
32
|
+
"@mui/lab": "^5.0.0-alpha.134",
|
|
33
|
+
"@mui/material": "^5.13.5",
|
|
35
34
|
"@types/react": "^18.2.22",
|
|
36
35
|
"@types/react-dom": "^18.2.7",
|
|
37
|
-
"
|
|
36
|
+
"babel-plugin-named-exports-order": "^0.0.2",
|
|
37
|
+
"prop-types": "^15.8.1",
|
|
38
|
+
"typescript": "^4.9.5",
|
|
39
|
+
"webpack": "^5.88.2"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"react": "^18.2.0",
|
|
43
|
+
"react-dom": "^18.2.0"
|
|
38
44
|
}
|
|
39
45
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { ChangeEvent } from 'react';
|
|
2
|
+
import { FormControl, InputLabel, Select, MenuItem, SelectChangeEvent } from '@mui/material';
|
|
3
|
+
import { MovaFormField } from './helpers/Types';
|
|
4
|
+
|
|
5
|
+
interface GenderSelectorProps {
|
|
6
|
+
handleSelectChange: (event: SelectChangeEvent<string>) => void;
|
|
7
|
+
form: {
|
|
8
|
+
gender: MovaFormField
|
|
9
|
+
};
|
|
10
|
+
required?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const GenderSelector: React.FC<GenderSelectorProps> = ({ handleSelectChange, form, required }) => {
|
|
14
|
+
return (
|
|
15
|
+
<FormControl fullWidth margin="normal" required={required}>
|
|
16
|
+
<InputLabel id="gender-label">Sexe</InputLabel>
|
|
17
|
+
<Select
|
|
18
|
+
labelId="gender-label"
|
|
19
|
+
id="gender"
|
|
20
|
+
name="gender"
|
|
21
|
+
value={form.gender.value}
|
|
22
|
+
onChange={e => handleSelectChange(e)}
|
|
23
|
+
>
|
|
24
|
+
<MenuItem value="MALE">Homme</MenuItem>
|
|
25
|
+
<MenuItem value="FEMALE">Femme</MenuItem>
|
|
26
|
+
<MenuItem value="OTHER">Autre</MenuItem>
|
|
27
|
+
</Select>
|
|
28
|
+
</FormControl>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default GenderSelector;
|
package/src/MovaLogin.tsx
CHANGED
|
@@ -159,10 +159,7 @@ const MovaLogin: FunctionComponent<MovaLoginProps> = ({ loading, movaAppType, on
|
|
|
159
159
|
<FormControlLabel control={<Checkbox value="remember" color="primary" />}
|
|
160
160
|
label="Se souvenir de moi"
|
|
161
161
|
/>
|
|
162
|
-
|
|
163
|
-
type={ButtonType.SUBMIT}
|
|
164
|
-
label="Se connecter" /> */}
|
|
165
|
-
|
|
162
|
+
|
|
166
163
|
<LoadingButton
|
|
167
164
|
loading={loading}
|
|
168
165
|
type="submit"
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { CSSProperties, FormEvent, FunctionComponent, useState } from "react";
|
|
2
|
+
import { LoadingButton } from '@mui/lab';
|
|
3
|
+
import LogoLarge from './assets/images/logo/logo_large.png';
|
|
4
|
+
import LogoProLarge from './assets/images/logo/logo_pro_large.png';
|
|
5
|
+
import GreenLeafImage from "./assets/images/leaf_green_large.png";
|
|
6
|
+
import PinkLeafImage from "./assets/images/leaf_pink_large.png";
|
|
7
|
+
import { Alert, AlertColor, Box, Checkbox, Container, CssBaseline, FormControl, FormControlLabel, FormHelperText, Grid, Link, SelectChangeEvent, TextField, Typography } from "@mui/material";
|
|
8
|
+
import MovaCopyright from "./MovaCopyright";
|
|
9
|
+
import { MovaLoginForm, MovaFormField, MovaUserSignUpForm } from "./helpers/Types";
|
|
10
|
+
import { MovaAppType } from "./helpers/Enums";
|
|
11
|
+
import { validateEmail } from "./helpers/Validator";
|
|
12
|
+
import GenderSelector from "./GenderSelector";
|
|
13
|
+
|
|
14
|
+
// Permet de centrer le contenu de l'application
|
|
15
|
+
const styles: CSSProperties = {
|
|
16
|
+
display: 'flex',
|
|
17
|
+
justifyContent: 'center',
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
height: '100vh', // Ajustez la hauteur en fonction de vos besoins
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const initialUserFormState = {
|
|
23
|
+
firstname: { value: '', isValid: true },
|
|
24
|
+
lastname: { value: '', isValid: true },
|
|
25
|
+
email: { value: '', isValid: true },
|
|
26
|
+
password: { value: '', isValid: true },
|
|
27
|
+
gender: { value: '', isValid: true },
|
|
28
|
+
birthDate: { value: '', isValid: true },
|
|
29
|
+
acceptsTerms: { value: false, isValid: true },
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Propriétés du composant
|
|
34
|
+
* movaAppType : type d'application Movalib au sein de laquelle le composant est injectée
|
|
35
|
+
* onSubmit : callbakc invoquée en cas de formulaire valide
|
|
36
|
+
* alertMessage : éventuel message à afficher
|
|
37
|
+
* alertSeverity : niveau d'alerte pour le message à afficher
|
|
38
|
+
* loading : permet de mettre éventuellement le bouton de soumission en état de chargement
|
|
39
|
+
*/
|
|
40
|
+
interface MovaSignUpProps {
|
|
41
|
+
movaAppType: MovaAppType,
|
|
42
|
+
onSubmit: (form: MovaLoginForm) => void,
|
|
43
|
+
alertMessage?: string,
|
|
44
|
+
alertSeverity?: AlertColor,
|
|
45
|
+
loading?: boolean
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const MovaLogin: FunctionComponent<MovaSignUpProps> = ({ loading, movaAppType, onSubmit, alertMessage, alertSeverity }) => {
|
|
49
|
+
|
|
50
|
+
const [userForm, setUserForm] = useState<MovaUserSignUpForm>(initialUserFormState);
|
|
51
|
+
|
|
52
|
+
const [message, setMessage] = useState<string>("");
|
|
53
|
+
//const [loading, setLoading] = useState(false);
|
|
54
|
+
|
|
55
|
+
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>): void => {
|
|
56
|
+
const fieldName: string = e.target.name;
|
|
57
|
+
const fieldValue: string = e.target.value;
|
|
58
|
+
const newField: MovaFormField = { [fieldName]: { value: fieldValue, isValid: true } };
|
|
59
|
+
|
|
60
|
+
setUserForm({ ...userForm, ...newField});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const handleCheckboxChange = (e: SelectChangeEvent<string>, checked: boolean): void => {
|
|
64
|
+
const fieldName: string = e.target.name;
|
|
65
|
+
const fieldValue: boolean = checked;
|
|
66
|
+
const newField: MovaFormField = { [fieldName]: { value: fieldValue, isValid: true } };
|
|
67
|
+
|
|
68
|
+
setUserForm({ ...userForm, ...newField});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const handleSelectChange = (e: SelectChangeEvent<string>): void => {
|
|
72
|
+
const fieldName: string = e.target.name;
|
|
73
|
+
const fieldValue: string = e.target.value;
|
|
74
|
+
const newField: MovaFormField = { [fieldName]: { value: fieldValue, isValid: true } };
|
|
75
|
+
|
|
76
|
+
setUserForm({ ...userForm, ...newField});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const handleSubmit = async (e: FormEvent) => {
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
try {
|
|
82
|
+
if(validateForm() && onSubmit) {
|
|
83
|
+
// Si le formulaire est valide, on appel la function callback transmise en props
|
|
84
|
+
onSubmit(userForm);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}catch (error){
|
|
88
|
+
console.error('Error occurred during submission:', error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const validateForm = () => {
|
|
93
|
+
let newForm: MovaUserSignUpForm = userForm;
|
|
94
|
+
|
|
95
|
+
// Validator email
|
|
96
|
+
if(!validateEmail(userForm.email.value)) {
|
|
97
|
+
const errorMsg: string = 'Adresse email invalide';
|
|
98
|
+
const newField: MovaFormField = { value: userForm.email.value, error: errorMsg, isValid: false };
|
|
99
|
+
newForm = { ...newForm, ...{ email: newField } };
|
|
100
|
+
} else {
|
|
101
|
+
const newField: MovaFormField = { value: userForm.email.value, error: '', isValid: true };
|
|
102
|
+
newForm = { ...newForm, ...{ email: newField } };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Validator password
|
|
106
|
+
if(userForm.password.value.length < 8) {
|
|
107
|
+
const errorMsg: string = 'Votre mot de passe doit faire au moins 8 caractères de long.';
|
|
108
|
+
const newField: MovaFormField = {value: userForm.password.value, error: errorMsg, isValid: false};
|
|
109
|
+
newForm = { ...newForm, ...{ password: newField } };
|
|
110
|
+
} else {
|
|
111
|
+
const newField: MovaFormField = { value: userForm.password.value, error: '', isValid: true };
|
|
112
|
+
newForm = { ...newForm, ...{ password: newField } };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
setUserForm(newForm);
|
|
116
|
+
|
|
117
|
+
return newForm.email.isValid && newForm.password.isValid;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const getMovaLogo = () => {
|
|
121
|
+
|
|
122
|
+
return movaAppType === MovaAppType.GARAGE ? LogoProLarge :
|
|
123
|
+
movaAppType === MovaAppType.USER ? LogoLarge :
|
|
124
|
+
movaAppType === MovaAppType.ADMIN ? LogoLarge : LogoLarge;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<div style={styles}>
|
|
130
|
+
<img src={GreenLeafImage} style={{position: 'fixed',
|
|
131
|
+
float:'left',
|
|
132
|
+
width: '250px',
|
|
133
|
+
height: '400px',
|
|
134
|
+
top: '-20%',
|
|
135
|
+
left: '3%',
|
|
136
|
+
opacity: '0.3',
|
|
137
|
+
zIndex: -8}} alt='Feuille Verte Movalib'></img>
|
|
138
|
+
|
|
139
|
+
<Container component="main" maxWidth="sm">
|
|
140
|
+
<CssBaseline />
|
|
141
|
+
<Box
|
|
142
|
+
sx={{
|
|
143
|
+
marginTop: 6,
|
|
144
|
+
display: 'flex',
|
|
145
|
+
flexDirection: 'column',
|
|
146
|
+
alignItems: 'center',
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
<img src={getMovaLogo()} style={{width:'50%'}}/>
|
|
150
|
+
<br />
|
|
151
|
+
<Typography variant="h2">Nouveau compte utilisateur</Typography>
|
|
152
|
+
</Box>
|
|
153
|
+
|
|
154
|
+
<Box component="form" onSubmit={handleSubmit} noValidate sx={{ mt: 1 }}>
|
|
155
|
+
<TextField
|
|
156
|
+
margin="normal"
|
|
157
|
+
required
|
|
158
|
+
autoFocus
|
|
159
|
+
fullWidth
|
|
160
|
+
id="firstname"
|
|
161
|
+
label="Prénom"
|
|
162
|
+
name="firstname"
|
|
163
|
+
autoComplete="given-name"
|
|
164
|
+
onChange={e => handleInputChange(e)}
|
|
165
|
+
value={userForm.firstname.value}
|
|
166
|
+
error={Boolean(userForm.firstname.error)}
|
|
167
|
+
helperText={userForm.firstname.error}
|
|
168
|
+
/>
|
|
169
|
+
<TextField
|
|
170
|
+
margin="normal"
|
|
171
|
+
required
|
|
172
|
+
fullWidth
|
|
173
|
+
id="lastname"
|
|
174
|
+
label="Nom"
|
|
175
|
+
name="lastname"
|
|
176
|
+
autoComplete="family-name"
|
|
177
|
+
onChange={e => handleInputChange(e)}
|
|
178
|
+
value={userForm.lastname.value}
|
|
179
|
+
error={Boolean(userForm.lastname.error)}
|
|
180
|
+
helperText={userForm.lastname.error}
|
|
181
|
+
/>
|
|
182
|
+
<TextField
|
|
183
|
+
margin="normal"
|
|
184
|
+
required
|
|
185
|
+
fullWidth
|
|
186
|
+
id="email"
|
|
187
|
+
label="Adresse email"
|
|
188
|
+
name="email"
|
|
189
|
+
autoComplete="email"
|
|
190
|
+
autoFocus
|
|
191
|
+
onChange={e => handleInputChange(e)}
|
|
192
|
+
value={userForm.email.value}
|
|
193
|
+
error={!userForm.email.isValid}
|
|
194
|
+
helperText={userForm.email.error}
|
|
195
|
+
/>
|
|
196
|
+
<TextField
|
|
197
|
+
margin="normal"
|
|
198
|
+
required
|
|
199
|
+
fullWidth
|
|
200
|
+
name="password"
|
|
201
|
+
label="Mot de passe"
|
|
202
|
+
type="password"
|
|
203
|
+
id="password"
|
|
204
|
+
autoComplete="current-password"
|
|
205
|
+
onChange={e => handleInputChange(e)}
|
|
206
|
+
value={userForm.password.value}
|
|
207
|
+
error={!userForm.password.isValid}
|
|
208
|
+
helperText={userForm.password.error}
|
|
209
|
+
/>
|
|
210
|
+
<GenderSelector handleSelectChange={handleSelectChange} form={userForm} required/>
|
|
211
|
+
<TextField
|
|
212
|
+
margin="normal"
|
|
213
|
+
required
|
|
214
|
+
label="Date de naissance"
|
|
215
|
+
type="date"
|
|
216
|
+
InputLabelProps={{
|
|
217
|
+
shrink: true,
|
|
218
|
+
}}
|
|
219
|
+
autoComplete="bday"
|
|
220
|
+
value={userForm.password.value}
|
|
221
|
+
error={!userForm.password.isValid}
|
|
222
|
+
helperText={userForm.password.error}
|
|
223
|
+
onChange={(e) => handleInputChange(e)}
|
|
224
|
+
/>
|
|
225
|
+
<FormControl error={!userForm.acceptsTerms.isValid}>
|
|
226
|
+
<FormControlLabel
|
|
227
|
+
control={
|
|
228
|
+
<Checkbox
|
|
229
|
+
color="primary"
|
|
230
|
+
checked={userForm.acceptsTerms.value}
|
|
231
|
+
onChange={(e, checked) => handleCheckboxChange(e, checked)}
|
|
232
|
+
/>
|
|
233
|
+
}
|
|
234
|
+
label={
|
|
235
|
+
<span>
|
|
236
|
+
J'accepte les{' '}
|
|
237
|
+
<Link href="/terms-and-conditions" target="_blank">
|
|
238
|
+
Conditions Générales d'Utilisation
|
|
239
|
+
</Link>
|
|
240
|
+
</span>
|
|
241
|
+
}
|
|
242
|
+
/>
|
|
243
|
+
<FormHelperText>{userForm.acceptsTerms.error}</FormHelperText>
|
|
244
|
+
</FormControl>
|
|
245
|
+
|
|
246
|
+
{alertMessage && alertSeverity && <Alert severity={alertSeverity} sx={{ mb: 2 }}>{alertMessage}</Alert>}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
<LoadingButton
|
|
250
|
+
loading={loading}
|
|
251
|
+
type="submit"
|
|
252
|
+
fullWidth
|
|
253
|
+
variant="contained"
|
|
254
|
+
sx={{ mt: 3, mb: 2 }}>
|
|
255
|
+
<span>Créer mon compte</span>
|
|
256
|
+
</LoadingButton>
|
|
257
|
+
|
|
258
|
+
</Box>
|
|
259
|
+
<MovaCopyright sx={{ mt: 8, mb: 4 }} />
|
|
260
|
+
</Container>
|
|
261
|
+
|
|
262
|
+
<img src={PinkLeafImage} style={{position: 'fixed',
|
|
263
|
+
float:'right',
|
|
264
|
+
width: '250px',
|
|
265
|
+
height: '400px',
|
|
266
|
+
bottom: '-20%',
|
|
267
|
+
right: '3%',
|
|
268
|
+
opacity: '0.3',
|
|
269
|
+
zIndex: '-10'}} alt='Feuille Rose Movalib'></img>
|
|
270
|
+
</div>
|
|
271
|
+
);
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
export default MovaLogin;
|
package/src/helpers/Types.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
export type MovaUserSignUpForm = {
|
|
2
|
+
firstname: MovaFormField,
|
|
3
|
+
lastname: MovaFormField,
|
|
4
|
+
email: MovaFormField,
|
|
5
|
+
password: MovaFormField,
|
|
6
|
+
gender: MovaFormField,
|
|
7
|
+
birthDate: MovaFormField,
|
|
8
|
+
acceptsTerms: MovaFormField
|
|
9
|
+
}
|
|
1
10
|
|
|
2
11
|
export type MovaLoginForm = {
|
|
3
12
|
email: MovaFormField,
|
package/src/index.ts
CHANGED
|
@@ -12,9 +12,8 @@ export { default as Role } from './models/Role';
|
|
|
12
12
|
export { default as Address } from './models/Address';
|
|
13
13
|
|
|
14
14
|
// Export des types
|
|
15
|
-
export type { MovaFormField } from './helpers/Types';
|
|
16
|
-
|
|
15
|
+
export type { MovaFormField, MovaLoginForm, MovaUserSignUpForm } from './helpers/Types';
|
|
16
|
+
|
|
17
17
|
|
|
18
18
|
// Export des enums
|
|
19
|
-
export { RoleType } from './helpers/Enums';
|
|
20
|
-
export { MovaAppType } from './helpers/Enums';
|
|
19
|
+
export { RoleType, MovaAppType } from './helpers/Enums';
|