mirror of
https://github.com/Nezumi-2711/javascript-training.git
synced 2026-09-22 20:01:31 +00:00
Change validator style
This commit is contained in:
@@ -23,14 +23,16 @@ export const DEFAULT_CATEGORY = {
|
|||||||
INCOME: 'Income',
|
INCOME: 'Income',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const REMOVE_CATEGORY = ['Income'];
|
||||||
|
|
||||||
export const DAY = [
|
export const DAY = [
|
||||||
|
'Sunday',
|
||||||
'Monday',
|
'Monday',
|
||||||
'Tuesday',
|
'Tuesday',
|
||||||
'Wednesday',
|
'Wednesday',
|
||||||
'Thursday',
|
'Thursday',
|
||||||
'Friday',
|
'Friday',
|
||||||
'Saturday',
|
'Saturday',
|
||||||
'Sunday',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export const MONTH = [
|
export const MONTH = [
|
||||||
@@ -54,4 +56,6 @@ export const MARK_ICON = { success: 'check', error: 'error' };
|
|||||||
export const REGEX = {
|
export const REGEX = {
|
||||||
PASSWORD:
|
PASSWORD:
|
||||||
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/,
|
/^(?=.*[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,}))$/,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 =
|
export const PASSWORD_NOT_STRONG =
|
||||||
'Password must at least one uppercase, one lowercase letter, one number and one special character!';
|
'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!';
|
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 DEFAULT_MESSAGE = 'Press OK to continue!';
|
||||||
|
|
||||||
export const ADD_TRANSACTION_SUCCESS = 'Add success!';
|
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!`;
|
||||||
|
|||||||
@@ -10,10 +10,6 @@ export default class HomeController {
|
|||||||
return this.service.userService.getInfoUserLogin();
|
return this.service.userService.getInfoUserLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerCheckWalletValid(idUser) {
|
|
||||||
return this.service.walletService.isValidWallet(idUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
handlerGetWalletUser(idUser) {
|
handlerGetWalletUser(idUser) {
|
||||||
return this.service.walletService.getWalletByIdUser(idUser);
|
return this.service.walletService.getWalletByIdUser(idUser);
|
||||||
}
|
}
|
||||||
@@ -46,7 +42,6 @@ export default class HomeController {
|
|||||||
if (this.homeView) {
|
if (this.homeView) {
|
||||||
this.homeView.initFunction(
|
this.homeView.initFunction(
|
||||||
this.handlerGetInfoUserLogin.bind(this),
|
this.handlerGetInfoUserLogin.bind(this),
|
||||||
this.handlerCheckWalletValid.bind(this),
|
|
||||||
this.handlerGetWalletUser.bind(this),
|
this.handlerGetWalletUser.bind(this),
|
||||||
this.handlerGetAllCategory.bind(this),
|
this.handlerGetAllCategory.bind(this),
|
||||||
this.handlerGetAllTransactions.bind(this),
|
this.handlerGetAllTransactions.bind(this),
|
||||||
|
|||||||
@@ -7,10 +7,18 @@ import FirebaseService from '../services/firebaseService';
|
|||||||
* @param {string} password Password input
|
* @param {string} password Password input
|
||||||
* @returns {boolean} Return true if validate password success, otherwise return false
|
* @returns {boolean} Return true if validate password success, otherwise return false
|
||||||
*/
|
*/
|
||||||
export const isValidatePassword = (password) => {
|
export const isValidPassword = (password) => {
|
||||||
return REGEX.PASSWORD.test(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
|
* A waiting function with s second
|
||||||
* @param {number} s The time will be waiting
|
* @param {number} s The time will be waiting
|
||||||
@@ -85,7 +93,7 @@ export const formatNumber = (number) => {
|
|||||||
export const changeDateFormat = (oldFormatDate) => {
|
export const changeDateFormat = (oldFormatDate) => {
|
||||||
const tempDate = new Date(oldFormatDate);
|
const tempDate = new Date(oldFormatDate);
|
||||||
|
|
||||||
const day = DAY[tempDate.getDay() - 1];
|
const day = DAY[tempDate.getDay()];
|
||||||
const date = tempDate.getDate();
|
const date = tempDate.getDate();
|
||||||
const month = MONTH[tempDate.getMonth()];
|
const month = MONTH[tempDate.getMonth()];
|
||||||
const year = tempDate.getFullYear();
|
const year = tempDate.getFullYear();
|
||||||
@@ -105,9 +113,7 @@ export const createTransactionDetailObject = (category, transactions) => {
|
|||||||
return amount;
|
return amount;
|
||||||
};
|
};
|
||||||
const listTransaction = () => {
|
const listTransaction = () => {
|
||||||
const results = [];
|
const results = transactions.map((transaction) => {
|
||||||
|
|
||||||
transactions.forEach((transaction) => {
|
|
||||||
const dateParts = changeDateFormat(transaction.date).split(','); // ['Monday', '14', 'September', '2023']
|
const dateParts = changeDateFormat(transaction.date).split(','); // ['Monday', '14', 'September', '2023']
|
||||||
const day = dateParts[1];
|
const day = dateParts[1];
|
||||||
const fullDateString = `${dateParts[0]}, ${dateParts[2]} ${dateParts[3]}`;
|
const fullDateString = `${dateParts[0]}, ${dateParts[2]} ${dateParts[3]}`;
|
||||||
@@ -119,7 +125,7 @@ export const createTransactionDetailObject = (category, transactions) => {
|
|||||||
amount: transaction.amount,
|
amount: transaction.amount,
|
||||||
};
|
};
|
||||||
|
|
||||||
results.push(tempData);
|
return tempData;
|
||||||
});
|
});
|
||||||
|
|
||||||
results.sort((a, b) => parseInt(b.id, 10) - parseInt(a.id, 10));
|
results.sort((a, b) => parseInt(b.id, 10) - parseInt(a.id, 10));
|
||||||
@@ -153,3 +159,15 @@ export const getAllTransactionByCategoryName = (categoryName, transactions) => {
|
|||||||
|
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const renderRequiredText = (field, element) => {
|
||||||
|
const markup = `
|
||||||
|
<p class="error-text">${MESSAGE.REQUIRED_MESSAGE(field)}</p>
|
||||||
|
`;
|
||||||
|
|
||||||
|
element.insertAdjacentHTML('afterend', markup);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const redirectToLoginPage = () => {
|
||||||
|
window.location.replace('/login');
|
||||||
|
};
|
||||||
|
|||||||
@@ -10,14 +10,11 @@ export default class CategoryService extends CommonService {
|
|||||||
|
|
||||||
async getAllCategory() {
|
async getAllCategory() {
|
||||||
const data = await this.getAllDataFromPath(this.defaultPath);
|
const data = await this.getAllDataFromPath(this.defaultPath);
|
||||||
const listCategory = [];
|
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
data.forEach((category) => {
|
return data.reverse().map((category) => {
|
||||||
listCategory.unshift(new Category(category));
|
return new Category(category);
|
||||||
});
|
});
|
||||||
|
|
||||||
return listCategory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -69,15 +69,12 @@ export default class CommonService {
|
|||||||
const results = await timeOutConnect(
|
const results = await timeOutConnect(
|
||||||
this.firebaseService.getAllDataFromPath(path),
|
this.firebaseService.getAllDataFromPath(path),
|
||||||
);
|
);
|
||||||
const listData = [];
|
|
||||||
|
|
||||||
if (results) {
|
if (results) {
|
||||||
// Convert format object
|
// Convert format object
|
||||||
results.forEach((data) => {
|
return results.map((data) => {
|
||||||
listData.push(convertDataObjectToModel(data));
|
return convertDataObjectToModel(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
return listData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -89,15 +86,12 @@ export default class CommonService {
|
|||||||
const results = await timeOutConnect(
|
const results = await timeOutConnect(
|
||||||
this.firebaseService.getListDataFromProp(path, property, value),
|
this.firebaseService.getListDataFromProp(path, property, value),
|
||||||
);
|
);
|
||||||
const listData = [];
|
|
||||||
|
|
||||||
if (results) {
|
if (results) {
|
||||||
// Convert format object
|
// Convert format object
|
||||||
results.forEach((data) => {
|
|
||||||
listData.push(convertDataObjectToModel(data));
|
|
||||||
});
|
|
||||||
|
|
||||||
return listData;
|
return results.map((data) => {
|
||||||
|
return convertDataObjectToModel(data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -22,11 +22,7 @@ export default class TransactionService extends CommonService {
|
|||||||
this.defaultPath,
|
this.defaultPath,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (results) {
|
return results || null;
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteTransaction(idTransaction) {
|
async deleteTransaction(idTransaction) {
|
||||||
|
|||||||
@@ -26,11 +26,7 @@ export default class UserService extends CommonService {
|
|||||||
async isValidUser(email) {
|
async isValidUser(email) {
|
||||||
const userExist = await this.getUserByEmail(email);
|
const userExist = await this.getUserByEmail(email);
|
||||||
|
|
||||||
if (userExist) {
|
return !!userExist;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,11 +37,7 @@ export default class UserService extends CommonService {
|
|||||||
async getUserByEmail(email) {
|
async getUserByEmail(email) {
|
||||||
const result = await this.getDataFromProp('email', email);
|
const result = await this.getDataFromProp('email', email);
|
||||||
|
|
||||||
if (result) {
|
return result || null;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,11 +109,7 @@ export default class UserService extends CommonService {
|
|||||||
async getUserByToken(accessToken) {
|
async getUserByToken(accessToken) {
|
||||||
const result = await this.getDataFromProp('accessToken', accessToken);
|
const result = await this.getDataFromProp('accessToken', accessToken);
|
||||||
|
|
||||||
if (result) {
|
return result || null;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static clearAccessToken() {
|
static clearAccessToken() {
|
||||||
|
|||||||
@@ -23,11 +23,7 @@ export default class WalletService extends CommonService {
|
|||||||
async isValidWallet(idUser) {
|
async isValidWallet(idUser) {
|
||||||
const wallet = await this.getWalletByIdUser(idUser);
|
const wallet = await this.getWalletByIdUser(idUser);
|
||||||
|
|
||||||
if (wallet) {
|
return !!wallet;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,10 +34,6 @@ export default class WalletService extends CommonService {
|
|||||||
async getWalletByIdUser(idUser) {
|
async getWalletByIdUser(idUser) {
|
||||||
const result = await this.getDataFromProp('idUser', idUser);
|
const result = await this.getDataFromProp('idUser', idUser);
|
||||||
|
|
||||||
if (result) {
|
return result || null;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) => `<li>${message}</li>`)
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
const markup = `
|
||||||
|
<ul class="form__error-message">
|
||||||
|
${messageItemMarkup}
|
||||||
|
</ul>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector('.form__title')
|
||||||
|
.insertAdjacentHTML('afterend', markup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 = `
|
|
||||||
<p class="form__error-message">${message}</p>
|
|
||||||
`;
|
|
||||||
|
|
||||||
document
|
|
||||||
.querySelector('.form__title')
|
|
||||||
.insertAdjacentHTML('afterend', markup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
BTN_CONTENT,
|
BTN_CONTENT,
|
||||||
DEFAULT_CATEGORY,
|
DEFAULT_CATEGORY,
|
||||||
FIRST_ADD_WALLET_NOTE,
|
FIRST_ADD_WALLET_NOTE,
|
||||||
|
REMOVE_CATEGORY,
|
||||||
} from '../constants/config';
|
} from '../constants/config';
|
||||||
import * as MESSAGE from '../constants/message';
|
import * as MESSAGE from '../constants/message';
|
||||||
import CommonView from './commonView';
|
import CommonView from './commonView';
|
||||||
@@ -14,6 +15,7 @@ import {
|
|||||||
formatNumber,
|
formatNumber,
|
||||||
getAllCategoryNameInTransactions,
|
getAllCategoryNameInTransactions,
|
||||||
getAllTransactionByCategoryName,
|
getAllTransactionByCategoryName,
|
||||||
|
renderRequiredText,
|
||||||
} from '../helpers/helpers';
|
} from '../helpers/helpers';
|
||||||
import defaultCategoryIcon from '../../assets/images/question-icon.svg';
|
import defaultCategoryIcon from '../../assets/images/question-icon.svg';
|
||||||
|
|
||||||
@@ -44,7 +46,6 @@ export default class HomeView extends CommonView {
|
|||||||
|
|
||||||
initFunction(
|
initFunction(
|
||||||
getInfoUserLogin,
|
getInfoUserLogin,
|
||||||
isValidWallet,
|
|
||||||
getWalletByIdUser,
|
getWalletByIdUser,
|
||||||
getAllCategory,
|
getAllCategory,
|
||||||
getAllTransactions,
|
getAllTransactions,
|
||||||
@@ -54,7 +55,6 @@ export default class HomeView extends CommonView {
|
|||||||
deleteTransaction,
|
deleteTransaction,
|
||||||
) {
|
) {
|
||||||
this.getInfoUserLogin = getInfoUserLogin;
|
this.getInfoUserLogin = getInfoUserLogin;
|
||||||
this.isValidWallet = isValidWallet;
|
|
||||||
this.getWalletByIdUser = getWalletByIdUser;
|
this.getWalletByIdUser = getWalletByIdUser;
|
||||||
this.getAllCategory = getAllCategory;
|
this.getAllCategory = getAllCategory;
|
||||||
this.getAllTransactions = getAllTransactions;
|
this.getAllTransactions = getAllTransactions;
|
||||||
@@ -75,14 +75,15 @@ export default class HomeView extends CommonView {
|
|||||||
window.location.replace('/login');
|
window.location.replace('/login');
|
||||||
} else {
|
} else {
|
||||||
this.user = user;
|
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
|
// Check user's wallet if have or not
|
||||||
if (!wallet) {
|
if (!this.wallet) {
|
||||||
// Show add wallet dialog
|
// Show add wallet dialog
|
||||||
this.walletDialog.showModal();
|
this.walletDialog.showModal();
|
||||||
} else {
|
} else {
|
||||||
// Init data
|
// Init data
|
||||||
|
await this.loadTransactionData();
|
||||||
await this.loadData();
|
await this.loadData();
|
||||||
|
|
||||||
// Load event page
|
// Load event page
|
||||||
@@ -95,7 +96,6 @@ export default class HomeView extends CommonView {
|
|||||||
|
|
||||||
async loadData() {
|
async loadData() {
|
||||||
await this.loadWalletUser();
|
await this.loadWalletUser();
|
||||||
await this.loadTransactionData();
|
|
||||||
this.loadSummaryTab();
|
this.loadSummaryTab();
|
||||||
await this.loadTransactionTab();
|
await this.loadTransactionTab();
|
||||||
}
|
}
|
||||||
@@ -126,17 +126,26 @@ export default class HomeView extends CommonView {
|
|||||||
this.saveWallet(this.wallet);
|
this.saveWallet(this.wallet);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateAmountWallet(amount) {
|
async updateAmountWallet() {
|
||||||
if (amount >= 0) {
|
let inflow = 0;
|
||||||
this.wallet.inflow += amount;
|
let outflow = 0;
|
||||||
|
|
||||||
|
// Init data first
|
||||||
|
this.transactionDetails = this.loadTransactionDetailsData();
|
||||||
|
|
||||||
|
this.transactionDetails.forEach((transaction) => {
|
||||||
|
if (transaction.totalAmount >= 0) {
|
||||||
|
inflow += transaction.totalAmount;
|
||||||
} else {
|
} else {
|
||||||
this.wallet.outflow += amount;
|
outflow -= transaction.totalAmount;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reassign value for wallet user;
|
||||||
|
this.wallet.inflow = inflow;
|
||||||
|
this.wallet.outflow = -outflow;
|
||||||
|
|
||||||
await this.saveWallet(this.wallet);
|
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
|
* @param {function} getAllCategory Get all category function
|
||||||
*/
|
*/
|
||||||
async loadCategory() {
|
async loadCategory() {
|
||||||
|
if (!this.listCategory) {
|
||||||
this.listCategory = await this.getAllCategory();
|
this.listCategory = await this.getAllCategory();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.listCategory) {
|
if (this.listCategory) {
|
||||||
this.renderCategoryItem();
|
this.renderCategoryList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,15 +187,16 @@ export default class HomeView extends CommonView {
|
|||||||
await this.loadCategory();
|
await this.loadCategory();
|
||||||
|
|
||||||
// Init data first
|
// Init data first
|
||||||
const transactionDetails = this.loadTransactionDetailsData();
|
this.transactionDetails = this.loadTransactionDetailsData();
|
||||||
|
|
||||||
const transactionEl = document.querySelector('.transaction');
|
const transactionEl = document.querySelector('.transaction');
|
||||||
const listTransactionDetailEl =
|
const listTransactionDetailEl =
|
||||||
transactionEl.querySelector('.transaction__list');
|
transactionEl.querySelector('.transaction__list');
|
||||||
|
|
||||||
const markup = [];
|
const markup = [];
|
||||||
|
|
||||||
if (transactionDetails) {
|
if (this.transactionDetails) {
|
||||||
transactionDetails.forEach((transactionDetail) => {
|
this.transactionDetails.forEach((transactionDetail) => {
|
||||||
markup.push(this.transactionDetailMarkup(transactionDetail));
|
markup.push(this.transactionDetailMarkup(transactionDetail));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -203,9 +215,7 @@ export default class HomeView extends CommonView {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Create transactions details object
|
// Create transactions details object
|
||||||
const tempList = [];
|
const tempList = listCategoryInTransaction.map((categoryName) => {
|
||||||
|
|
||||||
listCategoryInTransaction.forEach((categoryName) => {
|
|
||||||
// Get category object from list category has been loaded.
|
// Get category object from list category has been loaded.
|
||||||
const category = this.listCategory.filter(
|
const category = this.listCategory.filter(
|
||||||
(item) => item.name === categoryName,
|
(item) => item.name === categoryName,
|
||||||
@@ -216,11 +226,9 @@ export default class HomeView extends CommonView {
|
|||||||
this.listTransactions,
|
this.listTransactions,
|
||||||
);
|
);
|
||||||
|
|
||||||
tempList.push(
|
return createTransactionDetailObject(
|
||||||
createTransactionDetailObject(
|
|
||||||
Object.assign({}, ...category),
|
Object.assign({}, ...category),
|
||||||
transactions,
|
transactions,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -300,27 +308,35 @@ export default class HomeView extends CommonView {
|
|||||||
handlerEventTransactionDialog() {
|
handlerEventTransactionDialog() {
|
||||||
this.transactionDialog.addEventListener('submit', (e) => {
|
this.transactionDialog.addEventListener('submit', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
this.clearErrorTransactionDialog();
|
||||||
this.submitTransactionDialog();
|
this.submitTransactionDialog();
|
||||||
this.transactionDialog.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.transactionDialog.addEventListener('input', () => {
|
this.transactionDialog.addEventListener('input', () => {
|
||||||
const dateInput = this.transactionDialog.querySelector(
|
this.changeBtnStyleTransactionDialog();
|
||||||
"[name='selected_date']",
|
this.clearErrorTransactionDialog();
|
||||||
).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,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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 =
|
const deleteTransactionBtn =
|
||||||
this.transactionDialog.querySelector('.form__delete-btn');
|
this.transactionDialog.querySelector('.form__delete-btn');
|
||||||
|
|
||||||
@@ -336,9 +352,11 @@ export default class HomeView extends CommonView {
|
|||||||
|
|
||||||
await this.deleteTransaction(idEl.value);
|
await this.deleteTransaction(idEl.value);
|
||||||
|
|
||||||
this.showSuccessToast('Delete success!', MESSAGE.DEFAULT_MESSAGE);
|
// Reload data
|
||||||
|
await this.loadTransactionData();
|
||||||
await this.loadData();
|
await this.loadData();
|
||||||
|
|
||||||
|
this.showSuccessToast('Delete success!', MESSAGE.DEFAULT_MESSAGE);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.showErrorToast(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) {
|
initDataTransactionDialog(idTransaction) {
|
||||||
const transactionArr = this.listTransactions.filter(
|
const transactionArr = this.listTransactions.filter(
|
||||||
(obj) => obj.id === idTransaction,
|
(obj) => obj.id === idTransaction,
|
||||||
@@ -379,8 +414,6 @@ export default class HomeView extends CommonView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async submitTransactionDialog() {
|
async submitTransactionDialog() {
|
||||||
this.toggleLoaderSpinner();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const dateEl = this.transactionForm.querySelector(
|
const dateEl = this.transactionForm.querySelector(
|
||||||
"[name='selected_date']",
|
"[name='selected_date']",
|
||||||
@@ -393,11 +426,21 @@ export default class HomeView extends CommonView {
|
|||||||
const idEl = this.transactionForm.querySelector(
|
const idEl = this.transactionForm.querySelector(
|
||||||
"[name='id_transaction']",
|
"[name='id_transaction']",
|
||||||
);
|
);
|
||||||
|
const amount =
|
||||||
|
categoryNameEl.value === 'Income' ? +amountEl.value : -+amountEl.value; // Check if this is a income transaction, amount must plus
|
||||||
|
|
||||||
|
// Validate data user input
|
||||||
|
if (
|
||||||
|
this.validateTransactionForm(dateEl.value, categoryNameEl.value, amount)
|
||||||
|
) {
|
||||||
|
this.toggleLoaderSpinner();
|
||||||
|
this.transactionDialog.close();
|
||||||
|
|
||||||
const transaction = new Transaction({
|
const transaction = new Transaction({
|
||||||
id: idEl.value,
|
id: idEl.value,
|
||||||
categoryName: categoryNameEl.value,
|
categoryName: categoryNameEl.value,
|
||||||
date: dateEl.value,
|
date: dateEl.value,
|
||||||
amount: -+amountEl.value,
|
amount,
|
||||||
note: noteEl.value,
|
note: noteEl.value,
|
||||||
idUser: this.wallet.idUser,
|
idUser: this.wallet.idUser,
|
||||||
});
|
});
|
||||||
@@ -405,31 +448,65 @@ export default class HomeView extends CommonView {
|
|||||||
await this.saveTransaction(transaction);
|
await this.saveTransaction(transaction);
|
||||||
|
|
||||||
// Reload data
|
// Reload data
|
||||||
|
await this.loadTransactionData();
|
||||||
|
this.updateAmountWallet();
|
||||||
await this.loadData();
|
await this.loadData();
|
||||||
this.updateAmountWallet(-+amountEl.value);
|
|
||||||
|
|
||||||
|
if (!idEl.value) {
|
||||||
|
// Add success
|
||||||
this.showSuccessToast(
|
this.showSuccessToast(
|
||||||
MESSAGE.ADD_TRANSACTION_SUCCESS,
|
MESSAGE.ADD_TRANSACTION_SUCCESS,
|
||||||
MESSAGE.DEFAULT_MESSAGE,
|
MESSAGE.DEFAULT_MESSAGE,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
this.clearInputTransactionForm(this.transactionForm);
|
// Update success
|
||||||
} catch (error) {
|
this.showSuccessToast(
|
||||||
this.showErrorToast(error);
|
MESSAGE.UPDATE_TRANSACTION_SUCCESS,
|
||||||
|
MESSAGE.DEFAULT_MESSAGE,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.toggleLoaderSpinner();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearInputTransactionForm() {
|
clearInputTransactionForm() {
|
||||||
const categoryIcon = this.transactionForm.querySelector('.category-icon');
|
const categoryIcon = this.transactionForm.querySelector('.category-icon');
|
||||||
|
|
||||||
categoryIcon.src = defaultCategoryIcon;
|
categoryIcon.src = defaultCategoryIcon;
|
||||||
|
|
||||||
this.keySearchCategory = null; // Delete keyword search
|
this.keySearchCategory = null; // Delete keyword search
|
||||||
|
this.renderCategoryList(this.keySearchCategory);
|
||||||
this.renderCategoryItem(this.keySearchCategory);
|
|
||||||
|
|
||||||
this.transactionForm.reset();
|
this.transactionForm.reset();
|
||||||
}
|
}
|
||||||
// ---------------------END DIALOG---------------------//
|
// ---------------------END DIALOG---------------------//
|
||||||
@@ -462,15 +539,20 @@ export default class HomeView extends CommonView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Render category item
|
// 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');
|
const listCategoryEl = document.querySelector('.list-category');
|
||||||
|
|
||||||
listCategoryEl.innerHTML = ''; // Remove old category item
|
listCategoryEl.innerHTML = ''; // Remove old category item
|
||||||
|
|
||||||
listCategory.forEach((category) => {
|
newListCategory.forEach((category) => {
|
||||||
const markup = `
|
const markup = `
|
||||||
<div class="category-item ${
|
<div class="category-item ${
|
||||||
category.name === categorySelected ? 'selected' : ''
|
category.name === categorySelected ? 'selected' : ''
|
||||||
@@ -495,26 +577,48 @@ export default class HomeView extends CommonView {
|
|||||||
this.budgetDialog.addEventListener('submit', (e) => {
|
this.budgetDialog.addEventListener('submit', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
this.clearErrorStyleBudgetForm();
|
||||||
this.submitBudgetForm();
|
this.submitBudgetForm();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.budgetDialog.addEventListener('input', (e) => {
|
this.budgetDialog.addEventListener('input', (e) => {
|
||||||
const bodyDialog = e.target.closest('.dialog__body');
|
const bodyDialog = e.target.closest('.dialog__body');
|
||||||
this.validateBudgetForm(bodyDialog);
|
|
||||||
|
this.changeBtnStyle(bodyDialog);
|
||||||
|
this.clearErrorStyleBudgetForm();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
clearErrorStyleBudgetForm() {
|
||||||
|
// Clear error style
|
||||||
|
const inputFieldEls =
|
||||||
|
this.budgetDialog.querySelectorAll('.form__input-field');
|
||||||
|
const errorTexts = this.budgetDialog.querySelectorAll('.error-text');
|
||||||
|
|
||||||
|
inputFieldEls.forEach((item) => {
|
||||||
|
if (item.classList.contains('error-input'))
|
||||||
|
item.classList.remove('error-input');
|
||||||
|
});
|
||||||
|
|
||||||
|
errorTexts.forEach((item) => {
|
||||||
|
if (item) item.remove();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async submitBudgetForm() {
|
async submitBudgetForm() {
|
||||||
try {
|
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('selected_date');
|
||||||
const amount = form.get('amount');
|
const amount = form.get('amount');
|
||||||
const note = form.get('note');
|
const note = form.get('note');
|
||||||
|
|
||||||
|
// Validate data user input
|
||||||
|
|
||||||
|
if (this.validateBudgetForm(date, amount)) {
|
||||||
|
this.toggleLoaderSpinner(); // Enable loader spinner
|
||||||
|
this.budgetDialog.close(); // Close dialog
|
||||||
|
|
||||||
const transaction = new Transaction({
|
const transaction = new Transaction({
|
||||||
categoryName: DEFAULT_CATEGORY.INCOME,
|
categoryName: DEFAULT_CATEGORY.INCOME,
|
||||||
date,
|
date,
|
||||||
@@ -526,8 +630,9 @@ export default class HomeView extends CommonView {
|
|||||||
await this.saveTransaction(transaction);
|
await this.saveTransaction(transaction);
|
||||||
|
|
||||||
// Reload data
|
// Reload data
|
||||||
|
await this.loadTransactionData();
|
||||||
|
await this.updateAmountWallet();
|
||||||
await this.loadData();
|
await this.loadData();
|
||||||
await this.updateAmountWallet(+amount); // Update wallet
|
|
||||||
|
|
||||||
// Hide loader spinner
|
// Hide loader spinner
|
||||||
this.toggleLoaderSpinner();
|
this.toggleLoaderSpinner();
|
||||||
@@ -539,12 +644,34 @@ export default class HomeView extends CommonView {
|
|||||||
);
|
);
|
||||||
|
|
||||||
document.getElementById('formAddBudget').reset();
|
document.getElementById('formAddBudget').reset();
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.showErrorToast(error);
|
this.showErrorToast(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validateBudgetForm(bodyDialog) {
|
validateBudgetForm(date, amount) {
|
||||||
|
const inputFieldEl =
|
||||||
|
this.budgetDialog.querySelectorAll('.form__input-field');
|
||||||
|
|
||||||
|
if (!date || !amount) {
|
||||||
|
if (!date) {
|
||||||
|
renderRequiredText('date', inputFieldEl[0]);
|
||||||
|
inputFieldEl[0].classList.add('error-input');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amount) {
|
||||||
|
renderRequiredText('amount', inputFieldEl[1]);
|
||||||
|
inputFieldEl[1].classList.add('error-input');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
changeBtnStyle(bodyDialog) {
|
||||||
const date = bodyDialog.querySelector('.input-date').value;
|
const date = bodyDialog.querySelector('.input-date').value;
|
||||||
const amount = +bodyDialog.querySelector('.form__input-balance').value;
|
const amount = +bodyDialog.querySelector('.form__input-balance').value;
|
||||||
const saveBtn = bodyDialog.querySelector('.form__save-btn');
|
const saveBtn = bodyDialog.querySelector('.form__save-btn');
|
||||||
@@ -562,19 +689,34 @@ export default class HomeView extends CommonView {
|
|||||||
this.walletDialog.addEventListener('submit', (e) => {
|
this.walletDialog.addEventListener('submit', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
this.clearErrorStyleWalletDialog();
|
||||||
this.submitWalletForm();
|
this.submitWalletForm();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.walletDialog.addEventListener('input', (e) => {
|
this.walletDialog.addEventListener('input', (e) => {
|
||||||
const bodyDialog = e.target.closest('.dialog__body');
|
const bodyDialog = e.target.closest('.dialog__body');
|
||||||
this.validateWalletForm(bodyDialog);
|
|
||||||
|
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() {
|
async submitWalletForm() {
|
||||||
this.walletDialog.close();
|
|
||||||
this.toggleLoaderSpinner();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Wallet info
|
// Wallet info
|
||||||
const { walletForm } = document.forms;
|
const { walletForm } = document.forms;
|
||||||
@@ -582,19 +724,23 @@ export default class HomeView extends CommonView {
|
|||||||
const walletName = form.get('walletName');
|
const walletName = form.get('walletName');
|
||||||
const amount = form.get('amount');
|
const amount = form.get('amount');
|
||||||
|
|
||||||
const wallet = new Wallet({
|
if (this.validateWalletDialog(walletName, amount)) {
|
||||||
|
this.walletDialog.close();
|
||||||
|
this.toggleLoaderSpinner();
|
||||||
|
|
||||||
|
this.wallet = new Wallet({
|
||||||
walletName,
|
walletName,
|
||||||
amount: +amount,
|
amount: +amount,
|
||||||
idUser: this.user.id,
|
idUser: this.user.id,
|
||||||
inflow: +amount,
|
inflow: +amount,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.saveWallet(wallet);
|
await this.saveWallet(this.wallet);
|
||||||
|
|
||||||
// Transaction info
|
// Transaction info
|
||||||
const transaction = new Transaction({
|
const transaction = new Transaction({
|
||||||
categoryName: 'Income',
|
categoryName: 'Income',
|
||||||
date: new Date().toLocaleDateString('en-US'),
|
date: new Date().toISOString().slice(0, 10),
|
||||||
note: FIRST_ADD_WALLET_NOTE,
|
note: FIRST_ADD_WALLET_NOTE,
|
||||||
amount: +amount,
|
amount: +amount,
|
||||||
idUser: this.user.id,
|
idUser: this.user.id,
|
||||||
@@ -603,6 +749,7 @@ export default class HomeView extends CommonView {
|
|||||||
await this.saveTransaction(transaction);
|
await this.saveTransaction(transaction);
|
||||||
|
|
||||||
// Load data and event
|
// Load data and event
|
||||||
|
await this.loadTransactionData();
|
||||||
await this.loadData();
|
await this.loadData();
|
||||||
this.loadEvent();
|
this.loadEvent();
|
||||||
|
|
||||||
@@ -612,15 +759,38 @@ export default class HomeView extends CommonView {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await this.loadData(); // Load data from database into page
|
await this.loadData(); // Load data from database into page
|
||||||
} catch (error) {
|
|
||||||
// Show toast error
|
|
||||||
this.showErrorToast(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.toggleLoaderSpinner();
|
this.toggleLoaderSpinner();
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Show toast error
|
||||||
|
this.showErrorToast(error);
|
||||||
|
this.toggleLoaderSpinner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
validateWalletForm(bodyDialog) {
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
changeBtnStyleWalletDialog(bodyDialog) {
|
||||||
const walletName = bodyDialog.querySelector('.form__input-text').value;
|
const walletName = bodyDialog.querySelector('.form__input-text').value;
|
||||||
const amount = bodyDialog.querySelector('.form__input-balance').value;
|
const amount = bodyDialog.querySelector('.form__input-balance').value;
|
||||||
const saveBtn = bodyDialog.querySelector('.form__save-btn');
|
const saveBtn = bodyDialog.querySelector('.form__save-btn');
|
||||||
@@ -671,14 +841,14 @@ export default class HomeView extends CommonView {
|
|||||||
*/
|
*/
|
||||||
handlerTabsTransfer() {
|
handlerTabsTransfer() {
|
||||||
this.tabs.forEach((tab, index) => {
|
this.tabs.forEach((tab, index) => {
|
||||||
tab.addEventListener('click', () => {
|
tab.addEventListener('click', (e) => {
|
||||||
this.removeActiveTab();
|
this.removeActiveTab();
|
||||||
tab.classList.add('active');
|
tab.classList.add('active');
|
||||||
|
|
||||||
const line = document.querySelector('.app__line');
|
const line = document.querySelector('.app__line');
|
||||||
|
|
||||||
line.classList.toggle('right', line.classList.contains('left'));
|
line.style.width = `${e.target.offsetWidth}px`;
|
||||||
line.classList.toggle('left', !line.classList.contains('right'));
|
line.style.left = `${e.target.offsetLeft}px`;
|
||||||
|
|
||||||
this.allContent.forEach((content) => {
|
this.allContent.forEach((content) => {
|
||||||
content.classList.remove('active');
|
content.classList.remove('active');
|
||||||
@@ -709,6 +879,10 @@ export default class HomeView extends CommonView {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.addBudgetBtn.addEventListener('click', () => {
|
this.addBudgetBtn.addEventListener('click', () => {
|
||||||
|
// Set default value for date input
|
||||||
|
this.budgetDialog.querySelector("[name='selected_date']").valueAsDate =
|
||||||
|
new Date();
|
||||||
|
|
||||||
this.budgetDialog.showModal();
|
this.budgetDialog.showModal();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -743,11 +917,20 @@ export default class HomeView extends CommonView {
|
|||||||
showTransactionDialog(idTransaction = null) {
|
showTransactionDialog(idTransaction = null) {
|
||||||
this.clearInputTransactionForm();
|
this.clearInputTransactionForm();
|
||||||
|
|
||||||
|
// Show delete button only if it is a edit form
|
||||||
const deleteBtn = this.transactionDialog.querySelector('.form__delete-btn');
|
const deleteBtn = this.transactionDialog.querySelector('.form__delete-btn');
|
||||||
deleteBtn.classList.toggle('hide', !idTransaction);
|
deleteBtn.classList.toggle('hide', !idTransaction);
|
||||||
|
|
||||||
if (idTransaction) this.initDataTransactionDialog(idTransaction);
|
if (idTransaction) {
|
||||||
|
// Init data transaction to dialog
|
||||||
|
this.initDataTransactionDialog(idTransaction);
|
||||||
|
} else
|
||||||
|
this.transactionDialog.querySelector(
|
||||||
|
"[name='selected_date']",
|
||||||
|
).valueAsDate = new Date(); // Set default value for date input
|
||||||
|
|
||||||
|
// Change style submit btn
|
||||||
|
this.changeBtnStyleTransactionDialog();
|
||||||
this.transactionDialog.showModal();
|
this.transactionDialog.showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,6 +968,9 @@ export default class HomeView extends CommonView {
|
|||||||
|
|
||||||
// Close select category dialog
|
// Close select category dialog
|
||||||
this.categoryDialog.close();
|
this.categoryDialog.close();
|
||||||
|
|
||||||
|
// Clear error style for transaction dialog
|
||||||
|
this.clearErrorTransactionDialog();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -794,7 +980,7 @@ export default class HomeView extends CommonView {
|
|||||||
// Make the keyword search category name into global
|
// Make the keyword search category name into global
|
||||||
this.keySearchCategory = categoryNameEl.value;
|
this.keySearchCategory = categoryNameEl.value;
|
||||||
|
|
||||||
this.renderCategoryItem(this.keySearchCategory);
|
this.renderCategoryList(this.keySearchCategory);
|
||||||
}
|
}
|
||||||
this.categoryDialog.showModal();
|
this.categoryDialog.showModal();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import CommonLoginRegisterView from './commonLoginRegisterView';
|
import AuthenticationView from './authenticationView';
|
||||||
import { TYPE_TOAST, BTN_CONTENT } from '../constants/config';
|
import { TYPE_TOAST, BTN_CONTENT } from '../constants/config';
|
||||||
import * as MESSAGE from '../constants/message';
|
import * as MESSAGE from '../constants/message';
|
||||||
|
|
||||||
export default class LoginView extends CommonLoginRegisterView {
|
export default class LoginView extends AuthenticationView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -26,16 +26,31 @@ export default class LoginView extends CommonLoginRegisterView {
|
|||||||
* Get data from user input
|
* Get data from user input
|
||||||
* @returns {Object || null} Return object or null
|
* @returns {Object || null} Return object or null
|
||||||
*/
|
*/
|
||||||
getDataFromForm(event) {
|
validateForm(event) {
|
||||||
const formData = new FormData(event.target);
|
const formData = new FormData(event.target);
|
||||||
const email = formData.get('email');
|
const email = formData.get('email');
|
||||||
const password = formData.get('password');
|
const password = formData.get('password');
|
||||||
|
|
||||||
|
// Validate user input
|
||||||
|
this.listError = []; // Reset list error
|
||||||
|
const emailValid = this.validateEmail(email);
|
||||||
|
const passwordValid = this.validatePassword(password);
|
||||||
|
|
||||||
|
// Show error style
|
||||||
|
this.emailEl.classList.toggle('error-input', !emailValid);
|
||||||
|
this.inputPasswordEl.classList.toggle('error-input', !passwordValid);
|
||||||
|
|
||||||
|
if (emailValid && passwordValid) {
|
||||||
this.account = { email, password };
|
this.account = { email, password };
|
||||||
|
|
||||||
return this.account;
|
return this.account;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.showError(this.listError);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement error toast in site
|
* Implement error toast in site
|
||||||
* @param {string} content The content will show in error toast
|
* @param {string} content The content will show in error toast
|
||||||
@@ -73,7 +88,8 @@ export default class LoginView extends CommonLoginRegisterView {
|
|||||||
this.toggleLoaderSpinner();
|
this.toggleLoaderSpinner();
|
||||||
|
|
||||||
// Get data from form
|
// Get data from form
|
||||||
const userInput = this.getDataFromForm(event);
|
const userInput = this.validateForm(event);
|
||||||
|
if (userInput) {
|
||||||
// Check user exist
|
// Check user exist
|
||||||
const results = await loginUser(userInput.email, userInput.password);
|
const results = await loginUser(userInput.email, userInput.password);
|
||||||
|
|
||||||
@@ -83,6 +99,7 @@ export default class LoginView extends CommonLoginRegisterView {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw MESSAGE.ERROR_CREDENTIAL;
|
throw MESSAGE.ERROR_CREDENTIAL;
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Show toast error
|
// Show toast error
|
||||||
this.initErrorToast(error);
|
this.initErrorToast(error);
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
import { TYPE_TOAST, BTN_CONTENT } from '../constants/config';
|
import { TYPE_TOAST, BTN_CONTENT } from '../constants/config';
|
||||||
import * as MESSAGE from '../constants/message';
|
import * as MESSAGE from '../constants/message';
|
||||||
import CommonLoginRegisterView from './commonLoginRegisterView';
|
import AuthenticationView from './authenticationView';
|
||||||
import User from '../models/user';
|
import User from '../models/user';
|
||||||
|
import { redirectToLoginPage } from '../helpers/helpers';
|
||||||
|
|
||||||
export default class RegisterView extends CommonLoginRegisterView {
|
export default class RegisterView extends AuthenticationView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.dialog = document.querySelector('.toast');
|
this.dialog = document.querySelector('.toast');
|
||||||
|
this.toastBtn = document.querySelector('.toast__redirect-btn');
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadPage(getInfoUserLogin) {
|
async loadPage(getInfoUserLogin) {
|
||||||
@@ -26,21 +28,38 @@ export default class RegisterView extends CommonLoginRegisterView {
|
|||||||
* Get data from user input
|
* Get data from user input
|
||||||
* @returns {Object || null} Return object or null
|
* @returns {Object || null} Return object or null
|
||||||
*/
|
*/
|
||||||
getDataFromForm() {
|
validateForm() {
|
||||||
const { registerForm } = document.forms;
|
const { registerForm } = document.forms;
|
||||||
const formData = new FormData(registerForm);
|
const formData = new FormData(registerForm);
|
||||||
const email = formData.get('email');
|
const email = formData.get('email');
|
||||||
const password = formData.get('password');
|
const password = formData.get('password');
|
||||||
const passwordConfirm = formData.get('password_confirm');
|
const passwordConfirm = formData.get('password_confirm');
|
||||||
|
|
||||||
const account = { email, password, passwordConfirm };
|
// Validate user input
|
||||||
|
this.listError = []; // Reset list error
|
||||||
|
const emailValid = this.validateEmail(email);
|
||||||
|
const passwordValid = this.validatePassword(password);
|
||||||
|
const passwordConfirmValid = this.validatePasswordConfirm(
|
||||||
|
password,
|
||||||
|
passwordConfirm,
|
||||||
|
);
|
||||||
|
|
||||||
if (this.isValidateAccount(account)) {
|
// Show error style
|
||||||
const user = new User(account);
|
this.emailEl.classList.toggle('error-input', !emailValid);
|
||||||
|
this.inputPasswordEl.classList.toggle('error-input', !passwordValid);
|
||||||
|
this.inputPasswordConfirmEl.classList.toggle(
|
||||||
|
'error-input',
|
||||||
|
!passwordConfirmValid,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (emailValid && passwordValid && passwordConfirmValid) {
|
||||||
|
const user = new User({ email, password, passwordConfirm });
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.showError(this.listError);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,14 +68,17 @@ export default class RegisterView extends CommonLoginRegisterView {
|
|||||||
*/
|
*/
|
||||||
showRegisterSuccessToast() {
|
showRegisterSuccessToast() {
|
||||||
const typeToast = TYPE_TOAST.success;
|
const typeToast = TYPE_TOAST.success;
|
||||||
const title = 'Register Commpleted';
|
const title = MESSAGE.REGISTER_SUCCESS;
|
||||||
const content = 'Please login to continue!';
|
const content = MESSAGE.DEFAULT_MESSAGE;
|
||||||
const btnContent = 'OK';
|
const btnContent = BTN_CONTENT.OK;
|
||||||
|
|
||||||
this.initToastContent(typeToast, title, content, btnContent);
|
this.initToastContent(typeToast, title, content, btnContent);
|
||||||
|
|
||||||
// Show toast
|
// Show toast
|
||||||
this.toastDialog.showModal();
|
this.toastDialog.showModal();
|
||||||
|
|
||||||
|
// Add event for toast button
|
||||||
|
this.toastBtn.addEventListener('click', redirectToLoginPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,6 +93,9 @@ export default class RegisterView extends CommonLoginRegisterView {
|
|||||||
|
|
||||||
// Show toast
|
// Show toast
|
||||||
this.toastDialog.showModal();
|
this.toastDialog.showModal();
|
||||||
|
|
||||||
|
// Remove event for toast button
|
||||||
|
this.toastBtn.removeEventListener('click', redirectToLoginPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,8 +115,8 @@ export default class RegisterView extends CommonLoginRegisterView {
|
|||||||
// Load spinner
|
// Load spinner
|
||||||
this.toggleLoaderSpinner();
|
this.toggleLoaderSpinner();
|
||||||
|
|
||||||
// Get data from form
|
// Get validate form
|
||||||
const user = this.getDataFromForm();
|
const user = this.validateForm();
|
||||||
|
|
||||||
// Save user
|
// Save user
|
||||||
if (user) {
|
if (user) {
|
||||||
@@ -103,6 +128,9 @@ export default class RegisterView extends CommonLoginRegisterView {
|
|||||||
await saveUser(user);
|
await saveUser(user);
|
||||||
// Show toast success
|
// Show toast success
|
||||||
this.showRegisterSuccessToast();
|
this.showRegisterSuccessToast();
|
||||||
|
|
||||||
|
// Clear form
|
||||||
|
document.getElementById('registerForm').reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<!-- Dialog body -->
|
<!-- Dialog body -->
|
||||||
<div class="dialog__body">
|
<div class="dialog__body">
|
||||||
<form class="form" id="walletForm">
|
<form class="form" id="walletForm">
|
||||||
|
<div class="form__input-container">
|
||||||
<div class="form__input-field">
|
<div class="form__input-field">
|
||||||
<p class="form__label">Wallet name</p>
|
<p class="form__label">Wallet name</p>
|
||||||
<input
|
<input
|
||||||
@@ -25,10 +26,10 @@
|
|||||||
class="form__input-text"
|
class="form__input-text"
|
||||||
placeholder="Your wallet name?"
|
placeholder="Your wallet name?"
|
||||||
name="walletName"
|
name="walletName"
|
||||||
required
|
|
||||||
minlength="3"
|
minlength="3"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form__currency-balance">
|
<div class="form__currency-balance">
|
||||||
<div class="form__input-field">
|
<div class="form__input-field">
|
||||||
<p class="form__label">Currency</p>
|
<p class="form__label">Currency</p>
|
||||||
@@ -40,16 +41,17 @@
|
|||||||
<p class="form__text-currency">United States Dollar</p>
|
<p class="form__text-currency">United States Dollar</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form__input-container">
|
||||||
<div class="form__input-field">
|
<div class="form__input-field">
|
||||||
<p class="form__label">Initial Balance</p>
|
<p class="form__label">Initial Balance</p>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
class="form__input-balance"
|
class="form__input-balance"
|
||||||
name="amount"
|
name="amount"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<button type="submit" class="form__save-btn">SAVE</button>
|
<button type="submit" class="form__save-btn">SAVE</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -67,13 +69,20 @@
|
|||||||
<div class="dialog__body">
|
<div class="dialog__body">
|
||||||
<form class="form" id="formAddBudget">
|
<form class="form" id="formAddBudget">
|
||||||
<div class="form__date-amount-input">
|
<div class="form__date-amount-input">
|
||||||
|
<div class="form__input-container">
|
||||||
<div class="form__input-field">
|
<div class="form__input-field">
|
||||||
<p class="form__label">Date</p>
|
<p class="form__label">Date</p>
|
||||||
<div class="date-input-container">
|
<div class="date-input-container">
|
||||||
<input class="input-date" type="date" name="date" required />
|
<input
|
||||||
|
class="input-date"
|
||||||
|
type="date"
|
||||||
|
name="selected_date"
|
||||||
|
/>
|
||||||
<div class="icon-btn"></div>
|
<div class="icon-btn"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form__input-container">
|
||||||
<div class="form__input-field">
|
<div class="form__input-field">
|
||||||
<p class="form__label">Amount</p>
|
<p class="form__label">Amount</p>
|
||||||
<input
|
<input
|
||||||
@@ -81,10 +90,10 @@
|
|||||||
type="number"
|
type="number"
|
||||||
min="1"
|
min="1"
|
||||||
name="amount"
|
name="amount"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form__note-input">
|
<div class="form__note-input">
|
||||||
<p class="form__label">Note</p>
|
<p class="form__label">Note</p>
|
||||||
<input
|
<input
|
||||||
@@ -116,6 +125,7 @@
|
|||||||
<form class="form" id="formAddTransaction">
|
<form class="form" id="formAddTransaction">
|
||||||
<input type="text" name="id_transaction" hidden />
|
<input type="text" name="id_transaction" hidden />
|
||||||
<div class="form__date-category-amount-input">
|
<div class="form__date-category-amount-input">
|
||||||
|
<div class="form__input-container">
|
||||||
<div class="form__input-field">
|
<div class="form__input-field">
|
||||||
<p class="form__label">Date</p>
|
<p class="form__label">Date</p>
|
||||||
<div class="date-input-container">
|
<div class="date-input-container">
|
||||||
@@ -123,11 +133,12 @@
|
|||||||
class="input-date"
|
class="input-date"
|
||||||
type="date"
|
type="date"
|
||||||
name="selected_date"
|
name="selected_date"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
<span class="icon-btn"></span>
|
<span class="icon-btn"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form__input-container">
|
||||||
<div class="form__input-field" id="selectCategory">
|
<div class="form__input-field" id="selectCategory">
|
||||||
<p class="form__label">Category</p>
|
<p class="form__label">Category</p>
|
||||||
<div class="category-input-container">
|
<div class="category-input-container">
|
||||||
@@ -141,11 +152,12 @@
|
|||||||
name="category_name"
|
name="category_name"
|
||||||
class="category-name"
|
class="category-name"
|
||||||
placeholder="Select Category"
|
placeholder="Select Category"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
<div class="icon-btn"></div>
|
<div class="icon-btn"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form__input-container">
|
||||||
<div class="form__input-field">
|
<div class="form__input-field">
|
||||||
<p class="form__label">Amount</p>
|
<p class="form__label">Amount</p>
|
||||||
<input
|
<input
|
||||||
@@ -153,10 +165,10 @@
|
|||||||
type="number"
|
type="number"
|
||||||
name="amount"
|
name="amount"
|
||||||
value="0"
|
value="0"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form__note-input">
|
<div class="form__note-input">
|
||||||
<p class="form__label">Note</p>
|
<p class="form__label">Note</p>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -22,18 +22,16 @@
|
|||||||
<h1 class="form__title">Log In</h1>
|
<h1 class="form__title">Log In</h1>
|
||||||
<p class="form__description">Using Money Lover account</p>
|
<p class="form__description">Using Money Lover account</p>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="text"
|
||||||
class="form__input"
|
class="form__input"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
name="email"
|
name="email"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
name="password"
|
name="password"
|
||||||
class="form__input"
|
class="form__input"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
<button type="submit" class="form__submit-btn">Login</button>
|
<button type="submit" class="form__submit-btn">Login</button>
|
||||||
<p class="form__redirect-signup-text">
|
<p class="form__redirect-signup-text">
|
||||||
|
|||||||
@@ -21,27 +21,31 @@
|
|||||||
<div class="form__container">
|
<div class="form__container">
|
||||||
<h1 class="form__title">Register</h1>
|
<h1 class="form__title">Register</h1>
|
||||||
<p class="form__description">Using Money Lover account</p>
|
<p class="form__description">Using Money Lover account</p>
|
||||||
|
<div class="form__input-container">
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="text"
|
||||||
class="form__input"
|
class="form__input"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
name="email"
|
name="email"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="form__input-container">
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
name="password"
|
name="password"
|
||||||
class="form__input"
|
class="form__input"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="form__input-container">
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
name="password_confirm"
|
name="password_confirm"
|
||||||
class="form__input"
|
class="form__input"
|
||||||
placeholder="Confirm Password"
|
placeholder="Confirm Password"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="form__submit-btn">Register</button>
|
<button type="submit" class="form__submit-btn">Register</button>
|
||||||
<p class="form__redirect-signup-text">
|
<p class="form__redirect-signup-text">
|
||||||
Have you an account?
|
Have you an account?
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
@import './abstracts/variables';
|
@import './abstracts/variables';
|
||||||
|
|
||||||
// Bases
|
// Bases
|
||||||
@import './bases/base';
|
|
||||||
@import './bases/placeholder';
|
@import './bases/placeholder';
|
||||||
@import './bases/reset';
|
@import './bases/reset';
|
||||||
@import './bases/typography';
|
@import './bases/typography';
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
.overlay {
|
|
||||||
@extend %d-absolute;
|
|
||||||
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.3);
|
|
||||||
z-index: $zindex-lv-1;
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
@extend %active;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -51,3 +51,9 @@
|
|||||||
|
|
||||||
padding: 8 0px;
|
padding: 8 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%error-text {
|
||||||
|
align-self: flex-start;
|
||||||
|
padding-left: 5px;
|
||||||
|
color: $dark-error-color;
|
||||||
|
}
|
||||||
|
|||||||
@@ -143,16 +143,6 @@
|
|||||||
background-color: $primary-color;
|
background-color: $primary-color;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
transition: all 0.3s ease-in-out;
|
transition: all 0.3s ease-in-out;
|
||||||
|
|
||||||
&.left {
|
|
||||||
left: 152px;
|
|
||||||
width: 116px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.right {
|
|
||||||
left: 272px;
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,6 +334,10 @@
|
|||||||
font-size: $fs-md;
|
font-size: $fs-md;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__input-field {
|
||||||
|
height: fit-content;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,11 +358,11 @@
|
|||||||
@extend %d-flex;
|
@extend %d-flex;
|
||||||
@include flex-layout($gap: 32px);
|
@include flex-layout($gap: 32px);
|
||||||
|
|
||||||
& .form__input-field:first-child {
|
& .form__input-container:first-child .form__input-field {
|
||||||
width: 208px;
|
width: 208px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& .form__input-field:last-child {
|
& .form__input-container:last-child .form__input-field {
|
||||||
width: 240px;
|
width: 240px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -504,7 +498,7 @@
|
|||||||
&__input-field {
|
&__input-field {
|
||||||
@extend %rounded;
|
@extend %rounded;
|
||||||
|
|
||||||
padding: 6px 16px 13.5px 16px;
|
padding: 6px 16px 12px;
|
||||||
border: 1px solid $gray;
|
border: 1px solid $gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,6 +513,7 @@
|
|||||||
font-size: $fs-lg;
|
font-size: $fs-lg;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: none;
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -530,11 +525,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__input-balance {
|
&__input-balance {
|
||||||
font-size: $fs-md;
|
font-size: $fs-lg;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
margin-top: 6px;
|
height: 28px;
|
||||||
border: none;
|
border: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -599,6 +595,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
border: none;
|
border: none;
|
||||||
font-size: $fs-lg;
|
font-size: $fs-lg;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -614,7 +611,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
background-color: $white;
|
background-color: transparent;
|
||||||
border-top: 3px solid $dark-gray;
|
border-top: 3px solid $dark-gray;
|
||||||
border-right: 3px solid $dark-gray;
|
border-right: 3px solid $dark-gray;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
@@ -644,6 +641,7 @@
|
|||||||
color: $black;
|
color: $black;
|
||||||
border: none;
|
border: none;
|
||||||
caret-color: transparent;
|
caret-color: transparent;
|
||||||
|
background-color: transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
@@ -689,6 +687,24 @@
|
|||||||
color: $primary-color;
|
color: $primary-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-input {
|
||||||
|
background-color: $light-error-color;
|
||||||
|
border-color: $dark-error-color;
|
||||||
|
|
||||||
|
& .form__input-text::placeholder {
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-text {
|
||||||
|
@extend %error-text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form__input-container {
|
||||||
|
@extend %d-flex;
|
||||||
|
@include flex-layout($direction: column, $gap: 7px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-icon {
|
.close-icon {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
padding: 15px 15px;
|
padding: 15px 15px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
|
list-style: inside;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__description {
|
&__description {
|
||||||
@@ -69,6 +70,11 @@
|
|||||||
border: 2px solid $background-input-color;
|
border: 2px solid $background-input-color;
|
||||||
background-color: $background-input-color;
|
background-color: $background-input-color;
|
||||||
padding-inline: 14px;
|
padding-inline: 14px;
|
||||||
|
|
||||||
|
&-container {
|
||||||
|
@extend %d-flex;
|
||||||
|
@include flex-layout($direction: column, $gap: 7px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__submit-btn {
|
&__submit-btn {
|
||||||
@@ -87,4 +93,8 @@
|
|||||||
border: 2px solid $dark-error-color;
|
border: 2px solid $dark-error-color;
|
||||||
background-color: $light-error-color;
|
background-color: $light-error-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-text {
|
||||||
|
@extend %error-text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user