import { Component, computed, CUSTOM_ELEMENTS_SCHEMA, EventEmitter, inject, Input, OnInit, Output, signal } from '@angular/core'; import {Route, Router, RouterLink, RouterLinkActive} from '@angular/router'; import {MatListItem, MatListItemIcon, MatListItemTitle, MatNavList} from '@angular/material/list'; import {NgForOf} from '@angular/common'; import {MatIconButton} from '@angular/material/button'; import {MatTooltip} from '@angular/material/tooltip'; import {MatIcon} from '@angular/material/icon'; import {adminRouting} from '../../modules/admin-module/admin.routing'; export interface NavItem { path: string; // absolute path like /dashboard title: string; // label to show icon?: string; // material icon name exact?: boolean; // whether to match exactly } @Component({ selector: 'app-vertical-nav', imports: [ MatTooltip, MatIcon, MatListItemIcon, MatListItemTitle, RouterLinkActive, RouterLink, MatListItem, MatNavList, NgForOf, MatIconButton, ], templateUrl: './vertical-nav.component.html', styleUrl: './vertical-nav.component.scss', schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class VerticalNavComponent implements OnInit{ private router = inject(Router); // Optional: if you want to pass items directly instead of deriving from routes @Input() items: NavItem[] | null = null; // Optional: pass a specific Route[] (e.g., ADMIN_ROUTES). If not provided, uses router.config. @Input() routes: Route[] = []; // Optional: prepend a base path (e.g., '/admin') when using feature routes. @Input() basePath = ''; // Sidebar state (expanded/collapsed) opened = signal(true); navItems = signal([]); readonly hasItems = computed(() => (this.items?.length ?? this.navItems().length) > 0); @Output() collapsedChange = new EventEmitter(); constructor() { } ngOnInit(): void { this.navItems.set(this.deriveFromRoutes(this.routes, this.basePath)); } toggle(): void { this.opened.update(v => !v); this.collapsedChange.emit(!this.opened()); } private deriveFromRoutes(routes: Route[], base: string): NavItem[] { // Flatten one level; you can make this recursive if needed const items: NavItem[] = []; for (const r of routes) { if (!r || r.path === '**') continue; const data = (r as any).data || {}; const seg = r.path || ''; const nextBase = [base, seg].filter(Boolean).join('/'); /* // Recurse into children if present (common in feature modules) if (r.children && r.children.length) { items.push(...this.deriveFromRoutes(r.children, nextBase)); } */ if (data.nav === false) continue; const title = data.title as string | undefined; if (!title) continue; const icon = data.icon as string | undefined; const full = '/' + nextBase.replace(/\/+/g, '/'); items.push({ path: full, title, icon, exact: true }); } return items; } }