2026-07-05 03:37:35 +04:00
|
|
|
import { Component, ChangeDetectionStrategy, signal } from '@angular/core';
|
|
|
|
|
import { take } from 'rxjs/operators';
|
|
|
|
|
import { RouterLink } from '@angular/router';
|
2026-02-26 23:09:20 +04:00
|
|
|
import { TranslatePipe } from '../../i18n/translate.pipe';
|
2026-07-02 02:22:00 +04:00
|
|
|
import { LogoComponent } from '../logo/logo.component';
|
2026-07-03 01:58:08 +04:00
|
|
|
import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade';
|
2026-07-05 03:37:35 +04:00
|
|
|
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
|
|
|
|
import { ConfigService } from '../../core/config/config.service';
|
|
|
|
|
import { StaticPageResolverService } from '../../core/config/static-page-resolver.service';
|
|
|
|
|
import { BootstrapConfig, FooterNavigationGroupConfig, NavigationConfig, NavigationItemConfig, FooterNavigationItemConfig } from '../../shared/models/config';
|
|
|
|
|
import { LanguageService } from '../../services/language.service';
|
|
|
|
|
|
|
|
|
|
interface FooterResolvedItem {
|
|
|
|
|
id: string;
|
|
|
|
|
label: string;
|
|
|
|
|
route: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface FooterResolvedGroup {
|
|
|
|
|
id: string;
|
|
|
|
|
title: string;
|
|
|
|
|
items: FooterResolvedItem[];
|
|
|
|
|
}
|
2026-01-18 18:57:06 +04:00
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
|
selector: 'app-footer',
|
2026-07-05 03:37:35 +04:00
|
|
|
imports: [TranslatePipe, LogoComponent, RouterLink, LangRoutePipe],
|
2026-01-18 18:57:06 +04:00
|
|
|
templateUrl: './footer.component.html',
|
2026-02-19 01:23:25 +04:00
|
|
|
styleUrls: ['./footer.component.scss'],
|
|
|
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
2026-01-18 18:57:06 +04:00
|
|
|
})
|
|
|
|
|
export class FooterComponent {
|
2026-07-05 03:37:35 +04:00
|
|
|
readonly footerGroups = signal<FooterResolvedGroup[]>([]);
|
|
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
private readonly uiRuntime: UiRuntimeFacade,
|
|
|
|
|
private readonly configService: ConfigService,
|
|
|
|
|
private readonly staticPageResolver: StaticPageResolverService,
|
|
|
|
|
private readonly languageService: LanguageService
|
|
|
|
|
) {
|
|
|
|
|
this.configService.loadBootstrap().pipe(take(1)).subscribe({
|
|
|
|
|
next: bootstrap => {
|
|
|
|
|
this.footerGroups.set(this.resolveFooterGroups(bootstrap));
|
|
|
|
|
},
|
|
|
|
|
error: () => {
|
|
|
|
|
this.footerGroups.set([]);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-07-03 01:58:08 +04:00
|
|
|
|
2026-01-18 18:57:06 +04:00
|
|
|
currentYear = new Date().getFullYear();
|
2026-07-03 01:58:08 +04:00
|
|
|
|
|
|
|
|
get brandName(): string {
|
2026-07-05 00:38:21 +04:00
|
|
|
return this.uiRuntime.marketplaceName();
|
2026-07-03 01:58:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get contactEmail(): string {
|
|
|
|
|
return this.uiRuntime.contactEmail();
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-05 03:37:35 +04:00
|
|
|
private resolveFooterGroups(bootstrap: BootstrapConfig): FooterResolvedGroup[] {
|
|
|
|
|
const footer = bootstrap.navigation?.footer ?? [];
|
|
|
|
|
const lang = this.languageService.currentLanguage();
|
|
|
|
|
|
|
|
|
|
if (this.isGroupedFooter(footer)) {
|
|
|
|
|
return footer
|
|
|
|
|
.map((group, index) => this.resolveGroupFromConfig(group, bootstrap, lang, index))
|
|
|
|
|
.filter((group): group is FooterResolvedGroup => group != null && group.items.length > 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const items = (footer as NavigationItemConfig[])
|
|
|
|
|
.map(item => this.resolveLegacyItem(item, bootstrap, lang))
|
|
|
|
|
.filter((item): item is FooterResolvedItem => item != null);
|
|
|
|
|
|
|
|
|
|
if (!items.length) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [{
|
|
|
|
|
id: 'footer-group-default',
|
|
|
|
|
title: '',
|
|
|
|
|
items
|
|
|
|
|
}];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resolveGroupFromConfig(
|
|
|
|
|
group: FooterNavigationGroupConfig,
|
|
|
|
|
bootstrap: BootstrapConfig,
|
|
|
|
|
lang: string,
|
|
|
|
|
index: number
|
|
|
|
|
): FooterResolvedGroup | null {
|
|
|
|
|
const items = (group.items ?? [])
|
|
|
|
|
.map(item => this.resolveGroupItem(item, bootstrap, lang))
|
|
|
|
|
.filter((item): item is FooterResolvedItem => item != null);
|
|
|
|
|
|
|
|
|
|
if (!items.length) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: `footer-group-${index}`,
|
|
|
|
|
title: this.staticPageResolver.resolveFooterTitle(group.groupTitle, lang),
|
|
|
|
|
items
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resolveGroupItem(
|
|
|
|
|
item: FooterNavigationItemConfig,
|
|
|
|
|
bootstrap: BootstrapConfig,
|
|
|
|
|
lang: string
|
|
|
|
|
): FooterResolvedItem | null {
|
|
|
|
|
if (item.visible === false) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.type === 'staticPage' && item.key) {
|
|
|
|
|
const staticPage = this.staticPageResolver.resolveByKeyFromBootstrap(bootstrap, item.key, lang);
|
|
|
|
|
if (!staticPage) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: `static-${item.key}`,
|
|
|
|
|
label: staticPage.title,
|
|
|
|
|
route: staticPage.route
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const label = typeof item.label === 'string'
|
|
|
|
|
? item.label
|
|
|
|
|
: this.staticPageResolver.resolveFooterTitle(item.label, lang);
|
|
|
|
|
|
|
|
|
|
if (!item.route || !label) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: `${item.type}-${label}`,
|
|
|
|
|
label,
|
|
|
|
|
route: item.route
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resolveLegacyItem(item: NavigationItemConfig, bootstrap: BootstrapConfig, lang: string): FooterResolvedItem | null {
|
|
|
|
|
if (item.visible === false) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.type === 'staticPage' && item.key) {
|
|
|
|
|
const staticPage = this.staticPageResolver.resolveByKeyFromBootstrap(bootstrap, item.key, lang);
|
|
|
|
|
if (!staticPage) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: item.id,
|
|
|
|
|
label: staticPage.title,
|
|
|
|
|
route: staticPage.route
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!item.route) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: item.id,
|
|
|
|
|
label: item.labelKey ?? item.id,
|
|
|
|
|
route: item.route
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private isGroupedFooter(footer: NavigationConfig['footer']): footer is FooterNavigationGroupConfig[] {
|
|
|
|
|
return Array.isArray(footer) && footer.length > 0 && 'items' in footer[0];
|
|
|
|
|
}
|
2026-01-18 18:57:06 +04:00
|
|
|
}
|