feat(account-page): implement dynamic account navigation menus in sidebar and user dropdown

This commit is contained in:
2026-07-24 09:58:18 -03:00
parent fa0e9de886
commit 974f947fc6
12 changed files with 243 additions and 60 deletions

View File

@@ -1,11 +1,11 @@
<div class="sidebar-container">
<h2 class="sidebar-title">MI CUENTA</h2>
<div class="divider"></div>
<nav class="sidebar-nav">
<a routerLink="/mi-cuenta/datos-personales" routerLinkActive="active" class="nav-link"
>Datos Personales</a
>
<a routerLink="/mi-cuenta/compras" routerLinkActive="active" class="nav-link">Mis compras</a>
<a routerLink="/mi-cuenta/tickets" routerLinkActive="active" class="nav-link">Mis tickets</a>
<nav class="sidebar-nav" aria-label="Secciones de mi cuenta">
@for (menu of submenues(); track menu.code) {
<a [routerLink]="menu.route" routerLinkActive="active" class="nav-link">
{{ menuLabel(menu) }}
</a>
}
</nav>
</div>

View File

@@ -0,0 +1,80 @@
import { signal } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import { describe, expect, it } from 'vitest';
import { Tenant } from '../../../../../../core/services/tenant.interface';
import { TenantService } from '../../../../../../core/services/tenant.service';
import { AccountSidebar } from './account-sidebar';
describe('AccountSidebar', () => {
it('renders only the account submenus configured for the tenant', async () => {
const tenant = signal<Tenant>({
id: 1,
codigo: 'test',
nombre: 'Test',
dominio: 'localhost',
primary_color: '#000000',
secondary_color: '#000000',
danger_color: '#000000',
success_color: '#000000',
header_bg_color: '#ffffff',
footer_bg_color: '#ffffff',
header_logo: '',
footer_logo: '',
menues: [
{
id: 1,
code: 'account',
parent_menu_code: null,
content_type: 'dynamic',
route: '/mi-cuenta',
submenues: [
{
id: 2,
code: 'profile',
parent_menu_code: 'account',
content_type: 'dynamic',
route: '/mi-cuenta/datos-personales',
submenues: [],
},
{
id: 3,
code: 'purchases',
parent_menu_code: 'account',
content_type: 'dynamic',
route: '/mi-cuenta/compras',
submenues: [],
},
],
},
],
});
await TestBed.configureTestingModule({
imports: [AccountSidebar],
providers: [
provideRouter([]),
{
provide: TenantService,
useValue: { tenant: tenant.asReadonly() },
},
],
}).compileComponents();
const fixture = TestBed.createComponent(AccountSidebar);
fixture.detectChanges();
const element = fixture.nativeElement as HTMLElement;
const links = Array.from(element.querySelectorAll<HTMLAnchorElement>('.nav-link'));
expect(links.map((link) => link.textContent?.trim())).toEqual([
'Datos personales',
'Mis compras',
]);
expect(links.map((link) => link.getAttribute('href'))).toEqual([
'/mi-cuenta/datos-personales',
'/mi-cuenta/compras',
]);
});
});

View File

@@ -1,6 +1,10 @@
import { Component } from '@angular/core';
import { Component, computed, inject } from '@angular/core';
import { RouterLink, RouterLinkActive } from '@angular/router';
import { findMenu, getMenuLabel } from '../../../../../../core/services/menu.utils';
import { Menu } from '../../../../../../core/services/tenant.interface';
import { TenantService } from '../../../../../../core/services/tenant.service';
@Component({
selector: 'app-account-sidebar',
standalone: true,
@@ -8,4 +12,14 @@ import { RouterLink, RouterLinkActive } from '@angular/router';
templateUrl: './account-sidebar.html',
styleUrl: './account-sidebar.scss',
})
export class AccountSidebar {}
export class AccountSidebar {
private readonly tenantService = inject(TenantService);
protected readonly submenues = computed(
() => findMenu(this.tenantService.tenant()?.menues ?? [], 'account')?.submenues ?? [],
);
protected menuLabel(menu: Menu): string {
return getMenuLabel(menu);
}
}

View File

@@ -89,9 +89,7 @@ export const routes: Routes = [
path: 'preguntas-frecuentes',
canActivate: [hasMenuGuard('help.faq')],
loadComponent: () =>
import('./pages/help-page/pages/faq-page/faq-page').then(
(m) => m.FaqPage,
),
import('./pages/help-page/pages/faq-page/faq-page').then((m) => m.FaqPage),
},
{
path: 'contacto',
@@ -117,11 +115,9 @@ export const routes: Routes = [
},
{
path: 'mi-cuenta',
canActivate: [authGuard],
canActivate: [authGuard, hasMenuGuard('account')],
loadComponent: () =>
import('./pages/account-page/sidebar-layout/sidebar-layout').then(
(m) => m.SidebarLayout,
),
import('./pages/account-page/sidebar-layout/sidebar-layout').then((m) => m.SidebarLayout),
children: [
{
path: 'datos-personales',