theo_lafond_react_ci_cd 0.0.0
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/babel.config.cjs +6 -0
- package/cypress.config.js +12 -0
- package/dist/App.css +35 -0
- package/dist/App.js +147 -0
- package/dist/assets/react.svg +1 -0
- package/dist/components/PersonForm.css +63 -0
- package/dist/components/PersonForm.js +312 -0
- package/dist/domain/module.js +33 -0
- package/dist/domain/services/personService.js +126 -0
- package/dist/domain/validator.js +143 -0
- package/dist/index.css +64 -0
- package/dist/index.js +13 -0
- package/dist/main.js +11 -0
- package/dist/pages/Home.css +57 -0
- package/dist/pages/Home.js +102 -0
- package/dist/pages/Register.css +28 -0
- package/dist/pages/Register.js +40 -0
- package/dist/utils/errorMessages.js +46 -0
- package/eslint.config.js +29 -0
- package/jest.config.cjs +9 -0
- package/jsdoc.json +8 -0
- package/package.json +50 -0
- package/public/docs/App.jsx.html +114 -0
- package/public/docs/components_PersonForm.jsx.html +282 -0
- package/public/docs/domain_module.js.html +81 -0
- package/public/docs/domain_personService.js.html +69 -0
- package/public/docs/domain_validator.js.html +190 -0
- package/public/docs/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/public/docs/fonts/OpenSans-Bold-webfont.svg +1830 -0
- package/public/docs/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/public/docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/public/docs/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
- package/public/docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/public/docs/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/public/docs/fonts/OpenSans-Italic-webfont.svg +1830 -0
- package/public/docs/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/public/docs/fonts/OpenSans-Light-webfont.eot +0 -0
- package/public/docs/fonts/OpenSans-Light-webfont.svg +1831 -0
- package/public/docs/fonts/OpenSans-Light-webfont.woff +0 -0
- package/public/docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/public/docs/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
- package/public/docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/public/docs/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/public/docs/fonts/OpenSans-Regular-webfont.svg +1831 -0
- package/public/docs/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/public/docs/global.html +2439 -0
- package/public/docs/module-App.html +362 -0
- package/public/docs/module-Home.html +373 -0
- package/public/docs/module-PersonForm.html +723 -0
- package/public/docs/module-Register.html +281 -0
- package/public/docs/module.js.html +81 -0
- package/public/docs/pages_Home.jsx.html +106 -0
- package/public/docs/pages_Register.jsx.html +78 -0
- package/public/docs/scripts/linenumber.js +25 -0
- package/public/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/public/docs/scripts/prettify/lang-css.js +2 -0
- package/public/docs/scripts/prettify/prettify.js +28 -0
- package/public/docs/styles/jsdoc-default.css +358 -0
- package/public/docs/styles/prettify-jsdoc.css +111 -0
- package/public/docs/styles/prettify-tomorrow.css +132 -0
- package/public/docs/utils_errorMessages.js.html +87 -0
- package/public/docs/validator.js.html +179 -0
- package/public/vite.svg +1 -0
package/babel.config.cjs
ADDED
package/dist/App.css
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.logo {
|
|
2
|
+
height: 6em;
|
|
3
|
+
padding: 1.5em;
|
|
4
|
+
will-change: filter;
|
|
5
|
+
transition: filter 300ms;
|
|
6
|
+
}
|
|
7
|
+
.logo:hover {
|
|
8
|
+
filter: drop-shadow(0 0 2em #646cffaa);
|
|
9
|
+
}
|
|
10
|
+
.logo.react:hover {
|
|
11
|
+
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@keyframes logo-spin {
|
|
15
|
+
from {
|
|
16
|
+
transform: rotate(0deg);
|
|
17
|
+
}
|
|
18
|
+
to {
|
|
19
|
+
transform: rotate(360deg);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
24
|
+
a:nth-of-type(2) .logo {
|
|
25
|
+
animation: logo-spin infinite 20s linear;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.card {
|
|
30
|
+
padding: 2em;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.read-the-docs {
|
|
34
|
+
color: #888;
|
|
35
|
+
}
|
package/dist/App.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _reactRouterDom = require("react-router-dom");
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _Home = _interopRequireDefault(require("./pages/Home"));
|
|
10
|
+
var _Register = _interopRequireDefault(require("./pages/Register"));
|
|
11
|
+
var _personService = require("./domain/services/personService");
|
|
12
|
+
var _errorMessages = require("./utils/errorMessages.js");
|
|
13
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
15
|
+
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
16
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
17
|
+
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
18
|
+
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
|
|
19
|
+
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
20
|
+
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
21
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
22
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
23
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
24
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
25
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
26
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
27
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
28
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } /**
|
|
29
|
+
* Main App Component
|
|
30
|
+
*
|
|
31
|
+
* Handles routing, state management for registered persons,
|
|
32
|
+
* and API communication via Axios.
|
|
33
|
+
*
|
|
34
|
+
* @module App
|
|
35
|
+
* @component
|
|
36
|
+
* @returns {JSX.Element} The main application component with routes
|
|
37
|
+
*/
|
|
38
|
+
function App() {
|
|
39
|
+
var _useState = (0, _react.useState)([]),
|
|
40
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
41
|
+
persons = _useState2[0],
|
|
42
|
+
setPersons = _useState2[1];
|
|
43
|
+
var _useState3 = (0, _react.useState)(true),
|
|
44
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
45
|
+
loading = _useState4[0],
|
|
46
|
+
setLoading = _useState4[1];
|
|
47
|
+
var _useState5 = (0, _react.useState)(null),
|
|
48
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
49
|
+
serverError = _useState6[0],
|
|
50
|
+
setServerError = _useState6[1];
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Load users from API on component mount.
|
|
54
|
+
*/
|
|
55
|
+
(0, _react.useEffect)(function () {
|
|
56
|
+
function loadUsers() {
|
|
57
|
+
return _loadUsers.apply(this, arguments);
|
|
58
|
+
}
|
|
59
|
+
function _loadUsers() {
|
|
60
|
+
_loadUsers = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
61
|
+
var users, _t;
|
|
62
|
+
return _regenerator().w(function (_context) {
|
|
63
|
+
while (1) switch (_context.p = _context.n) {
|
|
64
|
+
case 0:
|
|
65
|
+
setLoading(true);
|
|
66
|
+
_context.p = 1;
|
|
67
|
+
_context.n = 2;
|
|
68
|
+
return (0, _personService.fetchUsers)();
|
|
69
|
+
case 2:
|
|
70
|
+
users = _context.v;
|
|
71
|
+
setPersons(users);
|
|
72
|
+
_context.n = 4;
|
|
73
|
+
break;
|
|
74
|
+
case 3:
|
|
75
|
+
_context.p = 3;
|
|
76
|
+
_t = _context.v;
|
|
77
|
+
setServerError(_errorMessages.errorMessages.SERVER_ERROR);
|
|
78
|
+
case 4:
|
|
79
|
+
_context.p = 4;
|
|
80
|
+
setLoading(false);
|
|
81
|
+
return _context.f(4);
|
|
82
|
+
case 5:
|
|
83
|
+
return _context.a(2);
|
|
84
|
+
}
|
|
85
|
+
}, _callee, null, [[1, 3, 4, 5]]);
|
|
86
|
+
}));
|
|
87
|
+
return _loadUsers.apply(this, arguments);
|
|
88
|
+
}
|
|
89
|
+
loadUsers();
|
|
90
|
+
}, []);
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Add a person to the application state using API service.
|
|
94
|
+
*
|
|
95
|
+
* Delegates business validation (email uniqueness simulation)
|
|
96
|
+
* to the domain service.
|
|
97
|
+
*
|
|
98
|
+
* @async
|
|
99
|
+
* @function addPerson
|
|
100
|
+
* @param {Object} person - Person object to add
|
|
101
|
+
* @throws {Error} Propagates errors thrown by createUser
|
|
102
|
+
*/
|
|
103
|
+
var addPerson = /*#__PURE__*/function () {
|
|
104
|
+
var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(person) {
|
|
105
|
+
var existingEmails, newUser;
|
|
106
|
+
return _regenerator().w(function (_context2) {
|
|
107
|
+
while (1) switch (_context2.n) {
|
|
108
|
+
case 0:
|
|
109
|
+
existingEmails = persons.map(function (p) {
|
|
110
|
+
return p.email.toLowerCase();
|
|
111
|
+
});
|
|
112
|
+
_context2.n = 1;
|
|
113
|
+
return (0, _personService.createUser)(person, existingEmails);
|
|
114
|
+
case 1:
|
|
115
|
+
newUser = _context2.v;
|
|
116
|
+
setPersons(function (prev) {
|
|
117
|
+
return [].concat(_toConsumableArray(prev), [newUser]);
|
|
118
|
+
});
|
|
119
|
+
case 2:
|
|
120
|
+
return _context2.a(2);
|
|
121
|
+
}
|
|
122
|
+
}, _callee2);
|
|
123
|
+
}));
|
|
124
|
+
return function addPerson(_x) {
|
|
125
|
+
return _ref.apply(this, arguments);
|
|
126
|
+
};
|
|
127
|
+
}();
|
|
128
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactRouterDom.BrowserRouter, {
|
|
129
|
+
basename: "/Test_cycle_TDD/",
|
|
130
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactRouterDom.Routes, {
|
|
131
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactRouterDom.Route, {
|
|
132
|
+
path: "/",
|
|
133
|
+
element: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Home["default"], {
|
|
134
|
+
persons: persons,
|
|
135
|
+
loading: loading,
|
|
136
|
+
serverError: serverError
|
|
137
|
+
})
|
|
138
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactRouterDom.Route, {
|
|
139
|
+
path: "/register",
|
|
140
|
+
element: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Register["default"], {
|
|
141
|
+
addPerson: addPerson
|
|
142
|
+
})
|
|
143
|
+
})]
|
|
144
|
+
})
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
var _default = exports["default"] = App;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/* src/components/PersonForm.css */
|
|
2
|
+
.card {
|
|
3
|
+
max-width: 400px;
|
|
4
|
+
margin: 2rem auto;
|
|
5
|
+
padding: 2rem;
|
|
6
|
+
border-radius: 8px;
|
|
7
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
8
|
+
background-color: #fff;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.person-form {
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
gap: 1rem;
|
|
15
|
+
width: 100%;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.form-group {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
width: 100%;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.form-group input {
|
|
25
|
+
width: 100%;
|
|
26
|
+
padding: 0.5rem;
|
|
27
|
+
font-size: 1rem;
|
|
28
|
+
border: 1px solid #ccc;
|
|
29
|
+
border-radius: 4px;
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.form-group input:focus {
|
|
34
|
+
border-color: #007bff;
|
|
35
|
+
outline: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.error {
|
|
39
|
+
color: red;
|
|
40
|
+
font-size: 0.85rem;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.success {
|
|
44
|
+
margin-top: 1rem;
|
|
45
|
+
color: green;
|
|
46
|
+
font-weight: bold;
|
|
47
|
+
text-align: center;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
button {
|
|
51
|
+
padding: 0.6rem;
|
|
52
|
+
font-size: 1rem;
|
|
53
|
+
border-radius: 4px;
|
|
54
|
+
border: none;
|
|
55
|
+
background-color: #007bff;
|
|
56
|
+
color: white;
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
button:disabled {
|
|
61
|
+
background-color: #ccc;
|
|
62
|
+
cursor: not-allowed;
|
|
63
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports["default"] = PersonForm;
|
|
8
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
var _validator = require("../domain/validator");
|
|
10
|
+
var _errorMessages = require("../utils/errorMessages");
|
|
11
|
+
var _reactToastify = require("react-toastify");
|
|
12
|
+
require("react-toastify/dist/ReactToastify.css");
|
|
13
|
+
require("./PersonForm.css");
|
|
14
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
15
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t2 in e) "default" !== _t2 && {}.hasOwnProperty.call(e, _t2) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t2)) && (i.get || i.set) ? o(f, _t2, i) : f[_t2] = e[_t2]); return f; })(e, t); }
|
|
16
|
+
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
17
|
+
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
18
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
19
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
20
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
21
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
22
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
23
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
24
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
25
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
26
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
27
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
28
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
29
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
30
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } /**
|
|
31
|
+
* PersonForm Component
|
|
32
|
+
*
|
|
33
|
+
* A form for registering a person. Handles field validation and submission.
|
|
34
|
+
* Displays validation errors and success notifications using react-toastify.
|
|
35
|
+
*
|
|
36
|
+
* @module PersonForm
|
|
37
|
+
* @component
|
|
38
|
+
*
|
|
39
|
+
* @param {Object} props
|
|
40
|
+
* @param {function(Object): void} props.addPerson - Callback function to add a person object to parent state or storage
|
|
41
|
+
*
|
|
42
|
+
* @returns {JSX.Element} The rendered registration form
|
|
43
|
+
*/
|
|
44
|
+
function PersonForm(_ref) {
|
|
45
|
+
var addPerson = _ref.addPerson;
|
|
46
|
+
var _useState = (0, _react.useState)({
|
|
47
|
+
firstName: '',
|
|
48
|
+
lastName: '',
|
|
49
|
+
email: '',
|
|
50
|
+
birthDate: '',
|
|
51
|
+
zip: '',
|
|
52
|
+
city: ''
|
|
53
|
+
}),
|
|
54
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
55
|
+
form = _useState2[0],
|
|
56
|
+
setForm = _useState2[1];
|
|
57
|
+
var _useState3 = (0, _react.useState)({}),
|
|
58
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
59
|
+
errors = _useState4[0],
|
|
60
|
+
setErrors = _useState4[1];
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Validate a single form field and update the error state.
|
|
64
|
+
* @module PersonForm
|
|
65
|
+
* @function validateField
|
|
66
|
+
* @private
|
|
67
|
+
* @param {string} name - Field name
|
|
68
|
+
* @param {string} value - Field value
|
|
69
|
+
*/
|
|
70
|
+
var validateField = function validateField(name, value) {
|
|
71
|
+
if (!value) {
|
|
72
|
+
setErrors(function (prev) {
|
|
73
|
+
return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, ''));
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
switch (name) {
|
|
79
|
+
case 'firstName':
|
|
80
|
+
(0, _validator.validateName)(value, 'firstName');
|
|
81
|
+
break;
|
|
82
|
+
case 'lastName':
|
|
83
|
+
(0, _validator.validateName)(value, 'lastName');
|
|
84
|
+
break;
|
|
85
|
+
case 'email':
|
|
86
|
+
(0, _validator.validateEmail)(value);
|
|
87
|
+
break;
|
|
88
|
+
case 'zip':
|
|
89
|
+
(0, _validator.validateZipCode)(value);
|
|
90
|
+
break;
|
|
91
|
+
case 'city':
|
|
92
|
+
(0, _validator.validateCity)(value);
|
|
93
|
+
break;
|
|
94
|
+
case 'birthDate':
|
|
95
|
+
(0, _validator.validateAge)(new Date(value));
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
setErrors(function (prev) {
|
|
99
|
+
return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, ''));
|
|
100
|
+
});
|
|
101
|
+
} catch (err) {
|
|
102
|
+
setErrors(function (prev) {
|
|
103
|
+
return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, err.message));
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Handle form field changes.
|
|
110
|
+
* @module PersonForm
|
|
111
|
+
* @function handleChange
|
|
112
|
+
* @private
|
|
113
|
+
* @param {Event} e - Input change event
|
|
114
|
+
*/
|
|
115
|
+
var handleChange = function handleChange(e) {
|
|
116
|
+
var _e$target = e.target,
|
|
117
|
+
name = _e$target.name,
|
|
118
|
+
value = _e$target.value;
|
|
119
|
+
setForm(function (prev) {
|
|
120
|
+
return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, value));
|
|
121
|
+
});
|
|
122
|
+
validateField(name, value);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Handle form submission.
|
|
127
|
+
* @module PersonForm
|
|
128
|
+
* @function handleSubmit
|
|
129
|
+
* @private
|
|
130
|
+
* @param {Event} e - Submit event
|
|
131
|
+
*/
|
|
132
|
+
var handleSubmit = /*#__PURE__*/function () {
|
|
133
|
+
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(e) {
|
|
134
|
+
var person, key, _t;
|
|
135
|
+
return _regenerator().w(function (_context) {
|
|
136
|
+
while (1) switch (_context.p = _context.n) {
|
|
137
|
+
case 0:
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
_context.p = 1;
|
|
140
|
+
person = {
|
|
141
|
+
firstName: form.firstName,
|
|
142
|
+
lastName: form.lastName,
|
|
143
|
+
email: form.email,
|
|
144
|
+
birthDate: new Date(form.birthDate),
|
|
145
|
+
zip: form.zip,
|
|
146
|
+
city: form.city
|
|
147
|
+
};
|
|
148
|
+
(0, _validator.validatePerson)(person);
|
|
149
|
+
_context.n = 2;
|
|
150
|
+
return addPerson(person);
|
|
151
|
+
case 2:
|
|
152
|
+
_reactToastify.toast.success("Enregistré avec succès !", {
|
|
153
|
+
toastId: "success-toast"
|
|
154
|
+
});
|
|
155
|
+
setForm({
|
|
156
|
+
firstName: '',
|
|
157
|
+
lastName: '',
|
|
158
|
+
email: '',
|
|
159
|
+
birthDate: '',
|
|
160
|
+
zip: '',
|
|
161
|
+
city: ''
|
|
162
|
+
});
|
|
163
|
+
setErrors({});
|
|
164
|
+
_context.n = 4;
|
|
165
|
+
break;
|
|
166
|
+
case 3:
|
|
167
|
+
_context.p = 3;
|
|
168
|
+
_t = _context.v;
|
|
169
|
+
/* istanbul ignore next */
|
|
170
|
+
key = 'form';
|
|
171
|
+
/* istanbul ignore next */
|
|
172
|
+
if (_t.message.includes('SERVER_ERROR')) {
|
|
173
|
+
_reactToastify.toast.error(_errorMessages.errorMessages.SERVER_ERROR, {
|
|
174
|
+
toastId: "server-error-toast",
|
|
175
|
+
className: 'toast-server-error'
|
|
176
|
+
});
|
|
177
|
+
} else if (_t.message.includes('FIRST_NAME')) key = 'firstName';else if (_t.message.includes('LAST_NAME')) key = 'lastName';else if (_t.message.includes('INVALID_EMAIL') || _t.message.includes('EMAIL_ALREADY_EXISTS')) key = 'email';else if (_t.message.includes('ZIP')) key = 'zip';else if (_t.message.includes('CITY')) key = 'city';else if (_t.message.includes('UNDERAGE') || _t.message.includes('FUTURE_DATE')) key = 'birthDate';
|
|
178
|
+
|
|
179
|
+
/* istanbul ignore next */
|
|
180
|
+
setErrors(_defineProperty({}, key, _t.message));
|
|
181
|
+
case 4:
|
|
182
|
+
return _context.a(2);
|
|
183
|
+
}
|
|
184
|
+
}, _callee, null, [[1, 3]]);
|
|
185
|
+
}));
|
|
186
|
+
return function handleSubmit(_x) {
|
|
187
|
+
return _ref2.apply(this, arguments);
|
|
188
|
+
};
|
|
189
|
+
}();
|
|
190
|
+
var isDisabled = !form.firstName || !form.lastName || !form.email || !form.birthDate || !form.zip || !form.city || Object.values(errors).some(Boolean);
|
|
191
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
192
|
+
className: "card",
|
|
193
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("h2", {
|
|
194
|
+
children: "Formulaire d'inscription"
|
|
195
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("form", {
|
|
196
|
+
onSubmit: handleSubmit,
|
|
197
|
+
className: "person-form",
|
|
198
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
199
|
+
className: "form-group",
|
|
200
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
|
|
201
|
+
"data-cy": "firstName",
|
|
202
|
+
name: "firstName",
|
|
203
|
+
"aria-label": "firstName",
|
|
204
|
+
placeholder: "Pr\xE9nom",
|
|
205
|
+
value: form.firstName,
|
|
206
|
+
onChange: handleChange,
|
|
207
|
+
onBlur: function onBlur(e) {
|
|
208
|
+
return validateField('firstName', e.target.value);
|
|
209
|
+
}
|
|
210
|
+
}), errors.firstName && /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
211
|
+
className: "error",
|
|
212
|
+
children: (0, _errorMessages.getErrorMessage)(errors.firstName)
|
|
213
|
+
})]
|
|
214
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
215
|
+
className: "form-group",
|
|
216
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
|
|
217
|
+
"data-cy": "lastName",
|
|
218
|
+
name: "lastName",
|
|
219
|
+
"aria-label": "lastName",
|
|
220
|
+
placeholder: "Nom",
|
|
221
|
+
value: form.lastName,
|
|
222
|
+
onChange: handleChange,
|
|
223
|
+
onBlur: function onBlur(e) {
|
|
224
|
+
return validateField('lastName', e.target.value);
|
|
225
|
+
}
|
|
226
|
+
}), errors.lastName && /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
227
|
+
className: "error",
|
|
228
|
+
children: (0, _errorMessages.getErrorMessage)(errors.lastName)
|
|
229
|
+
})]
|
|
230
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
231
|
+
className: "form-group",
|
|
232
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
|
|
233
|
+
"data-cy": "birthDate",
|
|
234
|
+
type: "date",
|
|
235
|
+
name: "birthDate",
|
|
236
|
+
"data-testid": "birthDate",
|
|
237
|
+
value: form.birthDate,
|
|
238
|
+
onChange: handleChange,
|
|
239
|
+
onBlur: function onBlur(e) {
|
|
240
|
+
return validateField('birthDate', e.target.value);
|
|
241
|
+
}
|
|
242
|
+
}), errors.birthDate && /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
243
|
+
className: "error",
|
|
244
|
+
children: (0, _errorMessages.getErrorMessage)(errors.birthDate)
|
|
245
|
+
})]
|
|
246
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
247
|
+
className: "form-group",
|
|
248
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
|
|
249
|
+
"data-cy": "zip",
|
|
250
|
+
name: "zip",
|
|
251
|
+
"aria-label": "zip",
|
|
252
|
+
placeholder: "Code Postal",
|
|
253
|
+
value: form.zip,
|
|
254
|
+
onChange: handleChange,
|
|
255
|
+
onBlur: function onBlur(e) {
|
|
256
|
+
return validateField('zip', e.target.value);
|
|
257
|
+
}
|
|
258
|
+
}), errors.zip && /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
259
|
+
className: "error",
|
|
260
|
+
children: (0, _errorMessages.getErrorMessage)(errors.zip)
|
|
261
|
+
})]
|
|
262
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
263
|
+
className: "form-group",
|
|
264
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
|
|
265
|
+
"data-cy": "city",
|
|
266
|
+
name: "city",
|
|
267
|
+
"aria-label": "city",
|
|
268
|
+
placeholder: "Ville",
|
|
269
|
+
value: form.city,
|
|
270
|
+
onChange: handleChange,
|
|
271
|
+
onBlur: function onBlur(e) {
|
|
272
|
+
return validateField('city', e.target.value);
|
|
273
|
+
}
|
|
274
|
+
}), errors.city && /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
275
|
+
className: "error",
|
|
276
|
+
children: (0, _errorMessages.getErrorMessage)(errors.city)
|
|
277
|
+
})]
|
|
278
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
279
|
+
className: "form-group",
|
|
280
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
|
|
281
|
+
"data-cy": "email",
|
|
282
|
+
name: "email",
|
|
283
|
+
"aria-label": "email",
|
|
284
|
+
placeholder: "Email",
|
|
285
|
+
value: form.email,
|
|
286
|
+
onChange: handleChange,
|
|
287
|
+
onBlur: function onBlur(e) {
|
|
288
|
+
return validateField('email', e.target.value);
|
|
289
|
+
}
|
|
290
|
+
}), errors.email && /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
291
|
+
className: "error",
|
|
292
|
+
children: (0, _errorMessages.getErrorMessage)(errors.email)
|
|
293
|
+
})]
|
|
294
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
|
|
295
|
+
"data-cy": "submit",
|
|
296
|
+
type: "submit",
|
|
297
|
+
disabled: isDisabled,
|
|
298
|
+
children: "Soumettre"
|
|
299
|
+
})]
|
|
300
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactToastify.ToastContainer, {
|
|
301
|
+
position: "top-right",
|
|
302
|
+
autoClose: 3000,
|
|
303
|
+
hideProgressBar: false,
|
|
304
|
+
newestOnTop: true,
|
|
305
|
+
closeOnClick: true,
|
|
306
|
+
rtl: false,
|
|
307
|
+
pauseOnFocusLoss: true,
|
|
308
|
+
draggable: true,
|
|
309
|
+
pauseOnHover: true
|
|
310
|
+
})]
|
|
311
|
+
});
|
|
312
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.calculateAge = calculateAge;
|
|
7
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
8
|
+
/**
|
|
9
|
+
* Calculate a person's age in years
|
|
10
|
+
*
|
|
11
|
+
* @param {object} p An object representing a person, implementing a birth Date parameter.
|
|
12
|
+
* @returns {number} The age in years of p.
|
|
13
|
+
*/
|
|
14
|
+
function calculateAge(p) {
|
|
15
|
+
if (!p) {
|
|
16
|
+
throw new Error("missing param p");
|
|
17
|
+
}
|
|
18
|
+
if (_typeof(p) !== "object") {
|
|
19
|
+
throw new TypeError("param p must be an object");
|
|
20
|
+
}
|
|
21
|
+
if (!("birth" in p)) {
|
|
22
|
+
throw new Error("missing birth field in param p");
|
|
23
|
+
}
|
|
24
|
+
if (!(p.birth instanceof Date)) {
|
|
25
|
+
throw new TypeError("birth must be a Date object");
|
|
26
|
+
}
|
|
27
|
+
if (Number.isNaN(p.birth.getTime())) {
|
|
28
|
+
throw new TypeError("invalid birth date");
|
|
29
|
+
}
|
|
30
|
+
var dateDiff = new Date(Date.now() - p.birth.getTime());
|
|
31
|
+
var age = Math.abs(dateDiff.getUTCFullYear() - 1970);
|
|
32
|
+
return age;
|
|
33
|
+
}
|