mirror of
https://github.com/Nezumi-2711/javascript-training.git
synced 2026-09-22 13:38:43 +00:00
Implement category search method
This commit is contained in:
@@ -24,6 +24,10 @@ export default class HomeController {
|
||||
return this.service.transactionService.saveTransaction(transaction);
|
||||
}
|
||||
|
||||
handlerGetAllCategory() {
|
||||
return this.service.categoryService.getAllCategory();
|
||||
}
|
||||
|
||||
init() {
|
||||
if (this.homeView) {
|
||||
this.homeView.addHandlerInputChangeWalletForm();
|
||||
@@ -36,6 +40,7 @@ export default class HomeController {
|
||||
this.handlerGetInfoUserLogin.bind(this),
|
||||
this.handlerCheckWalletValid.bind(this),
|
||||
this.handlerGetWalletUser.bind(this),
|
||||
this.handlerGetAllCategory.bind(this),
|
||||
);
|
||||
|
||||
this.homeView.addHandlerSubmitBudgetForm(
|
||||
@@ -44,6 +49,8 @@ export default class HomeController {
|
||||
);
|
||||
|
||||
this.homeView.addHandlerInputChangeBudgetForm();
|
||||
|
||||
this.homeView.handlerInputChangeCategoryDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export default class Category {
|
||||
constructor({ id, url, name }) {
|
||||
this.id = id;
|
||||
this.url = url;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import CommonService from './commonService';
|
||||
import Category from '../models/category';
|
||||
|
||||
export default class CategoryService extends CommonService {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.defaultPath = 'categories/';
|
||||
}
|
||||
|
||||
async getAllCategory() {
|
||||
const data = await this.getAllDataFromPath(this.defaultPath);
|
||||
const listCategory = [];
|
||||
|
||||
if (data) {
|
||||
data.forEach((category) => {
|
||||
listCategory.unshift(new Category(category));
|
||||
});
|
||||
|
||||
return listCategory;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -62,4 +62,16 @@ export default class CommonService {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async getAllDataFromPath(path = this.defaultPath) {
|
||||
this.connectToDb();
|
||||
|
||||
const result = await this.firebaseService.getAllDataFromPath(path);
|
||||
|
||||
const data = await timeOutConnect(result);
|
||||
|
||||
if (data) return data;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,35 @@ class FirebaseService {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
getAllDataFromPath(path) {
|
||||
return new Promise((resolve) => {
|
||||
onValue(
|
||||
ref(this.db, path),
|
||||
(snapshot) => {
|
||||
const data = [];
|
||||
|
||||
// snapshot is a type of data by Firebase define
|
||||
snapshot.forEach((childSnapshot) => {
|
||||
// const dataTemp = childSnapshot.val();
|
||||
|
||||
// if (dataTemp[property] === value) {
|
||||
// id = childSnapshot.key;
|
||||
// data = dataTemp;
|
||||
// }
|
||||
const id = childSnapshot.key;
|
||||
const val = childSnapshot.val();
|
||||
|
||||
data.push({ id, ...val });
|
||||
});
|
||||
resolve(data);
|
||||
},
|
||||
{
|
||||
onlyOnce: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new FirebaseService();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import CategoryService from './categoryService';
|
||||
import TransactionService from './transactionService';
|
||||
import UserService from './userService';
|
||||
import WalletService from './walletService';
|
||||
@@ -7,5 +8,6 @@ export default class Service {
|
||||
this.userService = new UserService();
|
||||
this.walletService = new WalletService();
|
||||
this.transactionService = new TransactionService();
|
||||
this.categoryService = new CategoryService();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,12 @@ export default class HomeView extends CommonView {
|
||||
this.walletDialog = document.getElementById('walletDialog');
|
||||
}
|
||||
|
||||
async loadPage(getInfoUserLogin, isValidWallet, getWalletByIdUser) {
|
||||
async loadPage(
|
||||
getInfoUserLogin,
|
||||
isValidWallet,
|
||||
getWalletByIdUser,
|
||||
getAllCategory,
|
||||
) {
|
||||
this.getWalletByIdUser = getWalletByIdUser; // Init function
|
||||
this.toggleLoaderSpinner();
|
||||
const user = await getInfoUserLogin();
|
||||
@@ -47,15 +52,89 @@ export default class HomeView extends CommonView {
|
||||
this.loadEvent();
|
||||
|
||||
// Init data
|
||||
this.loadData();
|
||||
this.loadData(getAllCategory);
|
||||
}
|
||||
}
|
||||
|
||||
this.toggleLoaderSpinner();
|
||||
}
|
||||
|
||||
async loadData() {
|
||||
const wallet = await this.getWalletByIdUser(this.user.id); // Get data wallet
|
||||
async loadData(getAllCategory) {
|
||||
await this.loadWalletUser();
|
||||
await this.loadCategory(getAllCategory);
|
||||
}
|
||||
|
||||
// ---------------------SELECTED CATEGORY DIALOG---------------------//
|
||||
/**
|
||||
* Load category data
|
||||
* @param {function} getAllCategory Get all category function
|
||||
*/
|
||||
async loadCategory(getAllCategory) {
|
||||
this.listCategory = await getAllCategory();
|
||||
|
||||
if (this.listCategory) {
|
||||
this.renderCategoryItem(this.listCategory);
|
||||
}
|
||||
}
|
||||
|
||||
handlerInputChangeCategoryDialog() {
|
||||
this.categoryDialog.addEventListener('input', () => {
|
||||
setTimeout(() => {
|
||||
this.searchCategory();
|
||||
}, 300);
|
||||
});
|
||||
}
|
||||
|
||||
searchCategory() {
|
||||
const searchCategoryEl =
|
||||
this.categoryDialog.querySelector("[name='category']");
|
||||
const searchValue = searchCategoryEl.value.trim().toLowerCase();
|
||||
let newListCategory = [];
|
||||
|
||||
if (searchValue) {
|
||||
this.listCategory.forEach((category) => {
|
||||
const categoryName = category.name.trim().toLowerCase();
|
||||
|
||||
if (categoryName.includes(searchValue)) {
|
||||
newListCategory.unshift(category);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
newListCategory = this.listCategory;
|
||||
}
|
||||
|
||||
// Render category item
|
||||
this.renderCategoryItem(newListCategory);
|
||||
}
|
||||
|
||||
renderCategoryItem(listCategory) {
|
||||
const listCategoryEl = document.querySelector('.list-category');
|
||||
|
||||
listCategoryEl.innerHTML = ''; // Remove old category item
|
||||
|
||||
listCategory.forEach((category) => {
|
||||
const markup = `
|
||||
<div class="category-item" value="${category.name}">
|
||||
<img
|
||||
class="icon-category"
|
||||
src="${category.url}"
|
||||
alt="${category.name} Icon"
|
||||
/>
|
||||
<p class="name-category">${category.name}</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
listCategoryEl.insertAdjacentHTML('afterbegin', markup);
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------------END DIALOG---------------------//
|
||||
|
||||
/**
|
||||
* Load wallet user
|
||||
*/
|
||||
async loadWalletUser() {
|
||||
const wallet = await this.getWalletByIdUser(this.user.id);
|
||||
const walletName = document.querySelector('.wallet__name');
|
||||
const walletPrice = document.querySelector('.wallet__price');
|
||||
const sign = wallet.amount >= 0 ? '+' : '-';
|
||||
|
||||
@@ -194,81 +194,7 @@
|
||||
</form>
|
||||
</div>
|
||||
<div class="dialog__body">
|
||||
<div class="list-category">
|
||||
<!-- Category item -->
|
||||
<div class="category-item">
|
||||
<img
|
||||
class="icon-category"
|
||||
src="../assets/images/ic_category_foodndrink.png.png"
|
||||
alt="Food & Beverage Icon"
|
||||
/>
|
||||
<p class="name-category">Food & Beverage</p>
|
||||
</div>
|
||||
<div class="category-item">
|
||||
<img
|
||||
class="icon-category"
|
||||
src="../assets/images/ic_category_foodndrink.png.png"
|
||||
alt="Food & Beverage Icon"
|
||||
/>
|
||||
<p class="name-category">Food & Beverage</p>
|
||||
</div>
|
||||
<div class="category-item">
|
||||
<img
|
||||
class="icon-category"
|
||||
src="../assets/images/ic_category_foodndrink.png.png"
|
||||
alt="Food & Beverage Icon"
|
||||
/>
|
||||
<p class="name-category">Food & Beverage</p>
|
||||
</div>
|
||||
<div class="category-item">
|
||||
<img
|
||||
class="icon-category"
|
||||
src="../assets/images/ic_category_foodndrink.png.png"
|
||||
alt="Food & Beverage Icon"
|
||||
/>
|
||||
<p class="name-category">Food & Beverage</p>
|
||||
</div>
|
||||
<div class="category-item">
|
||||
<img
|
||||
class="icon-category"
|
||||
src="../assets/images/ic_category_foodndrink.png.png"
|
||||
alt="Food & Beverage Icon"
|
||||
/>
|
||||
<p class="name-category">Food & Beverage</p>
|
||||
</div>
|
||||
<div class="category-item">
|
||||
<img
|
||||
class="icon-category"
|
||||
src="../assets/images/ic_category_foodndrink.png.png"
|
||||
alt="Food & Beverage Icon"
|
||||
/>
|
||||
<p class="name-category">Food & Beverage</p>
|
||||
</div>
|
||||
<div class="category-item">
|
||||
<img
|
||||
class="icon-category"
|
||||
src="../assets/images/ic_category_foodndrink.png.png"
|
||||
alt="Food & Beverage Icon"
|
||||
/>
|
||||
<p class="name-category">Food & Beverage</p>
|
||||
</div>
|
||||
<div class="category-item">
|
||||
<img
|
||||
class="icon-category"
|
||||
src="../assets/images/ic_category_foodndrink.png.png"
|
||||
alt="Food & Beverage Icon"
|
||||
/>
|
||||
<p class="name-category">Food & Beverage</p>
|
||||
</div>
|
||||
<div class="category-item">
|
||||
<img
|
||||
class="icon-category"
|
||||
src="../assets/images/ic_category_foodndrink.png.png"
|
||||
alt="Food & Beverage Icon"
|
||||
/>
|
||||
<p class="name-category">Food & Beverage</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-category"></div>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
@@ -412,5 +338,13 @@
|
||||
<!-- End app -->
|
||||
</div>
|
||||
<script type="module" src="../js/main.js"></script>
|
||||
<script>
|
||||
document
|
||||
.querySelector('.list-category')
|
||||
.addEventListener('click', (e) => {
|
||||
const value = e.target.getAttribute('value');
|
||||
alert(value);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -605,6 +605,11 @@
|
||||
color: $dark-gray;
|
||||
}
|
||||
|
||||
.icon-category {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.list-category {
|
||||
@extend %d-flex;
|
||||
@include flex-layout($direction: column);
|
||||
@@ -621,6 +626,13 @@
|
||||
margin-inline: 68px;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid $gray;
|
||||
transition: 0.3s;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover,
|
||||
&.selected {
|
||||
background-color: $hover-light-primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user