import { Injectable, inject } 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'; export interface DisplayableCategory { id: string; name: string; subCategories: DisplayableSubCategory[]; isOpenned: boolean; } export interface DisplayableSubCategory { id: string; name: string; } @Injectable({ providedIn: 'root' }) export class SideMenuService { private categoryRestService = inject(CategoryRestService); private snackBar = inject(MatSnackBar); private categoriesSubject = new BehaviorSubject([]); private isLoadingSubject = new BehaviorSubject(false); private isLoadedSubject = new BehaviorSubject(false); private mapToDisplayableCategory(category: Category): DisplayableCategory { return { id: category.id, name: category.name, subCategories: category.subCategories.map(subCategory => this.mapToDisplayableSubCategory(subCategory)), isOpenned: false }; } private mapToDisplayableSubCategory(subCategory: Category): DisplayableSubCategory { return { id: subCategory.id, name: subCategory.name } } private get categories(): DisplayableCategory[] { return this.categoriesSubject.value; } private save(categories: DisplayableCategory[]): void { this.categoriesSubject.next(categories); } get categories$(): Observable { return this.categoriesSubject.asObservable(); } get isLoading$(): Observable { return this.isLoadingSubject.asObservable(); } loadCategories(): void { this.isLoadingSubject.next(true); this.isLoadedSubject.next(false); this.categoryRestService.getCategories() .then(categories => { const displayableCategories = categories .filter(category => category.subCategories?.length) .map(category => this.mapToDisplayableCategory(category)); this.categoriesSubject.next(displayableCategories); }) .catch(error => { const errorMessage = $localize`An error occured while loading categories.`; console.error(errorMessage, error); this.snackBar.open(errorMessage, $localize`Close`, { duration: 5000 }); }) .finally(() => { this.isLoadingSubject.next(false); this.isLoadedSubject.next(true); }); } setOpenned(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); if (actualOpennedCategory && actualOpennedCategory.id === matchingCategory.id) { matchingCategory.isOpenned = false; } else { categories.forEach(categoryTemp => categoryTemp.isOpenned = false); matchingCategory.isOpenned = true; } this.save(categories); } } }