diff --git a/javascript-practice/src/js/constants/config.js b/javascript-practice/src/js/constants/config.js index 07b138e..f027b92 100644 --- a/javascript-practice/src/js/constants/config.js +++ b/javascript-practice/src/js/constants/config.js @@ -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,}))$/, }; diff --git a/javascript-practice/src/js/constants/message.js b/javascript-practice/src/js/constants/message.js index 7902312..6a4bad3 100644 --- a/javascript-practice/src/js/constants/message.js +++ b/javascript-practice/src/js/constants/message.js @@ -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!`; diff --git a/javascript-practice/src/js/controllers/homeController.js b/javascript-practice/src/js/controllers/homeController.js index a846768..e08905c 100644 --- a/javascript-practice/src/js/controllers/homeController.js +++ b/javascript-practice/src/js/controllers/homeController.js @@ -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), diff --git a/javascript-practice/src/js/helpers/helpers.js b/javascript-practice/src/js/helpers/helpers.js index 7b44388..7027169 100644 --- a/javascript-practice/src/js/helpers/helpers.js +++ b/javascript-practice/src/js/helpers/helpers.js @@ -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 = ` +

${MESSAGE.REQUIRED_MESSAGE(field)}

+ `; + + element.insertAdjacentHTML('afterend', markup); +}; + +export const redirectToLoginPage = () => { + window.location.replace('/login'); +}; diff --git a/javascript-practice/src/js/services/categoryService.js b/javascript-practice/src/js/services/categoryService.js index c0d48a3..a8c39ab 100644 --- a/javascript-practice/src/js/services/categoryService.js +++ b/javascript-practice/src/js/services/categoryService.js @@ -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; diff --git a/javascript-practice/src/js/services/commonService.js b/javascript-practice/src/js/services/commonService.js index e4cdf98..eb3d611 100644 --- a/javascript-practice/src/js/services/commonService.js +++ b/javascript-practice/src/js/services/commonService.js @@ -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; diff --git a/javascript-practice/src/js/services/transactionService.js b/javascript-practice/src/js/services/transactionService.js index e923435..5fc7ab8 100644 --- a/javascript-practice/src/js/services/transactionService.js +++ b/javascript-practice/src/js/services/transactionService.js @@ -22,11 +22,7 @@ export default class TransactionService extends CommonService { this.defaultPath, ); - if (results) { - return results; - } - - return null; + return results || null; } async deleteTransaction(idTransaction) { diff --git a/javascript-practice/src/js/services/userService.js b/javascript-practice/src/js/services/userService.js index b31d63a..79ea404 100644 --- a/javascript-practice/src/js/services/userService.js +++ b/javascript-practice/src/js/services/userService.js @@ -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() { diff --git a/javascript-practice/src/js/services/walletService.js b/javascript-practice/src/js/services/walletService.js index 614c42f..7092e11 100644 --- a/javascript-practice/src/js/services/walletService.js +++ b/javascript-practice/src/js/services/walletService.js @@ -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; } } diff --git a/javascript-practice/src/js/views/authenticationView.js b/javascript-practice/src/js/views/authenticationView.js new file mode 100644 index 0000000..29a3fbc --- /dev/null +++ b/javascript-practice/src/js/views/authenticationView.js @@ -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) => `
  • ${message}
  • `) + .join('\n'); + + const markup = ` + + `; + + document + .querySelector('.form__title') + .insertAdjacentHTML('afterend', markup); + } + } +} diff --git a/javascript-practice/src/js/views/commonLoginRegisterView.js b/javascript-practice/src/js/views/commonLoginRegisterView.js deleted file mode 100644 index 5a598a6..0000000 --- a/javascript-practice/src/js/views/commonLoginRegisterView.js +++ /dev/null @@ -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 = ` -

    ${message}

    - `; - - document - .querySelector('.form__title') - .insertAdjacentHTML('afterend', markup); - } -} diff --git a/javascript-practice/src/js/views/homeView.js b/javascript-practice/src/js/views/homeView.js index bd2c6b6..ad8908e 100644 --- a/javascript-practice/src/js/views/homeView.js +++ b/javascript-practice/src/js/views/homeView.js @@ -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; - } else { - this.wallet.outflow += 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 { + 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() { - this.listCategory = await this.getAllCategory(); + 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( - Object.assign({}, ...category), - transactions, - ), + 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,43 +426,87 @@ export default class HomeView extends CommonView { const idEl = this.transactionForm.querySelector( "[name='id_transaction']", ); - const transaction = new Transaction({ - id: idEl.value, - categoryName: categoryNameEl.value, - date: dateEl.value, - amount: -+amountEl.value, - note: noteEl.value, - idUser: this.wallet.idUser, - }); + const amount = + categoryNameEl.value === 'Income' ? +amountEl.value : -+amountEl.value; // Check if this is a income transaction, amount must plus - await this.saveTransaction(transaction); + // Validate data user input + if ( + this.validateTransactionForm(dateEl.value, categoryNameEl.value, amount) + ) { + this.toggleLoaderSpinner(); + this.transactionDialog.close(); - // Reload data - await this.loadData(); - this.updateAmountWallet(-+amountEl.value); + const transaction = new Transaction({ + id: idEl.value, + categoryName: categoryNameEl.value, + date: dateEl.value, + amount, + note: noteEl.value, + idUser: this.wallet.idUser, + }); - this.showSuccessToast( - MESSAGE.ADD_TRANSACTION_SUCCESS, - MESSAGE.DEFAULT_MESSAGE, - ); + await this.saveTransaction(transaction); - this.clearInputTransactionForm(this.transactionForm); + // Reload data + await this.loadTransactionData(); + this.updateAmountWallet(); + await this.loadData(); + + if (!idEl.value) { + // Add success + this.showSuccessToast( + MESSAGE.ADD_TRANSACTION_SUCCESS, + MESSAGE.DEFAULT_MESSAGE, + ); + } 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; } - this.toggleLoaderSpinner(); + 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 = `
    -
    -

    Wallet name

    - +
    +
    +

    Wallet name

    + +
    @@ -40,14 +41,15 @@

    United States Dollar

    -
    -

    Initial Balance

    - +
    +
    +

    Initial Balance

    + +
    @@ -67,22 +69,29 @@
    -
    -

    Date

    -
    - -
    +
    +
    +

    Date

    +
    + +
    +
    -
    -

    Amount

    - +
    +
    +

    Amount

    + +
    @@ -116,45 +125,48 @@
    -
    -

    Date

    -
    - - +
    +
    +

    Date

    +
    + + +
    -
    -

    Category

    -
    - Question icon - -
    +
    +
    +

    Category

    +
    + Question icon + +
    +
    -
    -

    Amount

    - +
    +
    +

    Amount

    + +
    diff --git a/javascript-practice/src/pages/login.html b/javascript-practice/src/pages/login.html index e759d46..bf48433 100644 --- a/javascript-practice/src/pages/login.html +++ b/javascript-practice/src/pages/login.html @@ -22,18 +22,16 @@

    Log In

    Using Money Lover account

    Register

    Using Money Lover account

    - - - +
    + +
    +
    + +
    +
    + +
    +