feat(categories): separate event and product navigation
This commit is contained in:
@@ -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()"
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user