implemented cart button
This commit is contained in:
721
client/package-lock.json
generated
721
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,8 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"browserifyf": "func() { browserify --debug -p [ tsify ] $1 > $2; }; func",
|
"browserifyf": "func() { browserify --debug -p [ tsify ] $1 > $2; }; func",
|
||||||
"watchifyf": "func() { watchify --debug --verbose -p [ tsify ] $1 -o $2; }; func"
|
"watchifyf": "func() { watchify --debug --verbose -p [ tsify ] $1 -o $2; }; func",
|
||||||
|
"watchifyfcss": "func() { watchify -g browserify-css --debug --verbose -p [ tsify ] $1 -o $2; }; func"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
"@types/jqueryui": "^1.12.14",
|
"@types/jqueryui": "^1.12.14",
|
||||||
"@types/xml2js": "^0.4.8",
|
"@types/xml2js": "^0.4.8",
|
||||||
"browserify": "^17.0.0",
|
"browserify": "^17.0.0",
|
||||||
|
"browserify-css": "^0.15.0",
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.0",
|
||||||
"jquery-ui": "^1.12.1",
|
"jquery-ui": "^1.12.1",
|
||||||
"tsify": "^5.0.2",
|
"tsify": "^5.0.2",
|
||||||
@@ -24,6 +26,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@panzoom/panzoom": "^4.3.2",
|
"@panzoom/panzoom": "^4.3.2",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
|
"jbox": "^1.2.14",
|
||||||
"xml2js": "^0.4.23"
|
"xml2js": "^0.4.23"
|
||||||
|
},
|
||||||
|
"browserify-css": {
|
||||||
|
"autoInject": true,
|
||||||
|
"minify": false,
|
||||||
|
"rootDir": "."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import * as Communication from "./modules/communication";
|
|||||||
import * as Parser from './modules/parser';
|
import * as Parser from './modules/parser';
|
||||||
import * as UI from "./modules/ui";
|
import * as UI from "./modules/ui";
|
||||||
import { config } from "./modules/config";
|
import { config } from "./modules/config";
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
let inputsWithValue: I.InputsWithValue;
|
let inputsWithValue: I.InputsWithValue;
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ function messagesHandler(e: any) {
|
|||||||
event: "parent_init_sendInputsWithValue",
|
event: "parent_init_sendInputsWithValue",
|
||||||
date: Date.now()
|
date: Date.now()
|
||||||
};
|
};
|
||||||
Communication.sendMessage(message, "iframeSeatmap")
|
Communication.sendMessage(message, "iframeSeatmap");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "child_init_needVenueXML": {
|
case "child_init_needVenueXML": {
|
||||||
@@ -34,7 +35,7 @@ function messagesHandler(e: any) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "child_needSeatmapXML": {
|
case "child_needSeatmapXML": {
|
||||||
const seatmapUrl: string = `${inputsWithValue["posturlRawDecoded"]}&inclseatmap=Y&seatmap=${data.message}`
|
const seatmapUrl: string = `${inputsWithValue["posturlRawDecoded"]}&inclseatmap=Y&seatmap=${data.message}`;
|
||||||
Communication.sendXML(seatmapUrl, "iframeSeatmap", "parent_sendSeatmapXML", "parent");
|
Communication.sendXML(seatmapUrl, "iframeSeatmap", "parent_sendSeatmapXML", "parent");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -42,12 +43,66 @@ function messagesHandler(e: any) {
|
|||||||
jQuery("#containerBookingBtn").show();
|
jQuery("#containerBookingBtn").show();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "child_needCheckoutResponse": {
|
||||||
|
// const inSelectedSeat: I.JSCSelectedSeat = data.message.selectedSeat;
|
||||||
|
const inUrl: string = data.message.url;
|
||||||
|
|
||||||
|
axios.get(inUrl, {
|
||||||
|
maxRedirects: 0
|
||||||
|
}).then(function (response) {
|
||||||
|
let isValidSeatSelection: boolean = false;
|
||||||
|
const content: string = response.data;
|
||||||
|
const parsedHTML: Node[] = jQuery.parseHTML(content);
|
||||||
|
const orderkey: string | undefined = jQuery(parsedHTML).find("#orderkey").val();
|
||||||
|
console.log(`orderkey: ${orderkey}`);
|
||||||
|
|
||||||
|
if (orderkey) {
|
||||||
|
isValidSeatSelection = true;
|
||||||
|
const cancelUrl = generateCheckoutCancelUrl(orderkey);
|
||||||
|
cancelCheckout(cancelUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
const message: I.Message = {
|
||||||
|
message: {
|
||||||
|
"isValidSeatSelection": isValidSeatSelection,
|
||||||
|
"parsedHTML": parsedHTML,
|
||||||
|
// "selectedSeat": inSelectedSeat
|
||||||
|
},
|
||||||
|
from: "parent",
|
||||||
|
event: "parent_sendCheckoutResponse",
|
||||||
|
date: Date.now()
|
||||||
|
};
|
||||||
|
Communication.sendMessage(message, "iframeSeatmap");
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log("error");
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cancelCheckout(inUrl: string) {
|
||||||
|
// use fetch instead of axios because of 302 redirect
|
||||||
|
// https://github.com/axios/axios/issues/932
|
||||||
|
fetch(inUrl, {
|
||||||
|
redirect: "manual"
|
||||||
|
}).then(() => {
|
||||||
|
console.log(`${inUrl} canceled`);
|
||||||
|
}).catch(function (error) {
|
||||||
|
console.log("error");
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateCheckoutCancelUrl(inOrderkey: string) {
|
||||||
|
return `${inputsWithValue["ticketPurchaseUrl"]}?user_context=${inputsWithValue["user_context"]}&pid=${inputsWithValue["pid"]}&orderkey=${inOrderkey}&trxstate=92`;
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener('load', function () {
|
window.addEventListener('load', function () {
|
||||||
const content: string = new XMLSerializer().serializeToString(document);
|
const content: string = new XMLSerializer().serializeToString(document);
|
||||||
inputsWithValue = { ...inputsWithValue, ...Parser.getInputs(content) };
|
inputsWithValue = { ...inputsWithValue, ...Parser.getInputs(content) };
|
||||||
@@ -64,7 +119,7 @@ window.addEventListener('load', function () {
|
|||||||
Communication.listenToMessages(messagesHandler);
|
Communication.listenToMessages(messagesHandler);
|
||||||
inputsWithValue = { ...inputsWithValue, ...Parser.getAdditionalInputs(content) };
|
inputsWithValue = { ...inputsWithValue, ...Parser.getAdditionalInputs(content) };
|
||||||
inputsWithValue = { ...inputsWithValue, ...Parser.getVenueImage() };
|
inputsWithValue = { ...inputsWithValue, ...Parser.getVenueImage() };
|
||||||
|
|
||||||
const importantNote = Parser.getImportantNote();
|
const importantNote = Parser.getImportantNote();
|
||||||
if (importantNote)
|
if (importantNote)
|
||||||
inputsWithValue = { ...inputsWithValue, ...importantNote };
|
inputsWithValue = { ...inputsWithValue, ...importantNote };
|
||||||
|
|||||||
@@ -13,5 +13,6 @@ export const config: I.Config = {
|
|||||||
urlJSCMaster: "https://tickets.zinomedia.de/libs/jQuery-Seat-Charts/jquery.seat-charts.min.js",
|
urlJSCMaster: "https://tickets.zinomedia.de/libs/jQuery-Seat-Charts/jquery.seat-charts.min.js",
|
||||||
urlCSSJSCStaging: "https://staging.tickets.zinomedia.de/libs/jQuery-Seat-Charts/jquery.seat-charts.css",
|
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",
|
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
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ export function getSeats(inXML: any): I.JSCSeats {
|
|||||||
return seatmapInitSeats;
|
return seatmapInitSeats;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function activateSeatsBySectionID(inXML: any, seatmap: any, inValue: string, ) {
|
export function activateSeatsBySectionID(inXML: any, seatmap: any, inValue: string,) {
|
||||||
const pricescaleArr: I.SeatmapPricescale[] = inXML.seatmap[0].pricescale_config[0].pricescale;
|
const pricescaleArr: I.SeatmapPricescale[] = inXML.seatmap[0].pricescale_config[0].pricescale;
|
||||||
|
|
||||||
pricescaleArr.forEach(element => {
|
pricescaleArr.forEach(element => {
|
||||||
@@ -38,33 +38,40 @@ export function getRows(inXML: any): number[] {
|
|||||||
|
|
||||||
export function generateMap(inXML: any): string[] {
|
export function generateMap(inXML: any): string[] {
|
||||||
const layout: I.SeatmapLayout = inXML.seatmap[0].layouts[0].layout[0];
|
const layout: I.SeatmapLayout = inXML.seatmap[0].layouts[0].layout[0];
|
||||||
console.log(layout);
|
|
||||||
const rows: I.LayoutRow2[] = layout.rows[0].row;
|
const rows: I.LayoutRow2[] = layout.rows[0].row;
|
||||||
const pricescaleArr: I.SeatmapPricescale[] = inXML.seatmap[0].pricescale_config[0].pricescale;
|
const pricescaleArr: I.SeatmapPricescale[] = inXML.seatmap[0].pricescale_config[0].pricescale;
|
||||||
|
const availabilityArr: I.JSCAvailability = inXML.seatmap[0].view_modes[0].view_mode[0].availability[0];
|
||||||
|
|
||||||
// Form: arrMatrix[Y][X]
|
// Form: arrMatrix[Y][X]
|
||||||
let arrMatrix: string[][] = createArrMatrix(parseInt(layout.height[0]), parseInt(layout.width[0]), "_");
|
let arrMatrix: string[][] = createArrMatrix(parseInt(layout.height[0]), parseInt(layout.width[0]), "_");
|
||||||
|
arrMatrix = enterSeatsInMatrix(rows, arrMatrix, pricescaleArr, availabilityArr);
|
||||||
arrMatrix = enterSeatsInMatrix(rows, arrMatrix, pricescaleArr);
|
|
||||||
const stringArrMatrix = generateStringArrMatrix(arrMatrix);
|
const stringArrMatrix = generateStringArrMatrix(arrMatrix);
|
||||||
|
|
||||||
return stringArrMatrix;
|
return stringArrMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateLegend(inXML: any, inNode: string): I.JSCLegend {
|
export function generateLegend(inVenueXML: I.VenueXML, inSeatmapXML: any, inNode: string): I.JSCLegend {
|
||||||
const pricescaleArr: I.SeatmapPricescale[] = inXML.seatmap[0].pricescale_config[0].pricescale;
|
const pricescaleArr: I.SeatmapPricescale[] = inSeatmapXML.seatmap[0].pricescale_config[0].pricescale;
|
||||||
console.log(pricescaleArr);
|
const venuePricescaleArr: I.Pricescale2[] = inVenueXML.venue[0].pricescales[0].pricescale;
|
||||||
let legend: I.JSCLegend = {
|
let legend: I.JSCLegend = {
|
||||||
node: jQuery(inNode),
|
node: jQuery(inNode),
|
||||||
items: []
|
items: []
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let key in pricescaleArr) {
|
for (let key in pricescaleArr) {
|
||||||
|
const id: string = pricescaleArr[key].id[0];
|
||||||
const seatsKey: string = String.fromCharCode(97 + parseInt(key)).toLocaleUpperCase();
|
const seatsKey: string = String.fromCharCode(97 + parseInt(key)).toLocaleUpperCase();
|
||||||
const price: string = `€${pricescaleArr[key].ref_price[0]}`;
|
|
||||||
const legendItem = [ seatsKey, "available", price ];
|
// get pricescale desc from venueXML
|
||||||
|
const desc = venuePricescaleArr.find(obj => {
|
||||||
|
const pricecaleID = obj.id[0];
|
||||||
|
return pricecaleID === id;
|
||||||
|
})?.desc[0];
|
||||||
|
|
||||||
|
const description: string = `${desc} €${pricescaleArr[key].ref_price[0]}`;
|
||||||
|
const legendItem = [seatsKey, "available", description];
|
||||||
legend.items.push(legendItem);
|
legend.items.push(legendItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return legend;
|
return legend;
|
||||||
}
|
}
|
||||||
@@ -73,7 +80,7 @@ export function setUnavailableSeats(inXML: any, seatmap: any): void {
|
|||||||
const availabilityArr: I.JSCAvailability = inXML.seatmap[0].view_modes[0].view_mode[0].availability[0];
|
const availabilityArr: I.JSCAvailability = inXML.seatmap[0].view_modes[0].view_mode[0].availability[0];
|
||||||
|
|
||||||
if (availabilityArr.unavailable_unselectable_mask[0] === "")
|
if (availabilityArr.unavailable_unselectable_mask[0] === "")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const unavailableArr: string[] = availabilityArr.unavailable_unselectable_mask[0].split(",");
|
const unavailableArr: string[] = availabilityArr.unavailable_unselectable_mask[0].split(",");
|
||||||
seatmap.status(unavailableArr, "unavailable");
|
seatmap.status(unavailableArr, "unavailable");
|
||||||
@@ -90,7 +97,10 @@ export function generateStringArrMatrix(inArrMatrix: string[][]): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function enterSeatsInMatrix(inRows: I.LayoutRow2[], inArrMatrix: string[][], inPricescaleArr: I.SeatmapPricescale[]): string[][] {
|
function enterSeatsInMatrix(inRows: I.LayoutRow2[], inArrMatrix: string[][], inPricescaleArr: I.SeatmapPricescale[], inAvailabilityArr: I.JSCAvailability): string[][] {
|
||||||
|
const availableArr: string[] = inAvailabilityArr.available_selectable_mask[0].split(",");
|
||||||
|
const unavailableArr: string[] = inAvailabilityArr.unavailable_unselectable_mask[0].split(",");
|
||||||
|
|
||||||
inRows.forEach(element => {
|
inRows.forEach(element => {
|
||||||
const row: I.LayoutRow2 = element;
|
const row: I.LayoutRow2 = element;
|
||||||
const Y: number = parseInt(row.y_cell_coord[0]);
|
const Y: number = parseInt(row.y_cell_coord[0]);
|
||||||
@@ -110,6 +120,10 @@ export function enterSeatsInMatrix(inRows: I.LayoutRow2[], inArrMatrix: string[]
|
|||||||
// 4: "13" -> Reihenbezeichnung
|
// 4: "13" -> Reihenbezeichnung
|
||||||
// 5: "4" -> ?
|
// 5: "4" -> ?
|
||||||
|
|
||||||
|
// skip blacked out seats
|
||||||
|
if (!availableArr.includes(seatArr[0]) && !unavailableArr.includes(seatArr[0]))
|
||||||
|
return;
|
||||||
|
|
||||||
// const X: number = parseInt(seatArr[5]);
|
// const X: number = parseInt(seatArr[5]);
|
||||||
const X: number = parseInt(seatArr[2]);
|
const X: number = parseInt(seatArr[2]);
|
||||||
const seatsKey = getSeatsKey(seatArr[0], inPricescaleArr);
|
const seatsKey = getSeatsKey(seatArr[0], inPricescaleArr);
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ export function getAdditionalInputs(inContent: string): { [key: string]: string
|
|||||||
const posturlRaw = inContent.match(/posturl:"(.+?)"/)![1];
|
const posturlRaw = inContent.match(/posturl:"(.+?)"/)![1];
|
||||||
const posturlRawDecoded = decodeURIComponent(posturlRaw);
|
const posturlRawDecoded = decodeURIComponent(posturlRaw);
|
||||||
const posturl = decodeURIComponent(`${posturlRaw}&event=${event}&holdcode=${holdcode}&nocache=0&inclpkg=Y&incloffer=Y&inclcartdetails=Y&inclCart=Y&inclvenue=Y`);
|
const posturl = decodeURIComponent(`${posturlRaw}&event=${event}&holdcode=${holdcode}&nocache=0&inclpkg=Y&incloffer=Y&inclcartdetails=Y&inclCart=Y&inclvenue=Y`);
|
||||||
const venueLocation = getVenueLocation()
|
const venueLocation = getVenueLocation();
|
||||||
|
const ticketPurchaseUrl = `${posturlRawDecoded.split("?")[0].split('/').slice(0,-1).join('/')}/TicketPurchase`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"event": event,
|
"event": event,
|
||||||
@@ -55,7 +56,8 @@ export function getAdditionalInputs(inContent: string): { [key: string]: string
|
|||||||
"posturlRaw": posturlRaw,
|
"posturlRaw": posturlRaw,
|
||||||
"posturlRawDecoded": posturlRawDecoded,
|
"posturlRawDecoded": posturlRawDecoded,
|
||||||
"posturl": posturl,
|
"posturl": posturl,
|
||||||
"venueLocation": venueLocation
|
"venueLocation": venueLocation,
|
||||||
|
"ticketPurchaseUrl": ticketPurchaseUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ export function setOptionSelect(inSeatmapListing: I.Seatmap[], inId: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function setEventInfo(inEventInfo: I.EventInfo, inInputswithValue: I.InputsWithValue): void {
|
export function setEventInfo(inEventInfo: I.EventInfo, inInputswithValue: I.InputsWithValue): void {
|
||||||
// console.log(inEventInfo);
|
|
||||||
jQuery("#eventInfoDesc span.fl-heading-text")[0].childNodes[0].textContent = inEventInfo.desc[0];
|
jQuery("#eventInfoDesc span.fl-heading-text")[0].childNodes[0].textContent = inEventInfo.desc[0];
|
||||||
jQuery("#eventInfoDate p")[0].childNodes[0].textContent = inEventInfo.start[0];
|
jQuery("#eventInfoDate p")[0].childNodes[0].textContent = inEventInfo.start[0];
|
||||||
jQuery("#eventInfoCapacity p")[0].childNodes[0].textContent = inEventInfo.venue_config_capacity[0];
|
jQuery("#eventInfoCapacity p")[0].childNodes[0].textContent = inEventInfo.venue_config_capacity[0];
|
||||||
|
|||||||
@@ -7,12 +7,19 @@ import * as JSC from "./modules/jsc";
|
|||||||
import { config } from "./modules/config";
|
import { config } from "./modules/config";
|
||||||
import Utils from './modules/utils';
|
import Utils from './modules/utils';
|
||||||
import { PanzoomObject } from "@panzoom/panzoom";
|
import { PanzoomObject } from "@panzoom/panzoom";
|
||||||
|
import jBox from 'jbox';
|
||||||
|
require('jbox/dist/jBox.all.css');
|
||||||
|
|
||||||
let inputsWithValue: I.InputsWithValue;
|
let inputsWithValue: I.InputsWithValue;
|
||||||
let seatmap: any;
|
let seatmap: any;
|
||||||
let panzoom: PanzoomObject | undefined;
|
let panzoom: PanzoomObject | undefined;
|
||||||
let venueXML: I.VenueXML;
|
let inVenueXML: I.VenueXML;
|
||||||
let seatmapXML: any;
|
let seatmapXML: any;
|
||||||
|
let state: I.State = {
|
||||||
|
priceOverall: "",
|
||||||
|
selectedSeatsArr: [],
|
||||||
|
selectedSeatsObj: {}
|
||||||
|
}
|
||||||
|
|
||||||
function messagesHandler(inE: any) {
|
function messagesHandler(inE: any) {
|
||||||
if (typeof (inE.data) !== 'string')
|
if (typeof (inE.data) !== 'string')
|
||||||
@@ -29,19 +36,19 @@ function messagesHandler(inE: any) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "parent_init_sendVenueXML": {
|
case "parent_init_sendVenueXML": {
|
||||||
venueXML = data.message.map_response;
|
inVenueXML = data.message.map_response;
|
||||||
|
|
||||||
// generate pricescale css classes
|
// generate pricescale css classes
|
||||||
const css = generatePricescaleCSS(venueXML);
|
const css = generatePricescaleCSS(inVenueXML);
|
||||||
Utils.inject(css, "cssCustom", "body");
|
Utils.inject(css, "cssCustom", "body");
|
||||||
console.log(css);
|
console.log(css);
|
||||||
|
|
||||||
// fill event info
|
// fill event info
|
||||||
const eventInfo = XMLHelper.getEventInfo(venueXML);
|
const eventInfo = XMLHelper.getEventInfo(inVenueXML);
|
||||||
UI.setEventInfo(eventInfo, inputsWithValue);
|
UI.setEventInfo(eventInfo, inputsWithValue);
|
||||||
|
|
||||||
// fill select dropdown
|
// fill select dropdown
|
||||||
const seatmapListing: I.Seatmap[] = XMLHelper.getSeatmapListing(venueXML);
|
const seatmapListing: I.Seatmap[] = XMLHelper.getSeatmapListing(inVenueXML);
|
||||||
console.log(seatmapListing);
|
console.log(seatmapListing);
|
||||||
UI.setOptionSelect(seatmapListing, "dropdownSeatmap");
|
UI.setOptionSelect(seatmapListing, "dropdownSeatmap");
|
||||||
|
|
||||||
@@ -63,23 +70,63 @@ function messagesHandler(inE: any) {
|
|||||||
const map: string[] = JSC.generateMap(seatmapXML);
|
const map: string[] = JSC.generateMap(seatmapXML);
|
||||||
const rows: number[] = JSC.getRows(seatmapXML);
|
const rows: number[] = JSC.getRows(seatmapXML);
|
||||||
const seats: I.JSCSeats = JSC.getSeats(seatmapXML);
|
const seats: I.JSCSeats = JSC.getSeats(seatmapXML);
|
||||||
const legend: I.JSCLegend = JSC.generateLegend(seatmapXML, "#JSCLegendInner");
|
const legend: I.JSCLegend = JSC.generateLegend(inVenueXML, seatmapXML, "#JSCLegendInner");
|
||||||
|
|
||||||
addSeatmap("#containerSeatmapInner", map, rows, seats, legend);
|
addSeatmap("#containerSeatmapInner", map, rows, seats, legend);
|
||||||
|
|
||||||
JSC.setUnavailableSeats(seatmapXML, seatmap);
|
JSC.setUnavailableSeats(seatmapXML, seatmap);
|
||||||
|
selectSeatsInCart();
|
||||||
UI.convertLegendToDropdown("dropdownLegend");
|
UI.convertLegendToDropdown("dropdownLegend");
|
||||||
dropdownLegendOnChange("#dropdownLegend");
|
dropdownLegendOnChange("#dropdownLegend");
|
||||||
panzoom = UI.addPanzoom("#containerSeatmapInner", ".panzoomZoomIn", ".panzoomZoomOut", "#panzoomResetZoom");
|
panzoom = UI.addPanzoom("#containerSeatmapInner", ".panzoomZoomIn", ".panzoomZoomOut", "#panzoomResetZoom");
|
||||||
UI.controlLoftloader("hide");
|
UI.controlLoftloader("hide");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "parent_sendCheckoutResponse": {
|
||||||
|
const inIsValidSeatSelection: boolean = data.message.isValidSeatSelection;
|
||||||
|
|
||||||
|
if (!inIsValidSeatSelection) {
|
||||||
|
showJBoxNotice(`Auswahl nicht möglich: Bitte lassen Sie keinen einzelnen Platz frei.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectSeatsInCart() {
|
||||||
|
state.selectedSeatsArr.forEach(arr => {
|
||||||
|
const seatID: string = arr[0];
|
||||||
|
|
||||||
|
if (seatmap.get(seatID))
|
||||||
|
seatmap.status(seatID, "selected");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showJBoxNotice(inContent: string, inAutoClose: number | boolean | undefined = 5000) {
|
||||||
|
new jBox('Notice', {
|
||||||
|
position: {x: 'center', y: 'top'},
|
||||||
|
offset: {x: 0, y: 320},
|
||||||
|
content: inContent,
|
||||||
|
autoClose: inAutoClose,
|
||||||
|
animation: { open: "zoomIn", close: "zoomOut" },
|
||||||
|
closeOnEsc: false,
|
||||||
|
closeButton: true,
|
||||||
|
closeOnMouseleave: false,
|
||||||
|
closeOnClick: false,
|
||||||
|
draggable: false,
|
||||||
|
color: "red",
|
||||||
|
stack: true,
|
||||||
|
showCountdown: true,
|
||||||
|
reposition: true,
|
||||||
|
responsiveWidth: true,
|
||||||
|
responsiveHeight: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function generatePricescaleCSS(inVenueXML: I.VenueXML): string {
|
function generatePricescaleCSS(inVenueXML: I.VenueXML): string {
|
||||||
const venuePricescalesArr: I.Pricescale2[] = inVenueXML.venue[0].pricescales[0].pricescale;
|
const venuePricescalesArr: I.Pricescale2[] = inVenueXML.venue[0].pricescales[0].pricescale;
|
||||||
let cssArr: string[] = [];
|
let cssArr: string[] = [];
|
||||||
@@ -87,10 +134,12 @@ function generatePricescaleCSS(inVenueXML: I.VenueXML): string {
|
|||||||
venuePricescalesArr.forEach(element => {
|
venuePricescalesArr.forEach(element => {
|
||||||
const ID: string = element.id[0];
|
const ID: string = element.id[0];
|
||||||
|
|
||||||
// todo: check if "" is correct when no color is set
|
// update: color always defined: fallback colors exist in system
|
||||||
let color: string = `#${element.color[0]} !important`;
|
let color: string = `#${element.color[0]} !important`;
|
||||||
if (color === "")
|
// if (color === "") {
|
||||||
color = Utils.generateRandomColor();
|
// console.log("no default color");
|
||||||
|
// color = Utils.generateRandomColor();
|
||||||
|
// }
|
||||||
|
|
||||||
cssArr.push(`._${ID} { background-color: ${color}; }`);
|
cssArr.push(`._${ID} { background-color: ${color}; }`);
|
||||||
});
|
});
|
||||||
@@ -102,9 +151,18 @@ window.addEventListener('load', function () {
|
|||||||
Utils.inject(config.urlJSCStaging, "js", "head");
|
Utils.inject(config.urlJSCStaging, "js", "head");
|
||||||
Utils.inject(config.urlCSSJSCStaging, "css", "body");
|
Utils.inject(config.urlCSSJSCStaging, "css", "body");
|
||||||
Utils.inject(config.urlCSSChildStaging, "css", "body");
|
Utils.inject(config.urlCSSChildStaging, "css", "body");
|
||||||
|
Utils.inject(config.urlCSSjQueryUI, "css", "body");
|
||||||
Communication.listenToMessages(messagesHandler);
|
Communication.listenToMessages(messagesHandler);
|
||||||
Utils.waitForSeatmap(Communication.showBookingBtnParent);
|
Utils.waitForSeatmap(Communication.showBookingBtnParent);
|
||||||
|
|
||||||
|
const btnCart: HTMLElement | null = document.getElementById("btnCart");
|
||||||
|
if (btnCart) {
|
||||||
|
btnCart.addEventListener("click", function () {
|
||||||
|
console.log("foo");
|
||||||
|
isValidSeatSelection();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const dropdownSeatmap: HTMLElement | null = document.getElementById("dropdownSeatmap");
|
const dropdownSeatmap: HTMLElement | null = document.getElementById("dropdownSeatmap");
|
||||||
if (dropdownSeatmap) {
|
if (dropdownSeatmap) {
|
||||||
dropdownSeatmap.addEventListener("change", function (this: HTMLSelectElement) {
|
dropdownSeatmap.addEventListener("change", function (this: HTMLSelectElement) {
|
||||||
@@ -114,10 +172,31 @@ window.addEventListener('load', function () {
|
|||||||
Communication.needSeatmapXML(value);
|
Communication.needSeatmapXML(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utils.waitForElement("#dropdownLegend", dropdownLegendOnChange);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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) {
|
function dropdownLegendOnChange(inSelector: string) {
|
||||||
const dropdownLegend = jQuery(inSelector).get(0);
|
const dropdownLegend = jQuery(inSelector).get(0);
|
||||||
dropdownLegend.addEventListener("change", function (this: HTMLSelectElement) {
|
dropdownLegend.addEventListener("change", function (this: HTMLSelectElement) {
|
||||||
@@ -139,7 +218,6 @@ function dropdownLegendOnChange(inSelector: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function changeDropdownLegendBGColor(inSelector: string, inValue: string, inClassName: string) {
|
function changeDropdownLegendBGColor(inSelector: string, inValue: string, inClassName: string) {
|
||||||
let bgColor: string = "#fafafa";
|
let bgColor: string = "#fafafa";
|
||||||
let color: string = "#5c5c5c";
|
let color: string = "#5c5c5c";
|
||||||
@@ -154,6 +232,124 @@ function changeDropdownLegendBGColor(inSelector: string, inValue: string, inClas
|
|||||||
jQuery(`${inSelector} option[value="all"]`).css("color", color);
|
jQuery(`${inSelector} option[value="all"]`).css("color", color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addSeatToState(inVenueXML: I.VenueXML, inSelectedSeat: I.JSCSelectedSeat) {
|
||||||
|
const seatID: string = inSelectedSeat.id;
|
||||||
|
const seatObj: I.StateJSCSelectedSeats = {
|
||||||
|
[seatID]: inSelectedSeat
|
||||||
|
}
|
||||||
|
|
||||||
|
state.selectedSeatsObj = { ...state.selectedSeatsObj, ...seatObj };
|
||||||
|
|
||||||
|
const pricescaleID: string = state.selectedSeatsObj[seatID].data.seatsObj.id[0];
|
||||||
|
const pricescaleObj: I.Pricescale5 | undefined = getVenuePriceStructurePricescaleObjByPricescaleID(inVenueXML, pricescaleID);
|
||||||
|
console.log(pricescaleObj);
|
||||||
|
|
||||||
|
if (!pricescaleObj) {
|
||||||
|
console.warn(`Cannot find corresponding venueXML pricescaleObj for pricescale with ID ${pricescaleID}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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?
|
||||||
|
|
||||||
|
state.selectedSeatsArr.push([seatID, firstBuyerTypeID, firstPriceStructureCode]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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`;
|
||||||
|
const message: I.Message = {
|
||||||
|
message: {
|
||||||
|
url: url,
|
||||||
|
},
|
||||||
|
from: "child",
|
||||||
|
event: "child_needCheckoutResponse",
|
||||||
|
date: Date.now()
|
||||||
|
};
|
||||||
|
Communication.sendMessage(message, "parent");
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateSelectedSeatIndexes(): string {
|
||||||
|
return (state.selectedSeatsArr.map(function (arr) {
|
||||||
|
return arr.join(",");
|
||||||
|
})).join("|");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVenuePriceStructurePricescaleObjByPricescaleID(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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeSeatFromState(inSelectedSeat: I.JSCSelectedSeat) {
|
||||||
|
const seatID: string = inSelectedSeat.id;
|
||||||
|
delete state.selectedSeatsObj[seatID];
|
||||||
|
const index = state.selectedSeatsArr.findIndex(arr => {
|
||||||
|
return arr[0] === inSelectedSeat.id;
|
||||||
|
});
|
||||||
|
state.selectedSeatsArr.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcOverallPrice(inVenueXML: I.VenueXML): string | undefined {
|
||||||
|
if (!state.selectedSeatsArr.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!pricescaleObj)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const seatPrice: number | undefined = getPriceByBuyertypeID(buyertypeID, pricescaleObj);
|
||||||
|
|
||||||
|
if (!seatPrice)
|
||||||
|
return;
|
||||||
|
|
||||||
|
overallPrice += seatPrice;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
state.priceOverall = overallPrice.toFixed(2);
|
||||||
|
|
||||||
|
return state.priceOverall;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPriceByBuyertypeID(inBuyertypeID: string, inPricescaleObj: I.Pricescale5) {
|
||||||
|
const price = inPricescaleObj?.buyer_type.find(arr => {
|
||||||
|
return arr.id[0] === inBuyertypeID;
|
||||||
|
})?.price[0];
|
||||||
|
|
||||||
|
if (price)
|
||||||
|
return parseFloat(price);
|
||||||
|
else
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBtnCartText() {
|
||||||
|
const numTickets = state.selectedSeatsArr.length;
|
||||||
|
let text: string = "";
|
||||||
|
|
||||||
|
console.log(numTickets);
|
||||||
|
|
||||||
|
if (state.priceOverall !== "")
|
||||||
|
numTickets === 1 ? text = `${numTickets} Ticket für €${state.priceOverall}` : text = `${numTickets} Tickets für €${state.priceOverall}`;
|
||||||
|
else
|
||||||
|
text = "0 Tickets für €0.00";
|
||||||
|
|
||||||
|
jQuery("#btnCart .fl-button-text")[0].innerText = text;
|
||||||
|
}
|
||||||
|
|
||||||
function addSeatmap(inSelector: string, inMap: string[], inRows: number[], inSeats: I.JSCSeats, inLegend: I.JSCLegend): void {
|
function addSeatmap(inSelector: string, inMap: string[], inRows: number[], inSeats: I.JSCSeats, inLegend: I.JSCLegend): void {
|
||||||
|
|
||||||
// console.log(inSeatmapInitMap);
|
// console.log(inSeatmapInitMap);
|
||||||
@@ -189,19 +385,33 @@ function addSeatmap(inSelector: string, inMap: string[], inRows: number[], inSea
|
|||||||
legend: inLegend,
|
legend: inLegend,
|
||||||
click: function () {
|
click: function () {
|
||||||
if (this.status() == 'available') {
|
if (this.status() == 'available') {
|
||||||
console.log("available");
|
const selectedSeat: I.JSCSelectedSeat = this.settings;
|
||||||
console.log(this);
|
console.log("seat selected");
|
||||||
//do some stuff, i.e. add to the cart
|
console.log(selectedSeat);
|
||||||
|
|
||||||
|
addSeatToState(inVenueXML, selectedSeat);
|
||||||
|
|
||||||
|
calcOverallPrice(inVenueXML);
|
||||||
|
setBtnCartText();
|
||||||
|
console.log(state.selectedSeatsArr);
|
||||||
|
|
||||||
return 'selected';
|
return 'selected';
|
||||||
}
|
}
|
||||||
else if (this.status() == 'selected') {
|
else if (this.status() == 'selected') {
|
||||||
console.log("selected");
|
const selectedSeat: I.JSCSelectedSeat = this.settings;
|
||||||
//seat has been vacated
|
console.log("seat unselected");
|
||||||
|
|
||||||
|
removeSeatFromState(selectedSeat);
|
||||||
|
|
||||||
|
calcOverallPrice(inVenueXML);
|
||||||
|
setBtnCartText();
|
||||||
|
console.log(state.selectedSeatsArr);
|
||||||
|
|
||||||
return 'available';
|
return 'available';
|
||||||
}
|
}
|
||||||
else if (this.status() == 'unavailable') {
|
else if (this.status() == 'unavailable') {
|
||||||
console.log("unavailable");
|
console.log("unavailable");
|
||||||
//seat has been already booked
|
|
||||||
return 'unavailable';
|
return 'unavailable';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -211,18 +421,4 @@ function addSeatmap(inSelector: string, inMap: string[], inRows: number[], inSea
|
|||||||
});
|
});
|
||||||
|
|
||||||
console.log(seatmap);
|
console.log(seatmap);
|
||||||
|
|
||||||
// //Make all available 'c' seats unavailable
|
|
||||||
// sc.find('c.available').status('unavailable');
|
|
||||||
|
|
||||||
// /*
|
|
||||||
// // Get seats with ids 2_6, 1_7 (more on ids later on)
|
|
||||||
// put them in a jQuery set and change some css
|
|
||||||
// */
|
|
||||||
// sc.get(['2_6', '1_7']).node().css({
|
|
||||||
// color: '#ffcfcf'
|
|
||||||
// });
|
|
||||||
|
|
||||||
// console.log('Seat 1_2 costs ' + sc.get('1_2').data().price + ' and is currently ' + sc.status('1_2'));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
35
client/src/types/types.d.ts
vendored
35
client/src/types/types.d.ts
vendored
@@ -1,3 +1,13 @@
|
|||||||
|
export interface State {
|
||||||
|
priceOverall: string;
|
||||||
|
selectedSeatsArr: string[][];
|
||||||
|
selectedSeatsObj: StateJSCSelectedSeats
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StateJSCSelectedSeats {
|
||||||
|
[key: string]: JSCSelectedSeat;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Inputs {
|
export interface Inputs {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
}
|
}
|
||||||
@@ -42,6 +52,7 @@ export interface InputsWithValue {
|
|||||||
venueImageSrc: string;
|
venueImageSrc: string;
|
||||||
venueImageHeight: number;
|
venueImageHeight: number;
|
||||||
venueImageWidth: number;
|
venueImageWidth: number;
|
||||||
|
ticketPurchaseUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
@@ -58,6 +69,7 @@ export interface Config {
|
|||||||
urlCSSParentStaging: string;
|
urlCSSParentStaging: string;
|
||||||
urlCSSParentMaster: string;
|
urlCSSParentMaster: string;
|
||||||
childHasVenueXML: boolean;
|
childHasVenueXML: boolean;
|
||||||
|
urlCSSjQueryUI: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
@@ -337,4 +349,27 @@ export interface JSCLegend {
|
|||||||
export interface JSCAvailability {
|
export interface JSCAvailability {
|
||||||
available_selectable_mask: string[];
|
available_selectable_mask: string[];
|
||||||
unavailable_unselectable_mask: string[];
|
unavailable_unselectable_mask: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSC seatObj settings
|
||||||
|
export interface Data {
|
||||||
|
classes: string;
|
||||||
|
seatsObj: SeatsObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Node {
|
||||||
|
[key: number]: JQuery<Node>;
|
||||||
|
length: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface JSCSelectedSeat {
|
||||||
|
status: string;
|
||||||
|
style: string;
|
||||||
|
data: Data;
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
row: number;
|
||||||
|
column: number;
|
||||||
|
character: string;
|
||||||
|
$node: Node;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user