From da5b6e397fa049154d97835e5d9f526692203619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hermerson=20Ara=C3=BAjo?= Date: Sat, 10 Feb 2024 14:34:55 -0300 Subject: [PATCH] refactor: create Form base class --- .eslintrc.json | 3 +- src/application/pages/login.html | 16 ++++- src/application/pages/partials/_head.html | 1 + src/application/public/js/form.js | 88 +++++++++++++++++++++++ src/application/public/js/login_form.js | 57 ++------------- src/application/public/js/validator.js | 30 ++++++-- 6 files changed, 135 insertions(+), 60 deletions(-) create mode 100644 src/application/public/js/form.js diff --git a/.eslintrc.json b/.eslintrc.json index 33e9b30..49ff50c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -8,7 +8,8 @@ "document": true, "utils": true, "Validator": true, - "grecaptcha": true + "grecaptcha": true, + "Form": true }, "extends": "airbnb-base", "parserOptions": { diff --git a/src/application/pages/login.html b/src/application/pages/login.html index 20d15d4..b716e70 100644 --- a/src/application/pages/login.html +++ b/src/application/pages/login.html @@ -16,6 +16,20 @@

{{title}}

{{> _footer}} \ No newline at end of file diff --git a/src/application/pages/partials/_head.html b/src/application/pages/partials/_head.html index cce01a0..396c838 100644 --- a/src/application/pages/partials/_head.html +++ b/src/application/pages/partials/_head.html @@ -18,6 +18,7 @@ + {{> components/links}} {{> components/scripts}} diff --git a/src/application/public/js/form.js b/src/application/public/js/form.js new file mode 100644 index 0000000..3558564 --- /dev/null +++ b/src/application/public/js/form.js @@ -0,0 +1,88 @@ +// eslint-disable-next-line no-unused-vars +class Form { + /** + * @property {Object[]} fields + * @property {Element} fields.input_element + * @property {Element} fields.error_message_element + * @property {string[]} fields.rules + */ + fields = []; + + /** + * @property {Element} form + */ + form; + + /** + * @param {Element} form + * @param {Object[]} fields + * @param {Element} fields[].input_element + * @param {Element} fields[].error_message_element + */ + constructor(form, fields) { + this.form = form; + this.fields = fields; + } + + init() { + this.fields.forEach(({ input_element, error_message_element, rules }) => { + input_element.addEventListener('blur', this.validateInput( + error_message_element, + input_element.getAttribute('name'), + rules, + ).bind(this)); + }); + + this.form.addEventListener('submit', this.submit.bind(this)); + } + + /** + * + * @returns {boolean} + */ + hasErrors() { + return this.fields.some(({ error_message_element }) => !!error_message_element.firstChild); + } + + /** + * + * @param {Event} event + */ + submit(event) { + console.log(event); + throw new Error('Not implemented'); + } + + /** + * @param {Element} error_message_element + * @param {string} field_name + * @param {string[]} rules + */ + validateInput(error_message_element, field_name, rules) { + return function onBlur(e) { + utils.removeChildsFromParent(error_message_element); + + const errors = Validator.setData({ [field_name]: e.target.value }) + .setRule(field_name, rules) + .validate(); + + if (errors.length) { + this.#appendErrorMessages(errors[0].messages, error_message_element); + } + }; + } + + /** + * + * @param {string[]} error_messages + * @param {Element} element + */ + #appendErrorMessages(error_messages, element) { + error_messages.forEach((message) => { + const li = document.createElement('li'); + const text = document.createTextNode(message); + li.appendChild(text); + element.appendChild(li); + }); + } +} diff --git a/src/application/public/js/login_form.js b/src/application/public/js/login_form.js index ef19a69..689ade9 100644 --- a/src/application/public/js/login_form.js +++ b/src/application/public/js/login_form.js @@ -1,58 +1,9 @@ // eslint-disable-next-line no-unused-vars -class LoginForm { - #login_form = document.getElementById('login-form'); - - #email_input = document.getElementById('email'); - - #email_error_messages_ul = document.getElementById('email-error-messages'); - - #password_input = document.getElementById('password'); - - #password_error_messages_ul = document.getElementById('password-error-messages'); - - init() { - this.#email_input.addEventListener('blur', this.#validateEmail.bind(this)); - this.#password_input.addEventListener('blur', this.#validatePassword.bind(this)); - this.#login_form.addEventListener('submit', this.#submit.bind(this)); - } - - static #appendErrorMessages(error_messages, element) { - error_messages.forEach((message) => { - const li = document.createElement('li'); - const text = document.createTextNode(message); - li.appendChild(text); - element.appendChild(li); - }); - } - - #validateEmail(e) { - utils.removeChildsFromParent(this.#email_error_messages_ul); - - const errors = Validator.setData({ email: e.target.value }) - .setRule('email', ['required', 'string', 'email']) - .validate(); - - if (errors.length) { - LoginForm.#appendErrorMessages(errors[0].messages, this.#email_error_messages_ul); - } - } - - #validatePassword(e) { - utils.removeChildsFromParent(this.#password_error_messages_ul); - - const errors = Validator.setData({ password: e.target.value }) - .setRule('password', ['required', 'string', 'min:8', 'password']) - .validate(); - - if (errors.length) { - LoginForm.#appendErrorMessages(errors[0].messages, this.#password_error_messages_ul); - } - } - - #submit(e) { +class LoginForm extends Form { + submit(e) { e.preventDefault(); - if (this.#email_error_messages_ul.firstChild && this.#password_error_messages_ul.firstChild) { + if (this.hasErrors()) { return; } @@ -71,7 +22,7 @@ class LoginForm { }); if (response.status === 204) { - this.#login_form.submit(); + this.form.submit(); } }); } diff --git a/src/application/public/js/validator.js b/src/application/public/js/validator.js index 631dbc9..e570516 100644 --- a/src/application/public/js/validator.js +++ b/src/application/public/js/validator.js @@ -56,7 +56,6 @@ const RULE_FUNCTIONS = { password: (value) => ( value !== undefined && typeof value === 'string' - && value.length <= 8 && !( value.includes('!') || value.includes('@') @@ -110,15 +109,30 @@ class Validator { this.#data = data; } + /** + * + * @param {Object} data + * @returns {Validator} + */ static setData(data) { return new Validator(data); } + /** + * + * @param {string} field + * @param {string[]} rule + * @returns {Validator} + */ setRule(field, rule) { this.#rule_map.set(field, rule); return this; } + /** + * + * @returns {Object[]} + */ validate() { const entries = this.#rule_map.entries(); @@ -131,18 +145,24 @@ class Validator { messages.push(`O campo ${fieldName} não é válido.`); } } else { - messages.push(...this.validateByArray(rule, field)); + messages.push(...this.#validateByArray(rule, field)); } if (messages.length > 0) { - this.addError({ field: fieldName, messages }); + this.#addError({ field: fieldName, messages }); } } return this.#errors; } - validateByArray(rule, field) { + /** + * + * @param {*} rule + * @param {*} field + * @returns {string[]} + */ + #validateByArray(rule, field) { const messages = []; for (let i = 0, len = rule.length; i < len; i += 1) { @@ -159,7 +179,7 @@ class Validator { return messages; } - addError(error) { + #addError(error) { const index = this.#errors.findIndex((e) => e.field === error.field); if (index !== -1) {