import { Component, ChangeDetectionStrategy, Renderer2, inject, DOCUMENT, computed } from '@angular/core'; import { Router, RouterLink, RouterLinkActive } from '@angular/router'; import { CartService } from '../../services/cart.service'; import { LanguageService } from '../../services/language.service'; import { LogoComponent } from '../logo/logo.component'; import { LanguageSelectorComponent } from '../language-selector/language-selector.component'; import { RegionSelectorComponent } from '../region-selector/region-selector.component'; import { LangRoutePipe } from '../../pipes/lang-route.pipe'; import { TranslatePipe } from '../../i18n/translate.pipe'; import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade'; import { UserExperienceFacade } from '../../facades/platform/user-experience.facade'; import { ConfigService } from '../../core/config/config.service'; import { FeatureConfigService } from '../../core/config/feature-config.service'; import { DEFAULT_HEADER_CONFIG, DEFAULT_USER_EXPERIENCE_CONFIG } from '../../shared/models/config'; import { StaticPageResolverService } from '../../core/config/static-page-resolver.service'; import { IconComponent } from '../../shared/ui/icon/icon.component'; import { AuthService } from '../../services/auth.service'; import { TelegramLoginComponent } from '../telegram-login/telegram-login.component'; @Component({ selector: 'app-header', imports: [RouterLink, RouterLinkActive, LogoComponent, LanguageSelectorComponent, RegionSelectorComponent, LangRoutePipe, TranslatePipe, IconComponent, TelegramLoginComponent], templateUrl: './header.component.html', styleUrls: ['./header.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) export class HeaderComponent { cartItemCount; cartTotal; menuOpen = false; private renderer = inject(Renderer2); private document = inject(DOCUMENT); private langService = inject(LanguageService); private uiRuntime = inject(UiRuntimeFacade); private uxFacade = inject(UserExperienceFacade); private configService = inject(ConfigService); private featureConfig = inject(FeatureConfigService); private staticPageResolver = inject(StaticPageResolverService); private authService = inject(AuthService); readonly isAuthenticated = this.authService.isAuthenticated; readonly wishlistCount = this.uxFacade.wishlistCount; readonly compareCount = this.uxFacade.compareCount; readonly userExperienceConfig = computed(() => this.resolveUserExperienceConfig()); readonly headerConfig = computed(() => this.resolveHeaderConfig()); readonly features = this.featureConfig.features; readonly headerPages = computed(() => this.resolveHeaderPages()); constructor(private cartService: CartService, private router: Router) { this.cartItemCount = this.cartService.itemCount; this.cartTotal = this.cartService.totalPrice; } get brandName(): string { return this.uiRuntime.marketplaceDisplayName(); } get logo(): string { return this.uiRuntime.logoUrl(); } get homeUrl(): string { return `/${this.langService.currentLanguage()}`; } toggleMenu(): void { this.menuOpen = !this.menuOpen; if (this.menuOpen) { this.renderer.addClass(this.document.body, 'platform-menu-open'); } else { this.renderer.removeClass(this.document.body, 'platform-menu-open'); } } closeMenu(): void { this.menuOpen = false; this.renderer.removeClass(this.document.body, 'platform-menu-open'); } navigateHome(event?: Event): void { event?.preventDefault(); this.closeMenu(); const homeUrl = this.homeUrl; const currentUrl = this.router.url.split('?')[0].split('#')[0]; if (currentUrl === homeUrl || currentUrl === `${homeUrl}/`) { this.document.defaultView?.scrollTo({ top: 0, behavior: 'smooth' }); return; } this.router.navigateByUrl(homeUrl).then(() => { this.document.defaultView?.scrollTo({ top: 0, behavior: 'auto' }); }); } navigateToSearch(): void { const lang = this.langService.currentLanguage(); this.router.navigate([`/${lang}/search`]); } navigateToCatalog(): void { this.closeMenu(); const lang = this.langService.currentLanguage(); this.router.navigate([`/${lang}`]).then(() => { setTimeout(() => { this.document.getElementById('catalog')?.scrollIntoView({ behavior: 'smooth' }); }, 100); }); } navigateToWishlist(): void { this.closeMenu(); const lang = this.langService.currentLanguage(); this.router.navigate([`/${lang}/wishlist`]); } navigateToCompare(): void { this.closeMenu(); const lang = this.langService.currentLanguage(); this.router.navigate([`/${lang}/compare`]); } login(): void { this.authService.requestLogin(); } logout(): void { this.authService.logout(); } navigateToStatic(route: string): void { this.closeMenu(); const lang = this.langService.currentLanguage(); this.router.navigate([`/${lang}${route.startsWith('/') ? route : `/${route}`}`]); } formatCartTotal(total: number): string { const locale = this.langService.currentLanguage() === 'en' ? 'en-US' : this.langService.currentLanguage() === 'hy' ? 'hy-AM' : 'ru-RU'; const fractionDigits = Number.isInteger(total) ? 0 : 2; const amount = new Intl.NumberFormat(locale, { minimumFractionDigits: fractionDigits, maximumFractionDigits: 2, }).format(total); const currencySymbol = this.langService.getCurrentCurrency()?.symbol ?? this.langService.currentCurrency(); return `${amount} ${currencySymbol}`; } private resolveUserExperienceConfig() { this.configService.bootstrapRevision(); const raw = (this.configService.getBootstrapSnapshot() as any)?.userExperience ?? {}; return { ...DEFAULT_USER_EXPERIENCE_CONFIG, ...raw, wishlist: { ...DEFAULT_USER_EXPERIENCE_CONFIG.wishlist, ...(raw.wishlist ?? {}) }, compare: { ...DEFAULT_USER_EXPERIENCE_CONFIG.compare, ...(raw.compare ?? {}) } }; } private resolveHeaderConfig() { this.configService.bootstrapRevision(); const raw = (this.configService.getBootstrapSnapshot() as any)?.header ?? {}; return { ...DEFAULT_HEADER_CONFIG, ...raw, }; } private resolveHeaderPages() { this.configService.bootstrapRevision(); const bootstrap = this.configService.getBootstrapSnapshot(); if (!bootstrap?.staticPages) { return [] as Array<{ id: string; title: string; route: string; icon?: string; order: number }>; } const lang = this.langService.currentLanguage(); const pages = Object.values(bootstrap.staticPages as Record) .filter(page => page.showInHeader === true) .map(page => { const resolved = this.staticPageResolver.resolveByKeyFromBootstrap(bootstrap, page.id, lang); return resolved ? { id: resolved.id, title: resolved.title, route: resolved.route, icon: resolved.icon, order: page.order ?? 0, } : null; }) .filter((page): page is { id: string; title: string; route: string; icon: string | undefined; order: number } => page !== null); return pages.sort((left, right) => left.order - right.order); } }