diff --git a/client/src/inject.ts b/client/src/inject.ts
index 3555af4..614c762 100644
--- a/client/src/inject.ts
+++ b/client/src/inject.ts
@@ -44,7 +44,6 @@ function messagesHandler(e: any) {
break;
}
case "child_needCheckoutResponse": {
- // const inSelectedSeat: I.JSCSelectedSeat = data.message.selectedSeat;
const inUrl: string = data.message.url;
axios.get(inUrl, {
@@ -66,6 +65,7 @@ function messagesHandler(e: any) {
message: {
"isValidSeatSelection": isValidSeatSelection,
"parsedHTML": parsedHTML,
+ "url": inUrl,
// "selectedSeat": inSelectedSeat
},
from: "parent",
@@ -80,6 +80,19 @@ function messagesHandler(e: any) {
});
break;
}
+ case "child_hide_dialog_titlebar": {
+ jQuery(".ui-dialog-titlebar").hide();
+ break;
+ }
+ case "child_show_dialog_titlebar": {
+ jQuery(".ui-dialog-titlebar").show();
+ break;
+ }
+ case "child_click_checkout": {
+ const inUrl: string = data.message.url;
+ window.location.href = inUrl;
+ break;
+ }
default:
break;
diff --git a/client/src/modules/config.ts b/client/src/modules/config.ts
index 19dc31a..e292b09 100644
--- a/client/src/modules/config.ts
+++ b/client/src/modules/config.ts
@@ -14,5 +14,6 @@ export const config: I.Config = {
urlCSSJSCStaging: "https://staging.tickets.zinomedia.de/libs/jQuery-Seat-Charts/jquery.seat-charts.css",
urlCSSJSCMaster: "https://tickets.zinomedia.de/libs/jQuery-Seat-Charts/jquery.seat-charts.css",
urlCSSjQueryUI: "https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css",
- childHasVenueXML: false
+ childHasVenueXML: false,
+ maxSelectedSeats: 10
}
\ No newline at end of file
diff --git a/client/src/modules/jsc.ts b/client/src/modules/jsc.ts
index 6cdfb83..c9c46a7 100644
--- a/client/src/modules/jsc.ts
+++ b/client/src/modules/jsc.ts
@@ -1,4 +1,5 @@
import * as I from "../types/types";
+import { state } from "../seatmap";
export function getSeats(inXML: any): I.JSCSeats {
const pricescaleArr: I.SeatmapPricescale[] = inXML.seatmap[0].pricescale_config[0].pricescale;
@@ -29,13 +30,84 @@ export function activateSeatsBySectionID(inXML: any, seatmap: any, inValue: stri
});
}
-export function getRows(inXML: any): number[] {
+export function getRowsNaming(inXML: any): string[] {
const layout: I.SeatmapLayout = inXML.seatmap[0].layouts[0].layout[0];
const height: number = parseInt(layout.height[0]);
+ // return Array.from({ length: height }, (_, i: number) => i + 1);
+ const namingArr = Array.from({ length: height }, (_) => "");
+ const rowsArr = layout.rows[0].row;
- return Array.from({ length: height }, (_, i: number) => i + 1);
+ rowsArr.forEach(element => {
+ const index: number = parseInt(element.y_cell_coord[0]);
+ const seatsArr: string[] = element.seats[0].split("|");
+ const seatArr: string[] = splitSeatStr(seatsArr[0]);
+ const row = seatArr[4];
+ namingArr[index] = row;
+ });
+
+ return namingArr;
}
+// export function getColumnNaming(inXML: any): string[] {
+// const layout: I.SeatmapLayout = inXML.seatmap[0].layouts[0].layout[0];
+
+
+
+// const width: number = parseInt(layout.width[0]);
+
+
+// const namingArr = Array.from({ length: width }, (_) => "");
+// const rowsArr = layout.rows[0].row;
+
+// // let seats: number[] = [];
+// // let x: number[] = [];
+// rowsArr.forEach(element => {
+// // const index: number = parseInt(element.y_cell_coord[0]);
+// const seatsArr: string[] = element.seats[0].split("|");
+
+// seatsArr.forEach(seatStr => {
+// const seatArr: string[] = splitSeatStr(seatStr);
+// // seats.push(parseInt(seatArr[5]));
+// // x.push(parseInt(seatArr[2]));
+
+// const x = parseInt(seatArr[2]);
+
+// // Form:
+// // 0: "568528" -> ID
+// // 1: "568528" -> ID
+// // 2: "21" -> X-Coord benutzen
+// // 3: "7024" -> section ID
+// // 4: "13" -> Reihenbezeichnung
+// // 5: "4" -> Platznummer
+// namingArr[x] = seatArr[5];
+
+
+// });
+
+// // const row = seatArr[4];
+// // namingArr[index] = row;
+// });
+
+// // console.log(seats);
+// // console.log(x);
+// // console.log(Math.min.apply(Math, seats));
+// // console.log(Math.max.apply(Math, seats));
+// // console.log(Math.min.apply(Math, x));
+// // console.log(Math.max.apply(Math, x));
+
+// // const minimum = Math.min.apply(Math, seats);
+// // let i = 0;
+// // for (let index = Math.min.apply(Math, x); index < Math.max.apply(Math, x); index++) {
+// // // const element = array[index];
+
+// // namingArr[index] = (minimum + i).toString();
+// // i++;
+// // }
+
+// console.log(namingArr);
+// return namingArr;
+// }
+
export function generateMap(inXML: any): string[] {
const layout: I.SeatmapLayout = inXML.seatmap[0].layouts[0].layout[0];
const rows: I.LayoutRow2[] = layout.rows[0].row;
@@ -58,11 +130,12 @@ export function generateLegend(inVenueXML: I.VenueXML, inSeatmapXML: any, inNode
items: []
}
+ // todo: dynamic function to get a pricescale property by id
for (let key in pricescaleArr) {
const id: string = pricescaleArr[key].id[0];
const seatsKey: string = String.fromCharCode(97 + parseInt(key)).toLocaleUpperCase();
- // get pricescale desc from venueXML
+ // get pricescale desc from venueXML
const desc = venuePricescaleArr.find(obj => {
const pricecaleID = obj.id[0];
return pricecaleID === id;
@@ -118,7 +191,7 @@ function enterSeatsInMatrix(inRows: I.LayoutRow2[], inArrMatrix: string[][], inP
// 2: "21" -> X-Coord benutzen
// 3: "7024" -> section ID
// 4: "13" -> Reihenbezeichnung
- // 5: "4" -> ?
+ // 5: "4" -> Platznummer
// skip blacked out seats
if (!availableArr.includes(seatArr[0]) && !unavailableArr.includes(seatArr[0]))
@@ -130,6 +203,9 @@ function enterSeatsInMatrix(inRows: I.LayoutRow2[], inArrMatrix: string[][], inP
if (seatsKey)
inArrMatrix[Y][X] = generateSeatStr(seatsKey, seatArr);
+
+ // save seatArr in state with seatID as key
+ state.layoutRows[seatArr[0]] = seatArr;
});
});
diff --git a/client/src/seatmap.ts b/client/src/seatmap.ts
index 2355342..2d37231 100644
--- a/client/src/seatmap.ts
+++ b/client/src/seatmap.ts
@@ -15,10 +15,20 @@ let seatmap: any;
let panzoom: PanzoomObject | undefined;
let inVenueXML: I.VenueXML;
let seatmapXML: any;
-let state: I.State = {
+export let state: I.State = {
priceOverall: "",
+ cartChanged: false,
selectedSeatsArr: [],
- selectedSeatsObj: {}
+ selectedSeatsObj: {},
+ layoutRows: {}
+}
+
+function getTrimCoord(arr: I.Trim) {
+ let [xTrim, yTrim] = arr.coord[0].split(",").map(Number);
+ xTrim -= 20;
+ yTrim -= 21;
+
+ return [xTrim, yTrim];
}
function messagesHandler(inE: any) {
@@ -68,27 +78,55 @@ function messagesHandler(inE: any) {
case "parent_sendSeatmapXML": {
seatmapXML = data.message.map_response;
const map: string[] = JSC.generateMap(seatmapXML);
- const rows: number[] = JSC.getRows(seatmapXML);
+ const rowsNaming: string[] = JSC.getRowsNaming(seatmapXML);
+ // const columnNaming: string[] = JSC.getColumnNaming(seatmapXML);
const seats: I.JSCSeats = JSC.getSeats(seatmapXML);
const legend: I.JSCLegend = JSC.generateLegend(inVenueXML, seatmapXML, "#JSCLegendInner");
- addSeatmap("#containerSeatmapInner", map, rows, seats, legend);
+ addSeatmap("#containerSeatmapInner", map, rowsNaming, seats, legend);
JSC.setUnavailableSeats(seatmapXML, seatmap);
selectSeatsInCart();
UI.convertLegendToDropdown("dropdownLegend");
dropdownLegendOnChange("#dropdownLegend");
+ // jQuery("#containerSeatmapInner").append('
foobar
');
+
+
+ processTrims();
+
panzoom = UI.addPanzoom("#containerSeatmapInner", ".panzoomZoomIn", ".panzoomZoomOut", "#panzoomResetZoom");
UI.controlLoftloader("hide");
+
+
+ new jBox("Tooltip", {
+ attach: jQuery(".seatCharts-seat"),
+ // title: "title",
+ // content: "foooobar",
+ onOpen: function (this: any) {
+ showSeatTooltip(this);
+ },
+ });
+
+
break;
}
case "parent_sendCheckoutResponse": {
+ console.log(data.message);
const inIsValidSeatSelection: boolean = data.message.isValidSeatSelection;
- if (!inIsValidSeatSelection) {
+ if (!inIsValidSeatSelection)
showJBoxNotice(`Auswahl nicht möglich: Bitte lassen Sie keinen einzelnen Platz frei.`);
+ else {
+ removeCartItems();
+ generateCartItems();
+ const url = generateCheckoutUrl();
+ setCheckoutBtn(url);
+ showModalCart();
+ console.log(state);
}
+ state.cartChanged = false;
+
break;
}
@@ -97,10 +135,294 @@ function messagesHandler(inE: any) {
}
}
+function processTrims() {
+ // Create sum of the height of every .seatCharts-row to get total height of seatmap
+ const heightTotal = calcHeightTotal();
+
+ // Height of a single .seatCharts-row
+ const heightPerRow = heightTotal / jQuery(".seatCharts-row").length;
+
+ // Maximum width of one seatCharts-row is the width we need
+ // Attention: Maximum width of #containerSeatmapInner is bigger than seatCharts-row, therefore use width of seatCharts-row
+ const totalWidth = jQuery(".seatCharts-row")[0].getBoundingClientRect().width;
+ const widthPerSeat = totalWidth / jQuery(".seatCharts-row")[0].childElementCount;
+
+ // const containerSeatmapInnerRect: DOMRect = jQuery("#containerSeatmapInner")[0].getBoundingClientRect();
+ // console.log(containerSeatmapInnerRect);
+
+ // const viewWidthQuotient = 100 / containerSeatmapInnerRect.width;
+
+ // Width: Calculate quotient to convert pixel (px) to viewwidth (vw) later
+ // 1px = (100vw / [document.documentElement.clientWidth] px)
+ // e.g. — If your viewport was 500px wide (equals by definition to 100vw) then
+ // 1px = (100vw / 500px) = 0.2vw
+ const viewWidthQuotient = 100 / totalWidth;
+
+ // const widthQuotient = widthTotal/1580;
+ // const widthQuotient = containerSeatmapInnerRect.width / 1580;
+
+ // Width: Quotient is later used to convert PVO trim x coord to absolute x-coord in browser
+ // Max-width of trim coord system is 1600 with offset of 20
+ // 1600 - 20 = 1580
+ const widthQuotient = totalWidth / 1580;
+
+ // Height: Quotient is later used to convert PVO trim y coord to absolute y-coord in browser
+ // Max-height of trim coord system is 425 with offset of 21
+ // 425 - 20 = 405
+ const heightQuotient = heightTotal / 405;
+
+ console.log(`heightTotal: ${heightTotal} heightPerRow: ${heightPerRow} heightQuotient: ${heightQuotient} totalWidth: ${totalWidth} widthPerSeat: ${widthPerSeat} widthQuotient: ${widthQuotient}`);
+
+ const trimArr: I.Trim[] = seatmapXML.seatmap[0].trims[0].trim;
+ trimArr.forEach(arr => {
+ const text: string = getTrimText(arr);
+ const [xTrim, yTrim] = getTrimCoord(arr);
+ const [leftVw, topPx] = calcTrimPos(xTrim, yTrim, heightPerRow, widthQuotient, heightQuotient, viewWidthQuotient, widthPerSeat);
+
+ console.log(`${text} -> x: ${xTrim} y: ${yTrim} -> x: ${leftVw} y: ${topPx}px`);
+
+ createTrim(leftVw, topPx, text);
+ });
+}
+
+function calcHeightTotal(): number {
+ let heightTotal = 0;
+ jQuery(".seatCharts-row").each(function () {
+ const domRect: DOMRect = this.getBoundingClientRect();
+ console.log(domRect);
+ heightTotal += domRect.height;
+ });
+
+ return heightTotal;
+}
+
+function createTrim(inLeft: number, inTop: number, inText: string) {
+ jQuery("#containerSeatmapInner").append(`
+
+ ${inText}
+
`);
+}
+
+function calcTrimPos(xTrim: number, yTrim: number, heightPerRow: number, widthQuotient: number, heightQuotient: number, viewWidthQuotient: number, widthPerSeat: number) {
+ let leftPx = Math.round(xTrim * widthQuotient);
+ // const leftVw = parseInt((leftPx * viewWidthQuotient).toFixed(3));
+ console.log(viewWidthQuotient);
+
+ let topPx = Math.round(yTrim * heightQuotient);
+
+ // if (topPx > heightPerRow)
+ // topPx -= heightPerRow;
+ console.log(heightPerRow);
+
+ // if (leftPx > widthPerSeat)
+ // leftPx -= widthPerSeat;
+ console.log(widthPerSeat);
+
+
+ // return [leftVw, topPx];
+ return [leftPx, topPx];
+}
+
+function getTrimText(arr: I.Trim): string {
+ const textArr: string[] = arr.text[0].split(";").filter(Boolean);
+
+ return textArr.map(element => {
+ const charCode = element.replace(/^\&\#/, "0");
+ return String.fromCharCode(parseInt(charCode, 16));
+ }).join("");
+}
+
+function showSeatTooltip(jBox: any): void {
+ const seatID: string = jBox.source[0].id;
+ const seat = state.layoutRows[seatID][5];
+ const row = state.layoutRows[seatID][4];
+ const sectionID = state.layoutRows[seatID][3];
+ const sectionDesc = getSectionDescBySectionID(inVenueXML, sectionID);
+ const tooltipContent = `${sectionDesc}
Reihe ${row} Platz ${seat}`;
+
+ jBox.setContent(tooltipContent);
+}
+
+function getSectionDescBySectionID(inVenueXML: I.VenueXML, sectionID: string): string | undefined {
+ const sectionArr = inVenueXML.master_config[0].section_config[0].section;
+
+ const sectionDesc = sectionArr.find(arr => {
+ return sectionID === arr.id[0];
+ })?.desc[0];
+
+ return sectionDesc;
+}
+
+function setCheckoutBtn(inUrl: string | undefined) {
+ if (!inUrl)
+ return;
+
+ const btnCheckout = jQuery("#modalCart-overlay #checkout .fl-button").get(0);
+ if (btnCheckout) {
+ btnCheckout.addEventListener("click", function () {
+ const message: I.Message = {
+ message: {
+ url: inUrl,
+ },
+ from: "child",
+ event: "child_click_checkout",
+ date: Date.now()
+ };
+ Communication.sendMessage(message, "parent");
+ });
+ }
+}
+
+function showModalCart() {
+ jQuery("#modalCart-overlay").fadeIn(300);
+ Communication.sendEventToParent("child_hide_dialog_titlebar");
+}
+
+function getVenuePricescalePropertyByPricescaleID(property: I.Pricescale2Properties, pricescaleID: string, inVenueXML: I.VenueXML) {
+ const venuePricescaleArr: I.Pricescale2[] = inVenueXML.venue[0].pricescales[0].pricescale;
+
+ return venuePricescaleArr.find(obj => {
+ if (obj.id[0] === pricescaleID)
+ return obj;
+
+ return undefined;
+ })?.[property][0];
+}
+
+function addCartItem(inSeatObj: I.JSCSelectedSeat) {
+ const color = `#${getVenuePricescalePropertyByPricescaleID("color", inSeatObj.data.seatsObj.id[0], inVenueXML)}`;
+ const category = getVenuePricescalePropertyByPricescaleID("desc", inSeatObj.data.seatsObj.id[0], inVenueXML);
+ const seat = state.layoutRows[inSeatObj.id][5];
+ const row = state.layoutRows[inSeatObj.id][4];
+ const sectionID = state.layoutRows[inSeatObj.id][3];
+ const sectionDesc = getSectionDescBySectionID(inVenueXML, sectionID);
+ const seatStr = `${sectionDesc}
Reihe ${row} Platz ${seat}`;
+ const buyerTypes: (string | undefined)[][] | undefined = getBuyerTypesByPricescaleID(inSeatObj.data.seatsObj.id[0]);
+ const cartId = `cartItem-${inSeatObj.id}`;
+ const dropdownBuyerTypesSelector = `#${cartId} .dropdownBuyerTypes`;
+
+ // const dropdownCrossSelector = `#${cartId} .cartItemCross`;
+
+ // jQuery("#cartItemHTML .fl-html").append(`
+ //
+ //
X
+ //
+ //
${category}
+ //
${seat}
+ //
+ //
`);
+
+ jQuery("#cartItemHTML .fl-html").append(`
+
+
+
${category}
+
${seatStr}
+
+
`);
+
+ fillDropdownBuyerTypes(buyerTypes, dropdownBuyerTypesSelector);
+
+ // todo: shorter version?
+ jQuery(dropdownBuyerTypesSelector).on('change', function (this: HTMLSelectElement) {
+ changedDropdownBuyerType(this, inSeatObj);
+ });
+
+ // jQuery(dropdownCrossSelector).on("click", function () {
+ // console.log("cross clicked");
+ // removeSeatFromState(inSeatObj);
+ // calcOverallPrice(inVenueXML);
+ // setBtnCartText();
+ // });
+}
+
+function changedDropdownBuyerType(inSelect: HTMLSelectElement, inSeatObj: I.JSCSelectedSeat) {
+ const index = state.selectedSeatsArr.findIndex(arr => {
+ return arr[0] === inSeatObj.id;
+ });
+
+
+
+ state.selectedSeatsArr[index][1] = inSelect.value;
+
+ const buyerTypeCode = getBuyerTypeCodeByBuyerTypeID(inVenueXML, inSelect.value);
+
+ if (buyerTypeCode)
+ state.selectedSeatsArr[index][2] = buyerTypeCode;
+
+ calcOverallPrice(inVenueXML);
+ setBtnCartText();
+
+ const url = generateCheckoutUrl();
+ console.log(url);
+ setCheckoutBtn(url);
+
+
+ console.log(state);
+}
+
+// todo: generalize dropdown fill options
+function fillDropdownBuyerTypes(inBuyerTypes: (string | undefined)[][] | undefined, inSelector: string) {
+ if (!inBuyerTypes)
+ return;
+
+ const dropdownBuyerTypes = jQuery(inSelector).get(0);
+ console.log(dropdownBuyerTypes);
+ console.log(inBuyerTypes);
+
+ inBuyerTypes.forEach(arr => {
+ if (!arr[0])
+ return;
+
+ let opt = document.createElement('option');
+ opt.value = arr[0];
+ opt.innerHTML = `${arr[2]} €${arr[1]}`;
+ dropdownBuyerTypes.appendChild(opt);
+ });
+}
+
+function getBuyerTypesByPricescaleID(inPricescaleID: string) {
+ const venuePricescaleArr = inVenueXML.price_structure[0].pricescale;
+ const buyerTypesArr = venuePricescaleArr.find(obj => {
+ return obj.id[0] === inPricescaleID;
+ })?.buyer_type;
+
+ if (!buyerTypesArr)
+ return;
+
+ const buyerTypes: (string | undefined)[][] = buyerTypesArr.map(arr => {
+ const buyerTypeDesc = inVenueXML.venue[0].buyer_types[0].buyer_type.find(obj => {
+ return obj.id[0] === arr.id[0] ? obj.desc[0] : undefined;
+ })?.desc[0];
+
+ return [arr.id[0], arr.price[0], buyerTypeDesc];
+ });
+
+ return buyerTypes;
+}
+
+function removeCartItems() {
+ jQuery("#cartItemHTML .cartItem").each(function () {
+ this.remove();
+ });
+}
+
+function generateCartItems() {
+ if (!state.selectedSeatsArr.length)
+ return;
+
+ for (const key in state.selectedSeatsObj) {
+ if (Object.prototype.hasOwnProperty.call(state.selectedSeatsObj, key)) {
+ const element = state.selectedSeatsObj[key];
+ addCartItem(element);
+ console.log(element);
+ }
+ }
+}
+
function selectSeatsInCart() {
state.selectedSeatsArr.forEach(arr => {
const seatID: string = arr[0];
-
+
if (seatmap.get(seatID))
seatmap.status(seatID, "selected");
});
@@ -108,8 +430,8 @@ function selectSeatsInCart() {
function showJBoxNotice(inContent: string, inAutoClose: number | boolean | undefined = 5000) {
new jBox('Notice', {
- position: {x: 'center', y: 'top'},
- offset: {x: 0, y: 320},
+ position: { x: 'center', y: 'top' },
+ offset: { x: 0, y: 320 },
content: inContent,
autoClose: inAutoClose,
animation: { open: "zoomIn", close: "zoomOut" },
@@ -147,6 +469,28 @@ function generatePricescaleCSS(inVenueXML: I.VenueXML): string {
return (cssArr.join("\r\n"));
}
+function initModalCart() {
+ jQuery("#modalCart-overlay").hide();
+
+ const btnClose = jQuery("#modalCart-overlay .uabb-close-icon").get(0);
+ const btnBack = jQuery("#modalCart-overlay #goBack .fl-button").get(0);
+
+
+ // const btnClose = jQuery("#modalCart-overlay .uabb-close-icon").get(0);
+
+ if (btnClose) {
+ btnClose.addEventListener("click", function () {
+ Communication.sendEventToParent("child_show_dialog_titlebar");
+ });
+ }
+
+ if (btnBack) {
+ btnBack.addEventListener("click", function () {
+ jQuery("#modalCart-overlay .uabb-close-icon").trigger("click");
+ });
+ }
+}
+
window.addEventListener('load', function () {
Utils.inject(config.urlJSCStaging, "js", "head");
Utils.inject(config.urlCSSJSCStaging, "css", "body");
@@ -155,11 +499,20 @@ window.addEventListener('load', function () {
Communication.listenToMessages(messagesHandler);
Utils.waitForSeatmap(Communication.showBookingBtnParent);
- const btnCart: HTMLElement | null = document.getElementById("btnCart");
+ Utils.waitForElement("#modalCart-overlay", initModalCart);
+ // Utils.waitForElement("#modalCart-overlay", () => jQuery("#modalCart-overlay").hide());
+
+
+ const btnCart = jQuery("#modalCart .uabb-button").get(0);
if (btnCart) {
btnCart.addEventListener("click", function () {
- console.log("foo");
- isValidSeatSelection();
+ console.log(state.selectedSeatsArr.length);
+
+ if (!state.selectedSeatsArr.length) {
+ showJBoxNotice(`Sie haben bislang keinen Platz ausgewählt.`);
+ return;
+ }
+ state.cartChanged ? isValidSeatSelection() : showModalCart();
});
}
@@ -174,29 +527,6 @@ window.addEventListener('load', function () {
}
});
-// function showNotification(duration: number) {
-// jQuery("#notificationColumn").css({ opacity: 0.0, visibility: "visible" }).animate({ opacity: 1 });
-// jQuery("#notificationColumn").promise().done(function () {
-// console.log("done showing");
-// setTimeout(() => {
-// hideNotification();
-// }, duration);
-// });
-// }
-
-// function hideNotification() {
-// jQuery("#notificationColumn").css({ opacity: 1.0, visibility: "visible" }).animate({ opacity: 0 });
-// jQuery("#notificationColumn").promise().done(function () {
-// console.log("done hiding");
-// });
-// }
-
-// function displayNotification(inContent: string, inDuration: number = 5000) {
-// jQuery("#notificationHeading .fl-heading-text")[0].innerText = inContent;
-// showNotification(inDuration);
-// }
-
-
function dropdownLegendOnChange(inSelector: string) {
const dropdownLegend = jQuery(inSelector).get(0);
dropdownLegend.addEventListener("change", function (this: HTMLSelectElement) {
@@ -241,7 +571,7 @@ function addSeatToState(inVenueXML: I.VenueXML, inSelectedSeat: I.JSCSelectedSea
state.selectedSeatsObj = { ...state.selectedSeatsObj, ...seatObj };
const pricescaleID: string = state.selectedSeatsObj[seatID].data.seatsObj.id[0];
- const pricescaleObj: I.Pricescale5 | undefined = getVenuePriceStructurePricescaleObjByPricescaleID(inVenueXML, pricescaleID);
+ const pricescaleObj: I.Pricescale5 | undefined = getVenuePriceStructurePropertyByPricescaleID(inVenueXML, pricescaleID);
console.log(pricescaleObj);
if (!pricescaleObj) {
@@ -251,14 +581,33 @@ function addSeatToState(inVenueXML: I.VenueXML, inSelectedSeat: I.JSCSelectedSea
// get id and code of first buyer type
const firstBuyerTypeID: string = pricescaleObj.buyer_type[0].id[0];
- const firstPriceStructureCode: string = inVenueXML.price_structure[0].code[0]; // todo: code of first price_structure always correct? what about multiple schablonen?
+ // const firstPriceStructureCode: string = inVenueXML.price_structure[0].code[0]; // todo: code of first price_structure always correct? what about multiple schablonen?
+ const buyerTypeCode: string | undefined = getBuyerTypeCodeByBuyerTypeID(inVenueXML, firstBuyerTypeID);
- state.selectedSeatsArr.push([seatID, firstBuyerTypeID, firstPriceStructureCode]);
+ if (buyerTypeCode) {
+ state.selectedSeatsArr.push([seatID, firstBuyerTypeID, buyerTypeCode]);
+ state.cartChanged = true;
+ }
+}
+
+function getBuyerTypeCodeByBuyerTypeID(inVenueXML: I.VenueXML, inBuyerTypeID: string): string | undefined {
+ const venueBuyerTypeArr = inVenueXML.venue[0].buyer_types[0].buyer_type;
+ return venueBuyerTypeArr.find(arr => {
+ return inBuyerTypeID === arr.id[0];
+ })?.code[0];
}
function isValidSeatSelection() {
- const selectedSeatIndexes: string = generateSelectedSeatIndexes();
- const url: string = `${inputsWithValue["ticketPurchaseUrl"]}?user_context=${inputsWithValue.user_context}&pid=${inputsWithValue["pid"]}&selected_seat_indexes=${selectedSeatIndexes}&trxstate=148`;
+ jQuery("#modalCart-overlay").hide();
+
+ if (!state.selectedSeatsArr.length)
+ return;
+
+ const url = generateCheckoutUrl();
+
+ // const selectedSeatIndexes: string = generateSelectedSeatIndexes();
+ // const url: string = `${inputsWithValue["ticketPurchaseUrl"]}?user_context=${inputsWithValue.user_context}&pid=${inputsWithValue["pid"]}&selected_seat_indexes=${selectedSeatIndexes}&trxstate=148`;
+
const message: I.Message = {
message: {
url: url,
@@ -270,13 +619,22 @@ function isValidSeatSelection() {
Communication.sendMessage(message, "parent");
}
+function generateCheckoutUrl(): string | undefined {
+ if (!state.selectedSeatsArr.length)
+ return;
+ else {
+ const selectedSeatIndexes: string = generateSelectedSeatIndexes();
+ return `${inputsWithValue["ticketPurchaseUrl"]}?user_context=${inputsWithValue.user_context}&pid=${inputsWithValue["pid"]}&selected_seat_indexes=${selectedSeatIndexes}&trxstate=148`;
+ }
+}
+
function generateSelectedSeatIndexes(): string {
return (state.selectedSeatsArr.map(function (arr) {
return arr.join(",");
})).join("|");
}
-function getVenuePriceStructurePricescaleObjByPricescaleID(inVenueXML: I.VenueXML, inID: string): I.Pricescale5 | undefined {
+function getVenuePriceStructurePropertyByPricescaleID(inVenueXML: I.VenueXML, inID: string): I.Pricescale5 | undefined {
const venuePricescaleArr: I.Pricescale5[] = inVenueXML.price_structure[0].pricescale;
return venuePricescaleArr.find(obj => {
return obj.id[0] === inID;
@@ -290,23 +648,26 @@ function removeSeatFromState(inSelectedSeat: I.JSCSelectedSeat) {
return arr[0] === inSelectedSeat.id;
});
state.selectedSeatsArr.splice(index, 1);
+ state.cartChanged = true;
+
+ if (!state.selectedSeatsArr.length)
+ jQuery("#modalCart-overlay").hide();
}
-function calcOverallPrice(inVenueXML: I.VenueXML): string | undefined {
- if (!state.selectedSeatsArr.length)
- return;
-
+function calcOverallPrice(inVenueXML: I.VenueXML): string | undefined {
+ if (!state.selectedSeatsArr.length) {
+ state.priceOverall = "0";
+ return "0";
+ }
+
let overallPrice: number = 0;
state.selectedSeatsArr.forEach(arr => {
const seatID: string = arr[0];
const buyertypeID: string = arr[1];
-
- // const selectedSeat: I.JSCSelectedSeat = seatmap.get(seatID).settings;
const selectedSeat: I.JSCSelectedSeat = state.selectedSeatsObj[seatID];
-
const pricescaleID: string = selectedSeat.data.seatsObj.id[0];
- const pricescaleObj: I.Pricescale5 | undefined = getVenuePriceStructurePricescaleObjByPricescaleID(inVenueXML, pricescaleID);
+ const pricescaleObj: I.Pricescale5 | undefined = getVenuePriceStructurePropertyByPricescaleID(inVenueXML, pricescaleID);
if (!pricescaleObj)
return;
@@ -319,7 +680,6 @@ function calcOverallPrice(inVenueXML: I.VenueXML): string | undefined {
overallPrice += seatPrice;
});
-
state.priceOverall = overallPrice.toFixed(2);
return state.priceOverall;
@@ -332,25 +692,42 @@ function getPriceByBuyertypeID(inBuyertypeID: string, inPricescaleObj: I.Pricesc
if (price)
return parseFloat(price);
- else
- return undefined;
+
+ return undefined;
}
function setBtnCartText() {
const numTickets = state.selectedSeatsArr.length;
let text: string = "";
+ let textModal: string = "";
console.log(numTickets);
- if (state.priceOverall !== "")
+ if (state.priceOverall !== "") {
numTickets === 1 ? text = `${numTickets} Ticket für €${state.priceOverall}` : text = `${numTickets} Tickets für €${state.priceOverall}`;
- else
+ textModal = `Summe (${numTickets} Plätze) €${state.priceOverall}`;
+ }
+ else {
text = "0 Tickets für €0.00";
+ textModal = `Summe (0 Plätze) €0,00`;
+ }
+
+ jQuery("#modalCart .uabb-button-text")[0].innerText = text;
+ jQuery("#modalCartSum .uabb-heading-text")[0].textContent = textModal;
- jQuery("#btnCart .fl-button-text")[0].innerText = text;
}
-function addSeatmap(inSelector: string, inMap: string[], inRows: number[], inSeats: I.JSCSeats, inLegend: I.JSCLegend): void {
+function maximumSelectedSeatsReached(inSeatObj: I.JSCSelectedSeat): boolean {
+ if (state.selectedSeatsArr.length >= config.maxSelectedSeats) {
+ showJBoxNotice(`Sie können maximal ${config.maxSelectedSeats} Plätze auswählen.`);
+ seatmap.status(inSeatObj.id, "available");
+ return true;
+ }
+
+ return false;
+}
+
+function addSeatmap(inSelector: string, inMap: string[], inRowsNaming: string[], inSeats: I.JSCSeats, inLegend: I.JSCLegend): void {
// console.log(inSeatmapInitMap);
// console.log(inSeats);
@@ -361,8 +738,8 @@ function addSeatmap(inSelector: string, inMap: string[], inRows: number[], inSea
seatmap = containerSeatmap.seatCharts({
naming: {
top: false,
- left: true,
- rows: inRows,
+ left: false,
+ rows: inRowsNaming,
},
map: inMap,
// map: [
@@ -389,30 +766,32 @@ function addSeatmap(inSelector: string, inMap: string[], inRows: number[], inSea
console.log("seat selected");
console.log(selectedSeat);
+ if (maximumSelectedSeatsReached(selectedSeat))
+ return "available";
+
addSeatToState(inVenueXML, selectedSeat);
calcOverallPrice(inVenueXML);
setBtnCartText();
console.log(state.selectedSeatsArr);
- return 'selected';
+ return "selected";
}
- else if (this.status() == 'selected') {
+ else if (this.status() === "selected") {
const selectedSeat: I.JSCSelectedSeat = this.settings;
console.log("seat unselected");
removeSeatFromState(selectedSeat);
-
calcOverallPrice(inVenueXML);
setBtnCartText();
console.log(state.selectedSeatsArr);
- return 'available';
+ return "available";
}
else if (this.status() == 'unavailable') {
console.log("unavailable");
- return 'unavailable';
+ return "unavailable";
}
else {
return this.style();
diff --git a/client/src/types/types.d.ts b/client/src/types/types.d.ts
index 3d0c086..eedbc36 100644
--- a/client/src/types/types.d.ts
+++ b/client/src/types/types.d.ts
@@ -1,7 +1,24 @@
+export interface Trim {
+ coord: string[];
+ enabled: string[];
+ id: string[];
+ image_path: string[];
+ metadata: string[];
+ text: string[];
+ type: string[];
+ target_seat_map_id: string[];
+}
+
export interface State {
priceOverall: string;
+ cartChanged: boolean;
selectedSeatsArr: string[][];
- selectedSeatsObj: StateJSCSelectedSeats
+ selectedSeatsObj: StateJSCSelectedSeats;
+ layoutRows: layoutRows;
+}
+
+interface layoutRows {
+ [key: string]: string[]
}
export interface StateJSCSelectedSeats {
@@ -70,6 +87,7 @@ export interface Config {
urlCSSParentMaster: string;
childHasVenueXML: boolean;
urlCSSjQueryUI: string;
+ maxSelectedSeats: number;
}
export interface Message {
@@ -128,6 +146,8 @@ export interface Event {
timestamp: string[];
}
+export type Pricescale2Properties = "code" | "color" | "desc" | "id" | "pricescale_group_id" | "text_color";
+
export interface Pricescale2 {
code: string[];
color: string[];