feat(categories): separate event and product navigation

This commit is contained in:
2026-09-21 09:24:24 -03:00
parent e7d24607a6
commit e0b1f27b97
6 changed files with 89 additions and 10 deletions

View File

@@ -12,8 +12,8 @@
[isAuthenticated]="isAuthenticated()"
[accountNavigationMenus]="accountNavigationMenus()"
[ticketsMenu]="ticketsMenu() ?? null"
[categories]="tenant()?.categories ?? []"
[displayCategories]="tenant()?.display_categories ?? true"
[categories]="navigationCategories()"
[displayCategories]="displayCategories()"
[displaySeachBar]="tenant()?.display_seach_bar ?? true"
[displayCart]="displayCart()"
[cartDisabled]="isCheckoutRoute()"

View File

@@ -294,6 +294,18 @@ describe('StoreLayoutComponent', () => {
header_type: 'immersive',
display_categories: true,
categories: [{ id: 11, nombre: 'Música', subcategories: [] }],
menues: [
...(tenant.menues ?? []),
{
id: 20,
code: 'product.category',
label: 'Categoría de productos',
parent_menu_code: null,
content_type: 'dynamic',
route: '/categoria/:id',
submenues: [],
},
],
});
const fixture = TestBed.createComponent(StoreLayoutComponent);
@@ -323,6 +335,43 @@ describe('StoreLayoutComponent', () => {
expect(element.querySelector('.immersive-categories')).toBeNull();
});
it('uses event categories and their dedicated route for multi-event storefronts', () => {
tenantState.set({
...tenant,
storefront_website_type_code: 'onticket_multi_event',
header_type: 'immersive',
display_categories: true,
categories: [],
event_categories: [{ id: 12, nombre: 'Teatro', subcategories: [] }],
menues: [
...(tenant.menues ?? []),
{
id: 21,
code: 'event.category',
label: 'Categoría de eventos',
parent_menu_code: null,
content_type: 'dynamic',
route: '/eventos/categoria/:id',
submenues: [],
},
],
});
const fixture = TestBed.createComponent(StoreLayoutComponent);
fixture.detectChanges();
const categoryButton = (fixture.nativeElement as HTMLElement).querySelector<HTMLButtonElement>(
'.immersive-categories button',
);
const navigate = vi.spyOn(TestBed.inject(Router), 'navigate');
expect(categoryButton?.textContent?.trim()).toBe('TEATRO');
categoryButton?.click();
expect(navigate).toHaveBeenCalledWith(['/eventos/categoria', 12], {
queryParams: { page: 1 },
});
});
it('opens the cart when requested through the openCart query parameter', () => {
const fixture = TestBed.createComponent(StoreLayoutComponent);
fixture.detectChanges();

View File

@@ -71,6 +71,23 @@ export class StoreLayoutComponent implements OnInit {
protected readonly isHomeRoute = signal(this.isHomeUrl(this.router.url));
protected readonly checkoutRemainingSeconds = this.checkoutCountdownService.remainingSeconds;
protected readonly isCreatingPurchase = signal(false);
private readonly isMultiEventStorefront = computed(
() => this.tenant()?.storefront_website_type_code === 'onticket_multi_event',
);
protected readonly navigationCategories = computed(() =>
this.isMultiEventStorefront()
? (this.tenant()?.event_categories ?? [])
: (this.tenant()?.categories ?? []),
);
private readonly categoryMenu = computed(() =>
findMenu(
this.tenant()?.menues ?? [],
this.isMultiEventStorefront() ? 'event.category' : 'product.category',
),
);
protected readonly displayCategories = computed(
() => (this.tenant()?.display_categories ?? true) && this.categoryMenu() !== undefined,
);
protected readonly displayCart = computed(() => this.tenant()?.display_cart ?? true);
protected readonly cartEditingPolicy = computed(() => this.tenant()?.cart_editing_policy ?? null);
protected readonly canModifyCart = computed(
@@ -281,7 +298,9 @@ export class StoreLayoutComponent implements OnInit {
}
protected onCategorySelect(category: Category): void {
void this.router.navigate(['/categoria', category.id], {
const route = this.isMultiEventStorefront() ? '/eventos/categoria' : '/categoria';
void this.router.navigate([route, category.id], {
queryParams: { page: 1 },
});
}

View File

@@ -153,7 +153,8 @@ export interface Tenant {
ticket_partial_refund_percentage?: string;
social_media?: SocialMedia[];
menues?: Menu[];
categories: Category[];
categories?: Category[];
event_categories?: Category[];
}
export type TenantBootstrapResponse = ApiResponse<Tenant>;

View File

@@ -22,10 +22,12 @@ import { EventListComponent } from '../../components/event-list/event-list.compo
export class EventCategoryPageComponent {
private readonly route = inject(ActivatedRoute);
private readonly tenant = inject(TenantService).tenant;
private readonly params = toSignal(this.route.paramMap, { initialValue: this.route.snapshot.paramMap });
private readonly params = toSignal(this.route.paramMap, {
initialValue: this.route.snapshot.paramMap,
});
protected readonly category = computed(() => {
const id = Number(this.params().get('id'));
return this.tenant()?.categories.find((category) => category.id === id) ?? null;
return this.tenant()?.event_categories?.find((category) => category.id === id) ?? null;
});
}

View File

@@ -30,7 +30,9 @@ export const routes: Routes = [
canMatch: [isMultiEventStorefront],
canActivate: [hasMenuGuard('event.index')],
loadComponent: () =>
import('./pages/event-home-page/event-home-page.component').then((m) => m.EventHomePageComponent),
import('./pages/event-home-page/event-home-page.component').then(
(m) => m.EventHomePageComponent,
),
},
{
path: '',
@@ -86,7 +88,9 @@ export const routes: Routes = [
path: 'buscar',
canMatch: [isMultiEventStorefront],
loadComponent: () =>
import('./pages/event-search-page/event-search-page.component').then((m) => m.EventSearchPageComponent),
import('./pages/event-search-page/event-search-page.component').then(
(m) => m.EventSearchPageComponent,
),
},
{
path: 'buscar',
@@ -98,11 +102,14 @@ export const routes: Routes = [
canMatch: [isMultiEventStorefront],
canActivate: [hasMenuGuard('event.detail')],
loadComponent: () =>
import('./pages/event-detail-page/event-detail-page.component').then((m) => m.EventDetailPageComponent),
import('./pages/event-detail-page/event-detail-page.component').then(
(m) => m.EventDetailPageComponent,
),
},
{
path: 'categoria/:id',
path: 'eventos/categoria/:id',
canMatch: [isMultiEventStorefront],
canActivate: [hasMenuGuard('event.category')],
loadComponent: () =>
import('./pages/event-category-page/event-category-page.component').then(
(m) => m.EventCategoryPageComponent,
@@ -110,6 +117,7 @@ export const routes: Routes = [
},
{
path: 'categoria/:id',
canActivate: [hasMenuGuard('product.category')],
loadComponent: () =>
import('./pages/category-items-page/category-items-page.component').then(
(m) => m.CategoryItemsPageComponent,