Compare commits
1 Commits
4469000695
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f33b55b1c8 |
@@ -1,6 +1,6 @@
|
||||
@for (category of categories$ | async; track category) {
|
||||
@for (category of categories(); track category.id) {
|
||||
<div class="category {{category.isOpenned ? 'openned' : ''}}">
|
||||
<div id="category-{{category.id}}" class="category-header" (click)="setOpenned(category)">
|
||||
<div id="category-{{category.id}}" class="category-header" (click)="setOpened(category)">
|
||||
{{ category.name }}
|
||||
<mat-icon>chevron_right</mat-icon>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {Component, EventEmitter, inject, OnInit, Output} from "@angular/core";
|
||||
import {Component, inject, OnInit, output, Signal} from "@angular/core";
|
||||
import {MatIconModule} from "@angular/material/icon";
|
||||
import {DisplayableCategory, SideMenuService} from "../side-menu.service";
|
||||
import {Observable} from "rxjs";
|
||||
import {RouterModule} from "@angular/router";
|
||||
|
||||
@Component({
|
||||
@@ -16,45 +15,44 @@ import {RouterModule} from "@angular/router";
|
||||
styleUrl: './categories-menu.component.scss'
|
||||
})
|
||||
export class CategoriesMenuComponent implements OnInit {
|
||||
private sideMenuService = inject(SideMenuService);
|
||||
@Output()
|
||||
categoryClicked = new EventEmitter<void>();
|
||||
readonly #sideMenuService = inject(SideMenuService);
|
||||
categoryClicked = output<void>();
|
||||
|
||||
ngOnInit(): void {
|
||||
this.sideMenuService.loadCategories();
|
||||
this.#sideMenuService.loadCategories();
|
||||
}
|
||||
|
||||
get categories$(): Observable<DisplayableCategory[]> {
|
||||
return this.sideMenuService.categories$;
|
||||
get categories(): Signal<DisplayableCategory[]> {
|
||||
return this.#sideMenuService.categories;
|
||||
}
|
||||
|
||||
setOpenned(category: DisplayableCategory): void {
|
||||
setOpened(category: DisplayableCategory): void {
|
||||
if (category.isOpenned) {
|
||||
const categoryDiv = document.getElementById(`category-${category.id}`);
|
||||
if (categoryDiv) {
|
||||
this.closeAccordion(categoryDiv);
|
||||
this.#closeAccordion(categoryDiv);
|
||||
}
|
||||
} else {
|
||||
const categoriesDivs = document.getElementsByClassName('category-header');
|
||||
Array.from(categoriesDivs)
|
||||
.map(category => category as HTMLElement)
|
||||
.forEach(categoryDiv => this.closeAccordion(categoryDiv));
|
||||
.forEach(categoryDiv => this.#closeAccordion(categoryDiv));
|
||||
|
||||
const categoryDiv = document.getElementById(`category-${category.id}`);
|
||||
if (categoryDiv) {
|
||||
this.openAccordion(categoryDiv);
|
||||
this.#openAccordion(categoryDiv);
|
||||
}
|
||||
}
|
||||
|
||||
this.sideMenuService.setOpenned(category);
|
||||
this.#sideMenuService.setOpened(category);
|
||||
}
|
||||
|
||||
private closeAccordion(categoryDiv: HTMLElement): void {
|
||||
#closeAccordion(categoryDiv: HTMLElement): void {
|
||||
const divContent = categoryDiv?.nextElementSibling as HTMLElement;
|
||||
divContent.style.maxHeight = '0';
|
||||
}
|
||||
|
||||
private openAccordion(categoryDiv: HTMLElement): void {
|
||||
#openAccordion(categoryDiv: HTMLElement): void {
|
||||
const divContent = categoryDiv?.nextElementSibling as HTMLElement;
|
||||
divContent.style.maxHeight = `${divContent.scrollHeight}px`;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
</button>
|
||||
</h1>
|
||||
<h2 i18n>Categories</h2>
|
||||
<app-categories-menu (categoryClicked)="close()"></app-categories-menu>
|
||||
<app-categories-menu (categoryClicked)="close()"/>
|
||||
</div>
|
||||
<div class="overlay {{ isOpened() ? 'displayed' : ''}}" (click)="close()"></div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {inject, Injectable} from '@angular/core';
|
||||
import {inject, Injectable, Signal, signal} from '@angular/core';
|
||||
import {MatSnackBar} from '@angular/material/snack-bar';
|
||||
import {BehaviorSubject, Observable} from 'rxjs';
|
||||
import {CategoryRestService} from '../../core/rest-services/category/category.rest-service';
|
||||
import {Category} from '../../core/rest-services/category/model/category';
|
||||
|
||||
@@ -20,68 +19,60 @@ export interface DisplayableSubCategory {
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SideMenuService {
|
||||
private categoryRestService = inject(CategoryRestService);
|
||||
private snackBar = inject(MatSnackBar);
|
||||
private categoriesSubject = new BehaviorSubject<DisplayableCategory[]>([]);
|
||||
private isLoadingSubject = new BehaviorSubject<boolean>(false);
|
||||
private isLoadedSubject = new BehaviorSubject<boolean>(false);
|
||||
readonly #categoryRestService = inject(CategoryRestService);
|
||||
readonly #snackBar = inject(MatSnackBar);
|
||||
#categories = signal<DisplayableCategory[]>([]);
|
||||
#isLoading = signal(false);
|
||||
isLoaded = signal(false);
|
||||
|
||||
private mapToDisplayableCategory(category: Category): DisplayableCategory {
|
||||
#mapToDisplayableCategory(category: Category): DisplayableCategory {
|
||||
return {
|
||||
id: category.id,
|
||||
name: category.name,
|
||||
subCategories: category.subCategories.map(subCategory => this.mapToDisplayableSubCategory(subCategory)),
|
||||
subCategories: category.subCategories.map(subCategory => this.#mapToDisplayableSubCategory(subCategory)),
|
||||
isOpenned: false
|
||||
};
|
||||
}
|
||||
|
||||
private mapToDisplayableSubCategory(subCategory: Category): DisplayableSubCategory {
|
||||
#mapToDisplayableSubCategory(subCategory: Category): DisplayableSubCategory {
|
||||
return {
|
||||
id: subCategory.id,
|
||||
name: subCategory.name
|
||||
}
|
||||
}
|
||||
|
||||
private get categories(): DisplayableCategory[] {
|
||||
return this.categoriesSubject.value;
|
||||
get categories(): Signal<DisplayableCategory[]> {
|
||||
return this.#categories.asReadonly();
|
||||
}
|
||||
|
||||
private save(categories: DisplayableCategory[]): void {
|
||||
this.categoriesSubject.next(categories);
|
||||
}
|
||||
|
||||
get categories$(): Observable<DisplayableCategory[]> {
|
||||
return this.categoriesSubject.asObservable();
|
||||
}
|
||||
|
||||
get isLoading$(): Observable<boolean> {
|
||||
return this.isLoadingSubject.asObservable();
|
||||
get isLoading(): Signal<boolean> {
|
||||
return this.#isLoading.asReadonly();
|
||||
}
|
||||
|
||||
loadCategories(): void {
|
||||
this.isLoadingSubject.next(true);
|
||||
this.isLoadedSubject.next(false);
|
||||
this.#isLoading.set(true);
|
||||
this.isLoaded.set(false);
|
||||
|
||||
this.categoryRestService.getCategories()
|
||||
this.#categoryRestService.getCategories()
|
||||
.then(categories => {
|
||||
const displayableCategories = categories
|
||||
.filter(category => category.subCategories?.length)
|
||||
.map(category => this.mapToDisplayableCategory(category));
|
||||
this.categoriesSubject.next(displayableCategories);
|
||||
.map(category => this.#mapToDisplayableCategory(category));
|
||||
this.#categories.set(displayableCategories);
|
||||
})
|
||||
.catch(error => {
|
||||
const errorMessage = $localize`An error occured while loading categories.`;
|
||||
console.error(errorMessage, error);
|
||||
this.snackBar.open(errorMessage, $localize`Close`, {duration: 5000});
|
||||
this.#snackBar.open(errorMessage, $localize`Close`, {duration: 5000});
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoadingSubject.next(false);
|
||||
this.isLoadedSubject.next(true);
|
||||
this.#isLoading.set(false);
|
||||
this.isLoaded.set(true);
|
||||
});
|
||||
}
|
||||
|
||||
setOpenned(category: DisplayableCategory): void {
|
||||
const categories = this.categories;
|
||||
setOpened(category: DisplayableCategory): void {
|
||||
const categories = this.#categories();
|
||||
const matchingCategory = categories.find(categoryTemp => categoryTemp.id === category.id);
|
||||
if (matchingCategory) {
|
||||
const actualOpennedCategory = categories.find(category => category.isOpenned);
|
||||
@@ -91,7 +82,7 @@ export class SideMenuService {
|
||||
categories.forEach(categoryTemp => categoryTemp.isOpenned = false);
|
||||
matchingCategory.isOpenned = true;
|
||||
}
|
||||
this.save(categories);
|
||||
this.#categories.set(categories);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user