import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { ProjectEditorFacade } from '../facade/project-editor.facade'; import { TranslatePipe } from '../../../i18n/translate.pipe'; import { NavigationItemConfig } from '../../../shared/models/config'; import { ButtonComponent } from '../../../shared/ui/button/button.component'; import { InputComponent } from '../../../shared/ui/input/input.component'; import { SectionCardComponent } from '../../../shared/ui/section-card/section-card.component'; import { ToggleComponent } from '../../../shared/ui/toggle/toggle.component'; import { LocaleTabsComponent } from '../../../shared/ui/locale-tabs/locale-tabs.component'; @Component({ selector: 'app-project-editor-navigation-section', standalone: true, imports: [FormsModule, TranslatePipe, ButtonComponent, InputComponent, SectionCardComponent, ToggleComponent, LocaleTabsComponent], templateUrl: './navigation-section.component.html', styleUrls: ['./section.shared.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) export class ProjectEditorNavigationSectionComponent { private readonly facade = inject(ProjectEditorFacade); readonly bootstrap = this.facade.bootstrap; readonly supportedLocales = computed(() => this.bootstrap()?.tenant.supportedLocales ?? []); readonly defaultLocale = computed(() => this.bootstrap()?.tenant.defaultLocale ?? ''); readonly activeLocale = signal(null); readonly headerLinks = computed(() => this.sorted(this.bootstrap()?.navigation.header ?? [])); readonly footerLinks = computed(() => { const footer = this.bootstrap()?.navigation.footer ?? []; if (footer.length === 0) { return []; } return 'items' in footer[0] ? null : this.sorted(footer as NavigationItemConfig[]); }); onActiveLocaleChange(locale: string): void { this.activeLocale.set(locale); } /** Display label used for the row heading — a stable identifier, not tied to the active locale. */ labelOf(item: NavigationItemConfig): string { if (typeof item.label === 'string' || !item.label) { return item.label ?? ''; } const defaultLocale = this.bootstrap()?.localization.defaultLocale ?? 'en'; return item.label[defaultLocale] ?? Object.values(item.label)[0] ?? ''; } /** Editable label for the currently active locale tab. Falls back to an empty string * when this locale has no translation yet, so switching locales lets you fill it in. */ editableLabel(item: NavigationItemConfig): string { const locale = this.activeLocale() ?? this.defaultLocale(); if (!item.label) { return ''; } if (typeof item.label === 'string') { return locale === this.defaultLocale() ? item.label : ''; } return item.label[locale] ?? ''; } addLink(target: 'header' | 'footer'): void { this.facade.addNavLink(target); } removeLink(target: 'header' | 'footer', id: string): void { this.facade.removeNavLink(target, id); } move(target: 'header' | 'footer', id: string, direction: -1 | 1): void { this.facade.reorderNavLink(target, id, direction); } updateLabel(target: 'header' | 'footer', id: string, value: string): void { const locale = this.activeLocale() ?? this.defaultLocale(); this.facade.updateNavLinkLabel(target, id, value, locale); } updateRoute(target: 'header' | 'footer', id: string, value: string): void { this.facade.updateNavLink(target, id, { route: value }); } updateVisible(target: 'header' | 'footer', id: string, value: boolean): void { this.facade.updateNavLink(target, id, { visible: value }); } private sorted(items: NavigationItemConfig[]): NavigationItemConfig[] { return [...items].sort((a, b) => (a.order ?? 0) - (b.order ?? 0)); } }