import { BreakpointObserver } from '@angular/cdk/layout'; import { CommonModule } from '@angular/common'; import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { NavigationEnd, Router, RouterModule } from '@angular/router'; import { faUserGear } from '@fortawesome/free-solid-svg-icons'; import { Collapse, Dropdown, initFlowbite } from 'flowbite'; import { KeycloakService } from 'keycloak-angular'; import onChange from 'on-change'; import { filter, Observable, Subject, Subscription } from 'rxjs'; import { User } from '../../../../../bizmatch-server/src/models/db.model'; import { BusinessListingCriteria, CommercialPropertyListingCriteria, emailToDirName, KeycloakUser, UserListingCriteria } from '../../../../../bizmatch-server/src/models/main.model'; import { environment } from '../../../environments/environment'; import { CriteriaChangeService } from '../../services/criteria-change.service'; import { SearchService } from '../../services/search.service'; import { SharedService } from '../../services/shared.service'; import { UserService } from '../../services/user.service'; import { compareObjects, createEmptyBusinessListingCriteria, createEmptyCommercialPropertyListingCriteria, createEmptyUserListingCriteria, getCriteriaStateObject, map2User } from '../../utils/utils'; import { DropdownComponent } from '../dropdown/dropdown.component'; import { ModalService } from '../search-modal/modal.service'; @Component({ selector: 'header', standalone: true, imports: [CommonModule, RouterModule, DropdownComponent, FormsModule], templateUrl: './header.component.html', styleUrl: './header.component.scss', }) export class HeaderComponent { public buildVersion = environment.buildVersion; user$: Observable; keycloakUser: KeycloakUser; user: User; activeItem; faUserGear = faUserGear; profileUrl: string; env = environment; private filterDropdown: Dropdown | null = null; isMobile: boolean = false; private destroy$ = new Subject(); prompt: string; private subscription: Subscription; criteria: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria; private routerSubscription: Subscription | undefined; baseRoute: string; constructor( public keycloakService: KeycloakService, private router: Router, private userService: UserService, private sharedService: SharedService, private breakpointObserver: BreakpointObserver, private modalService: ModalService, private searchService: SearchService, private criteriaChangeService: CriteriaChangeService, ) {} async ngOnInit() { const token = await this.keycloakService.getToken(); this.keycloakUser = map2User(token); if (this.keycloakUser) { this.user = await this.userService.getByMail(this.keycloakUser?.email); this.profileUrl = this.user.hasProfile ? `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`; } setTimeout(() => { initFlowbite(); }, 10); this.sharedService.currentProfilePhoto.subscribe(photoUrl => { if (photoUrl) { this.profileUrl = photoUrl; } }); this.checkCurrentRoute(this.router.url); this.routerSubscription = this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event: any) => { this.checkCurrentRoute(event.urlAfterRedirects); }); } private checkCurrentRoute(url: string): void { this.baseRoute = url.split('/')[1]; // Nimmt den ersten Teil der Route nach dem ersten '/' const specialRoutes = [, '', '']; if ('businessListings' === this.baseRoute) { //this.criteria = onChange(getCriteriaStateObject('business'), getSessionStorageHandlerWrapper('business')); //this.criteria = onChange(getCriteriaStateObject('business'), this.getSessionStorageHandler); this.criteria = this.createEnhancedProxy(getCriteriaStateObject('business')); } else if ('commercialPropertyListings' === this.baseRoute) { // this.criteria = onChange(getCriteriaStateObject('commercialProperty'), getSessionStorageHandlerWrapper('commercialProperty')); this.criteria = this.createEnhancedProxy(getCriteriaStateObject('commercialProperty')); } else if ('brokerListings' === this.baseRoute) { // this.criteria = onChange(getCriteriaStateObject('broker'), getSessionStorageHandlerWrapper('broker')); this.criteria = this.createEnhancedProxy(getCriteriaStateObject('broker')); } else { this.criteria = undefined; } } private createEnhancedProxy(obj: any) { const component = this; const sessionStorageHandler = function (path, value, previous, applyData) { let criteriaType = ''; if ('/businessListings' === window.location.pathname) { criteriaType = 'business'; } else if ('/commercialPropertyListings' === window.location.pathname) { criteriaType = 'commercialProperty'; } else if ('/brokerListings' === window.location.pathname) { criteriaType = 'broker'; } sessionStorage.setItem(`${criteriaType}_criteria`, JSON.stringify(this)); }; return onChange(obj, function (path, value, previous, applyData) { // Call the original sessionStorageHandler sessionStorageHandler.call(this, path, value, previous, applyData); // Notify about the criteria change using the component's context component.criteriaChangeService.notifyCriteriaChange(); }); } ngAfterViewInit() {} async openModal() { const accepted = await this.modalService.showModal(this.criteria); if (accepted) { this.searchService.search(this.criteria); } } navigateWithState(dest: string, state: any) { this.router.navigate([dest], { state: state }); } login() { this.keycloakService.login({ redirectUri: window.location.href, }); } register() { this.keycloakService.register({ redirectUri: `${window.location.origin}/account` }); } isActive(route: string): boolean { return this.router.url === route; } isListingUrl(): boolean { return ['/businessListings', '/commercialPropertyListings', '/brokerListings'].includes(this.router.url); } closeDropdown() { const dropdownButton = document.getElementById('user-menu-button'); const dropdownMenu = this.user ? document.getElementById('user-login') : document.getElementById('user-unknown'); if (dropdownButton && dropdownMenu) { const dropdown = new Dropdown(dropdownMenu, dropdownButton); dropdown.hide(); } } closeMobileMenu() { const targetElement = document.getElementById('navbar-user'); const triggerElement = document.querySelector('[data-collapse-toggle="navbar-user"]'); if (targetElement instanceof HTMLElement && triggerElement instanceof HTMLElement) { const collapse = new Collapse(targetElement, triggerElement); collapse.collapse(); } } closeMenus() { this.closeDropdown(); this.closeMobileMenu(); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } getNumberOfFiltersSet() { if (this.criteria?.criteriaType === 'broker') { return compareObjects(createEmptyUserListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius']); } else if (this.criteria?.criteriaType === 'business') { return compareObjects(createEmptyBusinessListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius']); } else if (this.criteria?.criteriaType === 'commercialProperty') { return compareObjects(createEmptyCommercialPropertyListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius']); } else { return 0; } } }