diff --git a/typescript-practice/src/ts/controllers/homeController.ts b/typescript-practice/src/ts/controllers/homeController.ts new file mode 100644 index 0000000..a2d4e44 --- /dev/null +++ b/typescript-practice/src/ts/controllers/homeController.ts @@ -0,0 +1,63 @@ +import HomeView from 'views/home/homeView'; +import Transform from '../helpers/transform'; +import Service from 'services'; +import View from 'views'; +import Wallet from 'models/wallet'; +import Transaction from 'models/transaction'; + +export default class HomeController { + public homeView: HomeView | null = null; + + constructor( + public service: Service, + public view: View, + ) { + this.service = service; + this.homeView = view.homeView; + } + + handlerGetInfoUserLogin() { + return this.service.userService.getInfoUserLogin(); + } + + handlerGetWalletByIdUser(idUser: number) { + return this.service.walletService.getWalletByIdUser(idUser); + } + + handlerSaveWallet(wallet: Wallet) { + return this.service.walletService.saveWallet(wallet); + } + + handlerSaveTransaction(transaction: Transaction) { + return this.service.transactionService.saveTransaction(transaction); + } + + // handlerGetAllCategory() { + // return this.service.categoryService.getAllCategory(); + // } + + // handlerGetAllTransactions(idUser) { + // return this.service.transactionService.getListTransactionByIdUser(idUser); + // } + + // handlerDeleteTransaction(idTransaction) { + // return this.service.transactionService.deleteTransaction(idTransaction); + // } + + init() { + if (this.homeView) { + this.homeView.initFunction( + this.handlerGetInfoUserLogin.bind(this), + this.handlerGetWalletByIdUser.bind(this), + this.handlerSaveWallet.bind(this), + this.handlerSaveTransaction.bind(this), + new Transform(), + ); + + this.homeView.loadPage(); + + // Subscribe listener data update + this.homeView.subscribeListenerData(); + } + } +} diff --git a/typescript-practice/src/ts/global/types.ts b/typescript-practice/src/ts/global/types.ts index 776e11d..c149d3a 100644 --- a/typescript-practice/src/ts/global/types.ts +++ b/typescript-practice/src/ts/global/types.ts @@ -1,3 +1,5 @@ +import Wallet from 'models/wallet'; + export interface IDataObject { id: string; data: T; @@ -14,10 +16,10 @@ export class DataObject { } } -export type TError = { +export interface TError { title: string; message: string; -}; +} export class CustomError extends Error { constructor( @@ -27,3 +29,14 @@ export class CustomError extends Error { super(message); } } + +export type TSignal = { + [key: string]: { + name: string; + handler: (value: Data) => void; + }; +}; + +export interface Data { + wallet: Wallet; +} diff --git a/typescript-practice/src/ts/helpers/data.ts b/typescript-practice/src/ts/helpers/data.ts index 57a2db8..5987417 100644 --- a/typescript-practice/src/ts/helpers/data.ts +++ b/typescript-practice/src/ts/helpers/data.ts @@ -1,6 +1,8 @@ +import localStorageService from 'services/localStorageService'; import { DataObject, IDataObject } from '../global/types'; +import { LOCAL_STORAGE } from 'constants/config'; -export const createIdUser = (): number => { +export const generateId = (): number => { return new Date().getTime(); }; @@ -30,3 +32,13 @@ export const createToken = (): string => { } return token; }; + +export const formatNumber = (number: number): string => { + return number.toLocaleString(undefined, { + minimumFractionDigits: 2, + }); +}; + +export const clearAccessToken = (): void => { + localStorageService.remove(LOCAL_STORAGE.ACCESS_TOKEN); +}; diff --git a/typescript-practice/src/ts/helpers/transform.ts b/typescript-practice/src/ts/helpers/transform.ts new file mode 100644 index 0000000..cadc84c --- /dev/null +++ b/typescript-practice/src/ts/helpers/transform.ts @@ -0,0 +1,33 @@ +import { TSignal, Data } from 'global/types'; + +export default class Transform { + public signal: TSignal; + + constructor() { + this.signal = {}; + } + + onSendSignal(fromClass: string, value: Data) { + Object.keys(this.signal).forEach((key) => { + const item = this.signal[key as keyof TSignal]; + + // Same receiver + if (item.name === fromClass) { + return; + } + + // Send signal + const { handler } = this.signal[key]; + if (handler) { + handler(value); + } + }); + } + + create( + className: string, + handler: ((value: Data) => void) | null = null, + ): void { + if (handler) this.signal[className] = { name: className, handler }; + } +} diff --git a/typescript-practice/src/ts/models/transaction.ts b/typescript-practice/src/ts/models/transaction.ts new file mode 100644 index 0000000..08dff5d --- /dev/null +++ b/typescript-practice/src/ts/models/transaction.ts @@ -0,0 +1,54 @@ +import { generateId } from 'helpers/data'; + +export default class Transaction { + private readonly _id: number; + + private _categoryName: string; + + private _date: string; + + private _note: string; + + private _amount: number; + + private _idUser: number; + + constructor( + categoryName: string, + date: string, + note: string, + amount: number, + idUser: number, + ) { + this._id = generateId(); + this._categoryName = categoryName; + this._date = date; + this._note = note; + this._amount = amount; + this._idUser = idUser; + } + + get id() { + return this._id; + } + + get categoryName() { + return this._categoryName; + } + + get date() { + return this._date; + } + + get note() { + return this._note; + } + + get amount() { + return this._amount; + } + + get idUser() { + return this._idUser; + } +} diff --git a/typescript-practice/src/ts/models/user.ts b/typescript-practice/src/ts/models/user.ts index 43f8dbf..bd30afd 100644 --- a/typescript-practice/src/ts/models/user.ts +++ b/typescript-practice/src/ts/models/user.ts @@ -1,4 +1,4 @@ -import { createIdUser } from '../helpers/data'; +import { generateId } from '../helpers/data'; export default class User { private readonly _id: number; @@ -10,7 +10,7 @@ export default class User { private _accessToken: string; constructor(email: string, password: string, accessToken?: string) { - this._id = createIdUser(); + this._id = generateId(); this._email = email; this._password = password || ''; this._accessToken = accessToken || ''; diff --git a/typescript-practice/src/ts/models/wallet.ts b/typescript-practice/src/ts/models/wallet.ts new file mode 100644 index 0000000..a2bc8b0 --- /dev/null +++ b/typescript-practice/src/ts/models/wallet.ts @@ -0,0 +1,50 @@ +import { generateId } from '../helpers/data'; + +export default class Wallet { + private readonly _id: number; + + private _walletName: string; + + private _inflow: number; + + private _outflow: number; + + private _idUser: number; + + constructor( + walletName: string, + inflow: number, + outflow: number, + idUser: number, + ) { + this._id = generateId(); + this._walletName = walletName; + this._inflow = inflow; + this._outflow = outflow; + this._idUser = idUser; + } + + get id() { + return this._id; + } + + get walletName() { + return this._walletName; + } + + get inflow() { + return this._inflow; + } + + get outflow() { + return this._outflow; + } + + get idUser() { + return this._idUser; + } + + get amountWallet() { + return this._inflow + this._outflow; + } +} diff --git a/typescript-practice/src/ts/services/commonService.ts b/typescript-practice/src/ts/services/commonService.ts index e01591c..ebbe8fc 100644 --- a/typescript-practice/src/ts/services/commonService.ts +++ b/typescript-practice/src/ts/services/commonService.ts @@ -77,7 +77,7 @@ export default class CommonService { return null; } - async getAllDataFromPath(path = this.defaultPath): Promise { + async getAllDataFromPath(path = this.defaultPath): Promise { this.connectToDb(); const results = await timeOutConnect( @@ -90,7 +90,7 @@ export default class CommonService { const tempData = data as DataObject; return convertDataObjectToModel(tempData); - }) as object[]; + }) as T; } return null; @@ -98,9 +98,9 @@ export default class CommonService { async getListDataFromProp( property: string, - value: object, + value: string, path: string = this.defaultPath, - ): Promise { + ): Promise { this.connectToDb(); const results = await timeOutConnect( @@ -114,14 +114,14 @@ export default class CommonService { const tempData = data as DataObject; return convertDataObjectToModel(tempData); - }) as object[]; + }) as T; } return null; } async deleteData( - id: string, + id: number, path = this.defaultPath, ): Promise { this.connectToDb(); diff --git a/typescript-practice/src/ts/services/firebaseService.ts b/typescript-practice/src/ts/services/firebaseService.ts index 17176a8..f6034d4 100644 --- a/typescript-practice/src/ts/services/firebaseService.ts +++ b/typescript-practice/src/ts/services/firebaseService.ts @@ -34,7 +34,7 @@ class FirebaseService { return set(ref(this._db, path), data); } - delete(id: string, path: string): Promise { + delete(id: number, path: string): Promise { return remove(ref(this._db, path + id)); } @@ -145,7 +145,7 @@ class FirebaseService { getListDataFromProp( path: string, property: string, - value: object, + value: string, ): Promise { return new Promise((resolve) => { onValue( diff --git a/typescript-practice/src/ts/services/index.ts b/typescript-practice/src/ts/services/index.ts index a9a3355..6331bee 100644 --- a/typescript-practice/src/ts/services/index.ts +++ b/typescript-practice/src/ts/services/index.ts @@ -1,9 +1,17 @@ +import TransactionService from './transactionService'; import UserService from './userService'; +import WalletService from './walletService'; export default class Service { public userService: UserService; + public walletService: WalletService; + + public transactionService: TransactionService; + constructor() { this.userService = new UserService(); + this.walletService = new WalletService(); + this.transactionService = new TransactionService(); } } diff --git a/typescript-practice/src/ts/services/transactionService.ts b/typescript-practice/src/ts/services/transactionService.ts new file mode 100644 index 0000000..c12f9ff --- /dev/null +++ b/typescript-practice/src/ts/services/transactionService.ts @@ -0,0 +1,34 @@ +import Transaction from 'models/transaction'; +import CommonService from './commonService'; + +export default class TransactionService extends CommonService { + constructor() { + super(); + + this.defaultPath = 'transactions/'; + } + + /** + * Save transaction into database + * @param {Object} transaction The wallet object need to be saved into database + */ + async saveTransaction(transaction: Transaction): Promise { + await this.save(transaction); + } + + async getListTransactionByIdUser( + idUser: number, + ): Promise { + const results = this.getListDataFromProp( + 'idUser', + idUser.toString(), + this.defaultPath, + ); + + return results || null; + } + + async deleteTransaction(idTransaction: number) { + await this.deleteData(idTransaction); + } +} diff --git a/typescript-practice/src/ts/services/userService.ts b/typescript-practice/src/ts/services/userService.ts index 6946368..3051f9d 100644 --- a/typescript-practice/src/ts/services/userService.ts +++ b/typescript-practice/src/ts/services/userService.ts @@ -109,8 +109,4 @@ export default class UserService { return result || null; } - - static clearAccessToken(): void { - LocalStorageService.remove(LOCAL_STORAGE.ACCESS_TOKEN); - } } diff --git a/typescript-practice/src/ts/services/walletService.ts b/typescript-practice/src/ts/services/walletService.ts new file mode 100644 index 0000000..dbb2f50 --- /dev/null +++ b/typescript-practice/src/ts/services/walletService.ts @@ -0,0 +1,43 @@ +import Wallet from '../models/wallet'; +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 database + */ + async saveWallet(wallet: Wallet): Promise { + 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 isValidWallet(idUser: number): Promise { + const wallet = await this.getWalletByIdUser(idUser); + + return !!wallet; + } + + /** + * 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: number): Promise { + const result = (await this.getDataFromProp( + 'idUser', + idUser.toString(), + )) as Wallet; + + return result || null; + } +} diff --git a/typescript-practice/src/ts/views/home/homeView.ts b/typescript-practice/src/ts/views/home/homeView.ts new file mode 100644 index 0000000..2e491eb --- /dev/null +++ b/typescript-practice/src/ts/views/home/homeView.ts @@ -0,0 +1,311 @@ +import { BTN_CONTENT, TypeToast } from '../../constants/config'; +import CommonView from '../commonView'; +import { clearAccessToken, formatNumber } from '../../helpers/data'; + +import WalletView from './walletView'; +import Wallet from 'models/wallet'; +import Transform from 'helpers/transform'; +import Transaction from 'models/transaction'; +import User from 'models/user'; +import { Data, TError } from 'global/types'; +import { DEFAULT_TITLE_ERROR_TOAST } from 'constants/messages/dialog'; +import { redirectToLoginPage } from 'helpers/url'; + +export default class HomeView extends CommonView { + private _tabs: NodeListOf; + + private _allContent: NodeListOf; + + private _cancelBtns: NodeListOf; + + private _saveBtns: NodeListOf; + + private _dialogs: NodeListOf; + + private _amountInputs: NodeListOf; + + private _transactionDialog: HTMLElement | null; + + private _walletView: WalletView; + + private _user: User | null = null; + + private _wallet: Wallet | null = null; + + private _getInfoUserLogin: (() => Promise) | null = null; + + private _getWalletByIdUser: + | ((idUser: number) => Promise) + | null = null; + + private _saveWallet: ((wallet: Wallet) => Promise) | null = null; + + private _saveTransaction: + | ((transaction: Transaction) => Promise) + | null = null; + + private _transform: Transform | null = null; + + constructor() { + super(); + + this._tabs = document.querySelectorAll('.app__tab-item'); + this._allContent = document.querySelectorAll('.app__content-item'); + this._cancelBtns = document.querySelectorAll('.form__cancel-btn'); + this._saveBtns = document.querySelectorAll('.form__save-btn'); + this._dialogs = document.querySelectorAll('.dialog'); + + this._amountInputs = document.querySelectorAll('.form__input-balance'); + + this._transactionDialog = document.getElementById('transactionDialog'); + + this._walletView = new WalletView(); + } + + initFunction( + getInfoUserLogin: () => Promise, + getWalletByIdUser: (idUser: number) => Promise, + saveWallet: (wallet: Wallet) => Promise, + saveTransaction: (transaction: Transaction) => Promise, + transform: Transform, + ) { + this._getInfoUserLogin = getInfoUserLogin; + this._getWalletByIdUser = getWalletByIdUser; + this._saveWallet = saveWallet; + this._saveTransaction = saveTransaction; + + this._transform = transform; + + // Init function for child view + this.initWalletViewFunction(); + } + + initWalletViewFunction() { + this._walletView.initFunction( + this._transform, + this.toggleLoaderSpinner.bind(this), + this._saveWallet, + this._saveTransaction, + this.loadData.bind(this), + this.loadEvent.bind(this), + this.showSuccessToast.bind(this), + this.showErrorToast.bind(this), + ); + } + + subscribeListenerData() { + this.subscribe(); + this._walletView.subscribe(); + } + + async loadData() { + // Send data to other class + this.sendData(); + + await this.loadWalletUser(); + } + + async loadPage() { + this.toggleLoaderSpinner(); + const user = await this._getInfoUserLogin!(); + + if (!user) { + // If user not login yet + clearAccessToken(); + window.location.replace('/login'); + } else { + // If user already login + this._user = user; + this._wallet = await this._getWalletByIdUser!(user.id); + + this.sendData(); + // Check user's wallet if have or not + if (!this._wallet) { + // Show add wallet dialog + this._walletView.showDialog(); + } else { + // Init data + await this.loadData(); + + // Load event page + this.loadEvent(); + } + } + + this.toggleLoaderSpinner(); + } + + // ---------------------LOAD DATA---------------------// + + subscribe() { + this._transform!.create('homeView', this.updateData.bind(this)); + } + + sendData() { + const data: Data = { + wallet: this._wallet!, + }; + + this._transform!.onSendSignal('homeView', data); + } + + updateData(data: Data) { + if (data.wallet) this._wallet = data.wallet; + } + + /** + * Load wallet user + */ + async loadWalletUser() { + const wallet = this._wallet + ? this._wallet + : await this._getWalletByIdUser!(this._user!.id); + const walletName = document.querySelector('.wallet__name'); + const walletPrice = document.querySelector('.wallet__price'); + const walletNameValue = wallet!.walletName; + const walletAmountValue = wallet!.amountWallet; + + const sign = walletAmountValue >= 0 ? '+' : '-'; + + this._wallet = wallet; // Make wallet into global variable + + walletName!.textContent = walletNameValue; + walletPrice!.textContent = `${sign}$ ${formatNumber( + Math.abs(walletAmountValue), + )}`; // Math.abs(walletAmountValue) to keep the value always > 0 + + // Update amount wallet into database + this._saveWallet!(this._wallet!); + } + + // ---------------------END---------------------// + + showSuccessToast(title: string, message: string) { + const typeToast = TypeToast.success; + const btnContent = BTN_CONTENT.OK; + + this.initToastContent(typeToast, title, message, btnContent); + + this.toastDialog!.showModal(); + } + + /** + * Implement error toast in site + * @param {string} content The content will show in error toast + */ + showErrorToast(error: TError | string): void { + const title = + typeof error === 'object' && error.title + ? error.title + : DEFAULT_TITLE_ERROR_TOAST; + + const content = + typeof error === 'object' && error.message + ? error.message + : (error as string); + + this.initToastContent(TypeToast.error, title, content, BTN_CONTENT.OK); + + if (this.toastDialog && this.toastBtn) { + // Show toast + this.toastDialog.showModal(); + + // Remove event for toast button + this.toastBtn.removeEventListener('click', redirectToLoginPage); + } + } + + // ------------------------------- HANDLER EVENT ------------------------------- // + + loadEvent() { + this.addCommonEventPage(); + this.handlerTabsTransfer(); + } + + /** + * Handle event when click on tabs + */ + handlerTabsTransfer() { + this._tabs.forEach((tab, index) => { + tab.addEventListener('click', (e: Event) => { + this.removeActiveTab(); + tab.classList.add('active'); + + const line = document.querySelector( + '.app__line', + ) as HTMLElement; + + const eventTarget = e.target as HTMLElement; + + line.style.width = `${eventTarget.offsetWidth}px`; + line.style.left = `${eventTarget.offsetLeft}px`; + + this._allContent.forEach((content) => { + content.classList.remove('active'); + }); + this._allContent[index].classList.add('active'); + }); + }); + } + + addCommonEventPage() { + // Add event close dialog when click outside + this._dialogs.forEach((dialog) => { + dialog.addEventListener('click', (e) => { + const dialogDimensions = dialog.getBoundingClientRect(); + const mouseEvent = e as MouseEvent; + if ( + mouseEvent.clientX < dialogDimensions.left || + mouseEvent.clientX > dialogDimensions.right || + mouseEvent.clientY < dialogDimensions.top || + mouseEvent.clientY > dialogDimensions.bottom + ) { + (dialog).close(); + } + }); + }); + + this._cancelBtns.forEach((btn) => { + btn.addEventListener('click', () => { + this.closeAllDialog(); + }); + }); + + // Prevent input =,-,e into amount input + this._amountInputs.forEach((item) => { + item.addEventListener( + 'keypress', + (e) => + ['+', '-', 'e'].includes((e).key) && + e.preventDefault(), + ); + }); + + // Prevent user input at category search + const categorySearchEl = document.querySelector( + '.category-name', + ) as Element; + categorySearchEl.addEventListener('keydown', (e) => { + e.preventDefault(); + }); + + const logoutBtn = document.querySelector('.logout-text') as Element; + logoutBtn.addEventListener('click', () => { + clearAccessToken(); + + window.location.replace('/login'); + }); + } + + closeAllDialog() { + this._dialogs.forEach((dialog) => { + (dialog).close(); + }); + } + + removeActiveTab() { + this._tabs.forEach((tab) => { + tab.classList.remove('active'); + }); + } +} diff --git a/typescript-practice/src/ts/views/home/walletView.ts b/typescript-practice/src/ts/views/home/walletView.ts new file mode 100644 index 0000000..4ebfe5e --- /dev/null +++ b/typescript-practice/src/ts/views/home/walletView.ts @@ -0,0 +1,176 @@ +import { FIRST_ADD_WALLET_NOTE } from '../constants/config'; +import Transaction from '../models/transaction'; +import Wallet from '../models/wallet'; +import * as MESSAGE from '../constants/message'; +import { renderRequiredText } from '../helpers/validateForm'; + +export default class WalletView { + constructor() { + this.walletDialog = document.getElementById('walletDialog'); + + this.addHandlerEventWalletForm(); + } + + initFunction( + transform, + toggleLoaderSpinner, + saveWallet, + saveTransaction, + loadData, + loadEvent, + showSuccessToast, + showErrorToast, + ) { + this.transform = transform; + this.toggleLoaderSpinner = toggleLoaderSpinner; + this.saveWallet = saveWallet; + this.saveTransaction = saveTransaction; + this.loadData = loadData; + this.loadEvent = loadEvent; + this.showSuccessToast = showSuccessToast; + this.showErrorToast = showErrorToast; + } + + subscribe() { + this.transform.create('walletView', this.updateData.bind(this)); + } + + sendData() { + const data = { + wallet: this.wallet, + listTransactions: this.listTransactions, + user: this.user, + }; + + this.transform.onSendSignal('walletView', data); + } + + updateData(data) { + if (data.wallet) this.wallet = data.wallet; + + if (data.listTransactions) this.listTransaction = data.listTransactions; + + if (data.listCategory) this.listCategory = data.listCategory; + + if (data.user) this.user = data.user; + } + + showDialog() { + this.walletDialog.showModal(); + } + + addHandlerEventWalletForm() { + this.walletDialog.addEventListener('submit', (e) => { + e.preventDefault(); + + this.clearErrorStyleWalletDialog(); + this.submitWalletForm(); + }); + + this.walletDialog.addEventListener('input', (e) => { + const bodyDialog = e.target.closest('.dialog__body'); + + 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() { + try { + // Wallet info + const { walletForm } = document.forms; + const form = new FormData(walletForm); + const walletName = form.get('walletName'); + const amount = form.get('amount'); + + if (this.validateWalletDialog(walletName, amount)) { + this.walletDialog.close(); + this.toggleLoaderSpinner(); + + this.wallet = new Wallet({ + walletName, + amount: +amount, + idUser: this.user.id, + inflow: +amount, + }); + + this.sendData(); + + await this.saveWallet(this.wallet); + // Transaction info + const transaction = new Transaction({ + categoryName: 'Income', + date: new Date().toISOString().slice(0, 10), + note: FIRST_ADD_WALLET_NOTE, + amount: +amount, + idUser: this.user.id, + }); + await this.saveTransaction(transaction); + // Load data and event + await this.loadTransactionData(); + await this.loadData(); + this.loadEvent(); + this.showSuccessToast( + MESSAGE.ADD_WALLET_SUCCESS, + MESSAGE.DEFAULT_MESSAGE, + ); + await this.loadData(); // Load data from database into page + + this.toggleLoaderSpinner(); + } + } catch (error) { + // Show toast error + this.showErrorToast(error); + this.toggleLoaderSpinner(); + } + } + + 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; + } + + // eslint-disable-next-line class-methods-use-this + 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'); + + if (walletName.length >= 3 && amount >= 1) { + saveBtn.classList.add('active'); + } else { + saveBtn.classList.remove('active'); + } + } +} diff --git a/typescript-practice/src/ts/views/index.ts b/typescript-practice/src/ts/views/index.ts index c3b08a6..8af6861 100644 --- a/typescript-practice/src/ts/views/index.ts +++ b/typescript-practice/src/ts/views/index.ts @@ -2,12 +2,15 @@ import { getSubdirectoryURL } from 'helpers/url'; import LoginView from './loginView'; import RegisterView from './registerView'; import { URL } from 'constants/config'; +import HomeView from './home/homeView'; export default class View { public registerView: RegisterView | null = null; public loginView: LoginView | null = null; + public homeView: HomeView | null = null; + constructor() { switch (getSubdirectoryURL()) { case URL.LOGIN: @@ -16,6 +19,8 @@ export default class View { case URL.REGISTER: this.registerView = new RegisterView(); break; + case URL.HOME: + this.homeView = new HomeView(); default: } }