tickera-angular-components 0.0.1-dev.167 → 0.0.1-dev.169

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 = {
@@ -1020,6 +1030,7 @@ var OrderItemType;
1020
1030
  OrderItemType["PRODUCT"] = "PRODUCT";
1021
1031
  OrderItemType["GIFT_BOND"] = "GIFT_BOND";
1022
1032
  OrderItemType["CORPORATE_BOND"] = "CORPORATE_BOND";
1033
+ OrderItemType["VIP_RECHARGE"] = "VIP_RECHARGE";
1023
1034
  })(OrderItemType || (OrderItemType = {}));
1024
1035
 
1025
1036
  var OrderStatus;
@@ -1090,6 +1101,7 @@ const ORDER_ITEM_TYPES_COLORS = {
1090
1101
  PRODUCT: { text: '#7e22ce', bg: '#faf5ff' },
1091
1102
  GIFT_BOND: { text: '#ca8a04', bg: '#fefce8' },
1092
1103
  CORPORATE_BOND: { text: '#0d9488', bg: '#ccfbf1' },
1104
+ VIP_RECHARGE: { text: '#940d89', bg: '#fbccf1' },
1093
1105
  };
1094
1106
  const ORDER_DISCOUNT_COLORS = {
1095
1107
  coupon: { text: '#1d4ed8', bg: '#eff6ff' },
@@ -3515,6 +3527,11 @@ class PerformanceBookingDataService {
3515
3527
  _allRenderData = signal([], ...(ngDevMode ? [{ debugName: "_allRenderData" }] : []));
3516
3528
  _visibleFloorIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "_visibleFloorIds" }] : []));
3517
3529
  _stageConfig = signal(DEFAULT_STAGE_CONFIG, ...(ngDevMode ? [{ debugName: "_stageConfig" }] : []));
3530
+ // Snapshot de tickets tal como llegó del último `setPerformanceBookingData`,
3531
+ // más los parches aplicados por `applySeatStatusUpdates` (SSE). Se guarda
3532
+ // aparte de `_allRenderData` porque hace falta la lista completa de
3533
+ // tickets para poder recalcular el render data con `processElementsToRenderData`.
3534
+ _lastTickets = [];
3518
3535
  show = computed(() => this._show(), ...(ngDevMode ? [{ debugName: "show" }] : []));
3519
3536
  hallFloors = computed(() => this._hallFloors(), ...(ngDevMode ? [{ debugName: "hallFloors" }] : []));
3520
3537
  selectedHallFloor = computed(() => this._selectedHallFloor(), ...(ngDevMode ? [{ debugName: "selectedHallFloor" }] : []));
@@ -3539,6 +3556,7 @@ class PerformanceBookingDataService {
3539
3556
  this._show.set(data.show);
3540
3557
  const roomMap = data.room_map;
3541
3558
  this._roomMap.set(roomMap);
3559
+ this._lastTickets = data.tickets ?? [];
3542
3560
  const hallFloors = data.room_map?.hall?.hall_floors ?? [];
3543
3561
  const selectedHallFloor = hallFloors.length > 0 ? hallFloors[0] : null;
3544
3562
  this._hallFloors.set(hallFloors);
@@ -3554,6 +3572,33 @@ class PerformanceBookingDataService {
3554
3572
  height: canvasSettings.height || 600,
3555
3573
  });
3556
3574
  }
3575
+ /** Aplica actualizaciones de estado de tickets recibidas por SSE (ver
3576
+ * SeatAvailabilitySseService) sin volver a pedir todo el booking-data:
3577
+ * parcha `_lastTickets` y vuelve a calcular el render data del mapa con
3578
+ * los mismos `elements`/`price_zones` (que no cambian en vivo). */
3579
+ applySeatStatusUpdates(updates) {
3580
+ if (!updates.length || !this._lastTickets.length)
3581
+ return;
3582
+ const roomMap = this._roomMap();
3583
+ if (!roomMap)
3584
+ return;
3585
+ const updatesById = new Map(updates.map((u) => [u.id, u]));
3586
+ let changed = false;
3587
+ for (const ticket of this._lastTickets) {
3588
+ const update = updatesById.get(ticket.id);
3589
+ if (!update)
3590
+ continue;
3591
+ if (ticket.status !== update.status || ticket.reserved_until !== update.reserved_until) {
3592
+ ticket.status = update.status;
3593
+ ticket.reserved_until = update.reserved_until;
3594
+ changed = true;
3595
+ }
3596
+ }
3597
+ if (!changed)
3598
+ return;
3599
+ const renderData = processElementsToRenderData(roomMap.elements, this._lastTickets, roomMap.price_zones);
3600
+ this._allRenderData.set(renderData);
3601
+ }
3557
3602
  setRoomMap(roomMap) {
3558
3603
  this._roomMap.set(roomMap);
3559
3604
  }
@@ -3786,6 +3831,34 @@ class TicketSelectionService {
3786
3831
  setTickets(tickets) {
3787
3832
  this._allTickets.set(tickets);
3788
3833
  }
3834
+ /** Aplica actualizaciones de estado recibidas por SSE (ver
3835
+ * SeatAvailabilitySseService). Muta los tickets existentes EN VEZ de
3836
+ * reemplazarlos por objetos nuevos: `_selectedTickets`/
3837
+ * `_selectedBlockedTickets` son Sets de referencias de objeto, no de ids,
3838
+ * así que reemplazar el array rompería la selección activa del usuario. */
3839
+ applySeatStatusUpdates(updates) {
3840
+ if (!updates.length)
3841
+ return;
3842
+ const updatesById = new Map(updates.map((u) => [u.id, u]));
3843
+ const current = this._allTickets();
3844
+ let changed = false;
3845
+ for (const ticket of current) {
3846
+ const update = updatesById.get(ticket.id);
3847
+ if (!update)
3848
+ continue;
3849
+ if (ticket.status !== update.status || ticket.reserved_until !== update.reserved_until) {
3850
+ ticket.status = update.status;
3851
+ ticket.reserved_until = update.reserved_until;
3852
+ changed = true;
3853
+ }
3854
+ }
3855
+ if (changed) {
3856
+ // Misma referencia de cada ticket, solo un array nuevo para disparar
3857
+ // la señal (Angular signals compara por referencia del array, no
3858
+ // hace deep-diff de su contenido).
3859
+ this._allTickets.set([...current]);
3860
+ }
3861
+ }
3789
3862
  setProducts(products) {
3790
3863
  this._products.set(products);
3791
3864
  }
@@ -4325,6 +4398,304 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
4325
4398
  args: [{ providedIn: 'root' }]
4326
4399
  }] });
4327
4400
 
4401
+ const RECONNECT_BASE_DELAY_MS$1 = 1000;
4402
+ const RECONNECT_MAX_DELAY_MS$1 = 15000;
4403
+ /**
4404
+ * Transporte SSE del estado de asientos en vivo. Es el único punto de la
4405
+ * librería que sabe de EventSource/HTTP para esto — aplica cada snapshot
4406
+ * recibido sobre PerformanceBookingDataService (repinta el mapa) y
4407
+ * TicketSelectionService (mantiene la disponibilidad al día para
4408
+ * validaciones de zona/límite de compra).
4409
+ *
4410
+ * Cada intento de reconexión pide un ticket NUEVO (el anterior es de un
4411
+ * solo uso y expira a los ~30s), con backoff exponencial acotado.
4412
+ */
4413
+ class SeatAvailabilitySseService {
4414
+ apiService;
4415
+ bookingDataService;
4416
+ ticketSelectionService;
4417
+ platformId;
4418
+ config;
4419
+ eventSource = null;
4420
+ reconnectTimer = null;
4421
+ reconnectAttempts = 0;
4422
+ currentPerformanceId = null;
4423
+ currentIsAdmin = false;
4424
+ stopped = true;
4425
+ constructor(apiService, bookingDataService, ticketSelectionService, platformId, config) {
4426
+ this.apiService = apiService;
4427
+ this.bookingDataService = bookingDataService;
4428
+ this.ticketSelectionService = ticketSelectionService;
4429
+ this.platformId = platformId;
4430
+ this.config = config;
4431
+ }
4432
+ connect(performanceId, opts = {}) {
4433
+ if (!isPlatformBrowser(this.platformId) || !performanceId)
4434
+ return;
4435
+ this.disconnect();
4436
+ this.stopped = false;
4437
+ this.currentPerformanceId = performanceId;
4438
+ this.currentIsAdmin = !!opts.isAdmin;
4439
+ this.reconnectAttempts = 0;
4440
+ this.openConnection();
4441
+ }
4442
+ disconnect() {
4443
+ this.stopped = true;
4444
+ this.currentPerformanceId = null;
4445
+ if (this.reconnectTimer) {
4446
+ clearTimeout(this.reconnectTimer);
4447
+ this.reconnectTimer = null;
4448
+ }
4449
+ this.eventSource?.close();
4450
+ this.eventSource = null;
4451
+ }
4452
+ openConnection() {
4453
+ const performanceId = this.currentPerformanceId;
4454
+ if (!performanceId || this.stopped)
4455
+ return;
4456
+ const ticketRoute = this.currentIsAdmin
4457
+ ? PERFORMANCES_API_ROUTES.seatEventsTicketAdmin(performanceId)
4458
+ : PERFORMANCES_API_ROUTES.seatEventsTicket(performanceId);
4459
+ this.apiService
4460
+ .post(ticketRoute, {})
4461
+ .subscribe({
4462
+ next: (res) => this.startStream(performanceId, res?.data?.ticket),
4463
+ error: () => this.scheduleReconnect(),
4464
+ });
4465
+ }
4466
+ startStream(performanceId, ticket) {
4467
+ if (!ticket || this.stopped || this.currentPerformanceId !== performanceId)
4468
+ return;
4469
+ const route = PERFORMANCES_API_ROUTES.seatEvents(performanceId);
4470
+ const url = `${this.config.apiUrl}${route}?ticket=${encodeURIComponent(ticket)}`;
4471
+ const eventSource = new EventSource(url);
4472
+ this.eventSource = eventSource;
4473
+ eventSource.onmessage = (event) => {
4474
+ this.reconnectAttempts = 0;
4475
+ try {
4476
+ const message = JSON.parse(event.data);
4477
+ if (message.type === 'snapshot') {
4478
+ this.bookingDataService.applySeatStatusUpdates(message.tickets);
4479
+ this.ticketSelectionService.applySeatStatusUpdates(message.tickets);
4480
+ }
4481
+ // 'heartbeat' solo mantiene viva la conexión a través de proxies, se ignora.
4482
+ }
4483
+ catch {
4484
+ // Mensaje inválido: se ignora, el próximo snapshot vuelve a sincronizar todo.
4485
+ }
4486
+ };
4487
+ eventSource.onerror = () => {
4488
+ eventSource.close();
4489
+ if (this.eventSource === eventSource)
4490
+ this.eventSource = null;
4491
+ this.scheduleReconnect();
4492
+ };
4493
+ }
4494
+ scheduleReconnect() {
4495
+ if (this.stopped || !this.currentPerformanceId)
4496
+ return;
4497
+ const delay = Math.min(RECONNECT_BASE_DELAY_MS$1 * Math.pow(2, this.reconnectAttempts), RECONNECT_MAX_DELAY_MS$1);
4498
+ this.reconnectAttempts++;
4499
+ this.reconnectTimer = setTimeout(() => {
4500
+ this.reconnectTimer = null;
4501
+ this.openConnection();
4502
+ }, delay);
4503
+ }
4504
+ 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 });
4505
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatAvailabilitySseService, providedIn: 'root' });
4506
+ }
4507
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SeatAvailabilitySseService, decorators: [{
4508
+ type: Injectable,
4509
+ args: [{ providedIn: 'root' }]
4510
+ }], ctorParameters: () => [{ type: ApiService }, { type: PerformanceBookingDataService }, { type: TicketSelectionService }, { type: Object, decorators: [{
4511
+ type: Inject,
4512
+ args: [PLATFORM_ID]
4513
+ }] }, { type: undefined, decorators: [{
4514
+ type: Inject,
4515
+ args: [TICKERA_COMPONENTS_CONFIG]
4516
+ }] }] });
4517
+
4518
+ const ADMISSION_MODAL_ID = 'admission-queue';
4519
+ const RECONNECT_BASE_DELAY_MS = 1000;
4520
+ const RECONNECT_MAX_DELAY_MS = 15000;
4521
+ /**
4522
+ * Cliente de la cola adaptativa (fase 4). No decide CUÁNDO se activa la
4523
+ * cola — eso es enteramente responsabilidad del backend (AdmissionGuard +
4524
+ * LoadBasedAdmissionPolicy) — este servicio solo sabe reaccionar al 429
4525
+ * `ADMISSION_QUEUE_REQUIRED` que ese guard puede devolver en
4526
+ * /carts/reserve y /orders/checkout.
4527
+ *
4528
+ * Uso típico en el punto de llamada (ver reservation-confirmation y
4529
+ * checkout-form): reintentar la request original dentro de un catchError:
4530
+ *
4531
+ * this.cartService.reserve(dto).pipe(
4532
+ * catchError((err) => {
4533
+ * if (!this.admissionQueueService.isAdmissionRequired(err)) return throwError(() => err);
4534
+ * const performanceId = this.admissionQueueService.getPerformanceId(err)!;
4535
+ * return this.admissionQueueService.waitForAdmission(performanceId).pipe(
4536
+ * switchMap(() => this.cartService.reserve(dto)),
4537
+ * );
4538
+ * }),
4539
+ * )
4540
+ *
4541
+ * Reutiliza el mismo transporte SSE con ticket de un solo uso de la fase 3
4542
+ * (ver SeatAvailabilitySseService) — acá el ticket llega directo en la
4543
+ * respuesta de /join, así que no hace falta un endpoint de ticket aparte;
4544
+ * cada reintento de conexión vuelve a hacer /join (el ticket anterior es
4545
+ * de un solo uso y expira a los ~30s).
4546
+ */
4547
+ class AdmissionQueueService {
4548
+ apiService;
4549
+ feedbackModalService;
4550
+ platformId;
4551
+ config;
4552
+ constructor(apiService, feedbackModalService, platformId, config) {
4553
+ this.apiService = apiService;
4554
+ this.feedbackModalService = feedbackModalService;
4555
+ this.platformId = platformId;
4556
+ this.config = config;
4557
+ }
4558
+ /** True si el error es el 429 específico de "alta demanda, únete a la fila". */
4559
+ isAdmissionRequired(error) {
4560
+ return (error instanceof HttpErrorResponse &&
4561
+ error.status === 429 &&
4562
+ error.error?.error?.code === 'ADMISSION_QUEUE_REQUIRED');
4563
+ }
4564
+ getPerformanceId(error) {
4565
+ const id = error.error?.error?.performance_id;
4566
+ return typeof id === 'number' ? id : null;
4567
+ }
4568
+ /**
4569
+ * Se une a la fila de `performanceId` y completa (emite una vez y cierra)
4570
+ * en cuanto el usuario queda admitido. Mientras espera, muestra un modal
4571
+ * ligero con la posición vigente, actualizado por SSE. Si quien se
4572
+ * suscribió se desuscribe antes de ser admitido (el usuario navega a
4573
+ * otro lado, cierra el modal, o el componente se destruye), libera el
4574
+ * lugar en la fila con /leave.
4575
+ */
4576
+ waitForAdmission(performanceId) {
4577
+ return new Observable((subscriber) => {
4578
+ if (!isPlatformBrowser(this.platformId)) {
4579
+ subscriber.complete();
4580
+ return;
4581
+ }
4582
+ let eventSource = null;
4583
+ let reconnectTimer = null;
4584
+ let reconnectAttempts = 0;
4585
+ let settled = false;
4586
+ let joined = false;
4587
+ const closeStream = () => {
4588
+ if (reconnectTimer) {
4589
+ clearTimeout(reconnectTimer);
4590
+ reconnectTimer = null;
4591
+ }
4592
+ eventSource?.close();
4593
+ eventSource = null;
4594
+ };
4595
+ const showWaitingModal = (position) => {
4596
+ this.feedbackModalService.addModal({
4597
+ id: ADMISSION_MODAL_ID,
4598
+ type: 'loading',
4599
+ title: 'Hay mucha demanda en este momento',
4600
+ message: position && position > 0
4601
+ ? `Estás en la fila, posición ${position}. Te avisamos apenas te toque.`
4602
+ : 'Estamos verificando tu turno, espera un momento…',
4603
+ isOpen: signal(true),
4604
+ showCloseButton: false,
4605
+ showHeader: false,
4606
+ });
4607
+ };
4608
+ const finish = () => {
4609
+ if (settled)
4610
+ return;
4611
+ settled = true;
4612
+ closeStream();
4613
+ this.feedbackModalService.removeModal(ADMISSION_MODAL_ID);
4614
+ subscriber.next();
4615
+ subscriber.complete();
4616
+ };
4617
+ const scheduleReconnect = () => {
4618
+ if (settled)
4619
+ return;
4620
+ const delay = Math.min(RECONNECT_BASE_DELAY_MS * Math.pow(2, reconnectAttempts), RECONNECT_MAX_DELAY_MS);
4621
+ reconnectAttempts++;
4622
+ reconnectTimer = setTimeout(() => {
4623
+ reconnectTimer = null;
4624
+ doJoin();
4625
+ }, delay);
4626
+ };
4627
+ const startStream = (ticket) => {
4628
+ if (settled)
4629
+ return;
4630
+ const route = ADMISSION_API_ROUTES.events(performanceId);
4631
+ const url = `${this.config.apiUrl}${route}?ticket=${encodeURIComponent(ticket)}`;
4632
+ const es = new EventSource(url);
4633
+ eventSource = es;
4634
+ es.onmessage = (event) => {
4635
+ reconnectAttempts = 0;
4636
+ try {
4637
+ const message = JSON.parse(event.data);
4638
+ if (message.type !== 'status')
4639
+ return;
4640
+ if (message.active) {
4641
+ finish();
4642
+ return;
4643
+ }
4644
+ showWaitingModal(message.position);
4645
+ }
4646
+ catch {
4647
+ // Mensaje inválido: se ignora, el próximo evento vuelve a sincronizar.
4648
+ }
4649
+ };
4650
+ es.onerror = () => {
4651
+ es.close();
4652
+ if (eventSource === es)
4653
+ eventSource = null;
4654
+ scheduleReconnect();
4655
+ };
4656
+ };
4657
+ const doJoin = () => {
4658
+ this.apiService
4659
+ .post(ADMISSION_API_ROUTES.join(performanceId), {})
4660
+ .subscribe({
4661
+ next: (res) => {
4662
+ joined = true;
4663
+ if (res.active) {
4664
+ finish();
4665
+ return;
4666
+ }
4667
+ showWaitingModal(res.position);
4668
+ startStream(res.ticket);
4669
+ },
4670
+ error: () => scheduleReconnect(),
4671
+ });
4672
+ };
4673
+ doJoin();
4674
+ return () => {
4675
+ if (settled)
4676
+ return;
4677
+ closeStream();
4678
+ this.feedbackModalService.removeModal(ADMISSION_MODAL_ID);
4679
+ if (joined) {
4680
+ this.apiService.post(ADMISSION_API_ROUTES.leave(performanceId), {}).subscribe({ error: () => { } });
4681
+ }
4682
+ };
4683
+ });
4684
+ }
4685
+ 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 });
4686
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AdmissionQueueService, providedIn: 'root' });
4687
+ }
4688
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AdmissionQueueService, decorators: [{
4689
+ type: Injectable,
4690
+ args: [{ providedIn: 'root' }]
4691
+ }], ctorParameters: () => [{ type: ApiService }, { type: FeedbackModalService }, { type: Object, decorators: [{
4692
+ type: Inject,
4693
+ args: [PLATFORM_ID]
4694
+ }] }, { type: undefined, decorators: [{
4695
+ type: Inject,
4696
+ args: [TICKERA_COMPONENTS_CONFIG]
4697
+ }] }] });
4698
+
4328
4699
  class TicketQrService {
4329
4700
  apiService;
4330
4701
  constructor(apiService) {
@@ -9644,6 +10015,9 @@ class OrderItemsComponent {
9644
10015
  get corporateBonds() {
9645
10016
  return (this.orderItems?.filter(({ item_type }) => item_type === OrderItemType.CORPORATE_BOND) ?? []);
9646
10017
  }
10018
+ get vipRecharges() {
10019
+ return (this.orderItems?.filter(({ item_type }) => item_type === OrderItemType.VIP_RECHARGE) ?? []);
10020
+ }
9647
10021
  get showActionColumn() {
9648
10022
  return this.order.status === 'completed' && this.tickets.length > 0;
9649
10023
  }
@@ -9666,7 +10040,10 @@ class OrderItemsComponent {
9666
10040
  const corporateBonds = this.corporateBonds?.reduce((accumulator, currentTicket) => {
9667
10041
  return accumulator + currentTicket?.normal_price;
9668
10042
  }, 0);
9669
- return { products, tickets, giftBonds, corporateBonds };
10043
+ const vipRecharges = this.vipRecharges?.reduce((accumulator, currentTicket) => {
10044
+ return accumulator + currentTicket?.normal_price;
10045
+ }, 0);
10046
+ return { products, tickets, giftBonds, corporateBonds, vipRecharges };
9670
10047
  }
9671
10048
  openTicketQr(ticketUuid, description) {
9672
10049
  this.ticketQrModalService.open(ticketUuid, description);
@@ -10016,5 +10393,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
10016
10393
  * Generated bundle index. Do not edit.
10017
10394
  */
10018
10395
 
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 };
10396
+ 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
10397
  //# sourceMappingURL=tickera-angular-components.mjs.map