@movalib/movalib-commons 1.0.13 → 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 +23 -0
- 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/assets/images/logo/logo_large.png +0 -0
- package/dist/assets/images/logo/logo_pro_large.png +0 -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 +15 -12
- package/src/GenderSelector.tsx +32 -0
- package/src/MovaCopyright.tsx +17 -0
- package/src/MovaLogin.tsx +202 -0
- package/src/MovaSignUp.tsx +274 -0
- package/src/MovaSnackbar.tsx +65 -0
- package/src/TestButton.tsx +12 -0
- package/src/assets/images/logo/header_logo.png +0 -0
- package/src/assets/images/logo/header_logo_pro.png +0 -0
- package/src/helpers/Enums.ts +38 -0
- package/src/helpers/Tools.ts +1 -0
- package/src/helpers/Types.ts +20 -0
- package/src/helpers/Validator.ts +57 -0
- package/src/index.ts +19 -0
- package/src/models/Address.ts +28 -0
- package/src/models/Role.ts +16 -0
- package/src/models/User.ts +59 -0
- package/src/react-app-env.d.ts +1 -0
- package/tsconfig.json +114 -0
- /package/dist/assets/{assets/images → images}/logo/header_logo.png +0 -0
- /package/dist/assets/{assets/images → images}/logo/header_logo_pro.png +0 -0
- /package/{dist/assets → src}/assets/images/leaf_green_large.png +0 -0
- /package/{dist/assets → src}/assets/images/leaf_orange_large.png +0 -0
- /package/{dist/assets → src}/assets/images/leaf_pink_large.png +0 -0
- /package/{dist/assets → src}/assets/images/logo/logo_large.png +0 -0
- /package/{dist/assets → src}/assets/images/logo/logo_pro_large.png +0 -0
|
@@ -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;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// MovaSnackbar.tsx
|
|
2
|
+
import React, { FunctionComponent } from 'react';
|
|
3
|
+
import { Snackbar, Alert, IconButton, SnackbarCloseReason } from '@mui/material';
|
|
4
|
+
import CloseIcon from '@mui/icons-material/CloseRounded';
|
|
5
|
+
|
|
6
|
+
interface MovaSnackbarProps {
|
|
7
|
+
snackbar: {
|
|
8
|
+
open: boolean;
|
|
9
|
+
message: string;
|
|
10
|
+
severity: 'success' | 'info' | 'warning' | 'error' | undefined;
|
|
11
|
+
};
|
|
12
|
+
setSnackbar: (snackbar: {
|
|
13
|
+
open: boolean;
|
|
14
|
+
message: string;
|
|
15
|
+
severity: 'success' | 'info' | 'warning' | 'error' | undefined;
|
|
16
|
+
}) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const MovaSnackbar: FunctionComponent<MovaSnackbarProps> = ({ snackbar, setSnackbar }) => {
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Gestion de la fermeture de la snackbar. Si la raison de cette fermeture est
|
|
23
|
+
* un clic en dehors de la zone de contenu on intercepte et annule la fermeture 'clickaway'.
|
|
24
|
+
* @param event Evénnement de fermeture
|
|
25
|
+
* @param reason Origine de l'événnement de fermeture
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
const handleClose = (event: globalThis.Event | React.SyntheticEvent<any, globalThis.Event>,
|
|
29
|
+
reason: SnackbarCloseReason) => {
|
|
30
|
+
|
|
31
|
+
if (reason === 'clickaway') return;
|
|
32
|
+
|
|
33
|
+
setSnackbar({ open: false, message: '', severity: undefined });
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const handleCloseAlert = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
37
|
+
setSnackbar({ open: false, message: '', severity: undefined });
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Snackbar open={snackbar.open} autoHideDuration={5000} onClose={handleClose}>
|
|
42
|
+
<Alert severity={snackbar.severity} variant="filled" sx={{ width: '100%' }}
|
|
43
|
+
action={
|
|
44
|
+
<>
|
|
45
|
+
{/* TODO : possiblité d'annuler l'action qui vient d'avoir lieu */}
|
|
46
|
+
{/* <Button color="inherit" size="small" onClick={handleCancelAction}>
|
|
47
|
+
Annuler
|
|
48
|
+
</Button> */}
|
|
49
|
+
<IconButton
|
|
50
|
+
size="small"
|
|
51
|
+
aria-label="close"
|
|
52
|
+
color="inherit"
|
|
53
|
+
onClick={handleCloseAlert}
|
|
54
|
+
>
|
|
55
|
+
<CloseIcon fontSize="small" />
|
|
56
|
+
</IconButton>
|
|
57
|
+
</>
|
|
58
|
+
}>
|
|
59
|
+
{snackbar.message}
|
|
60
|
+
</Alert>
|
|
61
|
+
</Snackbar>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default MovaSnackbar;
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
export enum MovaAppType {
|
|
3
|
+
/**
|
|
4
|
+
* Application Garagiste
|
|
5
|
+
*/
|
|
6
|
+
GARAGE = "GARAGE",
|
|
7
|
+
/**
|
|
8
|
+
* Application Utilisateur (automobiliste)
|
|
9
|
+
*/
|
|
10
|
+
USER = "USER",
|
|
11
|
+
/**
|
|
12
|
+
* Application Administrateur (MovaTeam)
|
|
13
|
+
*/
|
|
14
|
+
ADMIN = "ADMIN"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export enum RoleType {
|
|
18
|
+
/**
|
|
19
|
+
* Client du centre auto (automobiliste)
|
|
20
|
+
*/
|
|
21
|
+
CUSTOMER = "CUSTOMER",
|
|
22
|
+
/**
|
|
23
|
+
* Technicien du centre auto
|
|
24
|
+
*/
|
|
25
|
+
TECHNICIAN = "GARAGE_LEADER",
|
|
26
|
+
/**
|
|
27
|
+
* Chef d'atelier
|
|
28
|
+
*/
|
|
29
|
+
GARAGE_LEADER = "GARAGE_LEADER",
|
|
30
|
+
/**
|
|
31
|
+
* Administrateur du centre auto (propriétaire ou dirigeant)
|
|
32
|
+
*/
|
|
33
|
+
GARAGE_ADMIN = "ADMINISTRATOR",
|
|
34
|
+
/**
|
|
35
|
+
* Super-Administrateur (team Movalib)
|
|
36
|
+
*/
|
|
37
|
+
MOVALIB_ADMIN = "MOVALIB_ADMIN",
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
}
|
|
10
|
+
|
|
11
|
+
export type MovaLoginForm = {
|
|
12
|
+
email: MovaFormField,
|
|
13
|
+
password: MovaFormField
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type MovaFormField = {
|
|
17
|
+
value?: any,
|
|
18
|
+
error?: string,
|
|
19
|
+
isValid?: boolean
|
|
20
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Un email valide
|
|
3
|
+
*/
|
|
4
|
+
const emailRegex:RegExp = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Un mot de passe qui contient au moins une majuscule, une minuscule, un chiffre
|
|
8
|
+
* et un caractère spécial. La longueur du mot de passe doit être d'au moins 8 caractères.
|
|
9
|
+
*/
|
|
10
|
+
const passwordRegex:RegExp = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Un numéro de téléphone (10 chiffres)
|
|
14
|
+
*/
|
|
15
|
+
const phoneNumberRegex:RegExp = /^\d{0,10}$/;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Un code postal (5 chiffres)
|
|
19
|
+
*/
|
|
20
|
+
const postalCodeRegex:RegExp = /^\d{5}$/;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Une URL valide
|
|
24
|
+
*/
|
|
25
|
+
const urlRegex:RegExp =/^(ftp|http|https):\/\/[^ "]+$/;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Un nom pouvant contenir des lettres, chiffres d'une taille comprise entre 3 et 20 caractères
|
|
29
|
+
*/
|
|
30
|
+
const userNameRegex:RegExp = /^[a-z0-9_-]{3,20}$/;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Un texte pouvant contenir des lettres, chiffres et quelques caractères spéciaux
|
|
34
|
+
*/
|
|
35
|
+
const textRegex:RegExp = /^[a-zA-Z0-9\s.,!?'"()+=-_-éèçà]+$/;
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
export function validatePhoneNumber(phoneNumber: string) : boolean {
|
|
39
|
+
if (phoneNumber === null || phoneNumber === undefined) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return phoneNumberRegex.test(phoneNumber);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function validateText(text: string) : boolean {
|
|
46
|
+
if (text === null || text === undefined) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return textRegex.test(text);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function validateEmail(email: string) : boolean {
|
|
53
|
+
if (email === null || email === undefined) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return emailRegex.test(email);
|
|
57
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
|
|
3
|
+
// Export des composants
|
|
4
|
+
export { default as TestButton } from './TestButton';
|
|
5
|
+
export { default as MovaSnackbar } from './MovaSnackbar';
|
|
6
|
+
export { default as MovaLogin } from './MovaLogin';
|
|
7
|
+
export { default as MovaCopyright } from './MovaCopyright';
|
|
8
|
+
|
|
9
|
+
// Export des classes
|
|
10
|
+
export { default as User } from './models/User';
|
|
11
|
+
export { default as Role } from './models/Role';
|
|
12
|
+
export { default as Address } from './models/Address';
|
|
13
|
+
|
|
14
|
+
// Export des types
|
|
15
|
+
export type { MovaFormField, MovaLoginForm, MovaUserSignUpForm } from './helpers/Types';
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
// Export des enums
|
|
19
|
+
export { RoleType, MovaAppType } from './helpers/Enums';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default class Address {
|
|
2
|
+
|
|
3
|
+
id: string; // UUID
|
|
4
|
+
streetName: string; // Street number & name
|
|
5
|
+
postalCode: string; // Postal code
|
|
6
|
+
cityName: string; // City name
|
|
7
|
+
country: string; // Country name
|
|
8
|
+
countryCode: string; // Country ISO code
|
|
9
|
+
additional?: string; // Additional address information (optional)
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
id: string,
|
|
13
|
+
streetName: string,
|
|
14
|
+
postalCode: string,
|
|
15
|
+
cityName: string,
|
|
16
|
+
country: string,
|
|
17
|
+
countryCode: string,
|
|
18
|
+
additional?: string
|
|
19
|
+
) {
|
|
20
|
+
this.id = id;
|
|
21
|
+
this.streetName = streetName;
|
|
22
|
+
this.postalCode = postalCode;
|
|
23
|
+
this.cityName = cityName;
|
|
24
|
+
this.country = country;
|
|
25
|
+
this.countryCode = countryCode;
|
|
26
|
+
this.additional = additional;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default class Role {
|
|
2
|
+
|
|
3
|
+
id:string;
|
|
4
|
+
isActive: boolean;
|
|
5
|
+
authorizations: string[];
|
|
6
|
+
|
|
7
|
+
constructor(
|
|
8
|
+
id:string,
|
|
9
|
+
isActive: boolean = true,
|
|
10
|
+
authorizations: string[]
|
|
11
|
+
) {
|
|
12
|
+
this.id = id;
|
|
13
|
+
this.isActive = isActive;
|
|
14
|
+
this.authorizations = authorizations;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { RoleType } from "../helpers/Enums";
|
|
2
|
+
import Address from './Address';
|
|
3
|
+
|
|
4
|
+
export default class User {
|
|
5
|
+
|
|
6
|
+
// Properties
|
|
7
|
+
id: string;
|
|
8
|
+
roles: string[];
|
|
9
|
+
firstname: string;
|
|
10
|
+
lastname: string;
|
|
11
|
+
avatar: string;
|
|
12
|
+
email: string;
|
|
13
|
+
password: string;
|
|
14
|
+
created: Date;
|
|
15
|
+
addresses? : Address[]
|
|
16
|
+
phoneNumber?: string;
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
id: string,
|
|
20
|
+
roles: string[],
|
|
21
|
+
firstname: string = '',
|
|
22
|
+
lastname: string = '',
|
|
23
|
+
avatar: string = '',
|
|
24
|
+
email: string = '',
|
|
25
|
+
password: string = '',
|
|
26
|
+
created: Date = new Date(),
|
|
27
|
+
addresses?: Address[],
|
|
28
|
+
phoneNumber?: string
|
|
29
|
+
) {
|
|
30
|
+
this.id = id;
|
|
31
|
+
this.roles = roles;
|
|
32
|
+
this.firstname = firstname;
|
|
33
|
+
this.lastname = lastname;
|
|
34
|
+
this.avatar = avatar;
|
|
35
|
+
this.email = email;
|
|
36
|
+
this.password = password;
|
|
37
|
+
this.created = created;
|
|
38
|
+
this.addresses = addresses;
|
|
39
|
+
this.phoneNumber = phoneNumber;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static getFirstLetter = (user: User) : string => {
|
|
43
|
+
|
|
44
|
+
const firstLetter = user.lastname[0].toUpperCase();
|
|
45
|
+
return /[0-9]/.test(firstLetter) ? '0-9' : firstLetter;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static isCustomer = (user: User) : boolean => {
|
|
49
|
+
if(!user || !user.roles) return false;
|
|
50
|
+
|
|
51
|
+
return Boolean(user.roles.find(r => r = RoleType.CUSTOMER));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static isTechnician = (user: User) : boolean => {
|
|
55
|
+
if(!user || !user.roles) return false;
|
|
56
|
+
|
|
57
|
+
return Boolean(user.roles.find(r => r = RoleType.TECHNICIAN));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="react-scripts" />
|