mirror of
https://github.com/Nezumi-2711/javascript-training.git
synced 2026-09-23 04:09:58 +00:00
Fix code according to the comments
This commit is contained in:
@@ -4,7 +4,16 @@ export const MESSAGE = {
|
|||||||
'Password must at least one uppercase, one lowercase letter, one number and one special character!',
|
'Password must at least one uppercase, one lowercase letter, one number and one special character!',
|
||||||
ERROR_MESSAGE_DEFAULT: 'Something went wrong!',
|
ERROR_MESSAGE_DEFAULT: 'Something went wrong!',
|
||||||
TIME_OUT_ERROR: 'Connection time out! Please try again!',
|
TIME_OUT_ERROR: 'Connection time out! Please try again!',
|
||||||
ERROR_CREDENTIAL: 'Email or password not match! Please try again!',
|
ERROR_CREDENTIAL: {
|
||||||
|
title: 'Error Credential',
|
||||||
|
message: 'Email or password not match! Please try again!',
|
||||||
|
},
|
||||||
|
DEFAULT_TITLE_ERROR_POPUP: 'Error',
|
||||||
|
USER_EXIST_ERROR: 'User is exists! Please try another email!',
|
||||||
|
};
|
||||||
|
export const BTN_CONTENT = {
|
||||||
|
GOT_IT: 'Got it!',
|
||||||
|
OK: 'Ok',
|
||||||
};
|
};
|
||||||
export const TYPE_POPUP = { success: 'success', error: 'error' };
|
export const TYPE_POPUP = { success: 'success', error: 'error' };
|
||||||
export const MARK_ICON = { success: 'check', error: 'error' };
|
export const MARK_ICON = { success: 'check', error: 'error' };
|
||||||
|
|||||||
@@ -4,20 +4,13 @@ export default class LoginController {
|
|||||||
this.loginView = view.loginView;
|
this.loginView = view.loginView;
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerGetUserByEmail(email) {
|
handlerValidateUser(email, password) {
|
||||||
return this.service.userService.getUserByEmail(email);
|
return this.service.userService.validateUser(email, password);
|
||||||
}
|
|
||||||
|
|
||||||
handlerCreateTokenUser(user) {
|
|
||||||
return this.service.userService.createTokenUser(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
if (this.loginView.isLoginPage()) {
|
if (this.loginView.isLoginPage()) {
|
||||||
this.loginView.addHandlerForm(
|
this.loginView.addHandlerForm(this.handlerValidateUser.bind(this));
|
||||||
this.handlerGetUserByEmail.bind(this),
|
|
||||||
this.handlerCreateTokenUser.bind(this),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,3 +50,17 @@ export const createToken = () => {
|
|||||||
}
|
}
|
||||||
return token;
|
return token;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const convertModelToDataObject = (model) => {
|
||||||
|
const { id, ...data } = model;
|
||||||
|
|
||||||
|
return { id, data };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const convertDataObjectToModel = (data) => {
|
||||||
|
const model = data.data;
|
||||||
|
|
||||||
|
model.id = data.id;
|
||||||
|
|
||||||
|
return model;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export default class User {
|
export default class User {
|
||||||
constructor({ email, password, walletName = '' }) {
|
constructor({ email, password, walletName = '' }) {
|
||||||
|
this.id = User.createIdUser();
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.walletName = walletName;
|
this.walletName = walletName;
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { timeOutConnect } from '../helpers/helpers';
|
import {
|
||||||
|
convertDataObjectToModel,
|
||||||
|
convertModelToDataObject,
|
||||||
|
timeOutConnect,
|
||||||
|
} from '../helpers/helpers';
|
||||||
import FirebaseService from './firebaseService';
|
import FirebaseService from './firebaseService';
|
||||||
|
|
||||||
export default class CommonService {
|
export default class CommonService {
|
||||||
@@ -14,23 +18,20 @@ export default class CommonService {
|
|||||||
this.firebaseService.reconnect();
|
this.firebaseService.reconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async getDataFromProp(property, value, path = this.defaultPath) {
|
||||||
* Find the id of data on database
|
|
||||||
* @param {string} property The property want to get value
|
|
||||||
* @param {string} value The value of property
|
|
||||||
* @param {path} path The path of datbase
|
|
||||||
* @returns {string} The id of data object
|
|
||||||
*/
|
|
||||||
async findIdByProperty(property, value, path = this.defaultPath) {
|
|
||||||
this.connectToDb();
|
this.connectToDb();
|
||||||
const existUser = this.firebaseService.findIdByProperty(
|
const existUser = this.firebaseService.getDataFromProp(
|
||||||
path,
|
path,
|
||||||
property,
|
property,
|
||||||
value,
|
value,
|
||||||
);
|
);
|
||||||
const result = await timeOutConnect(existUser);
|
const result = await timeOutConnect(existUser);
|
||||||
|
|
||||||
return result;
|
if (result.id && result.data) {
|
||||||
|
return convertDataObjectToModel(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,11 +39,16 @@ export default class CommonService {
|
|||||||
* @param {*} data The data wants to save on database
|
* @param {*} data The data wants to save on database
|
||||||
* @param {string} path The path of database
|
* @param {string} path The path of database
|
||||||
*/
|
*/
|
||||||
async save(data, path = this.defaultPath) {
|
async save(model) {
|
||||||
this.connectToDb();
|
this.connectToDb();
|
||||||
const saveUser = this.firebaseService.save(data, path);
|
const results = convertModelToDataObject(model);
|
||||||
|
|
||||||
await timeOutConnect(saveUser);
|
const saveData = this.firebaseService.save(
|
||||||
|
results.data,
|
||||||
|
this.defaultPath + results.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
await timeOutConnect(saveData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -49,22 +49,24 @@ class FirebaseService {
|
|||||||
* @param {value} value The value to compare in database
|
* @param {value} value The value to compare in database
|
||||||
* @returns {Promise} Return the relsoves when find completed
|
* @returns {Promise} Return the relsoves when find completed
|
||||||
*/
|
*/
|
||||||
findIdByProperty(path, property, value) {
|
getDataFromProp(path, property, value) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
onValue(
|
onValue(
|
||||||
ref(this.db, path),
|
ref(this.db, path),
|
||||||
(snapshot) => {
|
(snapshot) => {
|
||||||
let result;
|
let id;
|
||||||
|
let data;
|
||||||
|
|
||||||
// snapshot is a type of data by Firebase define
|
// snapshot is a type of data by Firebase define
|
||||||
snapshot.forEach((childSnapshot) => {
|
snapshot.forEach((childSnapshot) => {
|
||||||
const data = childSnapshot.val();
|
const dataTemp = childSnapshot.val();
|
||||||
|
|
||||||
if (data[property] === value) {
|
if (dataTemp[property] === value) {
|
||||||
result = childSnapshot.key;
|
id = childSnapshot.key;
|
||||||
|
data = dataTemp;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
resolve(result);
|
resolve({ id, data });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onlyOnce: true,
|
onlyOnce: true,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { createToken } from '../helpers/helpers';
|
import { createToken } from '../helpers/helpers';
|
||||||
import User from '../models/user';
|
|
||||||
import CommonService from './commonService';
|
import CommonService from './commonService';
|
||||||
|
|
||||||
export default class UserService extends CommonService {
|
export default class UserService extends CommonService {
|
||||||
@@ -14,18 +13,7 @@ export default class UserService extends CommonService {
|
|||||||
* @param {Object} user The user object need to be saved into databae
|
* @param {Object} user The user object need to be saved into databae
|
||||||
*/
|
*/
|
||||||
saveUser(user) {
|
saveUser(user) {
|
||||||
const pathData = this.defaultPath + User.createIdUser();
|
this.save(user);
|
||||||
|
|
||||||
this.save(user, pathData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get user id by email
|
|
||||||
* @param {string} email Email need to be check
|
|
||||||
* @returns {Promise || number} Return id user when exist, otherwise will undefined
|
|
||||||
*/
|
|
||||||
getUserIdByEmail(email) {
|
|
||||||
return this.findIdByProperty('email', email);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +22,7 @@ export default class UserService extends CommonService {
|
|||||||
* @returns {boolean} Return true if find, otherwise return false
|
* @returns {boolean} Return true if find, otherwise return false
|
||||||
*/
|
*/
|
||||||
async checkUserExist(email) {
|
async checkUserExist(email) {
|
||||||
const userExist = await this.getUserIdByEmail(email);
|
const userExist = await this.getUserByEmail(email);
|
||||||
|
|
||||||
if (userExist) {
|
if (userExist) {
|
||||||
return true;
|
return true;
|
||||||
@@ -49,24 +37,37 @@ export default class UserService extends CommonService {
|
|||||||
* @returns {Object || null} Return new User Object if find, otherwise return null.
|
* @returns {Object || null} Return new User Object if find, otherwise return null.
|
||||||
*/
|
*/
|
||||||
async getUserByEmail(email) {
|
async getUserByEmail(email) {
|
||||||
const id = await this.getUserIdByEmail(email);
|
const result = await this.getDataFromProp('email', email);
|
||||||
|
|
||||||
if (id) {
|
if (result) {
|
||||||
const user = await this.getDataFromId(id);
|
return result;
|
||||||
|
|
||||||
return new User(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async createTokenUser(user) {
|
async validateUser(email, password) {
|
||||||
const id = await this.getUserIdByEmail(user.email);
|
const user = await this.getUserByEmail(email);
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
// Check password
|
||||||
|
if (user.password === password) {
|
||||||
|
// Create token for user
|
||||||
|
await this.createTokenUser(email);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createTokenUser(email) {
|
||||||
|
const user = await this.getUserByEmail(email);
|
||||||
|
|
||||||
// Add token to user object
|
// Add token to user object
|
||||||
const newUserData = new User(user);
|
const newUserData = user;
|
||||||
newUserData.accessToken = createToken();
|
newUserData.accessToken = createToken();
|
||||||
|
this.save(newUserData);
|
||||||
this.save(newUserData, this.defaultPath + id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
import CommonLoginRegisterView from './commonLoginRegisterView';
|
import CommonLoginRegisterView from './commonLoginRegisterView';
|
||||||
import * as CONSTANT from '../constants/constant';
|
import { MESSAGE, TYPE_POPUP, BTN_CONTENT } from '../constants/constant';
|
||||||
|
|
||||||
export default class LoginView extends CommonLoginRegisterView {
|
export default class LoginView extends CommonLoginRegisterView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.parentElement = document.querySelector('.form');
|
this.parentElement = document.querySelector('.form');
|
||||||
this.loginPage = document.getElementById('loginPage');
|
this.loginPage = document.URL.includes('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get data from user input
|
* Get data from user input
|
||||||
* @returns {Object || null} Return object or null
|
* @returns {Object || null} Return object or null
|
||||||
*/
|
*/
|
||||||
getDataFromForm() {
|
getDataFromForm(event) {
|
||||||
const { loginForm } = document.forms;
|
const formData = new FormData(event.target);
|
||||||
const formData = new FormData(loginForm);
|
|
||||||
const email = formData.get('email');
|
const email = formData.get('email');
|
||||||
const password = formData.get('password');
|
const password = formData.get('password');
|
||||||
|
|
||||||
@@ -28,12 +27,11 @@ export default class LoginView extends CommonLoginRegisterView {
|
|||||||
* Implement error popup in site
|
* Implement error popup in site
|
||||||
* @param {string} content The content will show in error popup
|
* @param {string} content The content will show in error popup
|
||||||
*/
|
*/
|
||||||
initErrorPopup(content) {
|
initErrorPopup(error) {
|
||||||
const typePopup = CONSTANT.TYPE_POPUP.error;
|
const title = error.title ? error.title : MESSAGE.DEFAULT_TITLE_ERROR_POPUP;
|
||||||
const title = 'Error!';
|
const content = error.message ? error.message : error;
|
||||||
const btnContent = 'Got it!';
|
|
||||||
|
|
||||||
this.initPopupContent(typePopup, title, content, btnContent);
|
this.initPopupContent(TYPE_POPUP.error, title, content, BTN_CONTENT.GOT_IT);
|
||||||
|
|
||||||
// Show popup
|
// Show popup
|
||||||
this.tooglePopupForm();
|
this.tooglePopupForm();
|
||||||
@@ -41,42 +39,36 @@ export default class LoginView extends CommonLoginRegisterView {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add event listener for form input
|
* Add event listener for form input
|
||||||
* @param {Function} getUserByEmail The function need to be set event
|
* @param {Function} validateUser The function need to be set event
|
||||||
* @param {Function} createTokenUser The function need to be set event
|
|
||||||
*/
|
*/
|
||||||
addHandlerForm(getUserByEmail, createTokenUser) {
|
addHandlerForm(validateUser) {
|
||||||
this.parentElement.addEventListener('submit', (e) => {
|
this.parentElement.addEventListener('submit', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.clearErrorMessage();
|
this.clearErrorMessage();
|
||||||
this.submitForm(getUserByEmail, createTokenUser);
|
this.submitForm(validateUser, e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The action when submit form
|
* The action when submit form
|
||||||
* @param {Function} getUserByEmail The function need to be set event
|
* @param {Function} validateUser The function need to be set event
|
||||||
* @param {Function} createTokenUser The function need to be set event
|
|
||||||
*/
|
*/
|
||||||
async submitForm(getUserByEmail, createTokenUser) {
|
async submitForm(validateUser, event) {
|
||||||
try {
|
try {
|
||||||
// Load spinner
|
// Load spinner
|
||||||
this.toogleLoaderSpinner();
|
this.toogleLoaderSpinner();
|
||||||
|
|
||||||
// Get data from form
|
// Get data from form
|
||||||
const userInput = this.getDataFromForm();
|
const userInput = this.getDataFromForm(event);
|
||||||
// Check user exist
|
// Check user exist
|
||||||
const user = await getUserByEmail(userInput.email);
|
const results = await validateUser(userInput.email, userInput.password);
|
||||||
|
|
||||||
if (user) {
|
if (results) {
|
||||||
// If user exist, compare password
|
|
||||||
if (userInput.password === user.password) {
|
|
||||||
await createTokenUser(user);
|
|
||||||
window.location.replace('/');
|
window.location.replace('/');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
throw MESSAGE.ERROR_CREDENTIAL;
|
||||||
throw Error(CONSTANT.MESSAGE.ERROR_CREDENTIAL);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Show popup error
|
// Show popup error
|
||||||
this.initErrorPopup(error);
|
this.initErrorPopup(error);
|
||||||
@@ -86,6 +78,6 @@ export default class LoginView extends CommonLoginRegisterView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isLoginPage() {
|
isLoginPage() {
|
||||||
return this.loginPage !== null;
|
return this.loginPage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { TYPE_POPUP } from '../constants/constant';
|
import { TYPE_POPUP, MESSAGE, BTN_CONTENT } from '../constants/constant';
|
||||||
import CommonLoginRegisterView from './commonLoginRegisterView';
|
import CommonLoginRegisterView from './commonLoginRegisterView';
|
||||||
import User from '../models/user';
|
import User from '../models/user';
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ export default class RegisterView extends CommonLoginRegisterView {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.registerPage = document.getElementById('registerPage');
|
this.registerPage = document.URL.includes('/register');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,12 +50,11 @@ export default class RegisterView extends CommonLoginRegisterView {
|
|||||||
* Implement error popup in site
|
* Implement error popup in site
|
||||||
* @param {string} content The content will show in error popup
|
* @param {string} content The content will show in error popup
|
||||||
*/
|
*/
|
||||||
initErrorPopup(content) {
|
initErrorPopup(error) {
|
||||||
const typePopup = TYPE_POPUP.error;
|
const title = error.title ? error.title : MESSAGE.DEFAULT_TITLE_ERROR_POPUP;
|
||||||
const title = 'Error';
|
const content = error.message ? error.message : error;
|
||||||
const btnContent = 'Got it!';
|
|
||||||
|
|
||||||
this.initPopupContent(typePopup, title, content, btnContent);
|
this.initPopupContent(TYPE_POPUP.error, title, content, BTN_CONTENT.OK);
|
||||||
|
|
||||||
// Show popup
|
// Show popup
|
||||||
this.tooglePopupForm();
|
this.tooglePopupForm();
|
||||||
@@ -86,7 +85,7 @@ export default class RegisterView extends CommonLoginRegisterView {
|
|||||||
// Check user exist
|
// Check user exist
|
||||||
const userExist = await checkExistUser(user.email);
|
const userExist = await checkExistUser(user.email);
|
||||||
if (userExist) {
|
if (userExist) {
|
||||||
throw Error('User is exists! Please try another email!');
|
throw Error(MESSAGE.USER_EXIST_ERROR);
|
||||||
} else {
|
} else {
|
||||||
await saveUser(user);
|
await saveUser(user);
|
||||||
// Show popup success
|
// Show popup success
|
||||||
@@ -103,6 +102,6 @@ export default class RegisterView extends CommonLoginRegisterView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isRegisterPage() {
|
isRegisterPage() {
|
||||||
return this.registerPage !== null;
|
return this.registerPage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<title>Login - Money Lover</title>
|
<title>Login - Money Lover</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main id="loginPage">
|
<main>
|
||||||
<div class="background">
|
<div class="background">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<img
|
<img
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<title>Register - Money Lover</title>
|
<title>Register - Money Lover</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main id="registerPage">
|
<main>
|
||||||
<div class="background">
|
<div class="background">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<img
|
<img
|
||||||
|
|||||||
Reference in New Issue
Block a user