tickera-angular-components 0.0.1-dev.32 β 0.0.1-dev.33
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.
- package/fesm2022/tickera-angular-components.mjs +1182 -1
- package/fesm2022/tickera-angular-components.mjs.map +1 -1
- package/index.d.ts +306 -148
- package/package.json +1 -1
|
@@ -480,6 +480,41 @@ var GiftBondStatus;
|
|
|
480
480
|
GiftBondStatus["CONSUMED"] = "CONSUMED";
|
|
481
481
|
})(GiftBondStatus || (GiftBondStatus = {}));
|
|
482
482
|
|
|
483
|
+
const TICKET_ELEMENT_TYPES = [
|
|
484
|
+
RoomMapElementType.SEAT_BLOCK,
|
|
485
|
+
RoomMapElementType.TABLE,
|
|
486
|
+
RoomMapElementType.ZONE,
|
|
487
|
+
];
|
|
488
|
+
const DEFAULT_STAGE_CONFIG = {
|
|
489
|
+
width: 800,
|
|
490
|
+
height: 600,
|
|
491
|
+
draggable: true,
|
|
492
|
+
scaleX: 1,
|
|
493
|
+
scaleY: 1,
|
|
494
|
+
x: 0,
|
|
495
|
+
y: 0,
|
|
496
|
+
};
|
|
497
|
+
const TICKET_STATUS_COLORS = {
|
|
498
|
+
[PerformanceTicketStatus.AVAILABLE]: '#22C55E',
|
|
499
|
+
[PerformanceTicketStatus.RESERVED]: '#EAB308',
|
|
500
|
+
[PerformanceTicketStatus.SOLD]: '#EF4444',
|
|
501
|
+
[PerformanceTicketStatus.BLOCKED]: '#6B7280',
|
|
502
|
+
};
|
|
503
|
+
const TICKET_STATUS_FILLS = {
|
|
504
|
+
[PerformanceTicketStatus.AVAILABLE]: '#DCFCE7',
|
|
505
|
+
[PerformanceTicketStatus.RESERVED]: '#FEF08A',
|
|
506
|
+
[PerformanceTicketStatus.SOLD]: '#FECACA',
|
|
507
|
+
[PerformanceTicketStatus.BLOCKED]: '#E5E7EB',
|
|
508
|
+
};
|
|
509
|
+
const TICKET_STATUS_LABELS = {
|
|
510
|
+
[PerformanceTicketStatus.AVAILABLE]: 'Disponible',
|
|
511
|
+
[PerformanceTicketStatus.RESERVED]: 'Reservado',
|
|
512
|
+
[PerformanceTicketStatus.SOLD]: 'Vendido',
|
|
513
|
+
[PerformanceTicketStatus.BLOCKED]: 'Bloqueado',
|
|
514
|
+
};
|
|
515
|
+
const TICKET_MAP_GRID_SIZE = 30;
|
|
516
|
+
const TICKET_MAP_TITLE_HEIGHT = 30;
|
|
517
|
+
|
|
483
518
|
var OrderItemType;
|
|
484
519
|
(function (OrderItemType) {
|
|
485
520
|
OrderItemType["TICKET"] = "TICKET";
|
|
@@ -497,6 +532,13 @@ var OrderStatus;
|
|
|
497
532
|
OrderStatus["REFUNDED"] = "refunded";
|
|
498
533
|
})(OrderStatus || (OrderStatus = {}));
|
|
499
534
|
|
|
535
|
+
var SelectedDiscountCardType;
|
|
536
|
+
(function (SelectedDiscountCardType) {
|
|
537
|
+
SelectedDiscountCardType["COUPON"] = "COUPON";
|
|
538
|
+
SelectedDiscountCardType["CORPORATE_BOND"] = "CORPORATE_BOND";
|
|
539
|
+
SelectedDiscountCardType["GIFT_BOND"] = "GIFT_BOND";
|
|
540
|
+
})(SelectedDiscountCardType || (SelectedDiscountCardType = {}));
|
|
541
|
+
|
|
500
542
|
const getCustomerFullname = (customer) => {
|
|
501
543
|
return `${customer.first_name || ''} ${customer.last_name || ''}`.trim();
|
|
502
544
|
};
|
|
@@ -577,6 +619,1145 @@ const formatCitiesResponseToSelect = (res) => {
|
|
|
577
619
|
}));
|
|
578
620
|
};
|
|
579
621
|
|
|
622
|
+
function drawRoundedRect(con, shape, x, y, width, height, cornerRadius) {
|
|
623
|
+
con.beginPath();
|
|
624
|
+
con.moveTo(x + cornerRadius, y);
|
|
625
|
+
con.lineTo(x + width - cornerRadius, y);
|
|
626
|
+
con.quadraticCurveTo(x + width, y, x + width, y + cornerRadius);
|
|
627
|
+
con.lineTo(x + width, y + height - cornerRadius);
|
|
628
|
+
con.quadraticCurveTo(x + width, y + height, x + width - cornerRadius, y + height);
|
|
629
|
+
con.lineTo(x + cornerRadius, y + height);
|
|
630
|
+
con.quadraticCurveTo(x, y + height, x, y + height - cornerRadius);
|
|
631
|
+
con.lineTo(x, y + cornerRadius);
|
|
632
|
+
con.quadraticCurveTo(x, y, x + cornerRadius, y);
|
|
633
|
+
con.closePath();
|
|
634
|
+
con.fillStrokeShape(shape);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
const generateExitScene = (con, shape) => {
|
|
638
|
+
const w = shape.width();
|
|
639
|
+
const h = shape.height();
|
|
640
|
+
const padding = 4;
|
|
641
|
+
con.save();
|
|
642
|
+
const exitX = padding;
|
|
643
|
+
const exitY = padding;
|
|
644
|
+
const exitWidth = w - padding * 2;
|
|
645
|
+
const exitHeight = h - padding * 2;
|
|
646
|
+
const cornerRadius = Math.min(exitWidth, exitHeight) * 0.2;
|
|
647
|
+
drawRoundedRect(con, shape, exitX, exitY, exitWidth, exitHeight, cornerRadius);
|
|
648
|
+
// Stage text - check if parent has element_name, otherwise use "ESCENARIO"
|
|
649
|
+
// const fontSize = Math.min(w, h) * 0.35;
|
|
650
|
+
con.font = `11px Arial`;
|
|
651
|
+
con.fillStyle = '#333333';
|
|
652
|
+
con.textAlign = 'center';
|
|
653
|
+
con.textBaseline = 'middle';
|
|
654
|
+
const centerX = w / 2;
|
|
655
|
+
const centerY = h / 2;
|
|
656
|
+
// Get parent element and check for element_name
|
|
657
|
+
const stageText = 'πͺ' + (shape?.attrs?.element_name || 'Salida');
|
|
658
|
+
con.fillText(stageText, centerX, centerY);
|
|
659
|
+
con.restore();
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
const generateHallwayScene = (con, shape) => {
|
|
663
|
+
const w = shape.width();
|
|
664
|
+
const h = shape.height();
|
|
665
|
+
const padding = 4;
|
|
666
|
+
con.save();
|
|
667
|
+
const exitX = padding;
|
|
668
|
+
const exitY = padding;
|
|
669
|
+
const exitWidth = w - padding * 2;
|
|
670
|
+
const exitHeight = h - padding * 2;
|
|
671
|
+
const cornerRadius = Math.min(exitWidth, exitHeight) * 0.2;
|
|
672
|
+
drawRoundedRect(con, shape, exitX, exitY, exitWidth, exitHeight, cornerRadius);
|
|
673
|
+
// Stage text - check if parent has element_name, otherwise use "ESCENARIO"
|
|
674
|
+
// const fontSize = Math.min(w, h) * 0.35;
|
|
675
|
+
con.font = `11px Arial`;
|
|
676
|
+
con.fillStyle = '#333333';
|
|
677
|
+
con.textAlign = 'center';
|
|
678
|
+
con.textBaseline = 'middle';
|
|
679
|
+
const centerX = w / 2;
|
|
680
|
+
const centerY = h / 2;
|
|
681
|
+
// Get parent element and check for element_name
|
|
682
|
+
const stageText = 'πΆπ½' + (shape?.attrs?.element_name || 'Pasillo');
|
|
683
|
+
con.fillText(stageText, centerX, centerY);
|
|
684
|
+
con.restore();
|
|
685
|
+
};
|
|
686
|
+
|
|
687
|
+
const generateProductionAreaScene = (con, shape) => {
|
|
688
|
+
const w = shape.width();
|
|
689
|
+
const h = shape.height();
|
|
690
|
+
const padding = 4;
|
|
691
|
+
con.save();
|
|
692
|
+
const exitX = padding;
|
|
693
|
+
const exitY = padding;
|
|
694
|
+
const exitWidth = w - padding * 2;
|
|
695
|
+
const exitHeight = h - padding * 2;
|
|
696
|
+
const cornerRadius = Math.min(exitWidth, exitHeight) * 0.2;
|
|
697
|
+
drawRoundedRect(con, shape, exitX, exitY, exitWidth, exitHeight, cornerRadius);
|
|
698
|
+
// Stage text - check if parent has element_name, otherwise use "ESCENARIO"
|
|
699
|
+
// const fontSize = Math.min(w, h) * 0.35;
|
|
700
|
+
con.font = `11px Arial`;
|
|
701
|
+
con.fillStyle = '#333333';
|
|
702
|
+
con.textAlign = 'center';
|
|
703
|
+
con.textBaseline = 'middle';
|
|
704
|
+
const centerX = w / 2;
|
|
705
|
+
const centerY = h / 2;
|
|
706
|
+
// Get parent element and check for element_name
|
|
707
|
+
const stageText = 'π οΈ' + (shape?.attrs?.element_name || 'Γrea de producciΓ³n');
|
|
708
|
+
con.fillText(stageText, centerX, centerY);
|
|
709
|
+
con.restore();
|
|
710
|
+
};
|
|
711
|
+
|
|
712
|
+
function tintColor(hex, amount = 0.7) {
|
|
713
|
+
const cleanHex = hex.replace('#', '');
|
|
714
|
+
const r = parseInt(cleanHex.substring(0, 2), 16);
|
|
715
|
+
const g = parseInt(cleanHex.substring(2, 4), 16);
|
|
716
|
+
const b = parseInt(cleanHex.substring(4, 6), 16);
|
|
717
|
+
const tintedR = Math.round(r + (255 - r) * amount);
|
|
718
|
+
const tintedG = Math.round(g + (255 - g) * amount);
|
|
719
|
+
const tintedB = Math.round(b + (255 - b) * amount);
|
|
720
|
+
return `#${tintedR.toString(16).padStart(2, '0')}${tintedG.toString(16).padStart(2, '0')}${tintedB.toString(16).padStart(2, '0')}`;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
const drawChairIcon$1 = (con, cx, cy, size) => {
|
|
724
|
+
con.beginPath();
|
|
725
|
+
const backWidth = size * 0.7;
|
|
726
|
+
const backHeight = size * 0.6;
|
|
727
|
+
const backX = cx - backWidth / 2;
|
|
728
|
+
const backY = cy - backHeight / 2 - size * 0.1;
|
|
729
|
+
con.moveTo(backX + backWidth * 0.2, backY);
|
|
730
|
+
con.lineTo(backX + backWidth * 0.8, backY);
|
|
731
|
+
con.quadraticCurveTo(backX + backWidth, backY, backX + backWidth, backY + backHeight * 0.2);
|
|
732
|
+
con.lineTo(backX + backWidth, backY + backHeight * 0.8);
|
|
733
|
+
con.quadraticCurveTo(backX + backWidth, backY + backHeight, backX + backWidth * 0.8, backY + backHeight);
|
|
734
|
+
con.lineTo(backX + backWidth * 0.2, backY + backHeight);
|
|
735
|
+
con.quadraticCurveTo(backX, backY + backHeight, backX, backY + backHeight * 0.8);
|
|
736
|
+
con.lineTo(backX, backY + backHeight * 0.2);
|
|
737
|
+
con.quadraticCurveTo(backX, backY, backX + backWidth * 0.2, backY);
|
|
738
|
+
const chairSeatWidth = size * 0.8;
|
|
739
|
+
const chairSeatHeight = size * 0.3;
|
|
740
|
+
const seatX = cx - chairSeatWidth / 2;
|
|
741
|
+
const seatY = cy + backHeight * 0.3;
|
|
742
|
+
con.moveTo(seatX, seatY);
|
|
743
|
+
con.lineTo(seatX + chairSeatWidth, seatY);
|
|
744
|
+
con.lineTo(seatX + chairSeatWidth * 0.9, seatY + chairSeatHeight);
|
|
745
|
+
con.lineTo(seatX + chairSeatWidth * 0.1, seatY + chairSeatHeight);
|
|
746
|
+
con.closePath();
|
|
747
|
+
const legWidth = size * 0.1;
|
|
748
|
+
const legHeight = size * 0.2;
|
|
749
|
+
con.moveTo(seatX + chairSeatWidth * 0.1, seatY + chairSeatHeight);
|
|
750
|
+
con.lineTo(seatX + chairSeatWidth * 0.1 + legWidth, seatY + chairSeatHeight);
|
|
751
|
+
con.lineTo(seatX + chairSeatWidth * 0.1 + legWidth, seatY + chairSeatHeight + legHeight);
|
|
752
|
+
con.lineTo(seatX + chairSeatWidth * 0.1, seatY + chairSeatHeight + legHeight);
|
|
753
|
+
con.moveTo(seatX + chairSeatWidth * 0.9 - legWidth, seatY + chairSeatHeight);
|
|
754
|
+
con.lineTo(seatX + chairSeatWidth * 0.9, seatY + chairSeatHeight);
|
|
755
|
+
con.lineTo(seatX + chairSeatWidth * 0.9, seatY + chairSeatHeight + legHeight);
|
|
756
|
+
con.lineTo(seatX + chairSeatWidth * 0.9 - legWidth, seatY + chairSeatHeight + legHeight);
|
|
757
|
+
con.closePath();
|
|
758
|
+
};
|
|
759
|
+
|
|
760
|
+
const drawHappyFace = (con, cx, cy, size) => {
|
|
761
|
+
const radius = size * 0.45;
|
|
762
|
+
con.beginPath();
|
|
763
|
+
con.arc(cx, cy, radius, 0, Math.PI * 2);
|
|
764
|
+
con.closePath();
|
|
765
|
+
con.fillStyle = '#DCFCE7';
|
|
766
|
+
con.fill();
|
|
767
|
+
con.strokeStyle = '#166534';
|
|
768
|
+
con.lineWidth = 2;
|
|
769
|
+
con.stroke();
|
|
770
|
+
const eyeR = radius * 0.12;
|
|
771
|
+
const eyeOffX = radius * 0.3;
|
|
772
|
+
const eyeOffY = radius * 0.15;
|
|
773
|
+
con.beginPath();
|
|
774
|
+
con.arc(cx - eyeOffX, cy - eyeOffY, eyeR, 0, Math.PI * 2);
|
|
775
|
+
con.closePath();
|
|
776
|
+
con.fillStyle = '#166534';
|
|
777
|
+
con.fill();
|
|
778
|
+
con.beginPath();
|
|
779
|
+
con.arc(cx + eyeOffX, cy - eyeOffY, eyeR, 0, Math.PI * 2);
|
|
780
|
+
con.closePath();
|
|
781
|
+
con.fill();
|
|
782
|
+
con.beginPath();
|
|
783
|
+
con.moveTo(cx - radius * 0.35, cy + radius * 0.05);
|
|
784
|
+
con.quadraticCurveTo(cx, cy + radius * 0.4, cx + radius * 0.35, cy + radius * 0.05);
|
|
785
|
+
con.strokeStyle = '#166534';
|
|
786
|
+
con.lineWidth = 2;
|
|
787
|
+
con.stroke();
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
const drawWheelchairIcon = (con, shape, cx, cy, size, fillColor = '#DBEAFE', strokeColor = '#60A5FA') => {
|
|
791
|
+
const reactSize = size * 0.75;
|
|
792
|
+
const x = cx - size / 2 + size * 0.1;
|
|
793
|
+
const y = cy - size / 2 + size * 0.1833;
|
|
794
|
+
const origFill = shape.getAttr('fill');
|
|
795
|
+
const origStroke = shape.getAttr('stroke');
|
|
796
|
+
shape.setAttr('fill', fillColor);
|
|
797
|
+
shape.setAttr('stroke', strokeColor);
|
|
798
|
+
con.beginPath();
|
|
799
|
+
con.rect(x, y, reactSize, reactSize);
|
|
800
|
+
con.closePath();
|
|
801
|
+
con.fillStrokeShape(shape);
|
|
802
|
+
shape.setAttr('fill', origFill);
|
|
803
|
+
shape.setAttr('stroke', origStroke);
|
|
804
|
+
con.font = `${size * 0.6}px serif`;
|
|
805
|
+
con.textAlign = 'center';
|
|
806
|
+
con.textBaseline = 'middle';
|
|
807
|
+
con.fillText('βΏ', cx + size * 0.0233, cy + size * 0.1417);
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
const numberToLetter$1 = (num) => {
|
|
811
|
+
if (num < 0)
|
|
812
|
+
return 'A';
|
|
813
|
+
let result = '';
|
|
814
|
+
let n = num;
|
|
815
|
+
while (n >= 0) {
|
|
816
|
+
result = String.fromCharCode(65 + (n % 26)) + result;
|
|
817
|
+
n = Math.floor(n / 26) - 1;
|
|
818
|
+
}
|
|
819
|
+
return result;
|
|
820
|
+
};
|
|
821
|
+
|
|
822
|
+
const getItemTypeIcon = (ticket) => {
|
|
823
|
+
if ([RoomMapElementType.SEAT_BLOCK, RoomMapElementType.TABLE].includes(ticket.element_type)) {
|
|
824
|
+
return ticket.is_accessible ? 'βΏοΈ' : 'πͺ';
|
|
825
|
+
}
|
|
826
|
+
if (ticket.element_type === RoomMapElementType.ZONE) {
|
|
827
|
+
return 'πΊοΈ';
|
|
828
|
+
}
|
|
829
|
+
return 'π';
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
const generateSeatBlockTicketScene = (con, shape, numerationConfig, ticketStatusMap) => {
|
|
833
|
+
const w = shape.width();
|
|
834
|
+
const h = shape.height();
|
|
835
|
+
const seatSize = TICKET_MAP_GRID_SIZE;
|
|
836
|
+
const chairScale = 0.8;
|
|
837
|
+
const elementName = shape?.attrs?.element_name || 'Asientos';
|
|
838
|
+
const showElementName = shape?.attrs?.show_element_name ?? true;
|
|
839
|
+
const seatsData = shape?.attrs?.seats;
|
|
840
|
+
const hasTitle = !!(elementName && showElementName);
|
|
841
|
+
const chairsStartY = hasTitle ? TICKET_MAP_GRID_SIZE : 0;
|
|
842
|
+
const cols = Math.floor(w / seatSize);
|
|
843
|
+
const rows = Math.floor((h - chairsStartY) / seatSize);
|
|
844
|
+
const config = numerationConfig || {
|
|
845
|
+
start_row_letter: 'A',
|
|
846
|
+
row_order: 'TOP_TO_BOTTOM',
|
|
847
|
+
start_column_number: 1,
|
|
848
|
+
column_order: 'LEFT_TO_RIGHT',
|
|
849
|
+
};
|
|
850
|
+
const startRowLetter = config?.start_row_letter?.toUpperCase() || 'A';
|
|
851
|
+
const startRowNum = startRowLetter.charCodeAt(0) - 65;
|
|
852
|
+
const origFill = shape.getAttr('fill');
|
|
853
|
+
const origStroke = shape.getAttr('stroke');
|
|
854
|
+
if (hasTitle) {
|
|
855
|
+
con.save();
|
|
856
|
+
const textFont = `bold 10px Arial`;
|
|
857
|
+
con.font = textFont;
|
|
858
|
+
const textWidth = con.measureText(elementName).width;
|
|
859
|
+
const paddingX = 10;
|
|
860
|
+
const containerHeight = 18;
|
|
861
|
+
const containerWidth = textWidth + paddingX * 2;
|
|
862
|
+
const containerX = (w - containerWidth) / 2;
|
|
863
|
+
const containerY = (TICKET_MAP_GRID_SIZE - containerHeight) / 2;
|
|
864
|
+
const lineY = TICKET_MAP_GRID_SIZE;
|
|
865
|
+
const strokeColor = shape.getAttr('stroke') || '#999';
|
|
866
|
+
con.beginPath();
|
|
867
|
+
con.moveTo(0, lineY);
|
|
868
|
+
con.lineTo(w, lineY);
|
|
869
|
+
con.strokeStyle = strokeColor;
|
|
870
|
+
con.lineWidth = 1;
|
|
871
|
+
con.stroke();
|
|
872
|
+
con.beginPath();
|
|
873
|
+
con.moveTo(containerX + 4, containerY);
|
|
874
|
+
con.lineTo(containerX + containerWidth - 4, containerY);
|
|
875
|
+
con.quadraticCurveTo(containerX + containerWidth, containerY, containerX + containerWidth, containerY + 4);
|
|
876
|
+
con.lineTo(containerX + containerWidth, containerY + containerHeight - 4);
|
|
877
|
+
con.quadraticCurveTo(containerX + containerWidth, containerY + containerHeight, containerX + containerWidth - 4, containerY + containerHeight);
|
|
878
|
+
con.lineTo(containerX + 4, containerY + containerHeight);
|
|
879
|
+
con.quadraticCurveTo(containerX, containerY + containerHeight, containerX, containerY + containerHeight - 4);
|
|
880
|
+
con.lineTo(containerX, containerY + 4);
|
|
881
|
+
con.quadraticCurveTo(containerX, containerY, containerX + 4, containerY);
|
|
882
|
+
con.closePath();
|
|
883
|
+
con.fillStrokeShape(shape);
|
|
884
|
+
con.font = textFont;
|
|
885
|
+
con.fillStyle = strokeColor;
|
|
886
|
+
con.textAlign = 'center';
|
|
887
|
+
con.textBaseline = 'middle';
|
|
888
|
+
con.fillText(elementName, w / 2, containerY + containerHeight / 2);
|
|
889
|
+
con.restore();
|
|
890
|
+
}
|
|
891
|
+
for (let x = 0; x < w; x += seatSize) {
|
|
892
|
+
for (let y = chairsStartY; y < h; y += seatSize) {
|
|
893
|
+
const colIndex = Math.floor(x / seatSize);
|
|
894
|
+
const rowIndex = Math.floor((y - chairsStartY) / seatSize);
|
|
895
|
+
let actualRowIndex = rowIndex;
|
|
896
|
+
if (config.row_order === 'BOTTOM_TO_TOP') {
|
|
897
|
+
actualRowIndex = rows - 1 - rowIndex;
|
|
898
|
+
}
|
|
899
|
+
let actualColIndex = colIndex;
|
|
900
|
+
if (config.column_order === 'RIGHT_TO_LEFT') {
|
|
901
|
+
actualColIndex = cols - 1 - colIndex;
|
|
902
|
+
}
|
|
903
|
+
const rowLetter = numberToLetter$1(startRowNum + actualRowIndex);
|
|
904
|
+
const colNumber = Number(config.start_column_number) + Number(actualColIndex);
|
|
905
|
+
const seatNumber = `${rowLetter}${colNumber}`;
|
|
906
|
+
const centerX = x + seatSize / 2 + 1;
|
|
907
|
+
const centerY = y + seatSize / 2 - 2;
|
|
908
|
+
const size = seatSize * chairScale;
|
|
909
|
+
const seatState = seatsData?.[rowIndex]?.[colIndex];
|
|
910
|
+
if (seatState?.is_non_existent)
|
|
911
|
+
continue;
|
|
912
|
+
con.save();
|
|
913
|
+
const selectedNumerations = shape.getAttr('selectedNumerations');
|
|
914
|
+
const isSelected = selectedNumerations?.has(seatNumber);
|
|
915
|
+
const ticketStatus = ticketStatusMap?.get(seatNumber);
|
|
916
|
+
const isLocked = ticketStatus != null && ticketStatus !== PerformanceTicketStatus.AVAILABLE;
|
|
917
|
+
if (isSelected) {
|
|
918
|
+
drawHappyFace(con, x + seatSize / 2, y + seatSize / 2, size);
|
|
919
|
+
}
|
|
920
|
+
else if (isLocked && seatState?.is_accessible) {
|
|
921
|
+
drawWheelchairIcon(con, shape, centerX, centerY, size, TICKET_STATUS_FILLS[ticketStatus], TICKET_STATUS_COLORS[ticketStatus]);
|
|
922
|
+
}
|
|
923
|
+
else if (isLocked) {
|
|
924
|
+
shape.setAttr('fill', TICKET_STATUS_FILLS[ticketStatus]);
|
|
925
|
+
shape.setAttr('stroke', TICKET_STATUS_COLORS[ticketStatus]);
|
|
926
|
+
drawChairIcon$1(con, centerX, centerY, size);
|
|
927
|
+
con.fillStrokeShape(shape);
|
|
928
|
+
shape.setAttr('fill', origFill);
|
|
929
|
+
shape.setAttr('stroke', origStroke);
|
|
930
|
+
con.fillStyle = '#333333';
|
|
931
|
+
con.font = `${size * 0.3}px Arial`;
|
|
932
|
+
con.textAlign = 'center';
|
|
933
|
+
con.textBaseline = 'middle';
|
|
934
|
+
con.fillText(seatNumber, centerX, centerY - 1);
|
|
935
|
+
}
|
|
936
|
+
else if (seatState?.is_accessible) {
|
|
937
|
+
drawWheelchairIcon(con, shape, centerX, centerY, size);
|
|
938
|
+
}
|
|
939
|
+
else {
|
|
940
|
+
drawChairIcon$1(con, centerX, centerY, size);
|
|
941
|
+
con.fillStrokeShape(shape);
|
|
942
|
+
shape.setAttr('fill', origFill);
|
|
943
|
+
shape.setAttr('stroke', origStroke);
|
|
944
|
+
con.fillStyle = '#333333';
|
|
945
|
+
con.font = `${size * 0.3}px Arial`;
|
|
946
|
+
con.textAlign = 'center';
|
|
947
|
+
con.textBaseline = 'middle';
|
|
948
|
+
con.fillText(seatNumber, centerX, centerY - 1);
|
|
949
|
+
}
|
|
950
|
+
con.restore();
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
shape.setAttr('fill', origFill);
|
|
954
|
+
shape.setAttr('stroke', origStroke);
|
|
955
|
+
};
|
|
956
|
+
|
|
957
|
+
const generateTableTicketScene = (con, shape, chairTicketStatuses, tableSeats) => {
|
|
958
|
+
const w = shape.width();
|
|
959
|
+
const h = shape.height();
|
|
960
|
+
const fillColor = shape.fill();
|
|
961
|
+
const strokeColor = shape.stroke();
|
|
962
|
+
const totalCapacity = shape?.attrs?.total_capacity ?? 0;
|
|
963
|
+
const zoneText = shape?.attrs?.element_name || 'Mesa';
|
|
964
|
+
const cx = w / 2;
|
|
965
|
+
const cy = h / 2;
|
|
966
|
+
const chairRadius = Math.min(w, h) * 0.1;
|
|
967
|
+
const gap = chairRadius * 0.4;
|
|
968
|
+
const tableRadius = Math.min(w, h) / 2 - chairRadius * 2 - gap;
|
|
969
|
+
con.save();
|
|
970
|
+
if (totalCapacity > 0) {
|
|
971
|
+
const orbitRadius = tableRadius + gap + chairRadius;
|
|
972
|
+
const selectedNumerations = shape.getAttr('selectedNumerations');
|
|
973
|
+
for (let i = 0; i < totalCapacity; i++) {
|
|
974
|
+
const seatState = tableSeats?.[0]?.[i];
|
|
975
|
+
if (seatState?.is_non_existent) {
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
const seatKey = `S${i + 1}`;
|
|
979
|
+
const isSelected = selectedNumerations?.has(seatKey);
|
|
980
|
+
const angle = (2 * Math.PI * i) / totalCapacity - Math.PI / 2;
|
|
981
|
+
const scx = cx + orbitRadius * Math.cos(angle);
|
|
982
|
+
const scy = cy + orbitRadius * Math.sin(angle);
|
|
983
|
+
const chairStatus = chairTicketStatuses?.[i];
|
|
984
|
+
const isLocked = chairStatus != null && chairStatus !== PerformanceTicketStatus.AVAILABLE;
|
|
985
|
+
if (isSelected) {
|
|
986
|
+
drawHappyFace(con, scx, scy, chairRadius * 2);
|
|
987
|
+
}
|
|
988
|
+
else if (isLocked && seatState?.is_accessible) {
|
|
989
|
+
drawWheelchairIcon(con, shape, scx, scy, chairRadius * 2, TICKET_STATUS_FILLS[chairStatus], TICKET_STATUS_COLORS[chairStatus]);
|
|
990
|
+
}
|
|
991
|
+
else if (isLocked) {
|
|
992
|
+
const origFill = shape.getAttr('fill');
|
|
993
|
+
const origStroke = shape.getAttr('stroke');
|
|
994
|
+
shape.setAttr('fill', TICKET_STATUS_FILLS[PerformanceTicketStatus.BLOCKED]);
|
|
995
|
+
shape.setAttr('stroke', TICKET_STATUS_COLORS[PerformanceTicketStatus.BLOCKED]);
|
|
996
|
+
con.beginPath();
|
|
997
|
+
con.arc(scx, scy, chairRadius, 0, Math.PI * 2);
|
|
998
|
+
con.closePath();
|
|
999
|
+
con.lineWidth = Math.max(1, chairRadius * 0.15);
|
|
1000
|
+
con.stroke();
|
|
1001
|
+
con.fillStrokeShape(shape);
|
|
1002
|
+
shape.setAttr('fill', origFill);
|
|
1003
|
+
shape.setAttr('stroke', origStroke);
|
|
1004
|
+
}
|
|
1005
|
+
else if (seatState?.is_accessible) {
|
|
1006
|
+
drawWheelchairIcon(con, shape, scx, scy, chairRadius * 2);
|
|
1007
|
+
}
|
|
1008
|
+
else {
|
|
1009
|
+
con.beginPath();
|
|
1010
|
+
con.arc(scx, scy, chairRadius, 0, Math.PI * 2);
|
|
1011
|
+
con.closePath();
|
|
1012
|
+
con.lineWidth = Math.max(1, chairRadius * 0.15);
|
|
1013
|
+
con.stroke();
|
|
1014
|
+
con.fillStrokeShape(shape);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
con.beginPath();
|
|
1019
|
+
con.arc(cx, cy, tableRadius, 0, Math.PI * 2);
|
|
1020
|
+
con.closePath();
|
|
1021
|
+
con.fillStrokeShape(shape);
|
|
1022
|
+
const fontSize = tableRadius * 0.45;
|
|
1023
|
+
con.font = `${fontSize}px Arial`;
|
|
1024
|
+
con.fillStyle = strokeColor;
|
|
1025
|
+
con.textAlign = 'center';
|
|
1026
|
+
con.textBaseline = 'middle';
|
|
1027
|
+
con.fillText(zoneText, cx, cy);
|
|
1028
|
+
con.restore();
|
|
1029
|
+
};
|
|
1030
|
+
|
|
1031
|
+
const KONVA_SHAPE_MAPPINGS = {
|
|
1032
|
+
[RoomMapElementType.STAGE]: {
|
|
1033
|
+
config: {
|
|
1034
|
+
width: TICKET_MAP_GRID_SIZE * 10,
|
|
1035
|
+
height: TICKET_MAP_GRID_SIZE * 2,
|
|
1036
|
+
fill: '#9C27B0',
|
|
1037
|
+
stroke: '#731d82',
|
|
1038
|
+
strokeWidth: 1,
|
|
1039
|
+
draggable: true,
|
|
1040
|
+
perfectDrawEnabled: false,
|
|
1041
|
+
sceneFunc: generateStageScene,
|
|
1042
|
+
},
|
|
1043
|
+
layer: 'background',
|
|
1044
|
+
},
|
|
1045
|
+
[RoomMapElementType.SEAT_BLOCK]: {
|
|
1046
|
+
config: {
|
|
1047
|
+
width: TICKET_MAP_GRID_SIZE * 5,
|
|
1048
|
+
height: TICKET_MAP_GRID_SIZE,
|
|
1049
|
+
fill: '#ffffff',
|
|
1050
|
+
stroke: '#909090',
|
|
1051
|
+
strokeWidth: 1,
|
|
1052
|
+
draggable: true,
|
|
1053
|
+
perfectDrawEnabled: false,
|
|
1054
|
+
sceneFunc: generateSeatBlockScene,
|
|
1055
|
+
},
|
|
1056
|
+
layer: 'elements',
|
|
1057
|
+
},
|
|
1058
|
+
[RoomMapElementType.TABLE]: {
|
|
1059
|
+
config: {
|
|
1060
|
+
width: TICKET_MAP_GRID_SIZE * 3,
|
|
1061
|
+
height: TICKET_MAP_GRID_SIZE * 2,
|
|
1062
|
+
fill: '#ffffff',
|
|
1063
|
+
stroke: '#909090',
|
|
1064
|
+
strokeWidth: 2,
|
|
1065
|
+
cornerRadius: 5,
|
|
1066
|
+
draggable: true,
|
|
1067
|
+
perfectDrawEnabled: false,
|
|
1068
|
+
sceneFunc: generateTableScene,
|
|
1069
|
+
},
|
|
1070
|
+
layer: 'elements',
|
|
1071
|
+
},
|
|
1072
|
+
[RoomMapElementType.ZONE]: {
|
|
1073
|
+
config: {
|
|
1074
|
+
width: TICKET_MAP_GRID_SIZE * 10,
|
|
1075
|
+
height: TICKET_MAP_GRID_SIZE * 3,
|
|
1076
|
+
fill: '#ffffff',
|
|
1077
|
+
stroke: '#909090',
|
|
1078
|
+
strokeWidth: 1,
|
|
1079
|
+
cornerRadius: 2,
|
|
1080
|
+
draggable: true,
|
|
1081
|
+
opacity: 1,
|
|
1082
|
+
perfectDrawEnabled: false,
|
|
1083
|
+
sceneFunc: generateZoneScene,
|
|
1084
|
+
},
|
|
1085
|
+
layer: 'background',
|
|
1086
|
+
},
|
|
1087
|
+
[RoomMapElementType.EXIT]: {
|
|
1088
|
+
config: {
|
|
1089
|
+
width: TICKET_MAP_GRID_SIZE * 3,
|
|
1090
|
+
height: TICKET_MAP_GRID_SIZE,
|
|
1091
|
+
fill: '#efefef',
|
|
1092
|
+
stroke: '#aaaaaa',
|
|
1093
|
+
strokeWidth: 1,
|
|
1094
|
+
draggable: true,
|
|
1095
|
+
perfectDrawEnabled: false,
|
|
1096
|
+
sceneFunc: generateExitScene,
|
|
1097
|
+
},
|
|
1098
|
+
layer: 'foreground',
|
|
1099
|
+
},
|
|
1100
|
+
[RoomMapElementType.PRODUCTION_AREA]: {
|
|
1101
|
+
config: {
|
|
1102
|
+
width: TICKET_MAP_GRID_SIZE * 4,
|
|
1103
|
+
height: TICKET_MAP_GRID_SIZE,
|
|
1104
|
+
fill: '#efefef',
|
|
1105
|
+
stroke: '#aaaaaa',
|
|
1106
|
+
strokeWidth: 1,
|
|
1107
|
+
draggable: true,
|
|
1108
|
+
perfectDrawEnabled: false,
|
|
1109
|
+
sceneFunc: generateProductionAreaScene,
|
|
1110
|
+
},
|
|
1111
|
+
layer: 'background',
|
|
1112
|
+
},
|
|
1113
|
+
[RoomMapElementType.UNAVAILABLE_SPACE]: {
|
|
1114
|
+
config: {
|
|
1115
|
+
width: TICKET_MAP_GRID_SIZE * 4,
|
|
1116
|
+
height: TICKET_MAP_GRID_SIZE,
|
|
1117
|
+
fill: '#efefef',
|
|
1118
|
+
stroke: '#aaaaaa',
|
|
1119
|
+
strokeWidth: 1,
|
|
1120
|
+
draggable: true,
|
|
1121
|
+
perfectDrawEnabled: false,
|
|
1122
|
+
sceneFunc: generateUnavailableSpaceScene,
|
|
1123
|
+
},
|
|
1124
|
+
layer: 'background',
|
|
1125
|
+
},
|
|
1126
|
+
[RoomMapElementType.STAIR]: {
|
|
1127
|
+
config: {
|
|
1128
|
+
width: TICKET_MAP_GRID_SIZE * 3,
|
|
1129
|
+
height: TICKET_MAP_GRID_SIZE,
|
|
1130
|
+
fill: '#efefef',
|
|
1131
|
+
stroke: '#aaaaaa',
|
|
1132
|
+
strokeWidth: 1,
|
|
1133
|
+
draggable: true,
|
|
1134
|
+
perfectDrawEnabled: false,
|
|
1135
|
+
sceneFunc: generateStairScene,
|
|
1136
|
+
},
|
|
1137
|
+
layer: 'background',
|
|
1138
|
+
},
|
|
1139
|
+
[RoomMapElementType.HALLWAY]: {
|
|
1140
|
+
config: {
|
|
1141
|
+
width: TICKET_MAP_GRID_SIZE * 3,
|
|
1142
|
+
height: TICKET_MAP_GRID_SIZE,
|
|
1143
|
+
fill: '#efefef',
|
|
1144
|
+
stroke: '#aaaaaa',
|
|
1145
|
+
strokeWidth: 1,
|
|
1146
|
+
draggable: true,
|
|
1147
|
+
perfectDrawEnabled: false,
|
|
1148
|
+
sceneFunc: generateHallwayScene,
|
|
1149
|
+
},
|
|
1150
|
+
layer: 'background',
|
|
1151
|
+
},
|
|
1152
|
+
};
|
|
1153
|
+
|
|
1154
|
+
function buildSeatLabel(rowIndex, colIndex, rows, cols, config) {
|
|
1155
|
+
let actualRowIndex = rowIndex;
|
|
1156
|
+
if (config.row_order === 'BOTTOM_TO_TOP') {
|
|
1157
|
+
actualRowIndex = rows - 1 - rowIndex;
|
|
1158
|
+
}
|
|
1159
|
+
let actualColIndex = colIndex;
|
|
1160
|
+
if (config.column_order === 'RIGHT_TO_LEFT') {
|
|
1161
|
+
actualColIndex = cols - 1 - colIndex;
|
|
1162
|
+
}
|
|
1163
|
+
const startRowNum = (config.start_row_letter?.toUpperCase() || 'A').charCodeAt(0) - 65;
|
|
1164
|
+
const rowLetter = numberToLetter$1(startRowNum + actualRowIndex);
|
|
1165
|
+
const colNumber = Number(config.start_column_number) + Number(actualColIndex);
|
|
1166
|
+
return `${rowLetter}${colNumber}`;
|
|
1167
|
+
}
|
|
1168
|
+
function buildSeatPositions(element) {
|
|
1169
|
+
const config = element.numeration_config || {
|
|
1170
|
+
start_row_letter: 'A',
|
|
1171
|
+
row_order: 'TOP_TO_BOTTOM',
|
|
1172
|
+
start_column_number: 1,
|
|
1173
|
+
column_order: 'LEFT_TO_RIGHT',
|
|
1174
|
+
};
|
|
1175
|
+
const w = element.konva_shape?.config?.width || 300;
|
|
1176
|
+
const h = element.konva_shape?.config?.height || 300;
|
|
1177
|
+
const hasTitle = !!(element.element_name && element.show_element_name !== false);
|
|
1178
|
+
const chairsStartY = hasTitle ? TICKET_MAP_TITLE_HEIGHT : 0;
|
|
1179
|
+
const cols = Math.floor(w / TICKET_MAP_GRID_SIZE);
|
|
1180
|
+
const rows = Math.floor((h - chairsStartY) / TICKET_MAP_GRID_SIZE);
|
|
1181
|
+
const positions = [];
|
|
1182
|
+
for (let rowIndex = 0; rowIndex < rows; rowIndex++) {
|
|
1183
|
+
const row = [];
|
|
1184
|
+
for (let colIndex = 0; colIndex < cols; colIndex++) {
|
|
1185
|
+
const seatLabel = buildSeatLabel(rowIndex, colIndex, rows, cols, config);
|
|
1186
|
+
const seatState = element.seats?.[rowIndex]?.[colIndex];
|
|
1187
|
+
if (seatState?.is_non_existent) {
|
|
1188
|
+
row.push({ rowIndex, colIndex, seatLabel });
|
|
1189
|
+
continue;
|
|
1190
|
+
}
|
|
1191
|
+
row.push({ rowIndex, colIndex, seatLabel });
|
|
1192
|
+
}
|
|
1193
|
+
positions.push(row);
|
|
1194
|
+
}
|
|
1195
|
+
return positions;
|
|
1196
|
+
}
|
|
1197
|
+
function buildChairPositions(element) {
|
|
1198
|
+
const w = element.konva_shape?.config?.width || 150;
|
|
1199
|
+
const h = element.konva_shape?.config?.height || 150;
|
|
1200
|
+
const totalCapacity = element.total_capacity || 0;
|
|
1201
|
+
const chairRadius = Math.min(w, h) * 0.1;
|
|
1202
|
+
const gap = chairRadius * 0.4;
|
|
1203
|
+
const tableRadius = Math.min(w, h) / 2 - chairRadius * 2 - gap;
|
|
1204
|
+
const cx = w / 2;
|
|
1205
|
+
const cy = h / 2;
|
|
1206
|
+
const positions = [];
|
|
1207
|
+
if (totalCapacity > 0) {
|
|
1208
|
+
const orbitRadius = tableRadius + gap + chairRadius;
|
|
1209
|
+
for (let i = 0; i < totalCapacity; i++) {
|
|
1210
|
+
const angle = (2 * Math.PI * i) / totalCapacity - Math.PI / 2;
|
|
1211
|
+
const scx = cx + orbitRadius * Math.cos(angle);
|
|
1212
|
+
const scy = cy + orbitRadius * Math.sin(angle);
|
|
1213
|
+
positions.push({ index: i, angle, x: scx, y: scy });
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
return positions;
|
|
1217
|
+
}
|
|
1218
|
+
function processElementsToRenderData(elements, tickets, priceZones) {
|
|
1219
|
+
const ticketByElement = new Map();
|
|
1220
|
+
for (const ticket of tickets) {
|
|
1221
|
+
const existing = ticketByElement.get(ticket.room_map_element_id) || [];
|
|
1222
|
+
existing.push(ticket);
|
|
1223
|
+
ticketByElement.set(ticket.room_map_element_id, existing);
|
|
1224
|
+
}
|
|
1225
|
+
const result = [];
|
|
1226
|
+
for (const element of elements) {
|
|
1227
|
+
if (element.id == null)
|
|
1228
|
+
continue;
|
|
1229
|
+
const elementTickets = ticketByElement.get(element.id) || [];
|
|
1230
|
+
const elementBaseConfig = KONVA_SHAPE_MAPPINGS[element.type];
|
|
1231
|
+
let overrideFill;
|
|
1232
|
+
let overrideStroke;
|
|
1233
|
+
if (element.price_zone_id != null && priceZones) {
|
|
1234
|
+
const priceZone = priceZones.find((pz) => pz.id === element.price_zone_id);
|
|
1235
|
+
if (priceZone?.color) {
|
|
1236
|
+
overrideStroke = priceZone.color;
|
|
1237
|
+
overrideFill = tintColor(priceZone.color);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
let shapeConfig = {
|
|
1241
|
+
...element?.konva_shape?.config,
|
|
1242
|
+
draggable: false,
|
|
1243
|
+
...(overrideFill ? { fill: overrideFill } : {}),
|
|
1244
|
+
...(overrideStroke ? { stroke: overrideStroke } : {}),
|
|
1245
|
+
element_name: element.element_name || element.name,
|
|
1246
|
+
show_element_name: element.show_element_name ?? true,
|
|
1247
|
+
total_capacity: element.total_capacity,
|
|
1248
|
+
};
|
|
1249
|
+
const ticketByNumeration = new Map();
|
|
1250
|
+
for (const ticket of elementTickets) {
|
|
1251
|
+
if (ticket.seat_numeration != null) {
|
|
1252
|
+
ticketByNumeration.set(ticket.seat_numeration, ticket);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
let seatPositions;
|
|
1256
|
+
let chairPositions;
|
|
1257
|
+
if (element.type === RoomMapElementType.SEAT_BLOCK) {
|
|
1258
|
+
seatPositions = buildSeatPositions(element);
|
|
1259
|
+
const ticketStatusMap = new Map();
|
|
1260
|
+
for (const [numeration, ticket] of ticketByNumeration) {
|
|
1261
|
+
ticketStatusMap.set(numeration, ticket.status);
|
|
1262
|
+
}
|
|
1263
|
+
shapeConfig = {
|
|
1264
|
+
...shapeConfig,
|
|
1265
|
+
name: String(element.id),
|
|
1266
|
+
sceneFunc: (con, shape) => {
|
|
1267
|
+
generateSeatBlockTicketScene(con, shape, element.numeration_config, ticketStatusMap);
|
|
1268
|
+
},
|
|
1269
|
+
seats: element.seats,
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
if (element.type === RoomMapElementType.TABLE) {
|
|
1273
|
+
chairPositions = buildChairPositions(element);
|
|
1274
|
+
const chairStatuses = [];
|
|
1275
|
+
for (let i = 0; i < (element.total_capacity || 0); i++) {
|
|
1276
|
+
const key = `S${i + 1}`;
|
|
1277
|
+
const ticket = ticketByNumeration.get(key);
|
|
1278
|
+
chairStatuses.push(ticket?.status ?? PerformanceTicketStatus.AVAILABLE);
|
|
1279
|
+
}
|
|
1280
|
+
shapeConfig = {
|
|
1281
|
+
...shapeConfig,
|
|
1282
|
+
name: String(element.id),
|
|
1283
|
+
sceneFunc: (con, shape) => {
|
|
1284
|
+
generateTableTicketScene(con, shape, chairStatuses, element.seats);
|
|
1285
|
+
},
|
|
1286
|
+
seats: element.seats,
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
if (![RoomMapElementType.SEAT_BLOCK, RoomMapElementType.TABLE].includes(element.type)) {
|
|
1290
|
+
const defaultSceneFunc = elementBaseConfig?.config?.sceneFunc;
|
|
1291
|
+
if (defaultSceneFunc && !shapeConfig['sceneFunc']) {
|
|
1292
|
+
shapeConfig['sceneFunc'] = defaultSceneFunc;
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
let elementName = element.name ?? '';
|
|
1296
|
+
if (!!element.element_name) {
|
|
1297
|
+
elementName += `: ${element.element_name}`;
|
|
1298
|
+
}
|
|
1299
|
+
result.push({
|
|
1300
|
+
elementId: element.id,
|
|
1301
|
+
hallFloorId: element.hall_floor_id ?? null,
|
|
1302
|
+
type: element.type,
|
|
1303
|
+
shapeConfig,
|
|
1304
|
+
tickets: elementTickets,
|
|
1305
|
+
ticketByNumeration,
|
|
1306
|
+
elementName,
|
|
1307
|
+
seatPositions,
|
|
1308
|
+
chairPositions,
|
|
1309
|
+
zoneCapacity: element.total_capacity,
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
return result;
|
|
1313
|
+
}
|
|
1314
|
+
function findTicketAtPosition(renderData, relX, relY) {
|
|
1315
|
+
if (renderData.type === RoomMapElementType.SEAT_BLOCK && renderData.seatPositions) {
|
|
1316
|
+
const config = renderData.shapeConfig;
|
|
1317
|
+
const w = config['width'] || 300;
|
|
1318
|
+
const hasTitle = !!(renderData.elementName && config['show_element_name'] !== false);
|
|
1319
|
+
const chairsStartY = hasTitle ? TICKET_MAP_TITLE_HEIGHT : 0;
|
|
1320
|
+
const col = Math.floor(relX / TICKET_MAP_GRID_SIZE);
|
|
1321
|
+
const row = Math.floor((relY - chairsStartY) / TICKET_MAP_GRID_SIZE);
|
|
1322
|
+
if (col < 0 ||
|
|
1323
|
+
row < 0 ||
|
|
1324
|
+
row >= renderData.seatPositions.length ||
|
|
1325
|
+
col >= (renderData.seatPositions[0]?.length || 0)) {
|
|
1326
|
+
return null;
|
|
1327
|
+
}
|
|
1328
|
+
const seat = renderData.seatPositions[row]?.[col];
|
|
1329
|
+
if (!seat)
|
|
1330
|
+
return null;
|
|
1331
|
+
const seatState = renderData.shapeConfig['seats']?.[row]?.[col];
|
|
1332
|
+
if (seatState?.is_non_existent)
|
|
1333
|
+
return null;
|
|
1334
|
+
return renderData.ticketByNumeration.get(seat.seatLabel) || null;
|
|
1335
|
+
}
|
|
1336
|
+
if (renderData.type === RoomMapElementType.TABLE && renderData.chairPositions) {
|
|
1337
|
+
for (const chair of renderData.chairPositions) {
|
|
1338
|
+
const seatState = renderData.shapeConfig['seats']?.[0]?.[chair.index];
|
|
1339
|
+
if (seatState?.is_non_existent)
|
|
1340
|
+
continue;
|
|
1341
|
+
const dx = relX - chair.x;
|
|
1342
|
+
const dy = relY - chair.y;
|
|
1343
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
1344
|
+
const w = renderData.shapeConfig['width'] || 150;
|
|
1345
|
+
const h = renderData.shapeConfig['height'] || 150;
|
|
1346
|
+
const chairRadius = Math.min(w, h) * 0.1;
|
|
1347
|
+
if (distance <= chairRadius + 5) {
|
|
1348
|
+
const key = `S${chair.index + 1}`;
|
|
1349
|
+
return renderData.ticketByNumeration.get(key) || null;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
return null;
|
|
1353
|
+
}
|
|
1354
|
+
if (renderData.type === RoomMapElementType.ZONE) {
|
|
1355
|
+
for (const ticket of renderData.ticketByNumeration.values()) {
|
|
1356
|
+
return ticket;
|
|
1357
|
+
}
|
|
1358
|
+
return renderData.tickets[0] || null;
|
|
1359
|
+
}
|
|
1360
|
+
return null;
|
|
1361
|
+
}
|
|
1362
|
+
function findElementAtPosition(renderDataList, stageX, stageY) {
|
|
1363
|
+
for (let i = renderDataList.length - 1; i >= 0; i--) {
|
|
1364
|
+
const el = renderDataList[i];
|
|
1365
|
+
const cfg = el.shapeConfig;
|
|
1366
|
+
const ex = cfg['x'] || 0;
|
|
1367
|
+
const ey = cfg['y'] || 0;
|
|
1368
|
+
const ew = cfg['width'] || 0;
|
|
1369
|
+
const eh = cfg['height'] || 0;
|
|
1370
|
+
const rotation = cfg['rotation'] || 0;
|
|
1371
|
+
if (rotation) {
|
|
1372
|
+
const rad = rotation * (Math.PI / 180);
|
|
1373
|
+
const cos = Math.cos(-rad);
|
|
1374
|
+
const sin = Math.sin(-rad);
|
|
1375
|
+
const dx = stageX - ex;
|
|
1376
|
+
const dy = stageY - ey;
|
|
1377
|
+
const localX = dx * cos - dy * sin;
|
|
1378
|
+
const localY = dx * sin + dy * cos;
|
|
1379
|
+
if (localX >= 0 && localX <= ew && localY >= 0 && localY <= eh) {
|
|
1380
|
+
return { element: el, relX: localX, relY: localY };
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
else {
|
|
1384
|
+
if (stageX >= ex && stageX <= ex + ew && stageY >= ey && stageY <= ey + eh) {
|
|
1385
|
+
return { element: el, relX: stageX - ex, relY: stageY - ey };
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
return null;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
// Helper function to convert number to multi-letter label (A, B, ..., Z, AA, AB, ...)
|
|
1393
|
+
const numberToLetter = (num) => {
|
|
1394
|
+
if (num < 0)
|
|
1395
|
+
return 'A';
|
|
1396
|
+
let result = '';
|
|
1397
|
+
let n = num;
|
|
1398
|
+
while (n >= 0) {
|
|
1399
|
+
result = String.fromCharCode(65 + (n % 26)) + result;
|
|
1400
|
+
n = Math.floor(n / 26) - 1;
|
|
1401
|
+
}
|
|
1402
|
+
return result;
|
|
1403
|
+
};
|
|
1404
|
+
const drawChairIcon = (con, cx, cy, size) => {
|
|
1405
|
+
con.beginPath();
|
|
1406
|
+
const backWidth = size * 0.7;
|
|
1407
|
+
const backHeight = size * 0.6;
|
|
1408
|
+
const backX = cx - backWidth / 2;
|
|
1409
|
+
const backY = cy - backHeight / 2 - size * 0.1;
|
|
1410
|
+
con.moveTo(backX + backWidth * 0.2, backY);
|
|
1411
|
+
con.lineTo(backX + backWidth * 0.8, backY);
|
|
1412
|
+
con.quadraticCurveTo(backX + backWidth, backY, backX + backWidth, backY + backHeight * 0.2);
|
|
1413
|
+
con.lineTo(backX + backWidth, backY + backHeight * 0.8);
|
|
1414
|
+
con.quadraticCurveTo(backX + backWidth, backY + backHeight, backX + backWidth * 0.8, backY + backHeight);
|
|
1415
|
+
con.lineTo(backX + backWidth * 0.2, backY + backHeight);
|
|
1416
|
+
con.quadraticCurveTo(backX, backY + backHeight, backX, backY + backHeight * 0.8);
|
|
1417
|
+
con.lineTo(backX, backY + backHeight * 0.2);
|
|
1418
|
+
con.quadraticCurveTo(backX, backY, backX + backWidth * 0.2, backY);
|
|
1419
|
+
const chairSeatWidth = size * 0.8;
|
|
1420
|
+
const chairSeatHeight = size * 0.3;
|
|
1421
|
+
const seatX = cx - chairSeatWidth / 2;
|
|
1422
|
+
const seatY = cy + backHeight * 0.3;
|
|
1423
|
+
con.moveTo(seatX, seatY);
|
|
1424
|
+
con.lineTo(seatX + chairSeatWidth, seatY);
|
|
1425
|
+
con.lineTo(seatX + chairSeatWidth * 0.9, seatY + chairSeatHeight);
|
|
1426
|
+
con.lineTo(seatX + chairSeatWidth * 0.1, seatY + chairSeatHeight);
|
|
1427
|
+
con.closePath();
|
|
1428
|
+
const legWidth = size * 0.1;
|
|
1429
|
+
const legHeight = size * 0.2;
|
|
1430
|
+
con.moveTo(seatX + chairSeatWidth * 0.1, seatY + chairSeatHeight);
|
|
1431
|
+
con.lineTo(seatX + chairSeatWidth * 0.1 + legWidth, seatY + chairSeatHeight);
|
|
1432
|
+
con.lineTo(seatX + chairSeatWidth * 0.1 + legWidth, seatY + chairSeatHeight + legHeight);
|
|
1433
|
+
con.lineTo(seatX + chairSeatWidth * 0.1, seatY + chairSeatHeight + legHeight);
|
|
1434
|
+
con.moveTo(seatX + chairSeatWidth * 0.9 - legWidth, seatY + chairSeatHeight);
|
|
1435
|
+
con.lineTo(seatX + chairSeatWidth * 0.9, seatY + chairSeatHeight);
|
|
1436
|
+
con.lineTo(seatX + chairSeatWidth * 0.9, seatY + chairSeatHeight + legHeight);
|
|
1437
|
+
con.lineTo(seatX + chairSeatWidth * 0.9 - legWidth, seatY + chairSeatHeight + legHeight);
|
|
1438
|
+
con.closePath();
|
|
1439
|
+
};
|
|
1440
|
+
const generateSeatBlockScene = (con, shape, numerationConfig) => {
|
|
1441
|
+
const w = shape.width();
|
|
1442
|
+
const h = shape.height();
|
|
1443
|
+
const seatSize = TICKET_MAP_GRID_SIZE;
|
|
1444
|
+
const chairScale = 0.8;
|
|
1445
|
+
const elementName = shape?.attrs?.element_name || 'Asientos';
|
|
1446
|
+
const showElementName = shape?.attrs?.show_element_name ?? true;
|
|
1447
|
+
const seatsData = shape?.attrs?.seats;
|
|
1448
|
+
const hasTitle = !!(elementName && showElementName);
|
|
1449
|
+
const titleHeight = hasTitle ? TICKET_MAP_GRID_SIZE : 0;
|
|
1450
|
+
const chairsStartY = titleHeight;
|
|
1451
|
+
const cols = Math.floor(w / seatSize);
|
|
1452
|
+
const rows = Math.floor((h - chairsStartY) / seatSize);
|
|
1453
|
+
const config = numerationConfig || {
|
|
1454
|
+
start_row_letter: 'A',
|
|
1455
|
+
row_order: 'TOP_TO_BOTTOM',
|
|
1456
|
+
start_column_number: 1,
|
|
1457
|
+
column_order: 'LEFT_TO_RIGHT',
|
|
1458
|
+
};
|
|
1459
|
+
const startRowLetter = config?.start_row_letter?.toUpperCase() || 'A';
|
|
1460
|
+
const startRowNum = startRowLetter.charCodeAt(0) - 65;
|
|
1461
|
+
if (hasTitle) {
|
|
1462
|
+
con.save();
|
|
1463
|
+
const textFont = `bold 10px Arial`;
|
|
1464
|
+
con.font = textFont;
|
|
1465
|
+
const textWidth = con.measureText(elementName).width;
|
|
1466
|
+
const paddingX = 10;
|
|
1467
|
+
const containerHeight = 18;
|
|
1468
|
+
const containerWidth = textWidth + paddingX * 2;
|
|
1469
|
+
const containerX = (w - containerWidth) / 2;
|
|
1470
|
+
const containerY = (titleHeight - containerHeight) / 2;
|
|
1471
|
+
const borderRadius = 4;
|
|
1472
|
+
const lineY = titleHeight;
|
|
1473
|
+
const strokeColor = shape.getAttr('stroke') || '#999';
|
|
1474
|
+
con.beginPath();
|
|
1475
|
+
con.moveTo(0, lineY);
|
|
1476
|
+
con.lineTo(w, lineY);
|
|
1477
|
+
con.strokeStyle = strokeColor;
|
|
1478
|
+
con.lineWidth = 1;
|
|
1479
|
+
con.stroke();
|
|
1480
|
+
con.beginPath();
|
|
1481
|
+
con.moveTo(containerX + borderRadius, containerY);
|
|
1482
|
+
con.lineTo(containerX + containerWidth - borderRadius, containerY);
|
|
1483
|
+
con.quadraticCurveTo(containerX + containerWidth, containerY, containerX + containerWidth, containerY + borderRadius);
|
|
1484
|
+
con.lineTo(containerX + containerWidth, containerY + containerHeight - borderRadius);
|
|
1485
|
+
con.quadraticCurveTo(containerX + containerWidth, containerY + containerHeight, containerX + containerWidth - borderRadius, containerY + containerHeight);
|
|
1486
|
+
con.lineTo(containerX + borderRadius, containerY + containerHeight);
|
|
1487
|
+
con.quadraticCurveTo(containerX, containerY + containerHeight, containerX, containerY + containerHeight - borderRadius);
|
|
1488
|
+
con.lineTo(containerX, containerY + borderRadius);
|
|
1489
|
+
con.quadraticCurveTo(containerX, containerY, containerX + borderRadius, containerY);
|
|
1490
|
+
con.closePath();
|
|
1491
|
+
con.fillStrokeShape(shape);
|
|
1492
|
+
con.font = textFont;
|
|
1493
|
+
con.fillStyle = strokeColor;
|
|
1494
|
+
con.textAlign = 'center';
|
|
1495
|
+
con.textBaseline = 'middle';
|
|
1496
|
+
con.fillText(elementName, w / 2, containerY + containerHeight / 2);
|
|
1497
|
+
con.restore();
|
|
1498
|
+
}
|
|
1499
|
+
for (let x = 0; x < w; x += seatSize) {
|
|
1500
|
+
for (let y = chairsStartY; y < h; y += seatSize) {
|
|
1501
|
+
const colIndex = Math.floor(x / seatSize);
|
|
1502
|
+
const rowIndex = Math.floor((y - chairsStartY) / seatSize);
|
|
1503
|
+
let actualRowIndex = rowIndex;
|
|
1504
|
+
if (config.row_order === 'BOTTOM_TO_TOP') {
|
|
1505
|
+
actualRowIndex = rows - 1 - rowIndex;
|
|
1506
|
+
}
|
|
1507
|
+
let actualColIndex = colIndex;
|
|
1508
|
+
if (config.column_order === 'RIGHT_TO_LEFT') {
|
|
1509
|
+
actualColIndex = cols - 1 - colIndex;
|
|
1510
|
+
}
|
|
1511
|
+
const rowLetter = numberToLetter(startRowNum + actualRowIndex);
|
|
1512
|
+
const colNumber = Number(config.start_column_number) + Number(actualColIndex);
|
|
1513
|
+
const seatNumber = `${rowLetter}${colNumber}`;
|
|
1514
|
+
const centerX = x + seatSize / 2 + 1;
|
|
1515
|
+
const centerY = y + seatSize / 2 - 2;
|
|
1516
|
+
const size = seatSize * chairScale;
|
|
1517
|
+
// Check seat state
|
|
1518
|
+
const seatState = seatsData?.[rowIndex]?.[colIndex];
|
|
1519
|
+
// Skip non-existent seats
|
|
1520
|
+
if (seatState?.is_non_existent) {
|
|
1521
|
+
continue;
|
|
1522
|
+
}
|
|
1523
|
+
con.save();
|
|
1524
|
+
if (seatState?.is_accessible) {
|
|
1525
|
+
drawWheelchairIcon(con, shape, centerX, centerY, size);
|
|
1526
|
+
}
|
|
1527
|
+
else {
|
|
1528
|
+
drawChairIcon(con, centerX, centerY, size);
|
|
1529
|
+
con.fillStrokeShape(shape);
|
|
1530
|
+
// Draw seat number
|
|
1531
|
+
con.fillStyle = '#333333';
|
|
1532
|
+
con.font = `${size * 0.3}px Arial`;
|
|
1533
|
+
con.textAlign = 'center';
|
|
1534
|
+
con.textBaseline = 'middle';
|
|
1535
|
+
con.fillText(seatNumber, centerX, centerY - 1);
|
|
1536
|
+
}
|
|
1537
|
+
con.restore();
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
};
|
|
1541
|
+
|
|
1542
|
+
const generateStageScene = (con, shape) => {
|
|
1543
|
+
const w = shape.width();
|
|
1544
|
+
const h = shape.height();
|
|
1545
|
+
const padding = 4;
|
|
1546
|
+
con.save();
|
|
1547
|
+
// Stage background (rectangle with rounded corners)
|
|
1548
|
+
const exitX = padding;
|
|
1549
|
+
const exitY = padding;
|
|
1550
|
+
const exitWidth = w - padding * 2;
|
|
1551
|
+
const exitHeight = h - padding * 2;
|
|
1552
|
+
const cornerRadius = Math.min(exitWidth, exitHeight) * 0.2;
|
|
1553
|
+
con.beginPath();
|
|
1554
|
+
con.moveTo(exitX + cornerRadius, exitY);
|
|
1555
|
+
con.lineTo(exitX + exitWidth - cornerRadius, exitY);
|
|
1556
|
+
con.quadraticCurveTo(exitX + exitWidth, exitY, exitX + exitWidth, exitY + cornerRadius);
|
|
1557
|
+
con.lineTo(exitX + exitWidth, exitY + exitHeight);
|
|
1558
|
+
con.lineTo(exitX, exitY + exitHeight);
|
|
1559
|
+
con.lineTo(exitX, exitY + cornerRadius);
|
|
1560
|
+
con.quadraticCurveTo(exitX, exitY, exitX + cornerRadius, exitY);
|
|
1561
|
+
con.closePath();
|
|
1562
|
+
con.fillStrokeShape(shape);
|
|
1563
|
+
// Stage text
|
|
1564
|
+
const centerX = w / 2;
|
|
1565
|
+
const centerY = h / 2;
|
|
1566
|
+
con.font = `12px Arial`;
|
|
1567
|
+
con.fillStyle = shape.getAttr('stroke');
|
|
1568
|
+
con.textAlign = 'center';
|
|
1569
|
+
con.textBaseline = 'middle';
|
|
1570
|
+
const stageText = shape?.attrs?.element_name || 'Escenario';
|
|
1571
|
+
const dotRadius = 2.5;
|
|
1572
|
+
const dotGap = 10;
|
|
1573
|
+
const textWidth = con.measureText(stageText).width;
|
|
1574
|
+
// Dot before text
|
|
1575
|
+
con.beginPath();
|
|
1576
|
+
con.arc(centerX - textWidth / 2 - dotGap, centerY, dotRadius, 0, Math.PI * 2);
|
|
1577
|
+
con.fillStyle = shape.getAttr('stroke');
|
|
1578
|
+
con.fill();
|
|
1579
|
+
// Text
|
|
1580
|
+
con.fillText(stageText, centerX, centerY);
|
|
1581
|
+
// Dot after text
|
|
1582
|
+
con.beginPath();
|
|
1583
|
+
con.arc(centerX + textWidth / 2 + dotGap, centerY, dotRadius, 0, Math.PI * 2);
|
|
1584
|
+
con.fillStyle = shape.getAttr('stroke');
|
|
1585
|
+
con.fill();
|
|
1586
|
+
// Footer below the element: line and "βΌ Vista del pΓΊblico"
|
|
1587
|
+
const lineColor = '#b0b0b0';
|
|
1588
|
+
const footerCenterY = h + TICKET_MAP_GRID_SIZE / 2;
|
|
1589
|
+
con.beginPath();
|
|
1590
|
+
con.moveTo(0, footerCenterY);
|
|
1591
|
+
con.lineTo(w, footerCenterY);
|
|
1592
|
+
con.strokeStyle = lineColor;
|
|
1593
|
+
con.lineWidth = 1;
|
|
1594
|
+
con.stroke();
|
|
1595
|
+
const labelText = 'βΌ Vista del pΓΊblico';
|
|
1596
|
+
const textFont = `bold 10px Arial`;
|
|
1597
|
+
con.font = textFont;
|
|
1598
|
+
const labelWidth = con.measureText(labelText).width;
|
|
1599
|
+
const paddingX = 10;
|
|
1600
|
+
const containerHeight = 18;
|
|
1601
|
+
const containerWidth = labelWidth + paddingX * 2;
|
|
1602
|
+
const containerX = (w - containerWidth) / 2;
|
|
1603
|
+
const containerY = footerCenterY - containerHeight / 2;
|
|
1604
|
+
const borderRadius = 4;
|
|
1605
|
+
con.beginPath();
|
|
1606
|
+
con.moveTo(containerX + borderRadius, containerY);
|
|
1607
|
+
con.lineTo(containerX + containerWidth - borderRadius, containerY);
|
|
1608
|
+
con.quadraticCurveTo(containerX + containerWidth, containerY, containerX + containerWidth, containerY + borderRadius);
|
|
1609
|
+
con.lineTo(containerX + containerWidth, containerY + containerHeight - borderRadius);
|
|
1610
|
+
con.quadraticCurveTo(containerX + containerWidth, containerY + containerHeight, containerX + containerWidth - borderRadius, containerY + containerHeight);
|
|
1611
|
+
con.lineTo(containerX + borderRadius, containerY + containerHeight);
|
|
1612
|
+
con.quadraticCurveTo(containerX, containerY + containerHeight, containerX, containerY + containerHeight - borderRadius);
|
|
1613
|
+
con.lineTo(containerX, containerY + borderRadius);
|
|
1614
|
+
con.quadraticCurveTo(containerX, containerY, containerX + borderRadius, containerY);
|
|
1615
|
+
con.closePath();
|
|
1616
|
+
con.fillStyle = '#ededed';
|
|
1617
|
+
con.fill();
|
|
1618
|
+
con.strokeStyle = lineColor;
|
|
1619
|
+
con.lineWidth = 1;
|
|
1620
|
+
con.stroke();
|
|
1621
|
+
con.font = textFont;
|
|
1622
|
+
con.fillStyle = lineColor;
|
|
1623
|
+
con.textAlign = 'center';
|
|
1624
|
+
con.textBaseline = 'middle';
|
|
1625
|
+
con.fillText(labelText, w / 2, footerCenterY);
|
|
1626
|
+
con.restore();
|
|
1627
|
+
};
|
|
1628
|
+
|
|
1629
|
+
const generateStairScene = (con, shape) => {
|
|
1630
|
+
const w = shape.width();
|
|
1631
|
+
const h = shape.height();
|
|
1632
|
+
const padding = 4;
|
|
1633
|
+
con.save();
|
|
1634
|
+
const exitX = padding;
|
|
1635
|
+
const exitY = padding;
|
|
1636
|
+
const exitWidth = w - padding * 2;
|
|
1637
|
+
const exitHeight = h - padding * 2;
|
|
1638
|
+
const cornerRadius = Math.min(exitWidth, exitHeight) * 0.2;
|
|
1639
|
+
drawRoundedRect(con, shape, exitX, exitY, exitWidth, exitHeight, cornerRadius);
|
|
1640
|
+
// Stage text - check if parent has element_name, otherwise use "ESCENARIO"
|
|
1641
|
+
// const fontSize = Math.min(w, h) * 0.35;
|
|
1642
|
+
con.font = `11px Arial`;
|
|
1643
|
+
con.fillStyle = '#333333';
|
|
1644
|
+
con.textAlign = 'center';
|
|
1645
|
+
con.textBaseline = 'middle';
|
|
1646
|
+
const centerX = w / 2;
|
|
1647
|
+
const centerY = h / 2;
|
|
1648
|
+
// Get parent element and check for element_name
|
|
1649
|
+
const stageText = 'πͺ' + (shape?.attrs?.element_name || 'Escalera');
|
|
1650
|
+
con.fillText(stageText, centerX, centerY);
|
|
1651
|
+
con.restore();
|
|
1652
|
+
};
|
|
1653
|
+
|
|
1654
|
+
const generateTableScene = (con, shape) => {
|
|
1655
|
+
const w = shape.width();
|
|
1656
|
+
const h = shape.height();
|
|
1657
|
+
const fillColor = shape.fill();
|
|
1658
|
+
const strokeColor = shape.stroke();
|
|
1659
|
+
const totalCapacity = shape?.attrs?.total_capacity ?? 0;
|
|
1660
|
+
const zoneText = shape?.attrs?.element_name || 'Mesa';
|
|
1661
|
+
const seatsData = shape?.attrs?.seats;
|
|
1662
|
+
const cx = w / 2;
|
|
1663
|
+
const cy = h / 2;
|
|
1664
|
+
// Radio de la mesa: el mΓ‘s pequeΓ±o entre ancho y alto, con un poco de margen
|
|
1665
|
+
// para dejar espacio a las sillas alrededor
|
|
1666
|
+
const chairRadius = Math.min(w, h) * 0.1;
|
|
1667
|
+
const gap = chairRadius * 0.4; // espacio entre mesa y sillas
|
|
1668
|
+
const tableRadius = Math.min(w, h) / 2 - chairRadius * 2 - gap;
|
|
1669
|
+
con.save();
|
|
1670
|
+
// ββ Sillas (se dibujan primero para quedar detrΓ‘s) ββββββββββββββββββββββββββ
|
|
1671
|
+
if (totalCapacity > 0) {
|
|
1672
|
+
const orbitRadius = tableRadius + gap + chairRadius;
|
|
1673
|
+
for (let i = 0; i < totalCapacity; i++) {
|
|
1674
|
+
const seatState = seatsData?.[0]?.[i];
|
|
1675
|
+
if (seatState?.is_non_existent) {
|
|
1676
|
+
continue;
|
|
1677
|
+
}
|
|
1678
|
+
const angle = (2 * Math.PI * i) / totalCapacity - Math.PI / 2;
|
|
1679
|
+
const scx = cx + orbitRadius * Math.cos(angle);
|
|
1680
|
+
const scy = cy + orbitRadius * Math.sin(angle);
|
|
1681
|
+
if (seatState?.is_accessible) {
|
|
1682
|
+
drawWheelchairIcon(con, shape, scx, scy, chairRadius * 2);
|
|
1683
|
+
continue;
|
|
1684
|
+
}
|
|
1685
|
+
con.beginPath();
|
|
1686
|
+
con.arc(scx, scy, chairRadius, 0, Math.PI * 2);
|
|
1687
|
+
con.closePath();
|
|
1688
|
+
// Color de relleno de las sillas = stroke del shape
|
|
1689
|
+
con.fillStyle = strokeColor;
|
|
1690
|
+
con.fill();
|
|
1691
|
+
// Borde de las sillas = fill del shape
|
|
1692
|
+
con.strokeStyle = fillColor;
|
|
1693
|
+
con.lineWidth = Math.max(1, chairRadius * 0.15);
|
|
1694
|
+
con.stroke();
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
// ββ Mesa (cΓrculo central) ββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1698
|
+
con.beginPath();
|
|
1699
|
+
con.arc(cx, cy, tableRadius, 0, Math.PI * 2);
|
|
1700
|
+
con.closePath();
|
|
1701
|
+
con.fillStrokeShape(shape); // usa fill y stroke propios del shape de Konva
|
|
1702
|
+
// ββ Texto centrado ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1703
|
+
const fontSize = tableRadius * 0.45;
|
|
1704
|
+
con.font = `${fontSize}px Arial`;
|
|
1705
|
+
con.fillStyle = strokeColor;
|
|
1706
|
+
con.textAlign = 'center';
|
|
1707
|
+
con.textBaseline = 'middle';
|
|
1708
|
+
con.fillText(zoneText, cx, cy);
|
|
1709
|
+
con.restore();
|
|
1710
|
+
};
|
|
1711
|
+
|
|
1712
|
+
const generateUnavailableSpaceScene = (con, shape) => {
|
|
1713
|
+
const w = shape.width();
|
|
1714
|
+
const h = shape.height();
|
|
1715
|
+
const padding = 4;
|
|
1716
|
+
con.save();
|
|
1717
|
+
const exitX = padding;
|
|
1718
|
+
const exitY = padding;
|
|
1719
|
+
const exitWidth = w - padding * 2;
|
|
1720
|
+
const exitHeight = h - padding * 2;
|
|
1721
|
+
const cornerRadius = Math.min(exitWidth, exitHeight) * 0.2;
|
|
1722
|
+
drawRoundedRect(con, shape, exitX, exitY, exitWidth, exitHeight, cornerRadius);
|
|
1723
|
+
// Stage text - check if parent has element_name, otherwise use "ESCENARIO"
|
|
1724
|
+
// const fontSize = Math.min(w, h) * 0.35;
|
|
1725
|
+
con.font = `11px Arial`;
|
|
1726
|
+
con.fillStyle = '#333333';
|
|
1727
|
+
con.textAlign = 'center';
|
|
1728
|
+
con.textBaseline = 'middle';
|
|
1729
|
+
const centerX = w / 2;
|
|
1730
|
+
const centerY = h / 2;
|
|
1731
|
+
// Get parent element and check for element_name
|
|
1732
|
+
const stageText = 'π« ' + (shape?.attrs?.element_name || 'No disponible');
|
|
1733
|
+
con.fillText(stageText, centerX, centerY);
|
|
1734
|
+
con.restore();
|
|
1735
|
+
};
|
|
1736
|
+
|
|
1737
|
+
const generateZoneScene = (con, shape) => {
|
|
1738
|
+
const w = shape.width();
|
|
1739
|
+
const h = shape.height();
|
|
1740
|
+
const padding = 4;
|
|
1741
|
+
con.save();
|
|
1742
|
+
const zoneX = padding;
|
|
1743
|
+
const zoneY = padding;
|
|
1744
|
+
const zoneWidth = w - padding * 2;
|
|
1745
|
+
const zoneHeight = h - padding * 2;
|
|
1746
|
+
const cornerRadius = Math.min(zoneWidth, zoneHeight) * 0.05;
|
|
1747
|
+
drawRoundedRect(con, shape, zoneX, zoneY, zoneWidth, zoneHeight, cornerRadius);
|
|
1748
|
+
// Zone text - check if parent has element_name, otherwise use "Zona"
|
|
1749
|
+
con.font = `11px Arial`;
|
|
1750
|
+
con.fillStyle = shape.getAttr('stroke');
|
|
1751
|
+
con.textAlign = 'center';
|
|
1752
|
+
con.textBaseline = 'middle';
|
|
1753
|
+
const centerX = w / 2;
|
|
1754
|
+
const centerY = h / 2;
|
|
1755
|
+
// Get parent element and check for element_name
|
|
1756
|
+
const zoneText = shape?.attrs?.element_name || '';
|
|
1757
|
+
con.fillText(zoneText, centerX, centerY);
|
|
1758
|
+
con.restore();
|
|
1759
|
+
};
|
|
1760
|
+
|
|
580
1761
|
function MinTodayValidator(controlName) {
|
|
581
1762
|
return (formGroup) => {
|
|
582
1763
|
const group = formGroup;
|
|
@@ -5228,5 +6409,5 @@ i0.Ι΅Ι΅ngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
5228
6409
|
* Generated bundle index. Do not edit.
|
|
5229
6410
|
*/
|
|
5230
6411
|
|
|
5231
|
-
export { ADMIN_API_ROUTES, ALERT_ICONS, AdminSelectComponent, AdminService, ApiService, AppAlertComponent, 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, CorporateBondStatus, CountrySelectComponent, CountryService, CouponApplicability, CouponDiscountType, CouponStatus, CustomerSelectComponent, CustomerService, 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, GiftBondStatus, LanguageSwitcherComponent, MinTodayValidator, MustMatchValidator, OrderItemType, OrderStatus, PAYMENT_METHODS_OPTIONS, PERFORMANCES_API_ROUTES, PRICE_ZONES_API_ROUTES, PRODUCTS_API_ROUTES, PRODUCT_CATEGORIES_API_ROUTES, PRODUCT_TAGS_API_ROUTES, PRODUCT_TYPES_API_ROUTES, PerformanceCardComponent, PerformanceCardListComponent, PerformanceMultiSelectComponent, PerformanceSelectComponent, PerformanceService, PerformanceStatus, PerformanceStepperComponent, PerformanceTicketStatus, PerformancesListEventsService, PriceZoneEventService, PriceZoneFormModalService, PriceZoneSelectComponent, PriceZoneService, ProductCategoryService, ProductMultiSelectComponent, ProductSelectComponent, ProductService, ProductTagService, ProductTypeService, RoomMapElementOrientation, RoomMapElementType, SHOWS_API_ROUTES, STATE_API_ENDPOINTS, ShowMultiSelectComponent, ShowSelectComponent, ShowService, ShowsFilterComponent, StateSelectComponent, StatesService, TICKERA_COMPONENTS_CONFIG, TickeraTranslocoLoader, ToastService, ToggleSwitchComponent, VENUES_API_ROUTES, ZonePriceItemComponent, ZonePriceListComponent, authInterceptor, formatCitiesResponseToSelect, getBrowserLanguage, getCustomerFullname, getStoredLanguage, parseJsonToFormDataAdvanced, provideTickeraComponents, resolveLanguage, setStoredLanguage, transformImageToFile };
|
|
6412
|
+
export { ADMIN_API_ROUTES, ALERT_ICONS, AdminSelectComponent, AdminService, ApiService, AppAlertComponent, 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, CorporateBondStatus, CountrySelectComponent, CountryService, CouponApplicability, CouponDiscountType, CouponStatus, 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, GiftBondStatus, LanguageSwitcherComponent, MinTodayValidator, MustMatchValidator, OrderItemType, OrderStatus, PAYMENT_METHODS_OPTIONS, PERFORMANCES_API_ROUTES, PRICE_ZONES_API_ROUTES, PRODUCTS_API_ROUTES, PRODUCT_CATEGORIES_API_ROUTES, PRODUCT_TAGS_API_ROUTES, PRODUCT_TYPES_API_ROUTES, PerformanceCardComponent, PerformanceCardListComponent, PerformanceMultiSelectComponent, PerformanceSelectComponent, PerformanceService, PerformanceStatus, PerformanceStepperComponent, PerformanceTicketStatus, PerformancesListEventsService, PriceZoneEventService, PriceZoneFormModalService, PriceZoneSelectComponent, PriceZoneService, ProductCategoryService, ProductMultiSelectComponent, ProductSelectComponent, ProductService, ProductTagService, ProductTypeService, RoomMapElementOrientation, RoomMapElementType, SHOWS_API_ROUTES, STATE_API_ENDPOINTS, SelectedDiscountCardType, ShowMultiSelectComponent, ShowSelectComponent, ShowService, ShowsFilterComponent, StateSelectComponent, StatesService, TICKERA_COMPONENTS_CONFIG, TICKET_ELEMENT_TYPES, TICKET_MAP_GRID_SIZE, TICKET_MAP_TITLE_HEIGHT, TICKET_STATUS_COLORS, TICKET_STATUS_FILLS, TICKET_STATUS_LABELS, TickeraTranslocoLoader, ToastService, ToggleSwitchComponent, VENUES_API_ROUTES, ZonePriceItemComponent, ZonePriceListComponent, authInterceptor, drawChairIcon$1 as drawChairIcon, drawHappyFace, drawRoundedRect, drawWheelchairIcon, findElementAtPosition, findTicketAtPosition, formatCitiesResponseToSelect, generateExitScene, generateHallwayScene, generateProductionAreaScene, generateSeatBlockScene, generateSeatBlockTicketScene, generateStageScene, generateStairScene, generateTableScene, generateTableTicketScene, generateUnavailableSpaceScene, generateZoneScene, getBrowserLanguage, getCustomerFullname, getItemTypeIcon, getStoredLanguage, numberToLetter$1 as numberToLetter, parseJsonToFormDataAdvanced, processElementsToRenderData, provideTickeraComponents, resolveLanguage, setStoredLanguage, tintColor, transformImageToFile };
|
|
5232
6413
|
//# sourceMappingURL=tickera-angular-components.mjs.map
|