mirror of
https://github.com/Nezumi-2711/javascript-training.git
synced 2026-09-22 13:38:43 +00:00
Change validator style
This commit is contained in:
@@ -23,14 +23,16 @@ export const DEFAULT_CATEGORY = {
|
||||
INCOME: 'Income',
|
||||
};
|
||||
|
||||
export const REMOVE_CATEGORY = ['Income'];
|
||||
|
||||
export const DAY = [
|
||||
'Sunday',
|
||||
'Monday',
|
||||
'Tuesday',
|
||||
'Wednesday',
|
||||
'Thursday',
|
||||
'Friday',
|
||||
'Saturday',
|
||||
'Sunday',
|
||||
];
|
||||
|
||||
export const MONTH = [
|
||||
@@ -54,4 +56,6 @@ export const MARK_ICON = { success: 'check', error: 'error' };
|
||||
export const REGEX = {
|
||||
PASSWORD:
|
||||
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/,
|
||||
EMAIL:
|
||||
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
export const PASSWORD_NOT_MATCH = 'Password not match! Please try again!';
|
||||
export const PASSWORD_NOT_MATCH = 'Password not match!';
|
||||
|
||||
export const PASSWORD_NOT_STRONG =
|
||||
'Password must at least one uppercase, one lowercase letter, one number and one special character!';
|
||||
|
||||
export const ERROR_MESSAGE_DEFAULT = 'Something went wrong!';
|
||||
export const ERROR_MESSAGE_DEFAULT = ['Something went wrong!'];
|
||||
|
||||
export const TIME_OUT_ERROR = 'Connection time out! Please try again!';
|
||||
|
||||
@@ -21,3 +21,11 @@ export const ADD_WALLET_SUCCESS = 'Add wallet success!';
|
||||
export const DEFAULT_MESSAGE = 'Press OK to continue!';
|
||||
|
||||
export const ADD_TRANSACTION_SUCCESS = 'Add success!';
|
||||
|
||||
export const UPDATE_TRANSACTION_SUCCESS = 'Update success!';
|
||||
|
||||
export const REGISTER_SUCCESS = 'Register Success';
|
||||
|
||||
export const REQUIRED_MESSAGE = (field) => `The ${field} is required!`;
|
||||
|
||||
export const INVALID_EMAIL_FORMAT = `The email is not correct!`;
|
||||
|
||||
@@ -10,10 +10,6 @@ export default class HomeController {
|
||||
return this.service.userService.getInfoUserLogin();
|
||||
}
|
||||
|
||||
handlerCheckWalletValid(idUser) {
|
||||
return this.service.walletService.isValidWallet(idUser);
|
||||
}
|
||||
|
||||
handlerGetWalletUser(idUser) {
|
||||
return this.service.walletService.getWalletByIdUser(idUser);
|
||||
}
|
||||
@@ -46,7 +42,6 @@ export default class HomeController {
|
||||
if (this.homeView) {
|
||||
this.homeView.initFunction(
|
||||
this.handlerGetInfoUserLogin.bind(this),
|
||||
this.handlerCheckWalletValid.bind(this),
|
||||
this.handlerGetWalletUser.bind(this),
|
||||
this.handlerGetAllCategory.bind(this),
|
||||
this.handlerGetAllTransactions.bind(this),
|
||||
|
||||
@@ -7,10 +7,18 @@ import FirebaseService from '../services/firebaseService';
|
||||
* @param {string} password Password input
|
||||
* @returns {boolean} Return true if validate password success, otherwise return false
|
||||
*/
|
||||
export const isValidatePassword = (password) => {
|
||||
export const isValidPassword = (password) => {
|
||||
return REGEX.PASSWORD.test(password);
|
||||
};
|
||||
|
||||
export const isValidateEmail = (email) => {
|
||||
return String(email).toLowerCase().match(REGEX.EMAIL);
|
||||
};
|
||||
|
||||
export const compare2Password = (password, passwordConfirm) => {
|
||||
return password === passwordConfirm;
|
||||
};
|
||||
|
||||
/**
|
||||
* A waiting function with s second
|
||||
* @param {number} s The time will be waiting
|
||||
@@ -85,7 +93,7 @@ export const formatNumber = (number) => {
|
||||
export const changeDateFormat = (oldFormatDate) => {
|
||||
const tempDate = new Date(oldFormatDate);
|
||||
|
||||
const day = DAY[tempDate.getDay() - 1];
|
||||
const day = DAY[tempDate.getDay()];
|
||||
const date = tempDate.getDate();
|
||||
const month = MONTH[tempDate.getMonth()];
|
||||
const year = tempDate.getFullYear();
|
||||
@@ -105,9 +113,7 @@ export const createTransactionDetailObject = (category, transactions) => {
|
||||
return amount;
|
||||
};
|
||||
const listTransaction = () => {
|
||||
const results = [];
|
||||
|
||||
transactions.forEach((transaction) => {
|
||||
const results = transactions.map((transaction) => {
|
||||
const dateParts = changeDateFormat(transaction.date).split(','); // ['Monday', '14', 'September', '2023']
|
||||
const day = dateParts[1];
|
||||
const fullDateString = `${dateParts[0]}, ${dateParts[2]} ${dateParts[3]}`;
|
||||
@@ -119,7 +125,7 @@ export const createTransactionDetailObject = (category, transactions) => {
|
||||
amount: transaction.amount,
|
||||
};
|
||||
|
||||
results.push(tempData);
|
||||
return tempData;
|
||||
});
|
||||
|
||||
results.sort((a, b) => parseInt(b.id, 10) - parseInt(a.id, 10));
|
||||
@@ -153,3 +159,15 @@ export const getAllTransactionByCategoryName = (categoryName, transactions) => {
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
export const renderRequiredText = (field, element) => {
|
||||
const markup = `
|
||||
<p class="error-text">${MESSAGE.REQUIRED_MESSAGE(field)}</p>
|
||||
`;
|
||||
|
||||
element.insertAdjacentHTML('afterend', markup);
|
||||
};
|
||||
|
||||
export const redirectToLoginPage = () => {
|
||||
window.location.replace('/login');
|
||||
};
|
||||
|
||||
@@ -10,14 +10,11 @@ export default class CategoryService extends CommonService {
|
||||
|
||||
async getAllCategory() {
|
||||
const data = await this.getAllDataFromPath(this.defaultPath);
|
||||
const listCategory = [];
|
||||
|
||||
if (data) {
|
||||
data.forEach((category) => {
|
||||
listCategory.unshift(new Category(category));
|
||||
return data.reverse().map((category) => {
|
||||
return new Category(category);
|
||||
});
|
||||
|
||||
return listCategory;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -69,15 +69,12 @@ export default class CommonService {
|
||||
const results = await timeOutConnect(
|
||||
this.firebaseService.getAllDataFromPath(path),
|
||||
);
|
||||
const listData = [];
|
||||
|
||||
if (results) {
|
||||
// Convert format object
|
||||
results.forEach((data) => {
|
||||
listData.push(convertDataObjectToModel(data));
|
||||
return results.map((data) => {
|
||||
return convertDataObjectToModel(data);
|
||||
});
|
||||
|
||||
return listData;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -89,15 +86,12 @@ export default class CommonService {
|
||||
const results = await timeOutConnect(
|
||||
this.firebaseService.getListDataFromProp(path, property, value),
|
||||
);
|
||||
const listData = [];
|
||||
|
||||
if (results) {
|
||||
// Convert format object
|
||||
results.forEach((data) => {
|
||||
listData.push(convertDataObjectToModel(data));
|
||||
});
|
||||
|
||||
return listData;
|
||||
return results.map((data) => {
|
||||
return convertDataObjectToModel(data);
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -22,11 +22,7 @@ export default class TransactionService extends CommonService {
|
||||
this.defaultPath,
|
||||
);
|
||||
|
||||
if (results) {
|
||||
return results;
|
||||
}
|
||||
|
||||
return null;
|
||||
return results || null;
|
||||
}
|
||||
|
||||
async deleteTransaction(idTransaction) {
|
||||
|
||||
@@ -26,11 +26,7 @@ export default class UserService extends CommonService {
|
||||
async isValidUser(email) {
|
||||
const userExist = await this.getUserByEmail(email);
|
||||
|
||||
if (userExist) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return !!userExist;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,11 +37,7 @@ export default class UserService extends CommonService {
|
||||
async getUserByEmail(email) {
|
||||
const result = await this.getDataFromProp('email', email);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
return result || null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,11 +109,7 @@ export default class UserService extends CommonService {
|
||||
async getUserByToken(accessToken) {
|
||||
const result = await this.getDataFromProp('accessToken', accessToken);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
return result || null;
|
||||
}
|
||||
|
||||
static clearAccessToken() {
|
||||
|
||||
@@ -23,11 +23,7 @@ export default class WalletService extends CommonService {
|
||||
async isValidWallet(idUser) {
|
||||
const wallet = await this.getWalletByIdUser(idUser);
|
||||
|
||||
if (wallet) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return !!wallet;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,10 +34,6 @@ export default class WalletService extends CommonService {
|
||||
async getWalletByIdUser(idUser) {
|
||||
const result = await this.getDataFromProp('idUser', idUser);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
return result || null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import CommonView from './commonView';
|
||||
import * as MESSAGE from '../constants/message';
|
||||
import {
|
||||
compare2Password,
|
||||
isValidPassword,
|
||||
isValidateEmail,
|
||||
renderRequiredText,
|
||||
} from '../helpers/helpers';
|
||||
|
||||
export default class AuthenticationView extends CommonView {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.parentElement = document.querySelector('.form');
|
||||
this.emailEl = document.querySelector("[name='email']");
|
||||
this.messageDefault = MESSAGE.ERROR_MESSAGE_DEFAULT;
|
||||
this.inputPasswordEl = document.querySelector('input[name="password"]');
|
||||
this.inputPasswordConfirmEl = document.querySelector(
|
||||
'input[name="password_confirm"]',
|
||||
);
|
||||
|
||||
this.listError = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate user input data
|
||||
* @param {Object} account The account object with email, password, passwordConfirm field
|
||||
* @returns {boolean} Return true if validate success and return false if validate not success
|
||||
*/
|
||||
// isValidateAccount(account) {
|
||||
// if (account.password === account.passwordConfirm) {
|
||||
// if (isValidPassword(account.passwordConfirm)) {
|
||||
// return true;
|
||||
// }
|
||||
// this.showError(MESSAGE.PASSWORD_NOT_STRONG);
|
||||
// return false;
|
||||
// }
|
||||
// this.showError(MESSAGE.PASSWORD_NOT_MATCH);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
validateEmail(email) {
|
||||
if (email) {
|
||||
if (!isValidateEmail(email)) {
|
||||
this.listError.push(MESSAGE.INVALID_EMAIL_FORMAT);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
renderRequiredText('email', this.emailEl);
|
||||
return false;
|
||||
}
|
||||
|
||||
validatePassword(password) {
|
||||
if (password) {
|
||||
if (!isValidPassword(password)) {
|
||||
this.listError.push(MESSAGE.PASSWORD_NOT_STRONG);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
renderRequiredText('password', this.inputPasswordEl);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
validatePasswordConfirm(password, passwordConfirm) {
|
||||
if (passwordConfirm) {
|
||||
if (!compare2Password(password, passwordConfirm)) {
|
||||
this.listError.push(MESSAGE.PASSWORD_NOT_MATCH);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
renderRequiredText('confirm password', this.inputPasswordConfirmEl);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear error message at form
|
||||
*/
|
||||
clearErrorMessage() {
|
||||
// Reassign again to check error message element haved on page or not
|
||||
this.errorMessageEl = document.querySelector('.form__error-message');
|
||||
this.errorTextEl = document.querySelectorAll('.error-text');
|
||||
|
||||
// If have error message on page, remove it with style error input password
|
||||
if (this.errorMessageEl || this.errorTextEl.length > 0) {
|
||||
if (this.errorMessageEl) this.errorMessageEl.remove();
|
||||
|
||||
if (this.errorTextEl) {
|
||||
this.errorTextEl.forEach((item) => {
|
||||
item.remove();
|
||||
});
|
||||
}
|
||||
this.emailEl.classList.remove('error-input');
|
||||
this.inputPasswordEl.classList.remove('error-input');
|
||||
|
||||
if (this.inputPasswordConfirmEl)
|
||||
this.inputPasswordConfirmEl.classList.remove('error-input');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add event listener for input field at form
|
||||
*/
|
||||
addHandlerInputFormChange() {
|
||||
this.parentElement.addEventListener('input', () => {
|
||||
this.clearErrorMessage();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show error message with error style input password.
|
||||
* @param {string} message The error message you want show in form.
|
||||
*/
|
||||
showError(message) {
|
||||
this.renderError(message);
|
||||
}
|
||||
|
||||
toggleDialog() {
|
||||
this.dialog.classList.toggle('active');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show error message in form
|
||||
* @param {string} message The message will show in form
|
||||
*/
|
||||
renderError(messages = this.messageDefault) {
|
||||
if (messages.length > 0) {
|
||||
const messageItemMarkup = messages
|
||||
.map((message) => `<li>${message}</li>`)
|
||||
.join('\n');
|
||||
|
||||
const markup = `
|
||||
<ul class="form__error-message">
|
||||
${messageItemMarkup}
|
||||
</ul>
|
||||
`;
|
||||
|
||||
document
|
||||
.querySelector('.form__title')
|
||||
.insertAdjacentHTML('afterend', markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
import CommonView from './commonView';
|
||||
import * as MESSAGE from '../constants/message';
|
||||
import { isValidatePassword } from '../helpers/helpers';
|
||||
|
||||
export default class CommonLoginRegisterView extends CommonView {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.parentElement = document.querySelector('.form');
|
||||
this.messageDefault = MESSAGE.ERROR_MESSAGE_DEFAULT;
|
||||
this.inputPassword = document.querySelector('input[name="password"]');
|
||||
this.inputPasswordConfirm = document.querySelector(
|
||||
'input[name="password_confirm"]',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate user input data
|
||||
* @param {Object} account The account object with email, password, passwordConfirm field
|
||||
* @returns {boolean} Return true if validate success and return false if validate not success
|
||||
*/
|
||||
isValidateAccount(account) {
|
||||
if (account.password === account.passwordConfirm) {
|
||||
if (isValidatePassword(account.passwordConfirm)) {
|
||||
return true;
|
||||
}
|
||||
this.showError(MESSAGE.PASSWORD_NOT_STRONG);
|
||||
return false;
|
||||
}
|
||||
this.showError(MESSAGE.PASSWORD_NOT_MATCH);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show or hide style error input password
|
||||
*/
|
||||
toggleErrorStyleInputPass() {
|
||||
this.inputPassword.classList.toggle('error-input');
|
||||
this.inputPasswordConfirm.classList.toggle('error-input');
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear error message at form
|
||||
*/
|
||||
clearErrorMessage() {
|
||||
// Reassign again to check error message element haved on page or not
|
||||
this.errorMessageEl = document.querySelector('.form__error-message');
|
||||
|
||||
// If have error message on page, remove it with style error input password
|
||||
if (this.errorMessageEl) {
|
||||
this.errorMessageEl.remove();
|
||||
this.toggleErrorStyleInputPass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add event listener for input field at form
|
||||
*/
|
||||
addHandlerInputFormChange() {
|
||||
this.parentElement.addEventListener('input', () => {
|
||||
this.clearErrorMessage();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show error message with error style input password.
|
||||
* @param {string} message The error message you want show in form.
|
||||
*/
|
||||
showError(message) {
|
||||
this.renderError(message);
|
||||
this.toggleErrorStyleInputPass();
|
||||
}
|
||||
|
||||
toggleDialog() {
|
||||
this.dialog.classList.toggle('active');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show error message in form
|
||||
* @param {string} message The message will show in form
|
||||
*/
|
||||
renderError(message = this.messageDefault) {
|
||||
const markup = `
|
||||
<p class="form__error-message">${message}</p>
|
||||
`;
|
||||
|
||||
document
|
||||
.querySelector('.form__title')
|
||||
.insertAdjacentHTML('afterend', markup);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
BTN_CONTENT,
|
||||
DEFAULT_CATEGORY,
|
||||
FIRST_ADD_WALLET_NOTE,
|
||||
REMOVE_CATEGORY,
|
||||
} from '../constants/config';
|
||||
import * as MESSAGE from '../constants/message';
|
||||
import CommonView from './commonView';
|
||||
@@ -14,6 +15,7 @@ import {
|
||||
formatNumber,
|
||||
getAllCategoryNameInTransactions,
|
||||
getAllTransactionByCategoryName,
|
||||
renderRequiredText,
|
||||
} from '../helpers/helpers';
|
||||
import defaultCategoryIcon from '../../assets/images/question-icon.svg';
|
||||
|
||||
@@ -44,7 +46,6 @@ export default class HomeView extends CommonView {
|
||||
|
||||
initFunction(
|
||||
getInfoUserLogin,
|
||||
isValidWallet,
|
||||
getWalletByIdUser,
|
||||
getAllCategory,
|
||||
getAllTransactions,
|
||||
@@ -54,7 +55,6 @@ export default class HomeView extends CommonView {
|
||||
deleteTransaction,
|
||||
) {
|
||||
this.getInfoUserLogin = getInfoUserLogin;
|
||||
this.isValidWallet = isValidWallet;
|
||||
this.getWalletByIdUser = getWalletByIdUser;
|
||||
this.getAllCategory = getAllCategory;
|
||||
this.getAllTransactions = getAllTransactions;
|
||||
@@ -75,14 +75,15 @@ export default class HomeView extends CommonView {
|
||||
window.location.replace('/login');
|
||||
} else {
|
||||
this.user = user;
|
||||
const wallet = await this.isValidWallet(user.id);
|
||||
this.wallet = await this.getWalletByIdUser(user.id);
|
||||
|
||||
// Check user's wallet if have or not
|
||||
if (!wallet) {
|
||||
if (!this.wallet) {
|
||||
// Show add wallet dialog
|
||||
this.walletDialog.showModal();
|
||||
} else {
|
||||
// Init data
|
||||
await this.loadTransactionData();
|
||||
await this.loadData();
|
||||
|
||||
// Load event page
|
||||
@@ -95,7 +96,6 @@ export default class HomeView extends CommonView {
|
||||
|
||||
async loadData() {
|
||||
await this.loadWalletUser();
|
||||
await this.loadTransactionData();
|
||||
this.loadSummaryTab();
|
||||
await this.loadTransactionTab();
|
||||
}
|
||||
@@ -126,17 +126,26 @@ export default class HomeView extends CommonView {
|
||||
this.saveWallet(this.wallet);
|
||||
}
|
||||
|
||||
async updateAmountWallet(amount) {
|
||||
if (amount >= 0) {
|
||||
this.wallet.inflow += amount;
|
||||
async updateAmountWallet() {
|
||||
let inflow = 0;
|
||||
let outflow = 0;
|
||||
|
||||
// Init data first
|
||||
this.transactionDetails = this.loadTransactionDetailsData();
|
||||
|
||||
this.transactionDetails.forEach((transaction) => {
|
||||
if (transaction.totalAmount >= 0) {
|
||||
inflow += transaction.totalAmount;
|
||||
} else {
|
||||
this.wallet.outflow += amount;
|
||||
outflow -= transaction.totalAmount;
|
||||
}
|
||||
});
|
||||
|
||||
// Reassign value for wallet user;
|
||||
this.wallet.inflow = inflow;
|
||||
this.wallet.outflow = -outflow;
|
||||
|
||||
await this.saveWallet(this.wallet);
|
||||
|
||||
// Reload data
|
||||
await this.loadData();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,10 +153,12 @@ export default class HomeView extends CommonView {
|
||||
* @param {function} getAllCategory Get all category function
|
||||
*/
|
||||
async loadCategory() {
|
||||
if (!this.listCategory) {
|
||||
this.listCategory = await this.getAllCategory();
|
||||
}
|
||||
|
||||
if (this.listCategory) {
|
||||
this.renderCategoryItem();
|
||||
this.renderCategoryList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,15 +187,16 @@ export default class HomeView extends CommonView {
|
||||
await this.loadCategory();
|
||||
|
||||
// Init data first
|
||||
const transactionDetails = this.loadTransactionDetailsData();
|
||||
this.transactionDetails = this.loadTransactionDetailsData();
|
||||
|
||||
const transactionEl = document.querySelector('.transaction');
|
||||
const listTransactionDetailEl =
|
||||
transactionEl.querySelector('.transaction__list');
|
||||
|
||||
const markup = [];
|
||||
|
||||
if (transactionDetails) {
|
||||
transactionDetails.forEach((transactionDetail) => {
|
||||
if (this.transactionDetails) {
|
||||
this.transactionDetails.forEach((transactionDetail) => {
|
||||
markup.push(this.transactionDetailMarkup(transactionDetail));
|
||||
});
|
||||
}
|
||||
@@ -203,9 +215,7 @@ export default class HomeView extends CommonView {
|
||||
);
|
||||
|
||||
// Create transactions details object
|
||||
const tempList = [];
|
||||
|
||||
listCategoryInTransaction.forEach((categoryName) => {
|
||||
const tempList = listCategoryInTransaction.map((categoryName) => {
|
||||
// Get category object from list category has been loaded.
|
||||
const category = this.listCategory.filter(
|
||||
(item) => item.name === categoryName,
|
||||
@@ -216,11 +226,9 @@ export default class HomeView extends CommonView {
|
||||
this.listTransactions,
|
||||
);
|
||||
|
||||
tempList.push(
|
||||
createTransactionDetailObject(
|
||||
return createTransactionDetailObject(
|
||||
Object.assign({}, ...category),
|
||||
transactions,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -300,27 +308,35 @@ export default class HomeView extends CommonView {
|
||||
handlerEventTransactionDialog() {
|
||||
this.transactionDialog.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
this.clearErrorTransactionDialog();
|
||||
this.submitTransactionDialog();
|
||||
this.transactionDialog.close();
|
||||
});
|
||||
|
||||
this.transactionDialog.addEventListener('input', () => {
|
||||
const dateInput = this.transactionDialog.querySelector(
|
||||
"[name='selected_date']",
|
||||
).value;
|
||||
const categoryName = this.transactionDialog.querySelector(
|
||||
"[name='category_name']",
|
||||
).value;
|
||||
const amountInput =
|
||||
this.transactionDialog.querySelector("[name='amount']").value;
|
||||
const saveBtn = this.transactionDialog.querySelector('.form__save-btn');
|
||||
|
||||
saveBtn.classList.toggle(
|
||||
'active',
|
||||
dateInput && categoryName && amountInput >= 1,
|
||||
);
|
||||
this.changeBtnStyleTransactionDialog();
|
||||
this.clearErrorTransactionDialog();
|
||||
});
|
||||
|
||||
// Add delete transaction event
|
||||
this.deleteTransactionEvent();
|
||||
}
|
||||
|
||||
clearErrorTransactionDialog() {
|
||||
// Clear error style
|
||||
const inputFieldEls =
|
||||
this.transactionDialog.querySelectorAll('.form__input-field');
|
||||
const errorTextEls = this.transactionDialog.querySelectorAll('.error-text');
|
||||
|
||||
inputFieldEls.forEach((item) => {
|
||||
if (item.classList.contains('error-input'))
|
||||
item.classList.remove('error-input');
|
||||
});
|
||||
errorTextEls.forEach((item) => {
|
||||
if (item) item.remove();
|
||||
});
|
||||
}
|
||||
|
||||
deleteTransactionEvent() {
|
||||
const deleteTransactionBtn =
|
||||
this.transactionDialog.querySelector('.form__delete-btn');
|
||||
|
||||
@@ -336,9 +352,11 @@ export default class HomeView extends CommonView {
|
||||
|
||||
await this.deleteTransaction(idEl.value);
|
||||
|
||||
this.showSuccessToast('Delete success!', MESSAGE.DEFAULT_MESSAGE);
|
||||
|
||||
// Reload data
|
||||
await this.loadTransactionData();
|
||||
await this.loadData();
|
||||
|
||||
this.showSuccessToast('Delete success!', MESSAGE.DEFAULT_MESSAGE);
|
||||
} catch (error) {
|
||||
this.showErrorToast(error);
|
||||
}
|
||||
@@ -347,6 +365,23 @@ export default class HomeView extends CommonView {
|
||||
});
|
||||
}
|
||||
|
||||
changeBtnStyleTransactionDialog() {
|
||||
const dateInput = this.transactionDialog.querySelector(
|
||||
"[name='selected_date']",
|
||||
).value;
|
||||
const categoryName = this.transactionDialog.querySelector(
|
||||
"[name='category_name']",
|
||||
).value;
|
||||
const amountInput =
|
||||
this.transactionDialog.querySelector("[name='amount']").value;
|
||||
const saveBtn = this.transactionDialog.querySelector('.form__save-btn');
|
||||
|
||||
saveBtn.classList.toggle(
|
||||
'active',
|
||||
dateInput && categoryName && amountInput >= 1,
|
||||
);
|
||||
}
|
||||
|
||||
initDataTransactionDialog(idTransaction) {
|
||||
const transactionArr = this.listTransactions.filter(
|
||||
(obj) => obj.id === idTransaction,
|
||||
@@ -379,8 +414,6 @@ export default class HomeView extends CommonView {
|
||||
}
|
||||
|
||||
async submitTransactionDialog() {
|
||||
this.toggleLoaderSpinner();
|
||||
|
||||
try {
|
||||
const dateEl = this.transactionForm.querySelector(
|
||||
"[name='selected_date']",
|
||||
@@ -393,11 +426,21 @@ export default class HomeView extends CommonView {
|
||||
const idEl = this.transactionForm.querySelector(
|
||||
"[name='id_transaction']",
|
||||
);
|
||||
const amount =
|
||||
categoryNameEl.value === 'Income' ? +amountEl.value : -+amountEl.value; // Check if this is a income transaction, amount must plus
|
||||
|
||||
// Validate data user input
|
||||
if (
|
||||
this.validateTransactionForm(dateEl.value, categoryNameEl.value, amount)
|
||||
) {
|
||||
this.toggleLoaderSpinner();
|
||||
this.transactionDialog.close();
|
||||
|
||||
const transaction = new Transaction({
|
||||
id: idEl.value,
|
||||
categoryName: categoryNameEl.value,
|
||||
date: dateEl.value,
|
||||
amount: -+amountEl.value,
|
||||
amount,
|
||||
note: noteEl.value,
|
||||
idUser: this.wallet.idUser,
|
||||
});
|
||||
@@ -405,31 +448,65 @@ export default class HomeView extends CommonView {
|
||||
await this.saveTransaction(transaction);
|
||||
|
||||
// Reload data
|
||||
await this.loadTransactionData();
|
||||
this.updateAmountWallet();
|
||||
await this.loadData();
|
||||
this.updateAmountWallet(-+amountEl.value);
|
||||
|
||||
if (!idEl.value) {
|
||||
// Add success
|
||||
this.showSuccessToast(
|
||||
MESSAGE.ADD_TRANSACTION_SUCCESS,
|
||||
MESSAGE.DEFAULT_MESSAGE,
|
||||
);
|
||||
|
||||
this.clearInputTransactionForm(this.transactionForm);
|
||||
} catch (error) {
|
||||
this.showErrorToast(error);
|
||||
} else {
|
||||
// Update success
|
||||
this.showSuccessToast(
|
||||
MESSAGE.UPDATE_TRANSACTION_SUCCESS,
|
||||
MESSAGE.DEFAULT_MESSAGE,
|
||||
);
|
||||
}
|
||||
|
||||
this.toggleLoaderSpinner();
|
||||
this.clearInputTransactionForm(this.transactionForm);
|
||||
}
|
||||
} catch (error) {
|
||||
this.showErrorToast(error);
|
||||
this.toggleLoaderSpinner();
|
||||
}
|
||||
}
|
||||
|
||||
validateTransactionForm(date, categoryName, amount) {
|
||||
const inputFieldEls =
|
||||
this.transactionDialog.querySelectorAll('.form__input-field');
|
||||
|
||||
if (!date || !categoryName || !amount) {
|
||||
if (!date) {
|
||||
renderRequiredText('date', inputFieldEls[0]);
|
||||
inputFieldEls[0].classList.add('error-input');
|
||||
}
|
||||
|
||||
if (!categoryName) {
|
||||
renderRequiredText('category', inputFieldEls[1]);
|
||||
inputFieldEls[1].classList.add('error-input');
|
||||
}
|
||||
|
||||
if (!amount) {
|
||||
renderRequiredText('amount', inputFieldEls[2]);
|
||||
inputFieldEls[2].classList.add('error-input');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
clearInputTransactionForm() {
|
||||
const categoryIcon = this.transactionForm.querySelector('.category-icon');
|
||||
|
||||
categoryIcon.src = defaultCategoryIcon;
|
||||
|
||||
this.keySearchCategory = null; // Delete keyword search
|
||||
|
||||
this.renderCategoryItem(this.keySearchCategory);
|
||||
|
||||
this.renderCategoryList(this.keySearchCategory);
|
||||
this.transactionForm.reset();
|
||||
}
|
||||
// ---------------------END DIALOG---------------------//
|
||||
@@ -462,15 +539,20 @@ export default class HomeView extends CommonView {
|
||||
}
|
||||
|
||||
// Render category item
|
||||
this.renderCategoryItem(this.keySearchCategory, newListCategory);
|
||||
this.renderCategoryList(this.keySearchCategory, newListCategory);
|
||||
}
|
||||
|
||||
renderCategoryItem(categorySelected, listCategory = this.listCategory) {
|
||||
renderCategoryList(categorySelected, listCategory = this.listCategory) {
|
||||
// Remove category name unnecessary
|
||||
const newListCategory = listCategory.filter(
|
||||
(item) => !REMOVE_CATEGORY.includes(item.name),
|
||||
);
|
||||
|
||||
const listCategoryEl = document.querySelector('.list-category');
|
||||
|
||||
listCategoryEl.innerHTML = ''; // Remove old category item
|
||||
|
||||
listCategory.forEach((category) => {
|
||||
newListCategory.forEach((category) => {
|
||||
const markup = `
|
||||
<div class="category-item ${
|
||||
category.name === categorySelected ? 'selected' : ''
|
||||
@@ -495,26 +577,48 @@ export default class HomeView extends CommonView {
|
||||
this.budgetDialog.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
this.clearErrorStyleBudgetForm();
|
||||
this.submitBudgetForm();
|
||||
});
|
||||
|
||||
this.budgetDialog.addEventListener('input', (e) => {
|
||||
const bodyDialog = e.target.closest('.dialog__body');
|
||||
this.validateBudgetForm(bodyDialog);
|
||||
|
||||
this.changeBtnStyle(bodyDialog);
|
||||
this.clearErrorStyleBudgetForm();
|
||||
});
|
||||
}
|
||||
|
||||
clearErrorStyleBudgetForm() {
|
||||
// Clear error style
|
||||
const inputFieldEls =
|
||||
this.budgetDialog.querySelectorAll('.form__input-field');
|
||||
const errorTexts = this.budgetDialog.querySelectorAll('.error-text');
|
||||
|
||||
inputFieldEls.forEach((item) => {
|
||||
if (item.classList.contains('error-input'))
|
||||
item.classList.remove('error-input');
|
||||
});
|
||||
|
||||
errorTexts.forEach((item) => {
|
||||
if (item) item.remove();
|
||||
});
|
||||
}
|
||||
|
||||
async submitBudgetForm() {
|
||||
try {
|
||||
this.toggleLoaderSpinner(); // Enable loader spinner
|
||||
this.budgetDialog.close(); // Close dialog
|
||||
|
||||
const { formAddBudget } = document.forms;
|
||||
const form = new FormData(formAddBudget);
|
||||
const date = form.get('date');
|
||||
const date = form.get('selected_date');
|
||||
const amount = form.get('amount');
|
||||
const note = form.get('note');
|
||||
|
||||
// Validate data user input
|
||||
|
||||
if (this.validateBudgetForm(date, amount)) {
|
||||
this.toggleLoaderSpinner(); // Enable loader spinner
|
||||
this.budgetDialog.close(); // Close dialog
|
||||
|
||||
const transaction = new Transaction({
|
||||
categoryName: DEFAULT_CATEGORY.INCOME,
|
||||
date,
|
||||
@@ -526,8 +630,9 @@ export default class HomeView extends CommonView {
|
||||
await this.saveTransaction(transaction);
|
||||
|
||||
// Reload data
|
||||
await this.loadTransactionData();
|
||||
await this.updateAmountWallet();
|
||||
await this.loadData();
|
||||
await this.updateAmountWallet(+amount); // Update wallet
|
||||
|
||||
// Hide loader spinner
|
||||
this.toggleLoaderSpinner();
|
||||
@@ -539,12 +644,34 @@ export default class HomeView extends CommonView {
|
||||
);
|
||||
|
||||
document.getElementById('formAddBudget').reset();
|
||||
}
|
||||
} catch (error) {
|
||||
this.showErrorToast(error);
|
||||
}
|
||||
}
|
||||
|
||||
validateBudgetForm(bodyDialog) {
|
||||
validateBudgetForm(date, amount) {
|
||||
const inputFieldEl =
|
||||
this.budgetDialog.querySelectorAll('.form__input-field');
|
||||
|
||||
if (!date || !amount) {
|
||||
if (!date) {
|
||||
renderRequiredText('date', inputFieldEl[0]);
|
||||
inputFieldEl[0].classList.add('error-input');
|
||||
}
|
||||
|
||||
if (!amount) {
|
||||
renderRequiredText('amount', inputFieldEl[1]);
|
||||
inputFieldEl[1].classList.add('error-input');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
changeBtnStyle(bodyDialog) {
|
||||
const date = bodyDialog.querySelector('.input-date').value;
|
||||
const amount = +bodyDialog.querySelector('.form__input-balance').value;
|
||||
const saveBtn = bodyDialog.querySelector('.form__save-btn');
|
||||
@@ -562,19 +689,34 @@ export default class HomeView extends CommonView {
|
||||
this.walletDialog.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
this.clearErrorStyleWalletDialog();
|
||||
this.submitWalletForm();
|
||||
});
|
||||
|
||||
this.walletDialog.addEventListener('input', (e) => {
|
||||
const bodyDialog = e.target.closest('.dialog__body');
|
||||
this.validateWalletForm(bodyDialog);
|
||||
|
||||
this.changeBtnStyleWalletDialog(bodyDialog);
|
||||
this.clearErrorStyleWalletDialog();
|
||||
});
|
||||
}
|
||||
|
||||
clearErrorStyleWalletDialog() {
|
||||
const inputFieldEls =
|
||||
this.walletDialog.querySelectorAll('.form__input-field');
|
||||
const errorTextEls = this.walletDialog.querySelectorAll('.error-text');
|
||||
|
||||
inputFieldEls.forEach((item) => {
|
||||
if (item.classList.contains('error-input'))
|
||||
item.classList.remove('error-input');
|
||||
});
|
||||
|
||||
errorTextEls.forEach((item) => {
|
||||
if (item) item.remove();
|
||||
});
|
||||
}
|
||||
|
||||
async submitWalletForm() {
|
||||
this.walletDialog.close();
|
||||
this.toggleLoaderSpinner();
|
||||
|
||||
try {
|
||||
// Wallet info
|
||||
const { walletForm } = document.forms;
|
||||
@@ -582,19 +724,23 @@ export default class HomeView extends CommonView {
|
||||
const walletName = form.get('walletName');
|
||||
const amount = form.get('amount');
|
||||
|
||||
const wallet = new Wallet({
|
||||
if (this.validateWalletDialog(walletName, amount)) {
|
||||
this.walletDialog.close();
|
||||
this.toggleLoaderSpinner();
|
||||
|
||||
this.wallet = new Wallet({
|
||||
walletName,
|
||||
amount: +amount,
|
||||
idUser: this.user.id,
|
||||
inflow: +amount,
|
||||
});
|
||||
|
||||
await this.saveWallet(wallet);
|
||||
await this.saveWallet(this.wallet);
|
||||
|
||||
// Transaction info
|
||||
const transaction = new Transaction({
|
||||
categoryName: 'Income',
|
||||
date: new Date().toLocaleDateString('en-US'),
|
||||
date: new Date().toISOString().slice(0, 10),
|
||||
note: FIRST_ADD_WALLET_NOTE,
|
||||
amount: +amount,
|
||||
idUser: this.user.id,
|
||||
@@ -603,6 +749,7 @@ export default class HomeView extends CommonView {
|
||||
await this.saveTransaction(transaction);
|
||||
|
||||
// Load data and event
|
||||
await this.loadTransactionData();
|
||||
await this.loadData();
|
||||
this.loadEvent();
|
||||
|
||||
@@ -612,15 +759,38 @@ export default class HomeView extends CommonView {
|
||||
);
|
||||
|
||||
await this.loadData(); // Load data from database into page
|
||||
} catch (error) {
|
||||
// Show toast error
|
||||
this.showErrorToast(error);
|
||||
}
|
||||
|
||||
this.toggleLoaderSpinner();
|
||||
}
|
||||
} catch (error) {
|
||||
// Show toast error
|
||||
this.showErrorToast(error);
|
||||
this.toggleLoaderSpinner();
|
||||
}
|
||||
}
|
||||
|
||||
validateWalletForm(bodyDialog) {
|
||||
validateWalletDialog(walletName, amount) {
|
||||
const inputFieldEls =
|
||||
this.walletDialog.querySelectorAll('.form__input-field');
|
||||
|
||||
if (!walletName || !amount) {
|
||||
if (!walletName) {
|
||||
renderRequiredText('wallet name', inputFieldEls[0]);
|
||||
inputFieldEls[0].classList.add('error-input');
|
||||
}
|
||||
|
||||
if (!amount) {
|
||||
renderRequiredText('amount', inputFieldEls[2]);
|
||||
inputFieldEls[2].classList.add('error-input');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
changeBtnStyleWalletDialog(bodyDialog) {
|
||||
const walletName = bodyDialog.querySelector('.form__input-text').value;
|
||||
const amount = bodyDialog.querySelector('.form__input-balance').value;
|
||||
const saveBtn = bodyDialog.querySelector('.form__save-btn');
|
||||
@@ -671,14 +841,14 @@ export default class HomeView extends CommonView {
|
||||
*/
|
||||
handlerTabsTransfer() {
|
||||
this.tabs.forEach((tab, index) => {
|
||||
tab.addEventListener('click', () => {
|
||||
tab.addEventListener('click', (e) => {
|
||||
this.removeActiveTab();
|
||||
tab.classList.add('active');
|
||||
|
||||
const line = document.querySelector('.app__line');
|
||||
|
||||
line.classList.toggle('right', line.classList.contains('left'));
|
||||
line.classList.toggle('left', !line.classList.contains('right'));
|
||||
line.style.width = `${e.target.offsetWidth}px`;
|
||||
line.style.left = `${e.target.offsetLeft}px`;
|
||||
|
||||
this.allContent.forEach((content) => {
|
||||
content.classList.remove('active');
|
||||
@@ -709,6 +879,10 @@ export default class HomeView extends CommonView {
|
||||
});
|
||||
|
||||
this.addBudgetBtn.addEventListener('click', () => {
|
||||
// Set default value for date input
|
||||
this.budgetDialog.querySelector("[name='selected_date']").valueAsDate =
|
||||
new Date();
|
||||
|
||||
this.budgetDialog.showModal();
|
||||
});
|
||||
|
||||
@@ -743,11 +917,20 @@ export default class HomeView extends CommonView {
|
||||
showTransactionDialog(idTransaction = null) {
|
||||
this.clearInputTransactionForm();
|
||||
|
||||
// Show delete button only if it is a edit form
|
||||
const deleteBtn = this.transactionDialog.querySelector('.form__delete-btn');
|
||||
deleteBtn.classList.toggle('hide', !idTransaction);
|
||||
|
||||
if (idTransaction) this.initDataTransactionDialog(idTransaction);
|
||||
if (idTransaction) {
|
||||
// Init data transaction to dialog
|
||||
this.initDataTransactionDialog(idTransaction);
|
||||
} else
|
||||
this.transactionDialog.querySelector(
|
||||
"[name='selected_date']",
|
||||
).valueAsDate = new Date(); // Set default value for date input
|
||||
|
||||
// Change style submit btn
|
||||
this.changeBtnStyleTransactionDialog();
|
||||
this.transactionDialog.showModal();
|
||||
}
|
||||
|
||||
@@ -785,6 +968,9 @@ export default class HomeView extends CommonView {
|
||||
|
||||
// Close select category dialog
|
||||
this.categoryDialog.close();
|
||||
|
||||
// Clear error style for transaction dialog
|
||||
this.clearErrorTransactionDialog();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -794,7 +980,7 @@ export default class HomeView extends CommonView {
|
||||
// Make the keyword search category name into global
|
||||
this.keySearchCategory = categoryNameEl.value;
|
||||
|
||||
this.renderCategoryItem(this.keySearchCategory);
|
||||
this.renderCategoryList(this.keySearchCategory);
|
||||
}
|
||||
this.categoryDialog.showModal();
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import CommonLoginRegisterView from './commonLoginRegisterView';
|
||||
import AuthenticationView from './authenticationView';
|
||||
import { TYPE_TOAST, BTN_CONTENT } from '../constants/config';
|
||||
import * as MESSAGE from '../constants/message';
|
||||
|
||||
export default class LoginView extends CommonLoginRegisterView {
|
||||
export default class LoginView extends AuthenticationView {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@@ -26,16 +26,31 @@ export default class LoginView extends CommonLoginRegisterView {
|
||||
* Get data from user input
|
||||
* @returns {Object || null} Return object or null
|
||||
*/
|
||||
getDataFromForm(event) {
|
||||
validateForm(event) {
|
||||
const formData = new FormData(event.target);
|
||||
const email = formData.get('email');
|
||||
const password = formData.get('password');
|
||||
|
||||
// Validate user input
|
||||
this.listError = []; // Reset list error
|
||||
const emailValid = this.validateEmail(email);
|
||||
const passwordValid = this.validatePassword(password);
|
||||
|
||||
// Show error style
|
||||
this.emailEl.classList.toggle('error-input', !emailValid);
|
||||
this.inputPasswordEl.classList.toggle('error-input', !passwordValid);
|
||||
|
||||
if (emailValid && passwordValid) {
|
||||
this.account = { email, password };
|
||||
|
||||
return this.account;
|
||||
}
|
||||
|
||||
this.showError(this.listError);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement error toast in site
|
||||
* @param {string} content The content will show in error toast
|
||||
@@ -73,7 +88,8 @@ export default class LoginView extends CommonLoginRegisterView {
|
||||
this.toggleLoaderSpinner();
|
||||
|
||||
// Get data from form
|
||||
const userInput = this.getDataFromForm(event);
|
||||
const userInput = this.validateForm(event);
|
||||
if (userInput) {
|
||||
// Check user exist
|
||||
const results = await loginUser(userInput.email, userInput.password);
|
||||
|
||||
@@ -83,6 +99,7 @@ export default class LoginView extends CommonLoginRegisterView {
|
||||
return;
|
||||
}
|
||||
throw MESSAGE.ERROR_CREDENTIAL;
|
||||
}
|
||||
} catch (error) {
|
||||
// Show toast error
|
||||
this.initErrorToast(error);
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { TYPE_TOAST, BTN_CONTENT } from '../constants/config';
|
||||
import * as MESSAGE from '../constants/message';
|
||||
import CommonLoginRegisterView from './commonLoginRegisterView';
|
||||
import AuthenticationView from './authenticationView';
|
||||
import User from '../models/user';
|
||||
import { redirectToLoginPage } from '../helpers/helpers';
|
||||
|
||||
export default class RegisterView extends CommonLoginRegisterView {
|
||||
export default class RegisterView extends AuthenticationView {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.dialog = document.querySelector('.toast');
|
||||
this.toastBtn = document.querySelector('.toast__redirect-btn');
|
||||
}
|
||||
|
||||
async loadPage(getInfoUserLogin) {
|
||||
@@ -26,21 +28,38 @@ export default class RegisterView extends CommonLoginRegisterView {
|
||||
* Get data from user input
|
||||
* @returns {Object || null} Return object or null
|
||||
*/
|
||||
getDataFromForm() {
|
||||
validateForm() {
|
||||
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 };
|
||||
// Validate user input
|
||||
this.listError = []; // Reset list error
|
||||
const emailValid = this.validateEmail(email);
|
||||
const passwordValid = this.validatePassword(password);
|
||||
const passwordConfirmValid = this.validatePasswordConfirm(
|
||||
password,
|
||||
passwordConfirm,
|
||||
);
|
||||
|
||||
if (this.isValidateAccount(account)) {
|
||||
const user = new User(account);
|
||||
// Show error style
|
||||
this.emailEl.classList.toggle('error-input', !emailValid);
|
||||
this.inputPasswordEl.classList.toggle('error-input', !passwordValid);
|
||||
this.inputPasswordConfirmEl.classList.toggle(
|
||||
'error-input',
|
||||
!passwordConfirmValid,
|
||||
);
|
||||
|
||||
if (emailValid && passwordValid && passwordConfirmValid) {
|
||||
const user = new User({ email, password, passwordConfirm });
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
this.showError(this.listError);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -49,14 +68,17 @@ export default class RegisterView extends CommonLoginRegisterView {
|
||||
*/
|
||||
showRegisterSuccessToast() {
|
||||
const typeToast = TYPE_TOAST.success;
|
||||
const title = 'Register Commpleted';
|
||||
const content = 'Please login to continue!';
|
||||
const btnContent = 'OK';
|
||||
const title = MESSAGE.REGISTER_SUCCESS;
|
||||
const content = MESSAGE.DEFAULT_MESSAGE;
|
||||
const btnContent = BTN_CONTENT.OK;
|
||||
|
||||
this.initToastContent(typeToast, title, content, btnContent);
|
||||
|
||||
// Show toast
|
||||
this.toastDialog.showModal();
|
||||
|
||||
// Add event for toast button
|
||||
this.toastBtn.addEventListener('click', redirectToLoginPage);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,6 +93,9 @@ export default class RegisterView extends CommonLoginRegisterView {
|
||||
|
||||
// Show toast
|
||||
this.toastDialog.showModal();
|
||||
|
||||
// Remove event for toast button
|
||||
this.toastBtn.removeEventListener('click', redirectToLoginPage);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,8 +115,8 @@ export default class RegisterView extends CommonLoginRegisterView {
|
||||
// Load spinner
|
||||
this.toggleLoaderSpinner();
|
||||
|
||||
// Get data from form
|
||||
const user = this.getDataFromForm();
|
||||
// Get validate form
|
||||
const user = this.validateForm();
|
||||
|
||||
// Save user
|
||||
if (user) {
|
||||
@@ -103,6 +128,9 @@ export default class RegisterView extends CommonLoginRegisterView {
|
||||
await saveUser(user);
|
||||
// Show toast success
|
||||
this.showRegisterSuccessToast();
|
||||
|
||||
// Clear form
|
||||
document.getElementById('registerForm').reset();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<!-- Dialog body -->
|
||||
<div class="dialog__body">
|
||||
<form class="form" id="walletForm">
|
||||
<div class="form__input-container">
|
||||
<div class="form__input-field">
|
||||
<p class="form__label">Wallet name</p>
|
||||
<input
|
||||
@@ -25,10 +26,10 @@
|
||||
class="form__input-text"
|
||||
placeholder="Your wallet name?"
|
||||
name="walletName"
|
||||
required
|
||||
minlength="3"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form__currency-balance">
|
||||
<div class="form__input-field">
|
||||
<p class="form__label">Currency</p>
|
||||
@@ -40,16 +41,17 @@
|
||||
<p class="form__text-currency">United States Dollar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form__input-container">
|
||||
<div class="form__input-field">
|
||||
<p class="form__label">Initial Balance</p>
|
||||
<input
|
||||
type="number"
|
||||
class="form__input-balance"
|
||||
name="amount"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="form__save-btn">SAVE</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -67,13 +69,20 @@
|
||||
<div class="dialog__body">
|
||||
<form class="form" id="formAddBudget">
|
||||
<div class="form__date-amount-input">
|
||||
<div class="form__input-container">
|
||||
<div class="form__input-field">
|
||||
<p class="form__label">Date</p>
|
||||
<div class="date-input-container">
|
||||
<input class="input-date" type="date" name="date" required />
|
||||
<input
|
||||
class="input-date"
|
||||
type="date"
|
||||
name="selected_date"
|
||||
/>
|
||||
<div class="icon-btn"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form__input-container">
|
||||
<div class="form__input-field">
|
||||
<p class="form__label">Amount</p>
|
||||
<input
|
||||
@@ -81,10 +90,10 @@
|
||||
type="number"
|
||||
min="1"
|
||||
name="amount"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form__note-input">
|
||||
<p class="form__label">Note</p>
|
||||
<input
|
||||
@@ -116,6 +125,7 @@
|
||||
<form class="form" id="formAddTransaction">
|
||||
<input type="text" name="id_transaction" hidden />
|
||||
<div class="form__date-category-amount-input">
|
||||
<div class="form__input-container">
|
||||
<div class="form__input-field">
|
||||
<p class="form__label">Date</p>
|
||||
<div class="date-input-container">
|
||||
@@ -123,11 +133,12 @@
|
||||
class="input-date"
|
||||
type="date"
|
||||
name="selected_date"
|
||||
required
|
||||
/>
|
||||
<span class="icon-btn"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form__input-container">
|
||||
<div class="form__input-field" id="selectCategory">
|
||||
<p class="form__label">Category</p>
|
||||
<div class="category-input-container">
|
||||
@@ -141,11 +152,12 @@
|
||||
name="category_name"
|
||||
class="category-name"
|
||||
placeholder="Select Category"
|
||||
required
|
||||
/>
|
||||
<div class="icon-btn"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form__input-container">
|
||||
<div class="form__input-field">
|
||||
<p class="form__label">Amount</p>
|
||||
<input
|
||||
@@ -153,10 +165,10 @@
|
||||
type="number"
|
||||
name="amount"
|
||||
value="0"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form__note-input">
|
||||
<p class="form__label">Note</p>
|
||||
<input
|
||||
|
||||
@@ -22,18 +22,16 @@
|
||||
<h1 class="form__title">Log In</h1>
|
||||
<p class="form__description">Using Money Lover account</p>
|
||||
<input
|
||||
type="email"
|
||||
type="text"
|
||||
class="form__input"
|
||||
placeholder="Email"
|
||||
name="email"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
name="password"
|
||||
class="form__input"
|
||||
placeholder="Password"
|
||||
required
|
||||
/>
|
||||
<button type="submit" class="form__submit-btn">Login</button>
|
||||
<p class="form__redirect-signup-text">
|
||||
|
||||
@@ -21,27 +21,31 @@
|
||||
<div class="form__container">
|
||||
<h1 class="form__title">Register</h1>
|
||||
<p class="form__description">Using Money Lover account</p>
|
||||
<div class="form__input-container">
|
||||
<input
|
||||
type="email"
|
||||
type="text"
|
||||
class="form__input"
|
||||
placeholder="Email"
|
||||
name="email"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="form__input-container">
|
||||
<input
|
||||
type="password"
|
||||
name="password"
|
||||
class="form__input"
|
||||
placeholder="Password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="form__input-container">
|
||||
<input
|
||||
type="password"
|
||||
name="password_confirm"
|
||||
class="form__input"
|
||||
placeholder="Confirm Password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="form__submit-btn">Register</button>
|
||||
<p class="form__redirect-signup-text">
|
||||
Have you an account?
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
@import './abstracts/variables';
|
||||
|
||||
// Bases
|
||||
@import './bases/base';
|
||||
@import './bases/placeholder';
|
||||
@import './bases/reset';
|
||||
@import './bases/typography';
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
.overlay {
|
||||
@extend %d-absolute;
|
||||
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
z-index: $zindex-lv-1;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
|
||||
&.active {
|
||||
@extend %active;
|
||||
}
|
||||
}
|
||||
@@ -51,3 +51,9 @@
|
||||
|
||||
padding: 8 0px;
|
||||
}
|
||||
|
||||
%error-text {
|
||||
align-self: flex-start;
|
||||
padding-left: 5px;
|
||||
color: $dark-error-color;
|
||||
}
|
||||
|
||||
@@ -143,16 +143,6 @@
|
||||
background-color: $primary-color;
|
||||
border-radius: 10px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
|
||||
&.left {
|
||||
left: 152px;
|
||||
width: 116px;
|
||||
}
|
||||
|
||||
&.right {
|
||||
left: 272px;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,6 +334,10 @@
|
||||
font-size: $fs-md;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
&__input-field {
|
||||
height: fit-content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,11 +358,11 @@
|
||||
@extend %d-flex;
|
||||
@include flex-layout($gap: 32px);
|
||||
|
||||
& .form__input-field:first-child {
|
||||
& .form__input-container:first-child .form__input-field {
|
||||
width: 208px;
|
||||
}
|
||||
|
||||
& .form__input-field:last-child {
|
||||
& .form__input-container:last-child .form__input-field {
|
||||
width: 240px;
|
||||
}
|
||||
}
|
||||
@@ -504,7 +498,7 @@
|
||||
&__input-field {
|
||||
@extend %rounded;
|
||||
|
||||
padding: 6px 16px 13.5px 16px;
|
||||
padding: 6px 16px 12px;
|
||||
border: 1px solid $gray;
|
||||
}
|
||||
|
||||
@@ -519,6 +513,7 @@
|
||||
font-size: $fs-lg;
|
||||
width: 100%;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
@@ -530,11 +525,12 @@
|
||||
}
|
||||
|
||||
&__input-balance {
|
||||
font-size: $fs-md;
|
||||
font-size: $fs-lg;
|
||||
line-height: 20px;
|
||||
margin-top: 6px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
@@ -599,6 +595,7 @@
|
||||
width: 100%;
|
||||
border: none;
|
||||
font-size: $fs-lg;
|
||||
background-color: transparent;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
@@ -614,7 +611,7 @@
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 5px;
|
||||
background-color: $white;
|
||||
background-color: transparent;
|
||||
border-top: 3px solid $dark-gray;
|
||||
border-right: 3px solid $dark-gray;
|
||||
border-bottom: none;
|
||||
@@ -644,6 +641,7 @@
|
||||
color: $black;
|
||||
border: none;
|
||||
caret-color: transparent;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
|
||||
&:focus {
|
||||
@@ -689,6 +687,24 @@
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.error-input {
|
||||
background-color: $light-error-color;
|
||||
border-color: $dark-error-color;
|
||||
|
||||
& .form__input-text::placeholder {
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
.error-text {
|
||||
@extend %error-text;
|
||||
}
|
||||
|
||||
.form__input-container {
|
||||
@extend %d-flex;
|
||||
@include flex-layout($direction: column, $gap: 7px);
|
||||
}
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
padding: 15px 15px;
|
||||
border-radius: 10px;
|
||||
line-height: 22px;
|
||||
list-style: inside;
|
||||
}
|
||||
|
||||
&__description {
|
||||
@@ -69,6 +70,11 @@
|
||||
border: 2px solid $background-input-color;
|
||||
background-color: $background-input-color;
|
||||
padding-inline: 14px;
|
||||
|
||||
&-container {
|
||||
@extend %d-flex;
|
||||
@include flex-layout($direction: column, $gap: 7px);
|
||||
}
|
||||
}
|
||||
|
||||
&__submit-btn {
|
||||
@@ -87,4 +93,8 @@
|
||||
border: 2px solid $dark-error-color;
|
||||
background-color: $light-error-color;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
@extend %error-text;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user