diff --git a/typescript-practice/src/pages/index.html b/typescript-practice/src/pages/index.html
index bd438bd..810069e 100644
--- a/typescript-practice/src/pages/index.html
+++ b/typescript-practice/src/pages/index.html
@@ -250,7 +250,7 @@
diff --git a/typescript-practice/src/styles/pages/_index.scss b/typescript-practice/src/styles/pages/_index.scss
index 3e3b2f8..0ea8664 100644
--- a/typescript-practice/src/styles/pages/_index.scss
+++ b/typescript-practice/src/styles/pages/_index.scss
@@ -104,6 +104,8 @@
&__line {
position: absolute;
top: 66px;
+ left: 152px;
+ width: 116px;
height: 2px;
background-color: $primary-color;
border-radius: 10px;
diff --git a/typescript-practice/src/ts/constants/config.ts b/typescript-practice/src/ts/constants/config.ts
index d631bcd..dce8da0 100644
--- a/typescript-practice/src/ts/constants/config.ts
+++ b/typescript-practice/src/ts/constants/config.ts
@@ -11,14 +11,15 @@ export const LOCAL_STORAGE = {
ACCESS_TOKEN: 'accessToken',
};
-export enum TypeToast {
- success = 'success',
- error = 'error',
-}
-export enum MarkIcon {
- success = 'success',
- error = 'error',
-}
+export const TypeToast = {
+ success: 'success',
+ error: 'error',
+};
+
+export const MarkIcon = {
+ success: 'success',
+ error: 'error',
+};
export const REGEX = {
PASSWORD:
diff --git a/typescript-practice/src/ts/constants/messages/dialog.ts b/typescript-practice/src/ts/constants/messages.ts
similarity index 53%
rename from typescript-practice/src/ts/constants/messages/dialog.ts
rename to typescript-practice/src/ts/constants/messages.ts
index 5b5de7c..a3c69df 100644
--- a/typescript-practice/src/ts/constants/messages/dialog.ts
+++ b/typescript-practice/src/ts/constants/messages.ts
@@ -1,3 +1,17 @@
+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_CREDENTIAL = {
+ title: 'Error Credential',
+ message: 'Email or password not match! Please try again!',
+};
+
+export const INVALID_EMAIL_FORMAT = `The email is not correct!`;
+
+export const REQUIRED_MESSAGE = (field: string) => `The ${field} is required!`;
+
export const ERROR_MESSAGE_DEFAULT = ['Something went wrong!'];
export const TIME_OUT_ERROR = 'Connection time out! Please try again!';
diff --git a/typescript-practice/src/ts/constants/messages/form.ts b/typescript-practice/src/ts/constants/messages/form.ts
deleted file mode 100644
index 4491ead..0000000
--- a/typescript-practice/src/ts/constants/messages/form.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-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_CREDENTIAL = {
- title: 'Error Credential',
- message: 'Email or password not match! Please try again!',
-};
-
-export const INVALID_EMAIL_FORMAT = `The email is not correct!`;
-
-export const REQUIRED_MESSAGE = (field: string) => `The ${field} is required!`;
diff --git a/typescript-practice/src/ts/controllers/homeController.ts b/typescript-practice/src/ts/controllers/homeController.ts
index 8388e76..f6c6a65 100644
--- a/typescript-practice/src/ts/controllers/homeController.ts
+++ b/typescript-practice/src/ts/controllers/homeController.ts
@@ -1,10 +1,10 @@
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';
import Category from 'models/category';
+import { IHomeFunc } from 'global/types';
export default class HomeController {
public homeView: HomeView | null = null;
@@ -47,16 +47,17 @@ export default class HomeController {
init() {
if (this.homeView) {
- this.homeView.initFunction(
- this.handlerGetInfoUserLogin.bind(this),
- this.handlerGetWalletByIdUser.bind(this),
- this.handlerGetAllCategory.bind(this),
- this.handlerGetAllTransactions.bind(this),
- this.handlerSaveWallet.bind(this),
- this.handlerSaveTransaction.bind(this),
- this.handlerDeleteTransaction.bind(this),
- new Transform(),
- );
+ const func: IHomeFunc = {
+ getInfoUserLogin: this.handlerGetInfoUserLogin.bind(this),
+ getWalletByIdUser: this.handlerGetWalletByIdUser.bind(this),
+ getAllCategory: this.handlerGetAllCategory.bind(this),
+ getAllTransactions: this.handlerGetAllTransactions.bind(this),
+ saveWallet: this.handlerSaveWallet.bind(this),
+ saveTransaction: this.handlerSaveTransaction.bind(this),
+ deleteTransaction: this.handlerDeleteTransaction.bind(this),
+ };
+
+ this.homeView.initFunction(func);
this.homeView.loadPage();
diff --git a/typescript-practice/src/ts/global/types.ts b/typescript-practice/src/ts/global/types.ts
index 98350cb..e4ef3c3 100644
--- a/typescript-practice/src/ts/global/types.ts
+++ b/typescript-practice/src/ts/global/types.ts
@@ -19,11 +19,13 @@ export class DataObject
{
}
}
-export interface TError {
+export interface IError {
title: string;
message: string;
}
+export type TError = string | IError;
+
export class CustomError extends Error {
constructor(
public title: string,
@@ -33,13 +35,6 @@ export class CustomError extends Error {
}
}
-export type TSignal = {
- [key: string]: {
- name: string;
- handler: (value: Data) => void;
- };
-};
-
export interface Data {
wallet?: Wallet;
listTransactions?: Transaction[];
@@ -54,3 +49,50 @@ export interface ItemTransaction {
note: string;
amount: number;
}
+
+export type Nullable = T | null;
+export type PromiseVoid = () => Promise;
+export type VoidFunc = () => void;
+export type PromiseOrNull = () => Promise;
+
+export interface IHomeFunc {
+ getInfoUserLogin?: PromiseOrNull;
+ getWalletByIdUser?: (idUser: string) => Promise;
+ getAllCategory?: PromiseOrNull;
+ getAllTransactions?: (idUser: string) => Promise;
+ saveWallet?: (wallet: Wallet) => Promise;
+ saveTransaction?: (transaction: Transaction) => Promise;
+ deleteTransaction?: (idTransaction: string) => Promise;
+}
+
+export interface IBudgetViewFunc {
+ showErrorToast: (error: TError) => void;
+ showSuccessToast: (title: string, message: string) => void;
+ toggleLoaderSpinner: VoidFunc;
+ saveTransaction: Nullable<(transaction: Transaction) => Promise>;
+ loadTransactionData: PromiseVoid;
+ updateAmountWallet: PromiseVoid;
+ loadData: PromiseVoid;
+}
+
+export interface ITransactionViewFunc {
+ toggleLoaderSpinner: VoidFunc;
+ deleteTransaction: (idTransaction: string) => Promise;
+ loadTransactionData: PromiseVoid;
+ updateAmountWallet: PromiseVoid;
+ loadData: PromiseVoid;
+ showSuccessToast: (title: string, message: string) => void;
+ showErrorToast: (error: TError) => void;
+ saveTransaction: (transaction: Transaction) => Promise;
+}
+
+export interface IWalletViewFunc {
+ toggleLoaderSpinner: () => void;
+ saveWallet: ((wallet: Wallet) => Promise) | null;
+ saveTransaction: ((transaction: Transaction) => Promise) | null;
+ loadTransactionData: () => Promise;
+ loadData: () => Promise;
+ loadEvent: () => void;
+ showSuccessToast: (title: string, message: string) => void;
+ showErrorToast: (error: TError) => void;
+}
diff --git a/typescript-practice/src/ts/helpers/connect.ts b/typescript-practice/src/ts/helpers/connect.ts
index 39daafe..53d62e9 100644
--- a/typescript-practice/src/ts/helpers/connect.ts
+++ b/typescript-practice/src/ts/helpers/connect.ts
@@ -1,4 +1,4 @@
-import { TIME_OUT_ERROR } from '../constants/messages/dialog';
+import { TIME_OUT_ERROR } from '../constants/messages';
import { TIME_OUT_SEC } from '../constants/config';
import FirebaseService from '../services/firebaseService';
diff --git a/typescript-practice/src/ts/helpers/transform.ts b/typescript-practice/src/ts/helpers/evDataTrigger.ts
similarity index 65%
rename from typescript-practice/src/ts/helpers/transform.ts
rename to typescript-practice/src/ts/helpers/evDataTrigger.ts
index cadc84c..00178f7 100644
--- a/typescript-practice/src/ts/helpers/transform.ts
+++ b/typescript-practice/src/ts/helpers/evDataTrigger.ts
@@ -1,12 +1,25 @@
-import { TSignal, Data } from 'global/types';
+import { Data } from 'global/types';
+
+type TSignal = {
+ [key: string]: {
+ name: string;
+ handler: (value: Data) => void;
+ };
+};
+
+export default class EventDataTrigger {
+ private static _instance: EventDataTrigger;
-export default class Transform {
public signal: TSignal;
constructor() {
this.signal = {};
}
+ public static get Instance() {
+ return this._instance || (this._instance = new this());
+ }
+
onSendSignal(fromClass: string, value: Data) {
Object.keys(this.signal).forEach((key) => {
const item = this.signal[key as keyof TSignal];
diff --git a/typescript-practice/src/ts/helpers/url.ts b/typescript-practice/src/ts/helpers/url.ts
index bf01a04..40e8f06 100644
--- a/typescript-practice/src/ts/helpers/url.ts
+++ b/typescript-practice/src/ts/helpers/url.ts
@@ -1,8 +1,8 @@
-export const redirectToLoginPage = (): void => {
+export const redirectToLoginPage = () => {
window.location.replace('/login');
};
-export const getSubdirectoryURL = () => {
+export const getSubdirectoryURL = (): string => {
const url = window.location.href;
const parts = url.split('/'); // Results: ['http:', '', 'example.com', '']
const subDirectory = parts[3]; // Get subdirectory url only
diff --git a/typescript-practice/src/ts/helpers/validatorForm.ts b/typescript-practice/src/ts/helpers/validatorForm.ts
index 199f524..9cf70a5 100644
--- a/typescript-practice/src/ts/helpers/validatorForm.ts
+++ b/typescript-practice/src/ts/helpers/validatorForm.ts
@@ -1,5 +1,5 @@
import { REGEX } from '../constants/config';
-import { REQUIRED_MESSAGE } from '../constants/messages/form';
+import { REQUIRED_MESSAGE } from '../constants/messages';
/**
* Validate password
@@ -21,7 +21,7 @@ export const compare2Password = (
return password === passwordConfirm;
};
-export const renderRequiredText = (field: string, element: Element): void => {
+export const renderRequiredText = (field: string, element: Element) => {
const markup: string = `
${REQUIRED_MESSAGE(field)}
`;
diff --git a/typescript-practice/src/ts/models/category.ts b/typescript-practice/src/ts/models/category.ts
index 71988bb..c1c10cc 100644
--- a/typescript-practice/src/ts/models/category.ts
+++ b/typescript-practice/src/ts/models/category.ts
@@ -1,11 +1,9 @@
export default class Category {
- readonly id: string;
-
- url: string;
-
- name: string;
-
- constructor(id: string, url: string, name: string) {
+ constructor(
+ public id: string,
+ public url: string,
+ public name: string,
+ ) {
this.id = id;
this.url = url;
this.name = name;
diff --git a/typescript-practice/src/ts/models/user.ts b/typescript-practice/src/ts/models/user.ts
index 9b2fa4c..e71f324 100644
--- a/typescript-practice/src/ts/models/user.ts
+++ b/typescript-practice/src/ts/models/user.ts
@@ -1,16 +1,13 @@
import { generateId } from '../helpers/data';
export default class User {
- id: string;
-
- email: string;
-
- password: string;
-
- accessToken: string;
-
- constructor(email: string, password: string, accessToken?: string) {
- this.id = generateId();
+ constructor(
+ public id: string,
+ public email: string,
+ public password: string,
+ public accessToken?: string,
+ ) {
+ this.id = id ? 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
index 7e0e1a9..548da74 100644
--- a/typescript-practice/src/ts/models/wallet.ts
+++ b/typescript-practice/src/ts/models/wallet.ts
@@ -1,23 +1,14 @@
import { generateId } from '../helpers/data';
export default class Wallet {
- id: string;
-
- walletName: string;
-
- inflow: number;
-
- outflow: number;
-
- idUser: string;
-
constructor(
- walletName: string,
- inflow: number,
- outflow: number,
- idUser: string,
+ public id: string,
+ public walletName: string,
+ public inflow: number,
+ public outflow: number,
+ public idUser: string,
) {
- this.id = generateId();
+ this.id = id ? id : generateId();
this.walletName = walletName;
this.inflow = inflow;
this.outflow = outflow;
diff --git a/typescript-practice/src/ts/services/localStorageService.ts b/typescript-practice/src/ts/services/localStorageService.ts
index 5786cd5..5339fb3 100644
--- a/typescript-practice/src/ts/services/localStorageService.ts
+++ b/typescript-practice/src/ts/services/localStorageService.ts
@@ -5,7 +5,7 @@ class LocalStorageService {
this.localStorage = localStorage;
}
- add(key: string, value: string): void {
+ add(key: string, value: string) {
this.localStorage.setItem(key, value);
}
@@ -13,11 +13,11 @@ class LocalStorageService {
return this.localStorage.getItem(key);
}
- remove(key: string): void {
+ remove(key: string) {
this.localStorage.removeItem(key);
}
- clear(): void {
+ clear() {
this.localStorage.clear();
}
}
diff --git a/typescript-practice/src/ts/services/transactionService.ts b/typescript-practice/src/ts/services/transactionService.ts
index bb53cf9..54d8550 100644
--- a/typescript-practice/src/ts/services/transactionService.ts
+++ b/typescript-practice/src/ts/services/transactionService.ts
@@ -28,7 +28,7 @@ export default class TransactionService extends CommonService {
return results || null;
}
- async deleteTransaction(idTransaction: string) {
+ async deleteTransaction(idTransaction: string): Promise {
await this.deleteData(idTransaction);
}
}
diff --git a/typescript-practice/src/ts/views/authenticationView.ts b/typescript-practice/src/ts/views/authenticationView.ts
index a045dcc..77089c7 100644
--- a/typescript-practice/src/ts/views/authenticationView.ts
+++ b/typescript-practice/src/ts/views/authenticationView.ts
@@ -1,27 +1,28 @@
import CommonView from './commonView';
-import { ERROR_MESSAGE_DEFAULT } from '../constants/messages/dialog';
import {
INVALID_EMAIL_FORMAT,
PASSWORD_NOT_MATCH,
PASSWORD_NOT_STRONG,
-} from 'constants/messages/form';
+ ERROR_MESSAGE_DEFAULT,
+} from 'constants/messages';
import {
compare2Password,
isValidPassword,
isValidateEmail,
renderRequiredText,
} from '../helpers/validatorForm';
+import { Nullable } from 'global/types';
export default class AuthenticationView extends CommonView {
- public formEl: HTMLBodyElement | null;
+ public formEl: Nullable;
- public emailEl: HTMLBodyElement | null;
+ public emailEl: Nullable;
public messageDefault: string[];
- public inputPasswordEl: HTMLBodyElement | null;
+ public inputPasswordEl: Nullable;
- public inputPasswordConfirmEl: HTMLBodyElement | null;
+ public inputPasswordConfirmEl: Nullable;
public listError: string[];
@@ -70,7 +71,7 @@ export default class AuthenticationView extends CommonView {
return false;
}
- validatePasswordConfirm(password: string, passwordConfirm: string) {
+ validatePasswordConfirm(password: string, passwordConfirm: string): boolean {
if (passwordConfirm) {
if (!compare2Password(password, passwordConfirm)) {
this.listError.push(PASSWORD_NOT_MATCH);
@@ -120,7 +121,7 @@ export default class AuthenticationView extends CommonView {
/**
* Add event listener for input field at form
*/
- addHandlerInputFormChange(): void {
+ addHandlerInputFormChange() {
if (this.formEl)
this.formEl.addEventListener('input', () => {
this.clearErrorMessage();
@@ -131,7 +132,7 @@ export default class AuthenticationView extends CommonView {
* Show error message with error style input password.
* @param {string} message The error message you want show in form.
*/
- showError(message: string[]): void {
+ showError(message: string[]) {
this.renderError(message);
}
@@ -139,7 +140,7 @@ export default class AuthenticationView extends CommonView {
* Show error message in form
* @param {string} message The message will show in form
*/
- renderError(messages = this.messageDefault): void {
+ renderError(messages = this.messageDefault) {
if (messages.length > 0) {
const messageItemMarkup = messages
.map((message) => `${message}`)
diff --git a/typescript-practice/src/ts/views/commonView.ts b/typescript-practice/src/ts/views/commonView.ts
index f8ea0eb..32d2e71 100644
--- a/typescript-practice/src/ts/views/commonView.ts
+++ b/typescript-practice/src/ts/views/commonView.ts
@@ -1,17 +1,18 @@
+import { Nullable } from 'global/types';
import { MarkIcon, TypeToast } from '../constants/config';
export default class CommonView {
- public toastDialog: HTMLDialogElement | null = null;
+ public toastDialog: Nullable = null;
- public toastIcon: HTMLBodyElement | null = null;
+ public toastIcon: Nullable = null;
- public toastBtn: HTMLBodyElement | null = null;
+ public toastBtn: Nullable = null;
- public toastTitle: HTMLBodyElement | null = null;
+ public toastTitle: Nullable = null;
- public toastContent: HTMLBodyElement | null = null;
+ public toastContent: Nullable = null;
- public spinner: HTMLBodyElement | null = null;
+ public spinner: Nullable = null;
constructor() {
this.toastDialog = document.querySelector('.dialog .toast');
@@ -22,7 +23,7 @@ export default class CommonView {
/**
* Implement toast in site
*/
- initToast(): void {
+ initToast() {
const markup = `