tickera-angular-components 0.0.1-dev.165 → 0.0.1-dev.167
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -11,7 +11,7 @@ import { TippyDirective } from '@ngneat/helipopper';
|
|
|
11
11
|
export { TippyDirective } from '@ngneat/helipopper';
|
|
12
12
|
import * as i1 from '@angular/common/http';
|
|
13
13
|
import { HttpHeaders } from '@angular/common/http';
|
|
14
|
-
import { catchError, distinctUntilChanged, debounceTime, switchMap, takeUntil
|
|
14
|
+
import { catchError, map, tap, distinctUntilChanged, debounceTime, switchMap, takeUntil } from 'rxjs/operators';
|
|
15
15
|
import { toast } from 'ngx-sonner';
|
|
16
16
|
import { toObservable } from '@angular/core/rxjs-interop';
|
|
17
17
|
import * as i3$1 from '@angular/router';
|
|
@@ -1718,7 +1718,11 @@ function processElementsToRenderData(elements, tickets, priceZones) {
|
|
|
1718
1718
|
elementName,
|
|
1719
1719
|
seatPositions,
|
|
1720
1720
|
chairPositions,
|
|
1721
|
-
|
|
1721
|
+
// Disponibilidad real de la zona (no la capacidad total), para que el
|
|
1722
|
+
// tope de selección refleje lo que realmente queda por vender.
|
|
1723
|
+
zoneCapacity: element.type === RoomMapElementType.ZONE
|
|
1724
|
+
? elementTickets.filter((t) => t.status === PerformanceTicketStatus.AVAILABLE).length
|
|
1725
|
+
: element.total_capacity,
|
|
1722
1726
|
});
|
|
1723
1727
|
}
|
|
1724
1728
|
return result;
|
|
@@ -3444,6 +3448,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3444
3448
|
args: [{ providedIn: 'root' }]
|
|
3445
3449
|
}] });
|
|
3446
3450
|
|
|
3451
|
+
const MAX_TICKETS_SETTING_KEY = 'max_tickets_per_purchase';
|
|
3452
|
+
/**
|
|
3453
|
+
* Tope de entradas por selección/compra. Por defecto es `null` (sin límite),
|
|
3454
|
+
* que es lo que necesita el backoffice (admin puede seleccionar todo).
|
|
3455
|
+
* El ecommerce, que sí debe limitar, llama a `load()` una vez al iniciar la
|
|
3456
|
+
* app para traer el valor configurado en el formulario de personalización.
|
|
3457
|
+
*/
|
|
3458
|
+
class PurchaseLimitService {
|
|
3459
|
+
apiService;
|
|
3460
|
+
_maxTicketsPerSelection = signal(null, ...(ngDevMode ? [{ debugName: "_maxTicketsPerSelection" }] : []));
|
|
3461
|
+
maxTicketsPerSelection = this._maxTicketsPerSelection.asReadonly();
|
|
3462
|
+
constructor(apiService) {
|
|
3463
|
+
this.apiService = apiService;
|
|
3464
|
+
}
|
|
3465
|
+
setMaxTicketsPerSelection(max) {
|
|
3466
|
+
this._maxTicketsPerSelection.set(max && max > 0 ? max : null);
|
|
3467
|
+
}
|
|
3468
|
+
load() {
|
|
3469
|
+
return this.apiService.get('/settings?category=personalization').pipe(map(({ data }) => {
|
|
3470
|
+
const setting = data?.find((s) => s.key === MAX_TICKETS_SETTING_KEY);
|
|
3471
|
+
const parsed = setting?.value ? parseInt(setting.value, 10) : NaN;
|
|
3472
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
3473
|
+
}), tap((max) => this.setMaxTicketsPerSelection(max)), catchError(() => {
|
|
3474
|
+
// Si falla la carga, no bloqueamos la compra: queda sin límite hasta
|
|
3475
|
+
// que se pueda leer el setting correctamente.
|
|
3476
|
+
this.setMaxTicketsPerSelection(null);
|
|
3477
|
+
return of(null);
|
|
3478
|
+
}));
|
|
3479
|
+
}
|
|
3480
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PurchaseLimitService, deps: [{ token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3481
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PurchaseLimitService, providedIn: 'root' });
|
|
3482
|
+
}
|
|
3483
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PurchaseLimitService, decorators: [{
|
|
3484
|
+
type: Injectable,
|
|
3485
|
+
args: [{ providedIn: 'root' }]
|
|
3486
|
+
}], ctorParameters: () => [{ type: ApiService }] });
|
|
3487
|
+
|
|
3447
3488
|
class OrderTransactionDetailsModalService {
|
|
3448
3489
|
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
3449
3490
|
transaction = signal(null, ...(ngDevMode ? [{ debugName: "transaction" }] : []));
|
|
@@ -3684,6 +3725,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3684
3725
|
class TicketSelectionService {
|
|
3685
3726
|
bookingDataService = inject(PerformanceBookingDataService);
|
|
3686
3727
|
feedbackModalService = inject(FeedbackModalService);
|
|
3728
|
+
purchaseLimitService = inject(PurchaseLimitService);
|
|
3687
3729
|
selectionDetailsService = inject(TicketSelectionDetailsService);
|
|
3688
3730
|
selectionDiscountService = inject(TicketSelectionDiscountService);
|
|
3689
3731
|
_zoneQuantities = signal(new Map(), ...(ngDevMode ? [{ debugName: "_zoneQuantities" }] : []));
|
|
@@ -3705,6 +3747,27 @@ class TicketSelectionService {
|
|
|
3705
3747
|
selectedTicketIds = computed(() => this._selectedTickets(), ...(ngDevMode ? [{ debugName: "selectedTicketIds" }] : []));
|
|
3706
3748
|
selectedBlockedTicketIds = computed(() => this.selectedBlockedTickets().map((t) => t.id), ...(ngDevMode ? [{ debugName: "selectedBlockedTicketIds" }] : []));
|
|
3707
3749
|
selectedTicketIdList = computed(() => this.selectedTickets().map((t) => t.id), ...(ngDevMode ? [{ debugName: "selectedTicketIdList" }] : []));
|
|
3750
|
+
// Agrupa los tickets seleccionados de una "Zona de público" en un solo item
|
|
3751
|
+
// (con element_qty) para el resumen de selección; asientos y mesas se listan
|
|
3752
|
+
// individualmente, igual que antes.
|
|
3753
|
+
summaryItems = computed(() => {
|
|
3754
|
+
const zoneGroups = new Map();
|
|
3755
|
+
const result = [];
|
|
3756
|
+
for (const ticket of this.selectedTickets()) {
|
|
3757
|
+
if (ticket.element_type === RoomMapElementType.ZONE) {
|
|
3758
|
+
const group = zoneGroups.get(ticket.room_map_element_id) ?? [];
|
|
3759
|
+
group.push(ticket);
|
|
3760
|
+
zoneGroups.set(ticket.room_map_element_id, group);
|
|
3761
|
+
}
|
|
3762
|
+
else {
|
|
3763
|
+
result.push(ticket);
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
for (const group of zoneGroups.values()) {
|
|
3767
|
+
result.push({ ...group[0], element_qty: group.length });
|
|
3768
|
+
}
|
|
3769
|
+
return result;
|
|
3770
|
+
}, ...(ngDevMode ? [{ debugName: "summaryItems" }] : []));
|
|
3708
3771
|
products = computed(() => this._products(), ...(ngDevMode ? [{ debugName: "products" }] : []));
|
|
3709
3772
|
productQuantities = computed(() => this._productQuantities(), ...(ngDevMode ? [{ debugName: "productQuantities" }] : []));
|
|
3710
3773
|
selectedProductEntries = computed(() => {
|
|
@@ -3755,28 +3818,39 @@ class TicketSelectionService {
|
|
|
3755
3818
|
}
|
|
3756
3819
|
toggle(ticket) {
|
|
3757
3820
|
const list = this.getListByStatus(ticket);
|
|
3758
|
-
if (list)
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
else {
|
|
3765
|
-
next.add(ticket);
|
|
3766
|
-
}
|
|
3767
|
-
return next;
|
|
3768
|
-
});
|
|
3821
|
+
if (!list)
|
|
3822
|
+
return;
|
|
3823
|
+
const willAdd = !list().has(ticket);
|
|
3824
|
+
if (list === this._selectedTickets && willAdd && !this.canAddMoreToSelection(1)) {
|
|
3825
|
+
this.notifyPurchaseLimitReached();
|
|
3826
|
+
return;
|
|
3769
3827
|
}
|
|
3828
|
+
list.update((ids) => {
|
|
3829
|
+
const next = new Set(ids);
|
|
3830
|
+
if (next.has(ticket)) {
|
|
3831
|
+
next.delete(ticket);
|
|
3832
|
+
}
|
|
3833
|
+
else {
|
|
3834
|
+
next.add(ticket);
|
|
3835
|
+
}
|
|
3836
|
+
return next;
|
|
3837
|
+
});
|
|
3770
3838
|
}
|
|
3771
3839
|
select(ticket) {
|
|
3772
3840
|
const list = this.getListByStatus(ticket);
|
|
3773
|
-
if (list)
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3841
|
+
if (!list)
|
|
3842
|
+
return;
|
|
3843
|
+
if (list === this._selectedTickets &&
|
|
3844
|
+
!list().has(ticket) &&
|
|
3845
|
+
!this.canAddMoreToSelection(1)) {
|
|
3846
|
+
this.notifyPurchaseLimitReached();
|
|
3847
|
+
return;
|
|
3779
3848
|
}
|
|
3849
|
+
list.update((ids) => {
|
|
3850
|
+
const next = new Set(ids);
|
|
3851
|
+
next.add(ticket);
|
|
3852
|
+
return next;
|
|
3853
|
+
});
|
|
3780
3854
|
}
|
|
3781
3855
|
deselect(ticket) {
|
|
3782
3856
|
const list = this.getListByStatus(ticket);
|
|
@@ -3801,16 +3875,46 @@ class TicketSelectionService {
|
|
|
3801
3875
|
isSelected(ticket) {
|
|
3802
3876
|
return this._selectedTickets().has(ticket);
|
|
3803
3877
|
}
|
|
3878
|
+
// Se llama tanto al hacer click en el mapa como al pintar el resumen, así que
|
|
3879
|
+
// sincroniza siempre el tope con la disponibilidad más reciente, preservando
|
|
3880
|
+
// la cantidad ya seleccionada.
|
|
3804
3881
|
initZoneQuantity(elementId, maxCapacity) {
|
|
3805
3882
|
this._zoneQuantities.update((map) => {
|
|
3806
3883
|
const next = new Map(map);
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3884
|
+
const existing = next.get(elementId);
|
|
3885
|
+
next.set(elementId, {
|
|
3886
|
+
elementId,
|
|
3887
|
+
selectedCount: existing?.selectedCount ?? 0,
|
|
3888
|
+
maxCapacity,
|
|
3889
|
+
});
|
|
3810
3890
|
return next;
|
|
3811
3891
|
});
|
|
3812
3892
|
}
|
|
3893
|
+
getZoneMax(elementId) {
|
|
3894
|
+
return this._zoneQuantities().get(elementId)?.maxCapacity ?? 0;
|
|
3895
|
+
}
|
|
3896
|
+
getZoneSelectedCount(elementId) {
|
|
3897
|
+
return this._zoneQuantities().get(elementId)?.selectedCount ?? 0;
|
|
3898
|
+
}
|
|
3899
|
+
// Fija la cantidad seleccionada de una zona a un valor absoluto (lo que emite
|
|
3900
|
+
// el number-input del resumen), reutilizando el clamp/validación de disponibilidad
|
|
3901
|
+
// que ya hace adjustZoneQuantity en vez de duplicar esa lógica.
|
|
3902
|
+
setZoneQuantity(elementId, target) {
|
|
3903
|
+
const current = this.getZoneSelectedCount(elementId);
|
|
3904
|
+
const delta = Math.max(0, Math.trunc(target)) - current;
|
|
3905
|
+
if (delta !== 0) {
|
|
3906
|
+
this.adjustZoneQuantity(elementId, delta);
|
|
3907
|
+
}
|
|
3908
|
+
}
|
|
3813
3909
|
adjustZoneQuantity(elementId, delta) {
|
|
3910
|
+
if (delta > 0) {
|
|
3911
|
+
const allowance = this.remainingSelectionAllowance();
|
|
3912
|
+
if (allowance <= 0) {
|
|
3913
|
+
this.notifyPurchaseLimitReached();
|
|
3914
|
+
return;
|
|
3915
|
+
}
|
|
3916
|
+
delta = Math.min(delta, allowance);
|
|
3917
|
+
}
|
|
3814
3918
|
const zoneTickets = this._allTickets()
|
|
3815
3919
|
.filter((t) => t.room_map_element_id === elementId)
|
|
3816
3920
|
.sort((a, b) => ((a.seat_label || '') < (b.seat_label || '') ? -1 : 1));
|
|
@@ -3840,6 +3944,30 @@ class TicketSelectionService {
|
|
|
3840
3944
|
return next;
|
|
3841
3945
|
});
|
|
3842
3946
|
}
|
|
3947
|
+
// --- Tope de entradas por compra (solo activo si PurchaseLimitService tiene
|
|
3948
|
+
// un máximo cargado; el backoffice nunca lo carga, así que queda ilimitado) ---
|
|
3949
|
+
remainingSelectionAllowance() {
|
|
3950
|
+
const max = this.purchaseLimitService.maxTicketsPerSelection();
|
|
3951
|
+
if (max === null)
|
|
3952
|
+
return Infinity;
|
|
3953
|
+
return Math.max(0, max - this.selectedCount());
|
|
3954
|
+
}
|
|
3955
|
+
canAddMoreToSelection(additional) {
|
|
3956
|
+
return additional <= this.remainingSelectionAllowance();
|
|
3957
|
+
}
|
|
3958
|
+
notifyPurchaseLimitReached() {
|
|
3959
|
+
const max = this.purchaseLimitService.maxTicketsPerSelection();
|
|
3960
|
+
this.feedbackModalService.addModal({
|
|
3961
|
+
id: 'purchase-limit-reached',
|
|
3962
|
+
type: 'warning',
|
|
3963
|
+
title: 'Límite de entradas por compra',
|
|
3964
|
+
message: max != null
|
|
3965
|
+
? `Puedes seleccionar hasta ${max} entradas por compra. Si necesitas más, contáctanos para coordinar tu compra directamente con el teatro.`
|
|
3966
|
+
: 'Has alcanzado el máximo de entradas permitido para esta compra.',
|
|
3967
|
+
showCloseButton: true,
|
|
3968
|
+
isOpen: signal(true),
|
|
3969
|
+
});
|
|
3970
|
+
}
|
|
3843
3971
|
getZoneTickets(elementId) {
|
|
3844
3972
|
return this._allTickets()
|
|
3845
3973
|
.filter((t) => t.room_map_element_id === elementId)
|
|
@@ -9072,15 +9200,32 @@ class SeatSelectionSummaryItemComponent {
|
|
|
9072
9200
|
this.selectionService = selectionService;
|
|
9073
9201
|
}
|
|
9074
9202
|
getItemTypeIcon = getItemTypeIcon;
|
|
9203
|
+
// Las "Zonas de público" se compran por cantidad (varios tickets agrupados en
|
|
9204
|
+
// un solo item con element_qty); asientos y mesas siguen siendo selección 1:1.
|
|
9205
|
+
get isZone() {
|
|
9206
|
+
return this.item.element_type === RoomMapElementType.ZONE;
|
|
9207
|
+
}
|
|
9208
|
+
get zoneMax() {
|
|
9209
|
+
return this.selectionService.getZoneMax(this.item.room_map_element_id);
|
|
9210
|
+
}
|
|
9211
|
+
onZoneQuantityChange(value) {
|
|
9212
|
+
if (value === null)
|
|
9213
|
+
return;
|
|
9214
|
+
this.selectionService.setZoneQuantity(this.item.room_map_element_id, value);
|
|
9215
|
+
}
|
|
9075
9216
|
removeItem(ticket) {
|
|
9217
|
+
if (this.isZone) {
|
|
9218
|
+
this.selectionService.setZoneQuantity(ticket.room_map_element_id, 0);
|
|
9219
|
+
return;
|
|
9220
|
+
}
|
|
9076
9221
|
this.selectionService.deselect(ticket);
|
|
9077
9222
|
}
|
|
9078
9223
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatSelectionSummaryItemComponent, deps: [{ token: TicketSelectionService }], target: i0.ɵɵFactoryTarget.Component });
|
|
9079
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SeatSelectionSummaryItemComponent, isStandalone: true, selector: "seat-selection-summary-item", inputs: { item: "item" }, ngImport: i0, template: "<div class=\"seat-selection-summary-item\">\n <div class=\"seat-selection-summary-item__icon\">\n {{ getItemTypeIcon(item) }}\n </div>\n\n <div class=\"seat-selection-summary-item__content\">\n <div class=\"seat-selection-summary-item__content-label\">{{ item.seat_label }}</div>\n\n <div class=\"seat-selection-summary-item__content-price\">\n ${{ item.normal_price | number: '1.0' }}\n </div>\n\n @if (
|
|
9224
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SeatSelectionSummaryItemComponent, isStandalone: true, selector: "seat-selection-summary-item", inputs: { item: "item" }, ngImport: i0, template: "<div class=\"seat-selection-summary-item\">\n <div class=\"seat-selection-summary-item__icon\">\n {{ getItemTypeIcon(item) }}\n </div>\n\n <div class=\"seat-selection-summary-item__content\">\n <div class=\"seat-selection-summary-item__content-label\">{{ item.seat_label }}</div>\n\n <div class=\"seat-selection-summary-item__content-price\">\n ${{ item.normal_price | number: '1.0' }}\n </div>\n </div>\n\n <div class=\"seat-selection-summary-item__actions\">\n @if (isZone) {\n <number-input\n name=\"zone-quantity\"\n [ngModel]=\"item.element_qty ?? 1\"\n (ngModelChange)=\"onZoneQuantityChange($event)\"\n [min]=\"0\"\n [max]=\"zoneMax\"\n [step]=\"1\"\n fieldGroupClass=\"seat-selection-summary-item__qty-input\"\n />\n } @else {\n <app-button\n variant=\"transparent\"\n size=\"xs\"\n text=\"\"\n icon=\"ri-close-line\"\n (clicked)=\"removeItem(item)\"\n />\n }\n </div>\n</div>\n", styles: [".seat-selection-summary-item{align-items:center;display:flex;flex-flow:row nowrap;gap:.75rem;justify-content:flex-start;border-bottom:1px solid #e5e7eb;padding:.75rem 0;transition:background-color .2s ease}.seat-selection-summary-item:last-child{border-bottom:none}.seat-selection-summary-item:hover{background-color:#f9fafb}.seat-selection-summary-item__icon{align-items:center;border:1px solid #e5e7eb;border-radius:.25rem;display:flex;font-size:1.5rem;height:44px;justify-content:center;padding:.25rem;width:44px}.seat-selection-summary-item__content{display:flex;flex-direction:column;gap:.25rem}.seat-selection-summary-item__content-label{font-size:.75rem;font-weight:500;color:#6b7280}.seat-selection-summary-item__content-price{font-size:.875rem;font-weight:600;color:#111827}.seat-selection-summary-item__content-quantity{font-size:.75rem;color:#6b7280}.seat-selection-summary-item__actions{display:flex;align-items:center;gap:.5rem;margin-left:auto}.seat-selection-summary-item__qty-input{margin-right:.25rem;width:6.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AppButtonComponent, selector: "app-button", inputs: ["disabled", "loading", "type", "variant", "text", "size", "loadingText", "icon", "tooltip"], outputs: ["clicked"] }, { kind: "component", type: NumberInputComponent, selector: "number-input", inputs: ["label", "name", "id", "placeholder", "required", "readonly", "min", "max", "step", "fieldGroupClass"] }, { kind: "pipe", type: i1$1.DecimalPipe, name: "number" }] });
|
|
9080
9225
|
}
|
|
9081
9226
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatSelectionSummaryItemComponent, decorators: [{
|
|
9082
9227
|
type: Component,
|
|
9083
|
-
args: [{ selector: 'seat-selection-summary-item', standalone: true, imports: [CommonModule, AppButtonComponent], template: "<div class=\"seat-selection-summary-item\">\n <div class=\"seat-selection-summary-item__icon\">\n {{ getItemTypeIcon(item) }}\n </div>\n\n <div class=\"seat-selection-summary-item__content\">\n <div class=\"seat-selection-summary-item__content-label\">{{ item.seat_label }}</div>\n\n <div class=\"seat-selection-summary-item__content-price\">\n ${{ item.normal_price | number: '1.0' }}\n </div>\n\n @if (
|
|
9228
|
+
args: [{ selector: 'seat-selection-summary-item', standalone: true, imports: [CommonModule, FormsModule, AppButtonComponent, NumberInputComponent], template: "<div class=\"seat-selection-summary-item\">\n <div class=\"seat-selection-summary-item__icon\">\n {{ getItemTypeIcon(item) }}\n </div>\n\n <div class=\"seat-selection-summary-item__content\">\n <div class=\"seat-selection-summary-item__content-label\">{{ item.seat_label }}</div>\n\n <div class=\"seat-selection-summary-item__content-price\">\n ${{ item.normal_price | number: '1.0' }}\n </div>\n </div>\n\n <div class=\"seat-selection-summary-item__actions\">\n @if (isZone) {\n <number-input\n name=\"zone-quantity\"\n [ngModel]=\"item.element_qty ?? 1\"\n (ngModelChange)=\"onZoneQuantityChange($event)\"\n [min]=\"0\"\n [max]=\"zoneMax\"\n [step]=\"1\"\n fieldGroupClass=\"seat-selection-summary-item__qty-input\"\n />\n } @else {\n <app-button\n variant=\"transparent\"\n size=\"xs\"\n text=\"\"\n icon=\"ri-close-line\"\n (clicked)=\"removeItem(item)\"\n />\n }\n </div>\n</div>\n", styles: [".seat-selection-summary-item{align-items:center;display:flex;flex-flow:row nowrap;gap:.75rem;justify-content:flex-start;border-bottom:1px solid #e5e7eb;padding:.75rem 0;transition:background-color .2s ease}.seat-selection-summary-item:last-child{border-bottom:none}.seat-selection-summary-item:hover{background-color:#f9fafb}.seat-selection-summary-item__icon{align-items:center;border:1px solid #e5e7eb;border-radius:.25rem;display:flex;font-size:1.5rem;height:44px;justify-content:center;padding:.25rem;width:44px}.seat-selection-summary-item__content{display:flex;flex-direction:column;gap:.25rem}.seat-selection-summary-item__content-label{font-size:.75rem;font-weight:500;color:#6b7280}.seat-selection-summary-item__content-price{font-size:.875rem;font-weight:600;color:#111827}.seat-selection-summary-item__content-quantity{font-size:.75rem;color:#6b7280}.seat-selection-summary-item__actions{display:flex;align-items:center;gap:.5rem;margin-left:auto}.seat-selection-summary-item__qty-input{margin-right:.25rem;width:6.5rem}\n"] }]
|
|
9084
9229
|
}], ctorParameters: () => [{ type: TicketSelectionService }], propDecorators: { item: [{
|
|
9085
9230
|
type: Input,
|
|
9086
9231
|
args: [{ required: true }]
|
|
@@ -9093,8 +9238,15 @@ class SeatSelectionSummaryComponent {
|
|
|
9093
9238
|
constructor(selectionService) {
|
|
9094
9239
|
this.selectionService = selectionService;
|
|
9095
9240
|
}
|
|
9241
|
+
// Un item de zona representa un grupo (puede cambiar de ticket representante
|
|
9242
|
+
// al variar la cantidad), así que se trackea por elemento y no por ticket.id.
|
|
9243
|
+
trackByItem(item) {
|
|
9244
|
+
return item.element_type === RoomMapElementType.ZONE
|
|
9245
|
+
? `zone-${item.room_map_element_id}`
|
|
9246
|
+
: item.id;
|
|
9247
|
+
}
|
|
9096
9248
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatSelectionSummaryComponent, deps: [{ token: TicketSelectionService }], target: i0.ɵɵFactoryTarget.Component });
|
|
9097
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SeatSelectionSummaryComponent, isStandalone: true, selector: "seat-selection-summary", inputs: { title: "title", clearButtonText: "clearButtonText" }, ngImport: i0, template: "<ticket-map-widget>\n <ticket-map-widget-header [title]=\"title\" />\n\n @if (selectionService.selectedCount() > 0) {\n <div class=\"tickets-list\">\n @for (item of selectionService.
|
|
9249
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SeatSelectionSummaryComponent, isStandalone: true, selector: "seat-selection-summary", inputs: { title: "title", clearButtonText: "clearButtonText" }, ngImport: i0, template: "<ticket-map-widget>\n <ticket-map-widget-header [title]=\"title\" />\n\n @if (selectionService.selectedCount() > 0) {\n <div class=\"tickets-list\">\n @for (item of selectionService.summaryItems(); track trackByItem(item)) {\n <seat-selection-summary-item [item]=\"item\" />\n }\n </div>\n\n @if (selectionService.selectedCount() > 0) {\n <div class=\"tickets-actions\">\n <app-button\n size=\"xs\"\n [text]=\"clearButtonText\"\n icon=\"ri-delete-bin-line\"\n (clicked)=\"selectionService.clearSelection()\"\n />\n </div>\n }\n } @else {\n <seat-selection-empty-summary />\n }\n</ticket-map-widget>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AppButtonComponent, selector: "app-button", inputs: ["disabled", "loading", "type", "variant", "text", "size", "loadingText", "icon", "tooltip"], outputs: ["clicked"] }, { kind: "component", type: SeatSelectionEmptySummaryComponent, selector: "seat-selection-empty-summary" }, { kind: "component", type: SeatSelectionSummaryItemComponent, selector: "seat-selection-summary-item", inputs: ["item"] }, { kind: "component", type: TicketMapWidgetComponent, selector: "ticket-map-widget" }, { kind: "component", type: TicketMapWidgetHeaderComponent, selector: "ticket-map-widget-header", inputs: ["title"] }] });
|
|
9098
9250
|
}
|
|
9099
9251
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatSelectionSummaryComponent, decorators: [{
|
|
9100
9252
|
type: Component,
|
|
@@ -9105,7 +9257,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
9105
9257
|
SeatSelectionSummaryItemComponent,
|
|
9106
9258
|
TicketMapWidgetComponent,
|
|
9107
9259
|
TicketMapWidgetHeaderComponent,
|
|
9108
|
-
], template: "<ticket-map-widget>\n <ticket-map-widget-header [title]=\"title\" />\n\n @if (selectionService.selectedCount() > 0) {\n <div class=\"tickets-list\">\n @for (item of selectionService.
|
|
9260
|
+
], template: "<ticket-map-widget>\n <ticket-map-widget-header [title]=\"title\" />\n\n @if (selectionService.selectedCount() > 0) {\n <div class=\"tickets-list\">\n @for (item of selectionService.summaryItems(); track trackByItem(item)) {\n <seat-selection-summary-item [item]=\"item\" />\n }\n </div>\n\n @if (selectionService.selectedCount() > 0) {\n <div class=\"tickets-actions\">\n <app-button\n size=\"xs\"\n [text]=\"clearButtonText\"\n icon=\"ri-delete-bin-line\"\n (clicked)=\"selectionService.clearSelection()\"\n />\n </div>\n }\n } @else {\n <seat-selection-empty-summary />\n }\n</ticket-map-widget>\n" }]
|
|
9109
9261
|
}], ctorParameters: () => [{ type: TicketSelectionService }], propDecorators: { title: [{
|
|
9110
9262
|
type: Input
|
|
9111
9263
|
}], clearButtonText: [{
|
|
@@ -9864,5 +10016,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
9864
10016
|
* Generated bundle index. Do not edit.
|
|
9865
10017
|
*/
|
|
9866
10018
|
|
|
9867
|
-
export { ADMIN_API_ROUTES, ALERT_ICONS, AdminSelectComponent, AdminService, ApiService, AppAlertComponent, AppBadgeComponent, AppBreadcumbComponent, AppButtonComponent, AppLinkButtonComponent, AppModalComponent, AsyncSelectComponent, AuditInformationComponent, BASE_BUTTON_CLASSES, BASE_INPUT_CLASSES, BUTTON_SIZES_CLASSES, BUTTON_VARIANT_CLASSES, BaseModalService, CITY_API_ENDPOINTS, COUNTRY_API_ENDPOINTS, CUSTOMERS_API_ROUTES, ChangePasswordFormComponent, ChangePasswordFormService, CitiesService, CitySelectComponent, ColorPickerComponent, ConfirmationOrderModalComponent, ConfirmationOrderModalService, CorporateBondStatus, CountrySelectComponent, CountryService, CouponApplicability, CouponDiscountType, CouponStatus, CreatorType, CustomerSelectComponent, CustomerService, DEFAULT_STAGE_CONFIG, DOCUMENT_TYPES_OPTIONS, DateInputComponent, DateService, DaySelectorGridComponent, DeleteConfirmationComponent, DeleteConfirmationService, DynamicTableComponent, ERROR_INPUT_CLASSES, EndDateGreaterThanStartValidator, FORM_ERROR_MESSAGES, FeedbackModalComponent, FeedbackModalService, FileType, FileUploadComponent, FileUploadPreviewComponent, FormEditorComponent, FormInputComponent, FormSelectComponent, FormTextareaComponent, GiftBondPurchaseStatus, GiftBondStatus, KONVA_SHAPE_MAPPINGS, LanguageSwitcherComponent, MembershipStatus, MinTodayValidator, MustMatchValidator, NumberInputComponent, ORDER_DISCOUNT_COLORS, ORDER_ITEM_TYPES_COLORS, ORDER_STATUS_COLORS, OrderBillingInfoComponent, OrderDiscountAppliedComponent, OrderInformationComponent, OrderItemType, OrderItemTypeBadgeComponent, OrderItemsComponent, OrderStatus, OrderStatusBadgeComponent, OrderTransactionDetailsModalComponent, OrderTransactionDetailsModalService, OrderTransactionsComponent, PAYMENT_METHODS_OPTIONS, PERFORMANCES_API_ROUTES, PERFORMANCE_STATUS_COLORS, PERFORMANCE_TICKET_STATUS_COLORS, PHONE_COUNTRIES, PRICE_ZONES_API_ROUTES, PRODUCTS_API_ROUTES, PRODUCT_CATEGORIES_API_ROUTES, PRODUCT_TAGS_API_ROUTES, PRODUCT_TYPES_API_ROUTES, PaymentMethod, PerformanceBookingDataService, PerformanceCardComponent, PerformanceCardListComponent, PerformanceMultiSelectComponent, PerformanceSelectComponent, PerformanceService, PerformanceStatus, PerformanceStatusBadgeComponent, PerformanceStepperComponent, PerformanceTicketMapComponent, PerformanceTicketStatus, PerformanceTicketStatusBadgeComponent, PerformancesListEventsService, PhoneInputComponent, PriceZoneEventService, PriceZoneFormModalService, PriceZoneSelectComponent, PriceZoneService, ProductCategoryService, ProductMultiSelectComponent, ProductSelectComponent, ProductService, ProductTagService, ProductTypeService, RoomMapElementOrientation, RoomMapElementType, SHOWS_API_ROUTES, SHOW_TYPE_COLORS, STATE_API_ENDPOINTS, SeatSelectionEmptySummaryComponent, SeatSelectionSummaryComponent, SeatSelectionSummaryItemComponent, SelectedDiscountCardType, ShowCardComponent, ShowCardSkeletonComponent, ShowMultiSelectComponent, ShowSelectComponent, ShowService, ShowType, ShowTypeBadgeComponent, ShowsFilterComponent, StateSelectComponent, StatesService, TICKERA_COMPONENTS_CONFIG, TICKET_ELEMENT_TYPES, TICKET_MAP_GRID_SIZE, TICKET_MAP_LAST_TICKETS_LIMIT, TICKET_MAP_TITLE_HEIGHT, TICKET_STATUS_COLORS, TICKET_STATUS_FILLS, TICKET_STATUS_LABELS, TIcketMapProductSelectionComponent, TRANSACTION_STATUS_COLORS, TextExpandableComponent, TickeraTranslocoLoader, TicketMapFloorSelectorComponent, TicketMapPriceZonesComponent, TicketMapProductSelectionItemComponent, TicketMapTotalsComponent, TicketMapWidgetComponent, TicketMapWidgetHeaderComponent, TicketMapWrapperComponent, TicketMapZoomControlsComponent, TicketMapZoomService, TicketQrComponent, TicketQrModalComponent, TicketQrModalService, TicketQrService, TicketSelectionDetailsService, TicketSelectionDiscountService, TicketSelectionService, TicketSelectionTotalsService, ToastService, ToggleSwitchComponent, TransactionStatus, VENUES_API_ROUTES, VIP_CARDS_API_ROUTES, VipBalanceCardComponent, VipCardService, VipCardStatus, VipCardStatusBadgeComponent, VipRechargeModalComponent, VipTransactionType, VipTransactionsTableComponent, ZonePriceItemComponent, ZonePriceListComponent, authInterceptor, drawChairIcon$1 as drawChairIcon, drawHappyFace, drawRoundedRect, drawWheelchairIcon, emailValidator, findElementAtPosition, findTicketAtPosition, formatCitiesResponseToSelect, generateExitScene, generateHallwayScene, generateProductionAreaScene, generateSeatBlockScene, generateSeatBlockTicketScene, generateStageScene, generateStairScene, generateTableScene, generateTableTicketScene, generateUnavailableSpaceScene, generateZoneScene, getBrowserLanguage, getCustomerFullname, getItemTypeIcon, getOrderDiscount, getStoredLanguage, numberToLetter$1 as numberToLetter, parseJsonToFormDataAdvanced, phoneCountryFlag, processElementsToRenderData, provideTickeraComponents, resolveLanguage, setStoredLanguage, ticketCanOpenQr, tintColor, transformImageToFile, transformUrlParams };
|
|
10019
|
+
export { ADMIN_API_ROUTES, ALERT_ICONS, AdminSelectComponent, AdminService, ApiService, AppAlertComponent, AppBadgeComponent, AppBreadcumbComponent, AppButtonComponent, AppLinkButtonComponent, AppModalComponent, AsyncSelectComponent, AuditInformationComponent, BASE_BUTTON_CLASSES, BASE_INPUT_CLASSES, BUTTON_SIZES_CLASSES, BUTTON_VARIANT_CLASSES, BaseModalService, CITY_API_ENDPOINTS, COUNTRY_API_ENDPOINTS, CUSTOMERS_API_ROUTES, ChangePasswordFormComponent, ChangePasswordFormService, CitiesService, CitySelectComponent, ColorPickerComponent, ConfirmationOrderModalComponent, ConfirmationOrderModalService, CorporateBondStatus, CountrySelectComponent, CountryService, CouponApplicability, CouponDiscountType, CouponStatus, CreatorType, CustomerSelectComponent, CustomerService, DEFAULT_STAGE_CONFIG, DOCUMENT_TYPES_OPTIONS, DateInputComponent, DateService, DaySelectorGridComponent, DeleteConfirmationComponent, DeleteConfirmationService, DynamicTableComponent, ERROR_INPUT_CLASSES, EndDateGreaterThanStartValidator, FORM_ERROR_MESSAGES, FeedbackModalComponent, FeedbackModalService, FileType, FileUploadComponent, FileUploadPreviewComponent, FormEditorComponent, FormInputComponent, FormSelectComponent, FormTextareaComponent, GiftBondPurchaseStatus, GiftBondStatus, KONVA_SHAPE_MAPPINGS, LanguageSwitcherComponent, MembershipStatus, MinTodayValidator, MustMatchValidator, NumberInputComponent, ORDER_DISCOUNT_COLORS, ORDER_ITEM_TYPES_COLORS, ORDER_STATUS_COLORS, OrderBillingInfoComponent, OrderDiscountAppliedComponent, OrderInformationComponent, OrderItemType, OrderItemTypeBadgeComponent, OrderItemsComponent, OrderStatus, OrderStatusBadgeComponent, OrderTransactionDetailsModalComponent, OrderTransactionDetailsModalService, OrderTransactionsComponent, PAYMENT_METHODS_OPTIONS, PERFORMANCES_API_ROUTES, PERFORMANCE_STATUS_COLORS, PERFORMANCE_TICKET_STATUS_COLORS, PHONE_COUNTRIES, PRICE_ZONES_API_ROUTES, PRODUCTS_API_ROUTES, PRODUCT_CATEGORIES_API_ROUTES, PRODUCT_TAGS_API_ROUTES, PRODUCT_TYPES_API_ROUTES, PaymentMethod, PerformanceBookingDataService, PerformanceCardComponent, PerformanceCardListComponent, PerformanceMultiSelectComponent, PerformanceSelectComponent, PerformanceService, PerformanceStatus, PerformanceStatusBadgeComponent, PerformanceStepperComponent, PerformanceTicketMapComponent, PerformanceTicketStatus, PerformanceTicketStatusBadgeComponent, PerformancesListEventsService, PhoneInputComponent, PriceZoneEventService, PriceZoneFormModalService, PriceZoneSelectComponent, PriceZoneService, ProductCategoryService, ProductMultiSelectComponent, ProductSelectComponent, ProductService, ProductTagService, ProductTypeService, PurchaseLimitService, RoomMapElementOrientation, RoomMapElementType, SHOWS_API_ROUTES, SHOW_TYPE_COLORS, STATE_API_ENDPOINTS, SeatSelectionEmptySummaryComponent, SeatSelectionSummaryComponent, SeatSelectionSummaryItemComponent, SelectedDiscountCardType, ShowCardComponent, ShowCardSkeletonComponent, ShowMultiSelectComponent, ShowSelectComponent, ShowService, ShowType, ShowTypeBadgeComponent, ShowsFilterComponent, StateSelectComponent, StatesService, TICKERA_COMPONENTS_CONFIG, TICKET_ELEMENT_TYPES, TICKET_MAP_GRID_SIZE, TICKET_MAP_LAST_TICKETS_LIMIT, TICKET_MAP_TITLE_HEIGHT, TICKET_STATUS_COLORS, TICKET_STATUS_FILLS, TICKET_STATUS_LABELS, TIcketMapProductSelectionComponent, TRANSACTION_STATUS_COLORS, TextExpandableComponent, TickeraTranslocoLoader, TicketMapFloorSelectorComponent, TicketMapPriceZonesComponent, TicketMapProductSelectionItemComponent, TicketMapTotalsComponent, TicketMapWidgetComponent, TicketMapWidgetHeaderComponent, TicketMapWrapperComponent, TicketMapZoomControlsComponent, TicketMapZoomService, TicketQrComponent, TicketQrModalComponent, TicketQrModalService, TicketQrService, TicketSelectionDetailsService, TicketSelectionDiscountService, TicketSelectionService, TicketSelectionTotalsService, ToastService, ToggleSwitchComponent, TransactionStatus, VENUES_API_ROUTES, VIP_CARDS_API_ROUTES, VipBalanceCardComponent, VipCardService, VipCardStatus, VipCardStatusBadgeComponent, VipRechargeModalComponent, VipTransactionType, VipTransactionsTableComponent, ZonePriceItemComponent, ZonePriceListComponent, authInterceptor, drawChairIcon$1 as drawChairIcon, drawHappyFace, drawRoundedRect, drawWheelchairIcon, emailValidator, findElementAtPosition, findTicketAtPosition, formatCitiesResponseToSelect, generateExitScene, generateHallwayScene, generateProductionAreaScene, generateSeatBlockScene, generateSeatBlockTicketScene, generateStageScene, generateStairScene, generateTableScene, generateTableTicketScene, generateUnavailableSpaceScene, generateZoneScene, getBrowserLanguage, getCustomerFullname, getItemTypeIcon, getOrderDiscount, getStoredLanguage, numberToLetter$1 as numberToLetter, parseJsonToFormDataAdvanced, phoneCountryFlag, processElementsToRenderData, provideTickeraComponents, resolveLanguage, setStoredLanguage, ticketCanOpenQr, tintColor, transformImageToFile, transformUrlParams };
|
|
9868
10020
|
//# sourceMappingURL=tickera-angular-components.mjs.map
|