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 197ff8a..4b2496a 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
@@ -57,6 +57,30 @@
gap: 0.5rem;
}
+ &__columns {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) auto;
+ align-items: end;
+ gap: 0.5rem;
+ }
+
+ &__column-labels {
+ min-width: 0;
+ display: grid;
+ grid-template-columns: repeat(4, minmax(120px, 1fr));
+ gap: 0.5rem;
+ }
+
+ &__column-label {
+ color: #666;
+ font-size: 13px;
+ font-weight: 600;
+ }
+
+ &__action-spacer {
+ width: 38px;
+ }
+
&__row {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
@@ -160,6 +184,10 @@
grid-template-columns: 1fr;
}
+ &__columns {
+ display: none;
+ }
+
&__map {
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 d78db61..311d51a 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
@@ -209,6 +209,23 @@ describe('ProductTicketSelectorComponent', () => {
expect(removeButton?.classList.contains('icon-btn--bordered')).toBe(true);
});
+ it('shows one header row with the label of every selector', async () => {
+ const { fixture } = await createComponent({
+ maps: [mapResponse([variant(401, 'general', 'A', '1', '1')])],
+ });
+
+ const headerRows = fixture.nativeElement.querySelectorAll('.ticket-selector__columns');
+ const labels = fixture.nativeElement.querySelectorAll('.ticket-selector__column-label');
+
+ expect(headerRows).toHaveLength(1);
+ expect([...labels].map((label: Element) => label.textContent?.trim())).toEqual([
+ 'Tipo',
+ 'Sector',
+ 'Fila',
+ 'Asiento',
+ ]);
+ });
+
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 254af04..5803f48 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
@@ -71,7 +71,7 @@ export class ProductTicketSelectorComponent {
private readonly viewReady = signal(false);
private readonly mapReady = signal(false);
private readonly variants = signal([]);
- private readonly attributes = signal([]);
+ protected readonly attributes = signal([]);
private mapRequest: Subscription | null = null;
readonly productId = input.required();