diff --git a/javascript-practice/src/js/constants/config.js b/javascript-practice/src/js/constants/config.js index b879e6d..bf4e4e6 100644 --- a/javascript-practice/src/js/constants/config.js +++ b/javascript-practice/src/js/constants/config.js @@ -17,6 +17,35 @@ export const LOCAL_STORAGE = { ACCESS_TOKEN: 'accessToken', }; +export const DEFAULT_CATEGORY = { + INCOME: 'Income', +}; + +export const DAY = [ + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + 'Sunday', +]; + +export const MONTH = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', +]; + export const TYPE_TOAST = { success: 'success', error: 'error' }; export const MARK_ICON = { success: 'check', error: 'error' }; diff --git a/javascript-practice/src/js/constants/message.js b/javascript-practice/src/js/constants/message.js index b0e7995..7902312 100644 --- a/javascript-practice/src/js/constants/message.js +++ b/javascript-practice/src/js/constants/message.js @@ -15,3 +15,9 @@ export const ERROR_CREDENTIAL = { export const DEFAULT_TITLE_ERROR_TOAST = 'Error'; export const USER_EXIST_ERROR = 'User is exists! Please try another email!'; + +export const ADD_WALLET_SUCCESS = 'Add wallet success!'; + +export const DEFAULT_MESSAGE = 'Press OK to continue!'; + +export const ADD_TRANSACTION_SUCCESS = 'Add success!'; diff --git a/javascript-practice/src/js/constants/variable.js b/javascript-practice/src/js/constants/variable.js deleted file mode 100644 index 423aaef..0000000 --- a/javascript-practice/src/js/constants/variable.js +++ /dev/null @@ -1,20 +0,0 @@ -export const URL = { - LOGIN: 'login', - REGISTER: 'register', - HOME: '', -}; - -export const BTN_CONTENT = { - GOT_IT: 'Got it!', - OK: 'Ok', -}; - -export const LOCAL_STORAGE = { - ACCESS_TOKEN: 'accessToken', -}; - -export const TYPE_TOAST = { success: 'success', error: 'error' }; -export const MARK_ICON = { success: 'check', error: 'error' }; - -export const REGEX_PASSWORD = - /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/; diff --git a/javascript-practice/src/js/controllers/homeController.js b/javascript-practice/src/js/controllers/homeController.js index 2b5a7ce..4facfd0 100644 --- a/javascript-practice/src/js/controllers/homeController.js +++ b/javascript-practice/src/js/controllers/homeController.js @@ -20,6 +20,10 @@ export default class HomeController { return this.service.walletService.saveWallet(wallet); } + handlerSaveTransaction(transaction) { + return this.service.transactionService.saveTransaction(transaction); + } + init() { if (this.homeView) { this.homeView.addHandlerInputChangeWalletForm(); @@ -34,7 +38,12 @@ export default class HomeController { this.handlerGetWalletUser.bind(this), ); - this.homeView.addHandlerSubmitBudgetForm(); + this.homeView.addHandlerSubmitBudgetForm( + this.handlerSaveTransaction.bind(this), + this.handlerSaveWallet.bind(this), + ); + + this.homeView.addHandlerInputChangeBudgetForm(); } } } diff --git a/javascript-practice/src/js/helpers/helpers.js b/javascript-practice/src/js/helpers/helpers.js index 3592996..10c5701 100644 --- a/javascript-practice/src/js/helpers/helpers.js +++ b/javascript-practice/src/js/helpers/helpers.js @@ -1,5 +1,5 @@ import * as MESSAGE from '../constants/message'; -import { TIME_OUT_SEC, REGEX } from '../constants/config'; +import { TIME_OUT_SEC, REGEX, DAY, MONTH } from '../constants/config'; import FirebaseService from '../services/firebaseService'; /** @@ -81,3 +81,14 @@ export const formatNumber = (number) => { minimumFractionDigits: 2, }); }; + +export const changeDateFormat = (oldFormatDate) => { + const tempDate = new Date(oldFormatDate); + + const day = DAY[tempDate.getDay() - 1]; + const date = tempDate.getDate(); + const month = MONTH[tempDate.getMonth()]; + const year = tempDate.getFullYear(); + + return `${day}, ${date}, ${month}, ${year}`; +}; diff --git a/javascript-practice/src/js/services/transactionService.js b/javascript-practice/src/js/services/transactionService.js index 21eafee..15f8210 100644 --- a/javascript-practice/src/js/services/transactionService.js +++ b/javascript-practice/src/js/services/transactionService.js @@ -1,5 +1,4 @@ import CommonService from './commonService'; -import Transaction from '../models/transaction'; export default class TransactionService extends CommonService { constructor() { @@ -13,8 +12,6 @@ export default class TransactionService extends CommonService { * @param {Object} transaction The wallet object need to be saved into database */ async saveTransaction(transaction) { - const transactionObject = new Transaction(transaction); - - await this.save(transactionObject); + await this.save(transaction); } } diff --git a/javascript-practice/src/js/services/walletService.js b/javascript-practice/src/js/services/walletService.js index 11af7d6..614c42f 100644 --- a/javascript-practice/src/js/services/walletService.js +++ b/javascript-practice/src/js/services/walletService.js @@ -1,4 +1,3 @@ -import Wallet from '../models/wallet'; import CommonService from './commonService'; export default class WalletService extends CommonService { @@ -40,7 +39,7 @@ export default class WalletService extends CommonService { const result = await this.getDataFromProp('idUser', idUser); if (result) { - return new Wallet(result); + return result; } return null; diff --git a/javascript-practice/src/js/views/homeView.js b/javascript-practice/src/js/views/homeView.js index ac1df21..e1e0248 100644 --- a/javascript-practice/src/js/views/homeView.js +++ b/javascript-practice/src/js/views/homeView.js @@ -1,8 +1,10 @@ -import { TYPE_TOAST, BTN_CONTENT } from '../constants/variable'; +/* eslint-disable class-methods-use-this */ +import { TYPE_TOAST, BTN_CONTENT, DEFAULT_CATEGORY } from '../constants/config'; import * as MESSAGE from '../constants/message'; import CommonView from './commonView'; import Wallet from '../models/wallet'; -import { formatNumber } from '../helpers/helpers'; +import Transaction from '../models/transaction'; +import { changeDateFormat, formatNumber } from '../helpers/helpers'; export default class HomeView extends CommonView { constructor() { @@ -17,6 +19,7 @@ export default class HomeView extends CommonView { this.dialogs = document.querySelectorAll('.dialog'); this.categoryField = document.getElementById('selectCategory'); this.closeIcon = document.querySelector('.close-icon'); + this.amountInputs = document.querySelectorAll('.form__input-balance'); this.budgetDialog = document.getElementById('budgetDialog'); this.transactionDialog = document.getElementById('transactionDialog'); @@ -57,31 +60,86 @@ export default class HomeView extends CommonView { const walletPrice = document.querySelector('.wallet__price'); const sign = wallet.amount >= 0 ? '+' : '-'; const walletNameValue = wallet.walletName; - const walletAmountValue = formatNumber(wallet.amount); + // Math.abs(wallet.amount) to keep the value always > 0 + const walletAmountValue = formatNumber(Math.abs(wallet.amount)); - this.wallet = wallet; + this.wallet = wallet; // Make wallet into global variable walletName.textContent = walletNameValue; walletPrice.textContent = `${sign}$ ${walletAmountValue}`; } + async updateAmountWallet(amount, saveWallet) { + this.wallet.amount += +amount; + + await saveWallet(this.wallet); + } + // ---------------------ADD BUDGET DIALOG---------------------// - addHandlerSubmitBudgetForm() { + addHandlerSubmitBudgetForm(saveTransaction, saveWallet) { this.budgetDialog.addEventListener('submit', (e) => { e.preventDefault(); - this.submitBudgetForm(); + this.submitBudgetForm(saveTransaction, saveWallet); }); } - submitBudgetForm() { - const { formAddBudget } = document.forms; - const form = new FormData(formAddBudget); - const date = form.get('date'); - const amount = form.get('amount'); - const note = form.get('note'); + async submitBudgetForm(saveTransaction, saveWallet) { + try { + this.toggleLoaderSpinner(); // Enable loader spinner + this.budgetDialog.close(); // Close dialog - alert(`Date: ${date}, Amount: ${amount}, Note: ${note}`); + const { formAddBudget } = document.forms; + const form = new FormData(formAddBudget); + const date = form.get('date'); + const amount = form.get('amount'); + const note = form.get('note'); + + const transaction = new Transaction({ + categoryName: DEFAULT_CATEGORY.INCOME, + date: changeDateFormat(date), + amount: +amount, + note, + }); + + await saveTransaction(transaction); + + await this.updateAmountWallet(+amount, saveWallet); // Update wallet + + this.loadData(); + + // Hide loader spinner + this.toggleLoaderSpinner(); + + // Show success message + this.showSuccessToast( + MESSAGE.ADD_TRANSACTION_SUCCESS, + MESSAGE.DEFAULT_MESSAGE, + ); + + document.getElementById('formAddBudget').reset(); + } catch (error) { + this.initErrorToast(error); + } + } + + addHandlerInputChangeBudgetForm() { + this.budgetDialog.addEventListener('input', (e) => { + const bodyDialog = e.target.closest('.dialog__body'); + this.validateBudgetForm(bodyDialog); + }); + } + + validateBudgetForm(bodyDialog) { + const date = bodyDialog.querySelector('.input-date').value; + const amount = +bodyDialog.querySelector('.form__input-balance').value; + const saveBtn = bodyDialog.querySelector('.form__save-btn'); + + if (date.trim() && amount >= 1) { + saveBtn.classList.add('active'); + } else { + saveBtn.classList.remove('active'); + } } // ---------------------END DIALOG---------------------// @@ -97,18 +155,28 @@ export default class HomeView extends CommonView { async submitWalletForm(saveWallet) { this.walletDialog.close(); this.toggleLoaderSpinner(); + try { + const { walletForm } = document.forms; + const form = new FormData(walletForm); + const walletName = form.get('walletName'); + const amount = form.get('amount'); + const wallet = new Wallet({ - walletName: this.walletName, - amount: +this.amount, + walletName, + amount: +amount, idUser: this.user.id, }); await saveWallet(wallet); - this.showSuccessToast('Add wallet success', 'Click ok to continue!'); - this.loadEvent(); - this.loadData(); + this.showSuccessToast( + MESSAGE.ADD_WALLET_SUCCESS, + MESSAGE.DEFAULT_MESSAGE, + ); + + this.loadEvent(); // Load event page + this.loadData(); // Load data from database into page } catch (error) { // Show toast error this.initErrorToast(error); @@ -125,14 +193,14 @@ export default class HomeView extends CommonView { } validateWalletForm(bodyDialog) { - this.walletName = bodyDialog.querySelector('.form__input-text').value; - this.amount = bodyDialog.querySelector('.form__input-balance').value; - const saveBtns = bodyDialog.querySelector('.form__save-btn'); + const walletName = bodyDialog.querySelector('.form__input-text').value; + const amount = bodyDialog.querySelector('.form__input-balance').value; + const saveBtn = bodyDialog.querySelector('.form__save-btn'); - if (this.walletName.length >= 3 && this.amount.length >= 1) { - saveBtns.classList.add('active'); + if (walletName.length >= 3 && amount >= 1) { + saveBtn.classList.add('active'); } else { - saveBtns.classList.remove('active'); + saveBtn.classList.remove('active'); } } @@ -158,7 +226,7 @@ export default class HomeView extends CommonView { this.initToastContent(TYPE_TOAST.error, title, content, BTN_CONTENT.GOT_IT); // Show toast - this.dialogToast.showModal(); + this.toastDialog.showModal(); } // ------------------------------- HANDLER EVENT ------------------------------- // @@ -220,6 +288,14 @@ export default class HomeView extends CommonView { this.closeAllDialog(); }); }); + + // Prevent input =,-,e into amount input + this.amountInputs.forEach((item) => { + item.addEventListener( + 'keypress', + (e) => ['+', '-', 'e'].includes(e.key) && e.preventDefault(), + ); + }); } addEventSelectCategoryDialog() { diff --git a/javascript-practice/src/pages/index.html b/javascript-practice/src/pages/index.html index aed2465..18700ab 100644 --- a/javascript-practice/src/pages/index.html +++ b/javascript-practice/src/pages/index.html @@ -87,7 +87,7 @@