diff --git a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.html b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.html
index fc92f95..01df682 100644
--- a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.html
+++ b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.html
@@ -107,6 +107,17 @@
@if (imageUrl(); as image) {
-
+
}
diff --git a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.scss b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.scss
index 4b2496a..58cb81b 100644
--- a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.scss
+++ b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.scss
@@ -153,11 +153,27 @@
margin-top: 0.75rem;
}
- &__map {
+ &__map-button {
display: block;
width: min(100%, 720px);
- max-height: 680px;
margin: 3rem auto 0;
+ padding: 0;
+ overflow: hidden;
+ border: 0;
+ border-radius: 0.4rem;
+ background: transparent;
+ cursor: zoom-in;
+
+ &:focus-visible {
+ outline: 3px solid var(--tenant-primary);
+ outline-offset: 0.25rem;
+ }
+ }
+
+ &__map {
+ display: block;
+ width: 100%;
+ max-height: 680px;
object-fit: contain;
}
}
@@ -188,7 +204,7 @@
display: none;
}
- &__map {
+ &__map-button {
margin-top: 2rem;
}
}
diff --git a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.spec.ts b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.spec.ts
index 311d51a..9b0aebe 100644
--- a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.spec.ts
+++ b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.spec.ts
@@ -104,6 +104,10 @@ describe('ProductTicketSelectorComponent', () => {
};
catalogService.withoutLoading.mockReturnValue(catalogService);
cartService.withoutLoading.mockReturnValue(cartService);
+ const modalService = {
+ openConfirmDelete: vi.fn().mockReturnValue(of(true)),
+ openImage: vi.fn(),
+ };
await TestBed.configureTestingModule({
imports: [ProductTicketSelectorComponent],
@@ -112,7 +116,7 @@ describe('ProductTicketSelectorComponent', () => {
{ provide: CartService, useValue: cartService },
{
provide: ModalService,
- useValue: { openConfirmDelete: vi.fn().mockReturnValue(of(true)) },
+ useValue: modalService,
},
{ provide: ToastService, useValue: { danger: toastDanger } },
],
@@ -125,7 +129,7 @@ describe('ProductTicketSelectorComponent', () => {
await fixture.whenStable();
fixture.detectChanges();
- return { fixture, getVariantOptions, cartService, toastDanger };
+ return { fixture, getVariantOptions, cartService, toastDanger, modalService };
}
it('loads one map, recalculates the cascade locally and reserves only after the last select', async () => {
@@ -226,6 +230,25 @@ describe('ProductTicketSelectorComponent', () => {
]);
});
+ it('opens the zoomable image modal when the seating map is clicked', async () => {
+ const { fixture, modalService } = await createComponent({
+ maps: [mapResponse([variant(401, 'general', 'A', '1', '1')])],
+ });
+ fixture.componentRef.setInput('imageUrl', '/images/plano.png');
+ fixture.detectChanges();
+
+ const button = fixture.nativeElement.querySelector(
+ 'button[aria-label="Ampliar plano de ubicaciones"]',
+ ) as HTMLButtonElement;
+ button.click();
+
+ expect(modalService.openImage).toHaveBeenCalledWith({
+ title: 'Entrada',
+ src: '/images/plano.png',
+ alt: 'Plano de ubicaciones de Entrada',
+ });
+ });
+
it('clears only the seat after a stock conflict when the row still has alternatives', async () => {
const failed = variant(401, 'general', 'A', '1', '1');
const alternative = variant(402, 'general', 'A', '1', '2');
diff --git a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.ts b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.ts
index f420a03..7d96ec7 100644
--- a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.ts
+++ b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.ts
@@ -154,6 +154,14 @@ export class ProductTicketSelectorComponent {
if (this.hasSelection() && variantIds.length > 0) this.buy.emit(variantIds);
}
+ protected openImage(src: string): void {
+ this.modalService.openImage({
+ title: this.title(),
+ src,
+ alt: `Plano de ubicaciones de ${this.title()}`,
+ });
+ }
+
protected addRow(): void {
if (!this.canAddRow()) return;
const row = this.createRow(this.nextRowId++);