Add wallet method

This commit is contained in:
2023-09-10 22:19:17 +07:00
parent 10d9728ac6
commit befc683990
14 changed files with 274 additions and 36 deletions
@@ -10,6 +10,10 @@ export const MESSAGE = {
},
DEFAULT_TITLE_ERROR_POPUP: 'Error',
USER_EXIST_ERROR: 'User is exists! Please try another email!',
WELCOME: {
title: 'Login Successful!',
message: 'Welcome to Money Lover!',
},
};
export const URL = {
@@ -25,6 +29,7 @@ export const BTN_CONTENT = {
export const LOCAL_STORAGE = {
ACCESS_TOKEN: 'accessToken',
IS_FIRST_LOGIN: 'isFirstLogin',
};
export const TYPE_POPUP = { success: 'success', error: 'error' };
@@ -4,11 +4,28 @@ export default class HomeController {
this.homeView = view.homeView;
}
handlerGetInfoUserLogin() {
return this.service.userService.getInfoUserLogin();
}
handlerCheckWalletExist(idUser) {
return this.service.walletService.checkWalletExist(idUser);
}
handlerSaveWallet(wallet) {
return this.service.walletService.saveWallet(wallet);
}
init() {
if (this.homeView) {
this.homeView.handlerTabsTransfer();
this.homeView.addCommonEventPage();
this.homeView.addEventSelectCategoryDialog();
this.homeView.addHandlerInputChangeWalletForm();
this.homeView.addHandlerSubmitWalletForm(
this.handlerSaveWallet.bind(this),
);
this.homeView.loadPage(
this.handlerGetInfoUserLogin.bind(this),
this.handlerCheckWalletExist.bind(this),
);
}
}
}
@@ -70,5 +70,10 @@ export const getSubdirectoryURL = () => {
const subDirectory = parts[3]; // Get subdirectory url only
const index = subDirectory.indexOf('?');
if (index !== -1) {
return subDirectory.substring(0, index);
}
return subDirectory;
};
+1 -2
View File
@@ -1,9 +1,8 @@
export default class User {
constructor({ email, password, walletName = '', accessToken = '' }) {
constructor({ email, password, accessToken = '' }) {
this.id = User.createIdUser();
this.email = email;
this.password = password;
this.walletName = walletName;
this.accessToken = accessToken;
}
@@ -0,0 +1,20 @@
export default class Wallet {
constructor({
walletName = '',
amount = '',
inflow = 0,
outflow = 0,
idUser,
}) {
this.id = Wallet.createIdWallet();
this.walletName = walletName;
this.amout = amount;
this.inflow = inflow;
this.outflow = outflow;
this.idUser = idUser;
}
static createIdWallet() {
return new Date().getTime();
}
}
@@ -20,12 +20,12 @@ export default class CommonService {
async getDataFromProp(property, value, path = this.defaultPath) {
this.connectToDb();
const existUser = this.firebaseService.getDataFromProp(
const dataExists = this.firebaseService.getDataFromProp(
path,
property,
value,
);
const result = await timeOutConnect(existUser);
const result = await timeOutConnect(dataExists);
if (result.id && result.data) {
return convertDataObjectToModel(result);
@@ -8,7 +8,7 @@ class LocalStorageService {
}
get(key) {
this.localStorage.getItem(key);
return this.localStorage.getItem(key);
}
remove(key) {
@@ -1,7 +1,9 @@
import UserService from './userService';
import WalletService from './walletService';
export default class Service {
constructor() {
this.userService = new UserService();
this.walletService = new WalletService();
}
}
@@ -86,5 +86,41 @@ export default class UserService extends CommonService {
LOCAL_STORAGE.ACCESS_TOKEN,
newUserData.accessToken,
);
LocalStorageService.add(LOCAL_STORAGE.IS_FIRST_LOGIN, true);
}
async getInfoUserLogin() {
// Find access token
const accessToken = LocalStorageService.get(LOCAL_STORAGE.ACCESS_TOKEN);
if (accessToken) {
const user = await this.getUserByToken(accessToken);
if (LocalStorageService.get(LOCAL_STORAGE.IS_FIRST_LOGIN)) {
user.isFirstLogin = true;
LocalStorageService.remove(LOCAL_STORAGE.IS_FIRST_LOGIN);
}
return user;
}
return null;
}
/**
* Get user data from token access
* @param {string} accessToken Access token user
* @returns {Object || null} Return new User Object if find, otherwise return null.
*/
async getUserByToken(accessToken) {
const result = await this.getDataFromProp('accessToken', accessToken);
if (result) {
return result;
}
return null;
}
}
@@ -0,0 +1,47 @@
import CommonService from './commonService';
export default class WalletService extends CommonService {
constructor() {
super();
this.defaultPath = 'wallets/';
}
/**
* Save wallet into database
* @param {Object} wallet The wallet object need to be saved into databae
*/
async saveWallet(wallet) {
await this.save(wallet);
}
/**
* Check wallet exist in database
* @param {string} idUser The id user to find user's wallet
* @returns {boolean} Return true if find, otherwise return false
*/
async checkWalletExist(idUser) {
const walletExist = await this.getWalletByIdUser(idUser);
if (walletExist) {
return true;
}
return false;
}
/**
* Get wallet data from idUser
* @param {string} email The id user to find user's wallet
* @returns {Object || null} Return new Wallet Object if find, otherwise return null.
*/
async getWalletByIdUser(idUser) {
const result = await this.getDataFromProp('idUser', idUser);
if (result) {
return result;
}
return null;
}
}
@@ -6,6 +6,8 @@ export default class CommonLoginRegisterView extends CommonView {
constructor() {
super();
this.handleEventBtnPopupAndOverlay();
this.parentElement = document.querySelector('.form');
this.messageDefault = CONSTANT.MESSAGE.ERROR_MESSAGE_DEFAULT;
this.inputPassword = document.querySelector('input[name="password"]');
@@ -84,4 +86,16 @@ export default class CommonLoginRegisterView extends CommonView {
.querySelector('.form__title')
.insertAdjacentHTML('afterend', markup);
}
/**
* Add event listener for popup and overlay
*/
handleEventBtnPopupAndOverlay() {
this.popupBtn.addEventListener('click', this.tooglePopupForm.bind(this));
this.overlay.addEventListener('click', this.toogleDialog.bind(this));
}
toogleDialog() {
this.dialog.classList.toggle('active');
}
}
@@ -7,7 +7,6 @@ export default class CommonView {
this.initPopup();
this.initElementPopup();
this.initLoader();
this.handleEventBtnPopupAndOverlay();
}
/**
@@ -91,28 +90,6 @@ export default class CommonView {
this.popupBtn.textContent = btnContent;
}
/**
* Add event listener for popup and overlay
*/
handleEventBtnPopupAndOverlay() {
this.popupBtn.addEventListener('click', this.tooglePopupForm.bind(this));
this.overlay.addEventListener('click', this.toogleDialog.bind(this));
}
toogleDialog() {
this.overlay.classList.toggle('active');
if (this.dialog.length) {
// If it have more dialog
this.dialog.forEach((item) => {
if (item.classList.contains('active')) {
item.classList.remove('active');
}
});
} else {
this.dialog.classList.toggle('active');
}
}
/**
* Implement loader screen
*/
+110 -1
View File
@@ -1,4 +1,6 @@
import { TYPE_POPUP, MESSAGE, BTN_CONTENT } from '../constants/constant';
import CommonView from './commonView';
import Wallet from '../models/wallet';
export default class HomeView extends CommonView {
constructor() {
@@ -11,6 +13,7 @@ export default class HomeView extends CommonView {
this.overlay = document.querySelector('.overlay');
this.darkOverlay = document.querySelector('.dark-overlay');
this.dialog = document.querySelectorAll('.dialog');
this.saveBtn = document.querySelectorAll('.form__save-btn');
this.cancelBtn = document.querySelectorAll('.form__cancel-btn');
this.categoryField = document.getElementById('selectCategory');
this.closeIcon = document.querySelector('.close-icon');
@@ -18,6 +21,110 @@ export default class HomeView extends CommonView {
this.budgetForm = document.getElementById('budgetForm');
this.transactionForm = document.getElementById('transactionForm');
this.categoryForm = document.getElementById('categoryForm');
this.walletForm = document.getElementById('walletForm');
this.walletDialog = document.getElementById('walletDialog');
}
async loadPage(getInfoUserLogin, checkWalletExist) {
const user = await getInfoUserLogin();
if (!user) {
window.location.replace('/login');
} else {
this.user = user;
const walletExist = await checkWalletExist(user.id);
// Check user's wallet if have or not
if (!walletExist) {
// Show add wallet dialog
this.walletDialog.classList.add('active');
// If overlay is not exist on page
if (!this.overlay.classList.contains('active')) {
this.toggleActiveOverlay();
}
} else {
this.loadEvent();
}
}
}
addHandlerSubmitWalletForm(saveWallet) {
this.walletForm.addEventListener('submit', (e) => {
e.preventDefault();
this.submitWalletForm(saveWallet);
});
}
async submitWalletForm(saveWallet) {
try {
const wallet = new Wallet({
walletName: this.walletName,
amount: this.amount,
idUser: this.user.id,
});
await saveWallet(wallet);
this.hideDialog();
this.showSuccessPopup('Add wallet success', 'Click ok to continue!');
this.loadEvent();
} catch (error) {
// Show popup error
this.initErrorPopup(error);
}
}
addHandlerInputChangeWalletForm() {
this.walletForm.addEventListener('input', (e) => {
const bodyDialog = e.target.closest('.dialog__body');
this.validateWalletForm(bodyDialog);
});
}
validateWalletForm(bodyDialog) {
this.walletName = bodyDialog.querySelector('.form__input-text').value;
this.amount = bodyDialog.querySelector('.form__input-balance').value;
const saveBtn = bodyDialog.querySelector('.form__save-btn');
if (this.walletName.length >= 3 && this.amount.length >= 1) {
saveBtn.classList.add('active');
} else {
saveBtn.classList.remove('active');
}
}
showSuccessPopup(title, message) {
const typePopup = TYPE_POPUP.success;
const btnContent = BTN_CONTENT.OK;
this.initPopupContent(typePopup, title, message, btnContent);
// Show popup
this.tooglePopupForm();
}
/**
* Implement error popup in site
* @param {string} content The content will show in error popup
*/
initErrorPopup(error) {
const title = error.title ? error.title : MESSAGE.DEFAULT_TITLE_ERROR_POPUP;
const content = error.message ? error.message : error;
this.initPopupContent(TYPE_POPUP.error, title, content, BTN_CONTENT.GOT_IT);
// Show popup
this.tooglePopupForm();
}
/* ------------------------------- HANDLER EVENT ------------------------------- */
loadEvent() {
this.addCommonEventPage();
this.handlerTabsTransfer();
this.addEventSelectCategoryDialog();
}
/**
@@ -55,13 +162,14 @@ export default class HomeView extends CommonView {
this.cancelBtn.forEach((item) => {
item.addEventListener('click', () => {
this.hideDialog();
this.toggleActiveOverlay();
});
});
this.overlay.addEventListener('click', () => {
this.hideDialog();
});
this.popupBtn.addEventListener('click', this.tooglePopupForm.bind(this));
}
addEventSelectCategoryDialog() {
@@ -96,6 +204,7 @@ export default class HomeView extends CommonView {
item.classList.remove('active');
}
});
this.toggleActiveOverlay();
}
toggleActiveOverlay() {
+11 -4
View File
@@ -17,7 +17,7 @@
<button class="modal-box__redirect-btn">OK</button>
</div> -->
<!-- Add a wallet form -->
<div class="dialog" id="walletForm">
<div class="dialog" id="walletDialog">
<div class="dialog__add-wallet">
<!-- Dialog header -->
<div class="dialog__header">
@@ -25,14 +25,16 @@
</div>
<!-- Dialog body -->
<div class="dialog__body">
<form class="form">
<form class="form" id="walletForm">
<div class="form__input-field">
<p class="form__label">Wallet name</p>
<input
type="text"
class="form__input-text"
placeholder="Your wallet name?"
name="wallet-name"
name="walletName"
required
minlength="3"
/>
</div>
<div class="form__currency-balance">
@@ -48,7 +50,12 @@
</div>
<div class="form__input-field">
<p class="form__label">Initial Balance</p>
<input type="number" class="form__input-balance" value="0" />
<input
type="number"
class="form__input-balance"
name="amount"
required
/>
</div>
</div>
<button type="submit" class="form__save-btn">SAVE</button>