From 6bab2e9ab2eac3f2814c4356c96c825b296fac26 Mon Sep 17 00:00:00 2001 From: ncoronel Date: Thu, 2 Jul 2026 17:03:07 -0300 Subject: [PATCH] feat(store-header, store-layout): add user click event handling and navigation to login --- .../store-header/store-header.component.html | 1 + .../store-header/store-header.component.ts | 1 + .../store-layout/store-layout.component.html | 1 + .../store-layout.component.spec.ts | 50 ++++++++++++++++++- .../store-layout/store-layout.component.ts | 11 +++- 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/app/core/layout/store-layout/store-header/store-header.component.html b/src/app/core/layout/store-layout/store-header/store-header.component.html index 77a590c..72196e5 100644 --- a/src/app/core/layout/store-layout/store-header/store-header.component.html +++ b/src/app/core/layout/store-layout/store-header/store-header.component.html @@ -44,6 +44,7 @@ variant="user" ariaLabel="Mi cuenta" title="Mi cuenta" + (click)="userClick.emit()" /> diff --git a/src/app/core/layout/store-layout/store-header/store-header.component.ts b/src/app/core/layout/store-layout/store-header/store-header.component.ts index e6aa9d3..0882e36 100644 --- a/src/app/core/layout/store-layout/store-header/store-header.component.ts +++ b/src/app/core/layout/store-layout/store-header/store-header.component.ts @@ -12,4 +12,5 @@ export class StoreHeaderComponent { readonly logoUrl = input(null); readonly cartQuantity = input(0); readonly cartClick = output(); + readonly userClick = output(); } diff --git a/src/app/core/layout/store-layout/store-layout.component.html b/src/app/core/layout/store-layout/store-layout.component.html index 62fc3a3..ca7f51b 100644 --- a/src/app/core/layout/store-layout/store-layout.component.html +++ b/src/app/core/layout/store-layout/store-layout.component.html @@ -3,6 +3,7 @@ [cartQuantity]="cartQuantity()" [logoUrl]="tenant()?.header_logo ?? null" (cartClick)="isCartOpen.set(!isCartOpen())" + (userClick)="onUserClick()" /> @if (isCartOpen()) { diff --git a/src/app/core/layout/store-layout/store-layout.component.spec.ts b/src/app/core/layout/store-layout/store-layout.component.spec.ts index 21e8c08..f9da325 100644 --- a/src/app/core/layout/store-layout/store-layout.component.spec.ts +++ b/src/app/core/layout/store-layout/store-layout.component.spec.ts @@ -1,6 +1,7 @@ +import { describe, it, expect, beforeEach, vi } from 'vitest'; import { signal } from '@angular/core'; import { TestBed } from '@angular/core/testing'; -import { provideRouter } from '@angular/router'; +import { provideRouter, Router } from '@angular/router'; import { of } from 'rxjs'; @@ -8,6 +9,7 @@ import { Tenant } from '../../services/tenant.interface'; import { TenantService } from '../../services/tenant.service'; import { CartService } from '../../services/cart/cart.service'; import { ToastService } from '../../services/toast.service'; +import { AuthService } from '../../services/auth/auth.service'; import { StoreLayoutComponent } from './store-layout.component'; const tenant: Tenant = { @@ -60,6 +62,12 @@ describe('StoreLayoutComponent', () => { success: vi.fn(), dismiss: vi.fn() } + }, + { + provide: AuthService, + useValue: { + isAuthenticated: signal(false) + } } ] }).compileComponents(); @@ -98,4 +106,44 @@ describe('StoreLayoutComponent', () => { expect(compiled.querySelector('.fa-facebook')).not.toBeNull(); expect(compiled.querySelector('.fa-linkedin-in')).not.toBeNull(); }); + + it('redirects to /login when user icon is clicked and user is not logged in', () => { + const authService = TestBed.inject(AuthService); + const router = TestBed.inject(Router); + vi.spyOn(router, 'navigate'); + + // Set isAuthenticated to false + (authService.isAuthenticated as any).set(false); + + const fixture = TestBed.createComponent(StoreLayoutComponent); + fixture.detectChanges(); + + const compiled = fixture.nativeElement as HTMLElement; + const userButton = compiled.querySelector('app-icon-button[variant="user"] button') as HTMLButtonElement; + expect(userButton).not.toBeNull(); + userButton.click(); + fixture.detectChanges(); + + expect(router.navigate).toHaveBeenCalledWith(['/login']); + }); + + it('does not redirect to /login when user icon is clicked and user is logged in', () => { + const authService = TestBed.inject(AuthService); + const router = TestBed.inject(Router); + vi.spyOn(router, 'navigate'); + + // Set isAuthenticated to true + (authService.isAuthenticated as any).set(true); + + const fixture = TestBed.createComponent(StoreLayoutComponent); + fixture.detectChanges(); + + const compiled = fixture.nativeElement as HTMLElement; + const userButton = compiled.querySelector('app-icon-button[variant="user"] button') as HTMLButtonElement; + expect(userButton).not.toBeNull(); + userButton.click(); + fixture.detectChanges(); + + expect(router.navigate).not.toHaveBeenCalled(); + }); }); diff --git a/src/app/core/layout/store-layout/store-layout.component.ts b/src/app/core/layout/store-layout/store-layout.component.ts index 02f1d53..6c56df4 100644 --- a/src/app/core/layout/store-layout/store-layout.component.ts +++ b/src/app/core/layout/store-layout/store-layout.component.ts @@ -1,5 +1,5 @@ import { Component, computed, inject, OnInit, signal } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; +import { Router, RouterOutlet } from '@angular/router'; import { TenantService } from '../../services/tenant.service'; import { CartService } from '../../services/cart/cart.service'; import { StoreFooterComponent, StoreFooterSection, StoreSocialLink } from './store-footer/store-footer.component'; @@ -7,6 +7,7 @@ import { StoreHeaderComponent } from './store-header/store-header.component'; import { CartComponent, CartItemMock } from '../../../shared/components/cart/cart.component'; import { ButtonComponent } from '../../../shared/components/button/button.component'; import { CartItem } from '../../services/cart/cart.interface'; +import { AuthService } from '../../services/auth/auth.service'; @Component({ selector: 'app-store-layout', @@ -17,6 +18,8 @@ import { CartItem } from '../../services/cart/cart.interface'; export class StoreLayoutComponent implements OnInit { private readonly tenantService = inject(TenantService); private readonly cartService = inject(CartService); + private readonly authService = inject(AuthService); + private readonly router = inject(Router); protected readonly isCartOpen = signal(false); @@ -80,6 +83,12 @@ export class StoreLayoutComponent implements OnInit { }); } + protected onUserClick(): void { + if (!this.authService.isAuthenticated()) { + this.router.navigate(['/login']); + } + } + protected readonly footerSections: StoreFooterSection[] = [ {