mirror of
https://github.com/Nezumi-2711/javascript-training.git
synced 2026-09-22 20:01:31 +00:00
Show wallet info and add budget method
This commit is contained in:
@@ -17,6 +17,35 @@ export const LOCAL_STORAGE = {
|
|||||||
ACCESS_TOKEN: 'accessToken',
|
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 TYPE_TOAST = { success: 'success', error: 'error' };
|
||||||
export const MARK_ICON = { success: 'check', error: 'error' };
|
export const MARK_ICON = { success: 'check', error: 'error' };
|
||||||
|
|
||||||
|
|||||||
@@ -15,3 +15,9 @@ export const ERROR_CREDENTIAL = {
|
|||||||
export const DEFAULT_TITLE_ERROR_TOAST = 'Error';
|
export const DEFAULT_TITLE_ERROR_TOAST = 'Error';
|
||||||
|
|
||||||
export const USER_EXIST_ERROR = 'User is exists! Please try another email!';
|
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!';
|
||||||
|
|||||||
@@ -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,}$/;
|
|
||||||
@@ -20,6 +20,10 @@ export default class HomeController {
|
|||||||
return this.service.walletService.saveWallet(wallet);
|
return this.service.walletService.saveWallet(wallet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handlerSaveTransaction(transaction) {
|
||||||
|
return this.service.transactionService.saveTransaction(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
if (this.homeView) {
|
if (this.homeView) {
|
||||||
this.homeView.addHandlerInputChangeWalletForm();
|
this.homeView.addHandlerInputChangeWalletForm();
|
||||||
@@ -34,7 +38,12 @@ export default class HomeController {
|
|||||||
this.handlerGetWalletUser.bind(this),
|
this.handlerGetWalletUser.bind(this),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.homeView.addHandlerSubmitBudgetForm();
|
this.homeView.addHandlerSubmitBudgetForm(
|
||||||
|
this.handlerSaveTransaction.bind(this),
|
||||||
|
this.handlerSaveWallet.bind(this),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.homeView.addHandlerInputChangeBudgetForm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as MESSAGE from '../constants/message';
|
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';
|
import FirebaseService from '../services/firebaseService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,3 +81,14 @@ export const formatNumber = (number) => {
|
|||||||
minimumFractionDigits: 2,
|
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}`;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import CommonService from './commonService';
|
import CommonService from './commonService';
|
||||||
import Transaction from '../models/transaction';
|
|
||||||
|
|
||||||
export default class TransactionService extends CommonService {
|
export default class TransactionService extends CommonService {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -13,8 +12,6 @@ export default class TransactionService extends CommonService {
|
|||||||
* @param {Object} transaction The wallet object need to be saved into database
|
* @param {Object} transaction The wallet object need to be saved into database
|
||||||
*/
|
*/
|
||||||
async saveTransaction(transaction) {
|
async saveTransaction(transaction) {
|
||||||
const transactionObject = new Transaction(transaction);
|
await this.save(transaction);
|
||||||
|
|
||||||
await this.save(transactionObject);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import Wallet from '../models/wallet';
|
|
||||||
import CommonService from './commonService';
|
import CommonService from './commonService';
|
||||||
|
|
||||||
export default class WalletService extends CommonService {
|
export default class WalletService extends CommonService {
|
||||||
@@ -40,7 +39,7 @@ export default class WalletService extends CommonService {
|
|||||||
const result = await this.getDataFromProp('idUser', idUser);
|
const result = await this.getDataFromProp('idUser', idUser);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
return new Wallet(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -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 * as MESSAGE from '../constants/message';
|
||||||
import CommonView from './commonView';
|
import CommonView from './commonView';
|
||||||
import Wallet from '../models/wallet';
|
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 {
|
export default class HomeView extends CommonView {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -17,6 +19,7 @@ export default class HomeView extends CommonView {
|
|||||||
this.dialogs = document.querySelectorAll('.dialog');
|
this.dialogs = document.querySelectorAll('.dialog');
|
||||||
this.categoryField = document.getElementById('selectCategory');
|
this.categoryField = document.getElementById('selectCategory');
|
||||||
this.closeIcon = document.querySelector('.close-icon');
|
this.closeIcon = document.querySelector('.close-icon');
|
||||||
|
this.amountInputs = document.querySelectorAll('.form__input-balance');
|
||||||
|
|
||||||
this.budgetDialog = document.getElementById('budgetDialog');
|
this.budgetDialog = document.getElementById('budgetDialog');
|
||||||
this.transactionDialog = document.getElementById('transactionDialog');
|
this.transactionDialog = document.getElementById('transactionDialog');
|
||||||
@@ -57,31 +60,86 @@ export default class HomeView extends CommonView {
|
|||||||
const walletPrice = document.querySelector('.wallet__price');
|
const walletPrice = document.querySelector('.wallet__price');
|
||||||
const sign = wallet.amount >= 0 ? '+' : '-';
|
const sign = wallet.amount >= 0 ? '+' : '-';
|
||||||
const walletNameValue = wallet.walletName;
|
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;
|
walletName.textContent = walletNameValue;
|
||||||
walletPrice.textContent = `${sign}$ ${walletAmountValue}`;
|
walletPrice.textContent = `${sign}$ ${walletAmountValue}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateAmountWallet(amount, saveWallet) {
|
||||||
|
this.wallet.amount += +amount;
|
||||||
|
|
||||||
|
await saveWallet(this.wallet);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------ADD BUDGET DIALOG---------------------//
|
// ---------------------ADD BUDGET DIALOG---------------------//
|
||||||
addHandlerSubmitBudgetForm() {
|
addHandlerSubmitBudgetForm(saveTransaction, saveWallet) {
|
||||||
this.budgetDialog.addEventListener('submit', (e) => {
|
this.budgetDialog.addEventListener('submit', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
this.submitBudgetForm();
|
this.submitBudgetForm(saveTransaction, saveWallet);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
submitBudgetForm() {
|
async submitBudgetForm(saveTransaction, saveWallet) {
|
||||||
|
try {
|
||||||
|
this.toggleLoaderSpinner(); // Enable loader spinner
|
||||||
|
this.budgetDialog.close(); // Close dialog
|
||||||
|
|
||||||
const { formAddBudget } = document.forms;
|
const { formAddBudget } = document.forms;
|
||||||
const form = new FormData(formAddBudget);
|
const form = new FormData(formAddBudget);
|
||||||
const date = form.get('date');
|
const date = form.get('date');
|
||||||
const amount = form.get('amount');
|
const amount = form.get('amount');
|
||||||
const note = form.get('note');
|
const note = form.get('note');
|
||||||
|
|
||||||
alert(`Date: ${date}, Amount: ${amount}, Note: ${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---------------------//
|
// ---------------------END DIALOG---------------------//
|
||||||
|
|
||||||
@@ -97,18 +155,28 @@ export default class HomeView extends CommonView {
|
|||||||
async submitWalletForm(saveWallet) {
|
async submitWalletForm(saveWallet) {
|
||||||
this.walletDialog.close();
|
this.walletDialog.close();
|
||||||
this.toggleLoaderSpinner();
|
this.toggleLoaderSpinner();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const { walletForm } = document.forms;
|
||||||
|
const form = new FormData(walletForm);
|
||||||
|
const walletName = form.get('walletName');
|
||||||
|
const amount = form.get('amount');
|
||||||
|
|
||||||
const wallet = new Wallet({
|
const wallet = new Wallet({
|
||||||
walletName: this.walletName,
|
walletName,
|
||||||
amount: +this.amount,
|
amount: +amount,
|
||||||
idUser: this.user.id,
|
idUser: this.user.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
await saveWallet(wallet);
|
await saveWallet(wallet);
|
||||||
|
|
||||||
this.showSuccessToast('Add wallet success', 'Click ok to continue!');
|
this.showSuccessToast(
|
||||||
this.loadEvent();
|
MESSAGE.ADD_WALLET_SUCCESS,
|
||||||
this.loadData();
|
MESSAGE.DEFAULT_MESSAGE,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.loadEvent(); // Load event page
|
||||||
|
this.loadData(); // Load data from database into page
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Show toast error
|
// Show toast error
|
||||||
this.initErrorToast(error);
|
this.initErrorToast(error);
|
||||||
@@ -125,14 +193,14 @@ export default class HomeView extends CommonView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
validateWalletForm(bodyDialog) {
|
validateWalletForm(bodyDialog) {
|
||||||
this.walletName = bodyDialog.querySelector('.form__input-text').value;
|
const walletName = bodyDialog.querySelector('.form__input-text').value;
|
||||||
this.amount = bodyDialog.querySelector('.form__input-balance').value;
|
const amount = bodyDialog.querySelector('.form__input-balance').value;
|
||||||
const saveBtns = bodyDialog.querySelector('.form__save-btn');
|
const saveBtn = bodyDialog.querySelector('.form__save-btn');
|
||||||
|
|
||||||
if (this.walletName.length >= 3 && this.amount.length >= 1) {
|
if (walletName.length >= 3 && amount >= 1) {
|
||||||
saveBtns.classList.add('active');
|
saveBtn.classList.add('active');
|
||||||
} else {
|
} 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);
|
this.initToastContent(TYPE_TOAST.error, title, content, BTN_CONTENT.GOT_IT);
|
||||||
|
|
||||||
// Show toast
|
// Show toast
|
||||||
this.dialogToast.showModal();
|
this.toastDialog.showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------- HANDLER EVENT ------------------------------- //
|
// ------------------------------- HANDLER EVENT ------------------------------- //
|
||||||
@@ -220,6 +288,14 @@ export default class HomeView extends CommonView {
|
|||||||
this.closeAllDialog();
|
this.closeAllDialog();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Prevent input =,-,e into amount input
|
||||||
|
this.amountInputs.forEach((item) => {
|
||||||
|
item.addEventListener(
|
||||||
|
'keypress',
|
||||||
|
(e) => ['+', '-', 'e'].includes(e.key) && e.preventDefault(),
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addEventSelectCategoryDialog() {
|
addEventSelectCategoryDialog() {
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
<input
|
<input
|
||||||
class="form__input-balance"
|
class="form__input-balance"
|
||||||
type="number"
|
type="number"
|
||||||
value="0"
|
min="1"
|
||||||
name="amount"
|
name="amount"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user