tickera-angular-components 0.0.1-dev.166 → 0.0.1-dev.168
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.
|
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { InjectionToken, makeEnvironmentProviders, PLATFORM_ID, Inject, Injectable, signal, LOCALE_ID, computed, inject, EventEmitter, Input, Output, Component, ViewEncapsulation, HostListener, Self, Optional, Injector, forwardRef, effect, untracked, ViewChild } from '@angular/core';
|
|
3
3
|
import * as i2 from '@jsverse/transloco';
|
|
4
4
|
import { provideTransloco, TranslocoModule, TranslocoService } from '@jsverse/transloco';
|
|
5
|
-
import { from, throwError, BehaviorSubject, Subject, of, takeUntil as takeUntil$1 } from 'rxjs';
|
|
5
|
+
import { from, throwError, BehaviorSubject, Subject, of, Observable, takeUntil as takeUntil$1 } from 'rxjs';
|
|
6
6
|
import * as i1$1 from '@angular/common';
|
|
7
7
|
import { DATE_PIPE_DEFAULT_OPTIONS, isPlatformBrowser, formatDate, CommonModule, DatePipe } from '@angular/common';
|
|
8
8
|
import { provideTippyLoader, provideTippyConfig, popperVariation, tooltipVariation } from '@ngneat/helipopper/config';
|
|
@@ -10,7 +10,7 @@ export * from '@ngneat/helipopper/config';
|
|
|
10
10
|
import { TippyDirective } from '@ngneat/helipopper';
|
|
11
11
|
export { TippyDirective } from '@ngneat/helipopper';
|
|
12
12
|
import * as i1 from '@angular/common/http';
|
|
13
|
-
import { HttpHeaders } from '@angular/common/http';
|
|
13
|
+
import { HttpHeaders, HttpErrorResponse } from '@angular/common/http';
|
|
14
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';
|
|
@@ -490,6 +490,13 @@ const ADMIN_API_ROUTES = {
|
|
|
490
490
|
deleteOne: (id) => `/admins/${id}`,
|
|
491
491
|
};
|
|
492
492
|
|
|
493
|
+
const ADMISSION_API_ROUTES = {
|
|
494
|
+
join: (performanceId) => `/admission/${performanceId}/join`,
|
|
495
|
+
leave: (performanceId) => `/admission/${performanceId}/leave`,
|
|
496
|
+
status: (performanceId) => `/admission/${performanceId}/status`,
|
|
497
|
+
events: (performanceId) => `/admission/${performanceId}/events`,
|
|
498
|
+
};
|
|
499
|
+
|
|
493
500
|
const CITY_API_ENDPOINTS = {
|
|
494
501
|
findAll: '/cities',
|
|
495
502
|
create: '/cities',
|
|
@@ -530,6 +537,9 @@ const PERFORMANCES_API_ROUTES = {
|
|
|
530
537
|
ticketQrToken: (uuid) => `/performances/tickets/${uuid}/qr-token`,
|
|
531
538
|
getAvailableDays: '/performances/available-days',
|
|
532
539
|
publicAvailablePerformances: '/public/performances/daily',
|
|
540
|
+
seatEventsTicket: (id) => `/performances/${id}/seat-events/ticket`,
|
|
541
|
+
seatEventsTicketAdmin: (id) => `/performances/${id}/seat-events/ticket/admin`,
|
|
542
|
+
seatEvents: (id) => `/performances/${id}/seat-events`,
|
|
533
543
|
};
|
|
534
544
|
|
|
535
545
|
const PRICE_ZONES_API_ROUTES = {
|
|
@@ -3515,6 +3525,11 @@ class PerformanceBookingDataService {
|
|
|
3515
3525
|
_allRenderData = signal([], ...(ngDevMode ? [{ debugName: "_allRenderData" }] : []));
|
|
3516
3526
|
_visibleFloorIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "_visibleFloorIds" }] : []));
|
|
3517
3527
|
_stageConfig = signal(DEFAULT_STAGE_CONFIG, ...(ngDevMode ? [{ debugName: "_stageConfig" }] : []));
|
|
3528
|
+
// Snapshot de tickets tal como llegó del último `setPerformanceBookingData`,
|
|
3529
|
+
// más los parches aplicados por `applySeatStatusUpdates` (SSE). Se guarda
|
|
3530
|
+
// aparte de `_allRenderData` porque hace falta la lista completa de
|
|
3531
|
+
// tickets para poder recalcular el render data con `processElementsToRenderData`.
|
|
3532
|
+
_lastTickets = [];
|
|
3518
3533
|
show = computed(() => this._show(), ...(ngDevMode ? [{ debugName: "show" }] : []));
|
|
3519
3534
|
hallFloors = computed(() => this._hallFloors(), ...(ngDevMode ? [{ debugName: "hallFloors" }] : []));
|
|
3520
3535
|
selectedHallFloor = computed(() => this._selectedHallFloor(), ...(ngDevMode ? [{ debugName: "selectedHallFloor" }] : []));
|
|
@@ -3539,6 +3554,7 @@ class PerformanceBookingDataService {
|
|
|
3539
3554
|
this._show.set(data.show);
|
|
3540
3555
|
const roomMap = data.room_map;
|
|
3541
3556
|
this._roomMap.set(roomMap);
|
|
3557
|
+
this._lastTickets = data.tickets ?? [];
|
|
3542
3558
|
const hallFloors = data.room_map?.hall?.hall_floors ?? [];
|
|
3543
3559
|
const selectedHallFloor = hallFloors.length > 0 ? hallFloors[0] : null;
|
|
3544
3560
|
this._hallFloors.set(hallFloors);
|
|
@@ -3554,6 +3570,33 @@ class PerformanceBookingDataService {
|
|
|
3554
3570
|
height: canvasSettings.height || 600,
|
|
3555
3571
|
});
|
|
3556
3572
|
}
|
|
3573
|
+
/** Aplica actualizaciones de estado de tickets recibidas por SSE (ver
|
|
3574
|
+
* SeatAvailabilitySseService) sin volver a pedir todo el booking-data:
|
|
3575
|
+
* parcha `_lastTickets` y vuelve a calcular el render data del mapa con
|
|
3576
|
+
* los mismos `elements`/`price_zones` (que no cambian en vivo). */
|
|
3577
|
+
applySeatStatusUpdates(updates) {
|
|
3578
|
+
if (!updates.length || !this._lastTickets.length)
|
|
3579
|
+
return;
|
|
3580
|
+
const roomMap = this._roomMap();
|
|
3581
|
+
if (!roomMap)
|
|
3582
|
+
return;
|
|
3583
|
+
const updatesById = new Map(updates.map((u) => [u.id, u]));
|
|
3584
|
+
let changed = false;
|
|
3585
|
+
for (const ticket of this._lastTickets) {
|
|
3586
|
+
const update = updatesById.get(ticket.id);
|
|
3587
|
+
if (!update)
|
|
3588
|
+
continue;
|
|
3589
|
+
if (ticket.status !== update.status || ticket.reserved_until !== update.reserved_until) {
|
|
3590
|
+
ticket.status = update.status;
|
|
3591
|
+
ticket.reserved_until = update.reserved_until;
|
|
3592
|
+
changed = true;
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
if (!changed)
|
|
3596
|
+
return;
|
|
3597
|
+
const renderData = processElementsToRenderData(roomMap.elements, this._lastTickets, roomMap.price_zones);
|
|
3598
|
+
this._allRenderData.set(renderData);
|
|
3599
|
+
}
|
|
3557
3600
|
setRoomMap(roomMap) {
|
|
3558
3601
|
this._roomMap.set(roomMap);
|
|
3559
3602
|
}
|
|
@@ -3786,6 +3829,34 @@ class TicketSelectionService {
|
|
|
3786
3829
|
setTickets(tickets) {
|
|
3787
3830
|
this._allTickets.set(tickets);
|
|
3788
3831
|
}
|
|
3832
|
+
/** Aplica actualizaciones de estado recibidas por SSE (ver
|
|
3833
|
+
* SeatAvailabilitySseService). Muta los tickets existentes EN VEZ de
|
|
3834
|
+
* reemplazarlos por objetos nuevos: `_selectedTickets`/
|
|
3835
|
+
* `_selectedBlockedTickets` son Sets de referencias de objeto, no de ids,
|
|
3836
|
+
* así que reemplazar el array rompería la selección activa del usuario. */
|
|
3837
|
+
applySeatStatusUpdates(updates) {
|
|
3838
|
+
if (!updates.length)
|
|
3839
|
+
return;
|
|
3840
|
+
const updatesById = new Map(updates.map((u) => [u.id, u]));
|
|
3841
|
+
const current = this._allTickets();
|
|
3842
|
+
let changed = false;
|
|
3843
|
+
for (const ticket of current) {
|
|
3844
|
+
const update = updatesById.get(ticket.id);
|
|
3845
|
+
if (!update)
|
|
3846
|
+
continue;
|
|
3847
|
+
if (ticket.status !== update.status || ticket.reserved_until !== update.reserved_until) {
|
|
3848
|
+
ticket.status = update.status;
|
|
3849
|
+
ticket.reserved_until = update.reserved_until;
|
|
3850
|
+
changed = true;
|
|
3851
|
+
}
|
|
3852
|
+
}
|
|
3853
|
+
if (changed) {
|
|
3854
|
+
// Misma referencia de cada ticket, solo un array nuevo para disparar
|
|
3855
|
+
// la señal (Angular signals compara por referencia del array, no
|
|
3856
|
+
// hace deep-diff de su contenido).
|
|
3857
|
+
this._allTickets.set([...current]);
|
|
3858
|
+
}
|
|
3859
|
+
}
|
|
3789
3860
|
setProducts(products) {
|
|
3790
3861
|
this._products.set(products);
|
|
3791
3862
|
}
|
|
@@ -4325,6 +4396,304 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
4325
4396
|
args: [{ providedIn: 'root' }]
|
|
4326
4397
|
}] });
|
|
4327
4398
|
|
|
4399
|
+
const RECONNECT_BASE_DELAY_MS$1 = 1000;
|
|
4400
|
+
const RECONNECT_MAX_DELAY_MS$1 = 15000;
|
|
4401
|
+
/**
|
|
4402
|
+
* Transporte SSE del estado de asientos en vivo. Es el único punto de la
|
|
4403
|
+
* librería que sabe de EventSource/HTTP para esto — aplica cada snapshot
|
|
4404
|
+
* recibido sobre PerformanceBookingDataService (repinta el mapa) y
|
|
4405
|
+
* TicketSelectionService (mantiene la disponibilidad al día para
|
|
4406
|
+
* validaciones de zona/límite de compra).
|
|
4407
|
+
*
|
|
4408
|
+
* Cada intento de reconexión pide un ticket NUEVO (el anterior es de un
|
|
4409
|
+
* solo uso y expira a los ~30s), con backoff exponencial acotado.
|
|
4410
|
+
*/
|
|
4411
|
+
class SeatAvailabilitySseService {
|
|
4412
|
+
apiService;
|
|
4413
|
+
bookingDataService;
|
|
4414
|
+
ticketSelectionService;
|
|
4415
|
+
platformId;
|
|
4416
|
+
config;
|
|
4417
|
+
eventSource = null;
|
|
4418
|
+
reconnectTimer = null;
|
|
4419
|
+
reconnectAttempts = 0;
|
|
4420
|
+
currentPerformanceId = null;
|
|
4421
|
+
currentIsAdmin = false;
|
|
4422
|
+
stopped = true;
|
|
4423
|
+
constructor(apiService, bookingDataService, ticketSelectionService, platformId, config) {
|
|
4424
|
+
this.apiService = apiService;
|
|
4425
|
+
this.bookingDataService = bookingDataService;
|
|
4426
|
+
this.ticketSelectionService = ticketSelectionService;
|
|
4427
|
+
this.platformId = platformId;
|
|
4428
|
+
this.config = config;
|
|
4429
|
+
}
|
|
4430
|
+
connect(performanceId, opts = {}) {
|
|
4431
|
+
if (!isPlatformBrowser(this.platformId) || !performanceId)
|
|
4432
|
+
return;
|
|
4433
|
+
this.disconnect();
|
|
4434
|
+
this.stopped = false;
|
|
4435
|
+
this.currentPerformanceId = performanceId;
|
|
4436
|
+
this.currentIsAdmin = !!opts.isAdmin;
|
|
4437
|
+
this.reconnectAttempts = 0;
|
|
4438
|
+
this.openConnection();
|
|
4439
|
+
}
|
|
4440
|
+
disconnect() {
|
|
4441
|
+
this.stopped = true;
|
|
4442
|
+
this.currentPerformanceId = null;
|
|
4443
|
+
if (this.reconnectTimer) {
|
|
4444
|
+
clearTimeout(this.reconnectTimer);
|
|
4445
|
+
this.reconnectTimer = null;
|
|
4446
|
+
}
|
|
4447
|
+
this.eventSource?.close();
|
|
4448
|
+
this.eventSource = null;
|
|
4449
|
+
}
|
|
4450
|
+
openConnection() {
|
|
4451
|
+
const performanceId = this.currentPerformanceId;
|
|
4452
|
+
if (!performanceId || this.stopped)
|
|
4453
|
+
return;
|
|
4454
|
+
const ticketRoute = this.currentIsAdmin
|
|
4455
|
+
? PERFORMANCES_API_ROUTES.seatEventsTicketAdmin(performanceId)
|
|
4456
|
+
: PERFORMANCES_API_ROUTES.seatEventsTicket(performanceId);
|
|
4457
|
+
this.apiService
|
|
4458
|
+
.post(ticketRoute, {})
|
|
4459
|
+
.subscribe({
|
|
4460
|
+
next: (res) => this.startStream(performanceId, res?.data?.ticket),
|
|
4461
|
+
error: () => this.scheduleReconnect(),
|
|
4462
|
+
});
|
|
4463
|
+
}
|
|
4464
|
+
startStream(performanceId, ticket) {
|
|
4465
|
+
if (!ticket || this.stopped || this.currentPerformanceId !== performanceId)
|
|
4466
|
+
return;
|
|
4467
|
+
const route = PERFORMANCES_API_ROUTES.seatEvents(performanceId);
|
|
4468
|
+
const url = `${this.config.apiUrl}${route}?ticket=${encodeURIComponent(ticket)}`;
|
|
4469
|
+
const eventSource = new EventSource(url);
|
|
4470
|
+
this.eventSource = eventSource;
|
|
4471
|
+
eventSource.onmessage = (event) => {
|
|
4472
|
+
this.reconnectAttempts = 0;
|
|
4473
|
+
try {
|
|
4474
|
+
const message = JSON.parse(event.data);
|
|
4475
|
+
if (message.type === 'snapshot') {
|
|
4476
|
+
this.bookingDataService.applySeatStatusUpdates(message.tickets);
|
|
4477
|
+
this.ticketSelectionService.applySeatStatusUpdates(message.tickets);
|
|
4478
|
+
}
|
|
4479
|
+
// 'heartbeat' solo mantiene viva la conexión a través de proxies, se ignora.
|
|
4480
|
+
}
|
|
4481
|
+
catch {
|
|
4482
|
+
// Mensaje inválido: se ignora, el próximo snapshot vuelve a sincronizar todo.
|
|
4483
|
+
}
|
|
4484
|
+
};
|
|
4485
|
+
eventSource.onerror = () => {
|
|
4486
|
+
eventSource.close();
|
|
4487
|
+
if (this.eventSource === eventSource)
|
|
4488
|
+
this.eventSource = null;
|
|
4489
|
+
this.scheduleReconnect();
|
|
4490
|
+
};
|
|
4491
|
+
}
|
|
4492
|
+
scheduleReconnect() {
|
|
4493
|
+
if (this.stopped || !this.currentPerformanceId)
|
|
4494
|
+
return;
|
|
4495
|
+
const delay = Math.min(RECONNECT_BASE_DELAY_MS$1 * Math.pow(2, this.reconnectAttempts), RECONNECT_MAX_DELAY_MS$1);
|
|
4496
|
+
this.reconnectAttempts++;
|
|
4497
|
+
this.reconnectTimer = setTimeout(() => {
|
|
4498
|
+
this.reconnectTimer = null;
|
|
4499
|
+
this.openConnection();
|
|
4500
|
+
}, delay);
|
|
4501
|
+
}
|
|
4502
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatAvailabilitySseService, deps: [{ token: ApiService }, { token: PerformanceBookingDataService }, { token: TicketSelectionService }, { token: PLATFORM_ID }, { token: TICKERA_COMPONENTS_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4503
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatAvailabilitySseService, providedIn: 'root' });
|
|
4504
|
+
}
|
|
4505
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatAvailabilitySseService, decorators: [{
|
|
4506
|
+
type: Injectable,
|
|
4507
|
+
args: [{ providedIn: 'root' }]
|
|
4508
|
+
}], ctorParameters: () => [{ type: ApiService }, { type: PerformanceBookingDataService }, { type: TicketSelectionService }, { type: Object, decorators: [{
|
|
4509
|
+
type: Inject,
|
|
4510
|
+
args: [PLATFORM_ID]
|
|
4511
|
+
}] }, { type: undefined, decorators: [{
|
|
4512
|
+
type: Inject,
|
|
4513
|
+
args: [TICKERA_COMPONENTS_CONFIG]
|
|
4514
|
+
}] }] });
|
|
4515
|
+
|
|
4516
|
+
const ADMISSION_MODAL_ID = 'admission-queue';
|
|
4517
|
+
const RECONNECT_BASE_DELAY_MS = 1000;
|
|
4518
|
+
const RECONNECT_MAX_DELAY_MS = 15000;
|
|
4519
|
+
/**
|
|
4520
|
+
* Cliente de la cola adaptativa (fase 4). No decide CUÁNDO se activa la
|
|
4521
|
+
* cola — eso es enteramente responsabilidad del backend (AdmissionGuard +
|
|
4522
|
+
* LoadBasedAdmissionPolicy) — este servicio solo sabe reaccionar al 429
|
|
4523
|
+
* `ADMISSION_QUEUE_REQUIRED` que ese guard puede devolver en
|
|
4524
|
+
* /carts/reserve y /orders/checkout.
|
|
4525
|
+
*
|
|
4526
|
+
* Uso típico en el punto de llamada (ver reservation-confirmation y
|
|
4527
|
+
* checkout-form): reintentar la request original dentro de un catchError:
|
|
4528
|
+
*
|
|
4529
|
+
* this.cartService.reserve(dto).pipe(
|
|
4530
|
+
* catchError((err) => {
|
|
4531
|
+
* if (!this.admissionQueueService.isAdmissionRequired(err)) return throwError(() => err);
|
|
4532
|
+
* const performanceId = this.admissionQueueService.getPerformanceId(err)!;
|
|
4533
|
+
* return this.admissionQueueService.waitForAdmission(performanceId).pipe(
|
|
4534
|
+
* switchMap(() => this.cartService.reserve(dto)),
|
|
4535
|
+
* );
|
|
4536
|
+
* }),
|
|
4537
|
+
* )
|
|
4538
|
+
*
|
|
4539
|
+
* Reutiliza el mismo transporte SSE con ticket de un solo uso de la fase 3
|
|
4540
|
+
* (ver SeatAvailabilitySseService) — acá el ticket llega directo en la
|
|
4541
|
+
* respuesta de /join, así que no hace falta un endpoint de ticket aparte;
|
|
4542
|
+
* cada reintento de conexión vuelve a hacer /join (el ticket anterior es
|
|
4543
|
+
* de un solo uso y expira a los ~30s).
|
|
4544
|
+
*/
|
|
4545
|
+
class AdmissionQueueService {
|
|
4546
|
+
apiService;
|
|
4547
|
+
feedbackModalService;
|
|
4548
|
+
platformId;
|
|
4549
|
+
config;
|
|
4550
|
+
constructor(apiService, feedbackModalService, platformId, config) {
|
|
4551
|
+
this.apiService = apiService;
|
|
4552
|
+
this.feedbackModalService = feedbackModalService;
|
|
4553
|
+
this.platformId = platformId;
|
|
4554
|
+
this.config = config;
|
|
4555
|
+
}
|
|
4556
|
+
/** True si el error es el 429 específico de "alta demanda, únete a la fila". */
|
|
4557
|
+
isAdmissionRequired(error) {
|
|
4558
|
+
return (error instanceof HttpErrorResponse &&
|
|
4559
|
+
error.status === 429 &&
|
|
4560
|
+
error.error?.error?.code === 'ADMISSION_QUEUE_REQUIRED');
|
|
4561
|
+
}
|
|
4562
|
+
getPerformanceId(error) {
|
|
4563
|
+
const id = error.error?.error?.performance_id;
|
|
4564
|
+
return typeof id === 'number' ? id : null;
|
|
4565
|
+
}
|
|
4566
|
+
/**
|
|
4567
|
+
* Se une a la fila de `performanceId` y completa (emite una vez y cierra)
|
|
4568
|
+
* en cuanto el usuario queda admitido. Mientras espera, muestra un modal
|
|
4569
|
+
* ligero con la posición vigente, actualizado por SSE. Si quien se
|
|
4570
|
+
* suscribió se desuscribe antes de ser admitido (el usuario navega a
|
|
4571
|
+
* otro lado, cierra el modal, o el componente se destruye), libera el
|
|
4572
|
+
* lugar en la fila con /leave.
|
|
4573
|
+
*/
|
|
4574
|
+
waitForAdmission(performanceId) {
|
|
4575
|
+
return new Observable((subscriber) => {
|
|
4576
|
+
if (!isPlatformBrowser(this.platformId)) {
|
|
4577
|
+
subscriber.complete();
|
|
4578
|
+
return;
|
|
4579
|
+
}
|
|
4580
|
+
let eventSource = null;
|
|
4581
|
+
let reconnectTimer = null;
|
|
4582
|
+
let reconnectAttempts = 0;
|
|
4583
|
+
let settled = false;
|
|
4584
|
+
let joined = false;
|
|
4585
|
+
const closeStream = () => {
|
|
4586
|
+
if (reconnectTimer) {
|
|
4587
|
+
clearTimeout(reconnectTimer);
|
|
4588
|
+
reconnectTimer = null;
|
|
4589
|
+
}
|
|
4590
|
+
eventSource?.close();
|
|
4591
|
+
eventSource = null;
|
|
4592
|
+
};
|
|
4593
|
+
const showWaitingModal = (position) => {
|
|
4594
|
+
this.feedbackModalService.addModal({
|
|
4595
|
+
id: ADMISSION_MODAL_ID,
|
|
4596
|
+
type: 'loading',
|
|
4597
|
+
title: 'Hay mucha demanda en este momento',
|
|
4598
|
+
message: position && position > 0
|
|
4599
|
+
? `Estás en la fila, posición ${position}. Te avisamos apenas te toque.`
|
|
4600
|
+
: 'Estamos verificando tu turno, espera un momento…',
|
|
4601
|
+
isOpen: signal(true),
|
|
4602
|
+
showCloseButton: false,
|
|
4603
|
+
showHeader: false,
|
|
4604
|
+
});
|
|
4605
|
+
};
|
|
4606
|
+
const finish = () => {
|
|
4607
|
+
if (settled)
|
|
4608
|
+
return;
|
|
4609
|
+
settled = true;
|
|
4610
|
+
closeStream();
|
|
4611
|
+
this.feedbackModalService.removeModal(ADMISSION_MODAL_ID);
|
|
4612
|
+
subscriber.next();
|
|
4613
|
+
subscriber.complete();
|
|
4614
|
+
};
|
|
4615
|
+
const scheduleReconnect = () => {
|
|
4616
|
+
if (settled)
|
|
4617
|
+
return;
|
|
4618
|
+
const delay = Math.min(RECONNECT_BASE_DELAY_MS * Math.pow(2, reconnectAttempts), RECONNECT_MAX_DELAY_MS);
|
|
4619
|
+
reconnectAttempts++;
|
|
4620
|
+
reconnectTimer = setTimeout(() => {
|
|
4621
|
+
reconnectTimer = null;
|
|
4622
|
+
doJoin();
|
|
4623
|
+
}, delay);
|
|
4624
|
+
};
|
|
4625
|
+
const startStream = (ticket) => {
|
|
4626
|
+
if (settled)
|
|
4627
|
+
return;
|
|
4628
|
+
const route = ADMISSION_API_ROUTES.events(performanceId);
|
|
4629
|
+
const url = `${this.config.apiUrl}${route}?ticket=${encodeURIComponent(ticket)}`;
|
|
4630
|
+
const es = new EventSource(url);
|
|
4631
|
+
eventSource = es;
|
|
4632
|
+
es.onmessage = (event) => {
|
|
4633
|
+
reconnectAttempts = 0;
|
|
4634
|
+
try {
|
|
4635
|
+
const message = JSON.parse(event.data);
|
|
4636
|
+
if (message.type !== 'status')
|
|
4637
|
+
return;
|
|
4638
|
+
if (message.active) {
|
|
4639
|
+
finish();
|
|
4640
|
+
return;
|
|
4641
|
+
}
|
|
4642
|
+
showWaitingModal(message.position);
|
|
4643
|
+
}
|
|
4644
|
+
catch {
|
|
4645
|
+
// Mensaje inválido: se ignora, el próximo evento vuelve a sincronizar.
|
|
4646
|
+
}
|
|
4647
|
+
};
|
|
4648
|
+
es.onerror = () => {
|
|
4649
|
+
es.close();
|
|
4650
|
+
if (eventSource === es)
|
|
4651
|
+
eventSource = null;
|
|
4652
|
+
scheduleReconnect();
|
|
4653
|
+
};
|
|
4654
|
+
};
|
|
4655
|
+
const doJoin = () => {
|
|
4656
|
+
this.apiService
|
|
4657
|
+
.post(ADMISSION_API_ROUTES.join(performanceId), {})
|
|
4658
|
+
.subscribe({
|
|
4659
|
+
next: (res) => {
|
|
4660
|
+
joined = true;
|
|
4661
|
+
if (res.active) {
|
|
4662
|
+
finish();
|
|
4663
|
+
return;
|
|
4664
|
+
}
|
|
4665
|
+
showWaitingModal(res.position);
|
|
4666
|
+
startStream(res.ticket);
|
|
4667
|
+
},
|
|
4668
|
+
error: () => scheduleReconnect(),
|
|
4669
|
+
});
|
|
4670
|
+
};
|
|
4671
|
+
doJoin();
|
|
4672
|
+
return () => {
|
|
4673
|
+
if (settled)
|
|
4674
|
+
return;
|
|
4675
|
+
closeStream();
|
|
4676
|
+
this.feedbackModalService.removeModal(ADMISSION_MODAL_ID);
|
|
4677
|
+
if (joined) {
|
|
4678
|
+
this.apiService.post(ADMISSION_API_ROUTES.leave(performanceId), {}).subscribe({ error: () => { } });
|
|
4679
|
+
}
|
|
4680
|
+
};
|
|
4681
|
+
});
|
|
4682
|
+
}
|
|
4683
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AdmissionQueueService, deps: [{ token: ApiService }, { token: FeedbackModalService }, { token: PLATFORM_ID }, { token: TICKERA_COMPONENTS_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4684
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AdmissionQueueService, providedIn: 'root' });
|
|
4685
|
+
}
|
|
4686
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AdmissionQueueService, decorators: [{
|
|
4687
|
+
type: Injectable,
|
|
4688
|
+
args: [{ providedIn: 'root' }]
|
|
4689
|
+
}], ctorParameters: () => [{ type: ApiService }, { type: FeedbackModalService }, { type: Object, decorators: [{
|
|
4690
|
+
type: Inject,
|
|
4691
|
+
args: [PLATFORM_ID]
|
|
4692
|
+
}] }, { type: undefined, decorators: [{
|
|
4693
|
+
type: Inject,
|
|
4694
|
+
args: [TICKERA_COMPONENTS_CONFIG]
|
|
4695
|
+
}] }] });
|
|
4696
|
+
|
|
4328
4697
|
class TicketQrService {
|
|
4329
4698
|
apiService;
|
|
4330
4699
|
constructor(apiService) {
|
|
@@ -9221,11 +9590,11 @@ class SeatSelectionSummaryItemComponent {
|
|
|
9221
9590
|
this.selectionService.deselect(ticket);
|
|
9222
9591
|
}
|
|
9223
9592
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatSelectionSummaryItemComponent, deps: [{ token: TicketSelectionService }], target: i0.ɵɵFactoryTarget.Component });
|
|
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 }\n
|
|
9593
|
+
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" }] });
|
|
9225
9594
|
}
|
|
9226
9595
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatSelectionSummaryItemComponent, decorators: [{
|
|
9227
9596
|
type: Component,
|
|
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 }\n
|
|
9597
|
+
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"] }]
|
|
9229
9598
|
}], ctorParameters: () => [{ type: TicketSelectionService }], propDecorators: { item: [{
|
|
9230
9599
|
type: Input,
|
|
9231
9600
|
args: [{ required: true }]
|
|
@@ -10016,5 +10385,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10016
10385
|
* Generated bundle index. Do not edit.
|
|
10017
10386
|
*/
|
|
10018
10387
|
|
|
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 };
|
|
10388
|
+
export { ADMIN_API_ROUTES, ADMISSION_API_ROUTES, ALERT_ICONS, AdminSelectComponent, AdminService, AdmissionQueueService, 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, SeatAvailabilitySseService, 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 };
|
|
10020
10389
|
//# sourceMappingURL=tickera-angular-components.mjs.map
|