diff --git a/javascript-practice/src/js/helpers/helpers.js b/javascript-practice/src/js/helpers/helpers.js index ab8e3a7..23c7db4 100644 --- a/javascript-practice/src/js/helpers/helpers.js +++ b/javascript-practice/src/js/helpers/helpers.js @@ -1,8 +1,5 @@ -import { - TIME_OUT_SEC, - TIME_OUT_ERROR, - REGEX_PASSWORD, -} from '../constants/constant'; +import { TIME_OUT_ERROR } from '../constants/constant'; +import { REGEX_PASSWORD, TIME_OUT_SEC } from '../constants/config'; import FirebaseService from '../services/firebaseService'; export const validatePassword = (password) => { diff --git a/javascript-practice/src/js/services/firebaseService.js b/javascript-practice/src/js/services/firebaseService.js index 8e8ebef..d56af31 100644 --- a/javascript-practice/src/js/services/firebaseService.js +++ b/javascript-practice/src/js/services/firebaseService.js @@ -12,7 +12,7 @@ import { DATABASE_URL } from '../constants/config'; class FirebaseService { constructor() { const firebaseConfig = { - DATABASE_URL, + databaseUrl: DATABASE_URL, }; this.app = initializeApp(firebaseConfig); this.db = getDatabase(this.app); diff --git a/javascript-practice/src/js/services/service.js b/javascript-practice/src/js/services/service.js new file mode 100644 index 0000000..dd10508 --- /dev/null +++ b/javascript-practice/src/js/services/service.js @@ -0,0 +1,7 @@ +import UserService from './userService'; + +export default class Service { + constructor() { + this.userService = new UserService(); + } +} diff --git a/javascript-practice/src/js/services/userService.js b/javascript-practice/src/js/services/userService.js new file mode 100644 index 0000000..98eceee --- /dev/null +++ b/javascript-practice/src/js/services/userService.js @@ -0,0 +1,30 @@ +import { timeOutConnect } from '../helpers/helpers'; +import FirebaseService from './firebaseService'; +import User from '../models/userModel'; + +export default class UserService { + constructor() { + this.path = 'users/'; + } + + async saveUser(user) { + FirebaseService.reconnect(); + const saveUser = FirebaseService.save( + user, + this.path + User.createIdUser(), + ); + await timeOutConnect(saveUser); + } + + async checkExistUserByEmail(email) { + FirebaseService.reconnect(); + const existUser = FirebaseService.findKeyByPropery( + this.path, + 'email', + email, + ); + const result = await timeOutConnect(existUser); + + return result; + } +} diff --git a/javascript-practice/src/js/view/commonView.js b/javascript-practice/src/js/view/commonView.js new file mode 100644 index 0000000..968ef5f --- /dev/null +++ b/javascript-practice/src/js/view/commonView.js @@ -0,0 +1,89 @@ +import { MARK_ICON, TYPE_FORM } from '../constants/constant'; + +export default class CommonView { + constructor() { + this.overlayMarkup = '
'; + + this.initPopup(); + this.initElementPopup(); + this.initLoader(); + this.handleEventBtnPopupAndOverlay(); + } + + initPopup() { + this.rootElement = document.querySelector('body'); + + const markup = ` + ${this.overlayMarkup} + + `; + + this.rootElement.insertAdjacentHTML('afterbegin', markup); + } + + initElementPopup() { + // Init element + this.modalBox = document.querySelector('.modal-box'); + this.popupIcon = document.querySelector('.mark'); + this.popupBtn = document.querySelector('.modal-box__redirect-btn'); + this.popupTitle = document.querySelector('.modal-box__title'); + this.popupContent = document.querySelector('.modal-box__message'); + this.overlay = document.querySelector('.overlay'); + } + + toogleLoaderSpinner() { + this.spinner.classList.toggle('hidden'); + } + + tooglePopupForm() { + this.overlay.classList.toggle('active'); + this.modalBox.classList.toggle('active'); + } + + initPopupContent(typeForm, title, content, btnContent) { + // Remove old typeForm class if haved + this.modalBox.classList.forEach((classItem) => + classItem === TYPE_FORM.success || classItem === TYPE_FORM.error + ? this.modalBox.classList.remove(classItem) + : '', + ); + + // Remove old icon popup if haved + this.popupIcon.classList.forEach((classItem) => + classItem === MARK_ICON.success || classItem === MARK_ICON.error + ? this.popupIcon.classList.remove(classItem) + : '', + ); + + // Init content popup + this.modalBox.classList.add( + typeForm === TYPE_FORM.success ? TYPE_FORM.success : TYPE_FORM.error, + ); + this.popupIcon.classList.add( + typeForm === TYPE_FORM.success ? MARK_ICON.success : MARK_ICON.error, + ); + this.popupTitle.textContent = title; + this.popupContent.textContent = content; + this.popupBtn.textContent = btnContent; + } + + handleEventBtnPopupAndOverlay() { + this.popupBtn.addEventListener('click', this.tooglePopupForm.bind(this)); + this.overlay.addEventListener('click', this.tooglePopupForm.bind(this)); + } + + initLoader() { + const markup = ``; + + this.rootElement.insertAdjacentHTML('afterbegin', markup); + + // Init element + this.spinner = document.querySelector('.loader'); + } +} diff --git a/javascript-practice/src/js/view/registerView.js b/javascript-practice/src/js/view/registerView.js new file mode 100644 index 0000000..c96c028 --- /dev/null +++ b/javascript-practice/src/js/view/registerView.js @@ -0,0 +1,122 @@ +import { validatePassword } from '../helpers/helpers'; +import * as CONSTANT from '../constants/constant'; +import CommonView from './commonView'; +import User from '../models/userModel'; + +export default class RegisterView extends CommonView { + constructor() { + super(); + + this.parentElement = document.querySelector('.form'); + this.inputField = document.querySelectorAll('.form__input'); + + this.messageDefault = CONSTANT.MESSAGE.ERROR_MESSAGE_DEFAULT; + } + + // Function get data from form + getDataFromForm() { + const { registerForm } = document.forms; + const formData = new FormData(registerForm); + const email = formData.get('email'); + const password = formData.get('password'); + const passwordConfirm = formData.get('password_confirm'); + + const account = { email, password, passwordConfirm }; + + if (this.validateForm(account)) { + const user = new User(account); + return user; + } + return null; + } + + validateForm(account) { + if (account.password === account.passwordConfirm) { + if (validatePassword(account.passwordConfirm)) { + return true; + } + this.showError(CONSTANT.MESSAGE.PASSWORD_NOT_STRONG); + return false; + } + this.showError(CONSTANT.MESSAGE.PASSWORD_NOT_MATCH); + return false; + } + + // Handler event submit form + addHandlerForm(handler) { + this.parentElement.addEventListener('submit', (e) => { + e.preventDefault(); + this.clearErrorMessage(); + handler(); + }); + } + + changeToStyleErrorInputPassword() { + for (let index = 1; index < this.inputField.length; index += 1) { + this.inputField[index].style.background = '#ffc3c3'; + this.inputField[index].style.borderColor = '#ce1414'; + } + } + + clearStyleErrorInputPassword() { + for (let index = 1; index < this.inputField.length; index += 1) { + this.inputField[index].style.background = '#f5f5f5'; + this.inputField[index].style.borderColor = '#f5f5f5'; + } + } + + // Reassign again to check error message element haved on page or not + reassignVariableErrorMessage() { + this.errorMessage = document.querySelector('.form__error-message'); + } + + clearErrorMessage() { + this.reassignVariableErrorMessage(); + + // If have error message on page, remove it + if (this.errorMessage) { + this.errorMessage.remove(); + this.clearStyleErrorInputPassword(); + } + } + + addHandlerInputFormChange() { + this.parentElement.addEventListener('input', () => { + this.clearErrorMessage(); + }); + } + + showError(message) { + this.renderError(message); + this.changeToStyleErrorInputPassword(); + } + + initRegisterSuccessPopup() { + const typeForm = CONSTANT.TYPE_FORM.success; + const title = 'Register Commpleted'; + const content = 'Please login to continue!'; + const btnContent = 'OK'; + + this.initPopupContent(typeForm, title, content, btnContent); + } + + initErrorPopup(content) { + const typeForm = CONSTANT.TYPE_FORM.error; + const title = 'Error'; + const btnContent = 'Got it!'; + + this.initPopupContent(typeForm, title, content, btnContent); + } + + renderError(message) { + const markup = ` +

${ + !message ? this.messageDefault : message + }

+ `; + + document + .querySelector('.form__title') + .insertAdjacentHTML('afterend', markup); + } +} diff --git a/javascript-practice/src/js/view/view.js b/javascript-practice/src/js/view/view.js index 70b786d..a2a1675 100644 --- a/javascript-practice/src/js/view/view.js +++ b/javascript-practice/src/js/view/view.js @@ -1 +1,7 @@ -// TODO +import RegisterView from './registerView'; + +export default class View { + constructor() { + this.registerView = new RegisterView(); + } +}