diff --git a/client/src/modules/cart.ts b/client/src/modules/cart.ts index 2c00d15..03c23da 100644 --- a/client/src/modules/cart.ts +++ b/client/src/modules/cart.ts @@ -40,7 +40,7 @@ export function changedDropdownBuyerType(inSelect: HTMLSelectElement, inSeatObj: calcOverallPrice(); CartButtons.setBtnCartText(); - const url = XMLHelper.generateCheckoutUrl(); + const url = generateCheckoutUrl(); Events.addRedirectCheckout(url); } @@ -73,6 +73,15 @@ export function initModalCart(): void { Events.addCartClose(); } +export function generateCheckoutUrl(): string | undefined { + if (!config.state.selectedSeatsArr.length) + return; + + const inputsWithValue = config.state.inputsWithValue!; + const selectedSeatIndexes: string = XMLHelper.generateSelectedSeatIndexes(); + return `${inputsWithValue["ticketPurchaseUrl"]}?user_context=${inputsWithValue.user_context}&pid=${inputsWithValue["pid"]}&selected_seat_indexes=${selectedSeatIndexes}&trxstate=148`; +} + function appendHTML(inCartID: string, inColor: string, inCategory: string | undefined, inSeatStr: string): void { jQuery("#cartItemHTML .fl-html").append(`
diff --git a/client/src/modules/communication.ts b/client/src/modules/communication.ts index 40ec435..777b4f8 100644 --- a/client/src/modules/communication.ts +++ b/client/src/modules/communication.ts @@ -1,5 +1,9 @@ import * as I from "../types/types"; -import * as xml from "./xmlhelper"; +import axios, { AxiosResponse } from 'axios'; +const xml2jsParser = require('xml2js').parseString; +import * as UI from "./ui"; +import { config } from "./config"; +import * as Cart from "./cart"; // rework try/catch ? export function sendMessage(inData: I.Message, inTo: string): void { @@ -22,7 +26,7 @@ export function listenToMessages(inHandler: CallableFunction): void { } export function sendXML(inUrl: string, inTo: string, inEvent: string, inFrom: string, inDate: number = Date.now()): void { - xml.getXMLPromise(inUrl).then((result: unknown): void => { + getXMLPromise(inUrl).then((result: unknown): void => { const message: I.Message = { date: inDate, from: inFrom, @@ -77,4 +81,47 @@ export function cancelCheckout(inUrl: string): void { console.log("error"); console.log(error); }); +} + +export function isValidSeatSelection(): void { + jQuery("#modalCart-overlay").hide(); + + if (!config.state.selectedSeatsArr.length) + return; + + UI.adjustUIToLoading(); + const url: string | undefined = Cart.generateCheckoutUrl(); + + const message: I.Message = { + message: { + url: url, + }, + from: "child", + event: "child_needCheckoutResponse", + date: Date.now() + }; + + sendMessage(message, "parent"); +} + +function getXMLPromise(inUrl: string): Promise { + return axios.get(inUrl) + .then((response: void | AxiosResponse) => { + return new Promise((resolve: any, reject: any) => { + const AxiosResponse = response; + if (AxiosResponse.status === 200 && AxiosResponse.headers["content-type"] === "text/xml;charset=utf-8") { + xml2jsParser(AxiosResponse.data, + { normalizeTags: true, normalize: true, mergeAttrs: true }, + (err: any, result: any) => { + if (err) + reject(err); + else + resolve(result); + }); + } + }); + }) + .catch((error) => { + console.log(error); + }); } \ No newline at end of file diff --git a/client/src/modules/events.ts b/client/src/modules/events.ts index 66068b1..5964092 100644 --- a/client/src/modules/events.ts +++ b/client/src/modules/events.ts @@ -1,7 +1,6 @@ import * as Communication from "./communication"; import * as UI from "./ui"; import { config } from "./config"; -import * as XMLHelper from "./xmlhelper"; import * as I from "../types/types"; import * as JSC from "./jsc"; import * as Cart from "./cart"; @@ -34,7 +33,7 @@ export function addModalCart(): void { if (!config.state.selectedSeatsArr.length) jBoxHelper.showJBoxNotice(`Sie haben bislang keinen Platz ausgewählt.`); else if (config.state.cartChanged) - XMLHelper.isValidSeatSelection(); + Communication.isValidSeatSelection(); else if (!config.state.cartChanged && config.state.isValidSeatSelection) UI.fadeInCartModal(); else if (!config.state.cartChanged && !config.state.isValidSeatSelection) diff --git a/client/src/modules/parser.ts b/client/src/modules/parser.ts index 44ac118..a4038e1 100644 --- a/client/src/modules/parser.ts +++ b/client/src/modules/parser.ts @@ -1,5 +1,7 @@ import * as I from "../types/types"; +import { config } from "./config"; var jQuery = require("jquery"); +import Utils from './utils'; export function getVenueLocation(): string { let spanArr: string[] = []; @@ -85,4 +87,31 @@ export function getSMAP(): string | undefined { const found: RegExpMatchArray | null = str.match(re); return found ? found[1] : undefined; +} + +export function getEventInfo(): I.EventInfo { + const venueXML: I.VenueXML = config.state.inVenueXML!; + const sectionArr: I.Section2[] = venueXML.master_config[0].section_inventory[0].section; + const eventObj: I.Event = venueXML.event[0]; + const event: I.Event = venueXML.event[0]; + const venue_config: I.VenueConfig = venueXML.venue_config[0]; + const dateObj: Date = new Date(parseInt(event.year[0]), parseInt(event.month[0]) - 1, parseInt(event.day[0]), parseInt(event.hour[0]), parseInt(event.minute[0])); + const start: string[] = [dateObj.toLocaleString(["de-DE"], { weekday: "long", day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", timeZoneName: "short" })]; + const weekday: string[] = [Utils.getDayName(dateObj, "de-DE")]; + const seats_available = sectionArr.map(item => parseInt(item.available[0])).reduce((prev, curr) => prev + curr); + + const eventExtend: I.EventExtend = { + venue_config_capacity: venue_config.capacity, + venue_config_code: venue_config.code, + venue_config_desc: venue_config.desc, + venue_config_id: venue_config.id, + venue_config_nav_image: venue_config.nav_image, + venue_config_nav_image_height: venue_config.nav_image_height, + venue_config_nav_image_width: venue_config.nav_image_width, + start: start, + weekday: weekday, + seats_available: seats_available, + }; + + return { ...eventObj, ...eventExtend }; } \ No newline at end of file diff --git a/client/src/modules/ui.ts b/client/src/modules/ui.ts index 27c72b3..4f4f035 100644 --- a/client/src/modules/ui.ts +++ b/client/src/modules/ui.ts @@ -3,6 +3,7 @@ import * as Communication from "./communication"; import { config } from "./config"; import * as Events from "./events"; import * as Panzoom from "./panzoom"; +import * as CartButtons from "./cartButtons"; export function setOptionSelect(inSeatmapListing: I.Seatmap[], inId: string): void { const seatmapDropdown: HTMLElement | null = document.getElementById(inId); @@ -78,4 +79,21 @@ export function changeVenueImage(): void { export function fadeInCartModal(): void { jQuery("#modalCart-overlay").fadeIn(300); Communication.sendEventToParent("child_hide_dialog_titlebar"); +} + +export function generatePricescaleCSS(): string { + const venueXML: I.VenueXML = config.state.inVenueXML!; + const venuePricescalesArr: I.Pricescale2[] = venueXML.venue[0].pricescales[0].pricescale; + + return venuePricescalesArr.map(arr => { + const ID: string = arr.id[0]; + let color: string = `#${arr.color[0]} !important`; // Update: Colors are always defined: fallback colors exist in system so every XML provides them + return `._${ID} { background-color: ${color}; }`; + }).join("\r\n"); +} + +export function adjustUIToLoading(): void { + CartButtons.showHideBtnCartLoading("show"); + jQuery("#modalCart i").hide(); + jQuery("#modalCart .uabb-button-text").addClass("dot-pulse"); } \ No newline at end of file diff --git a/client/src/modules/xmlhelper.ts b/client/src/modules/xmlhelper.ts index 6b3e00c..2922133 100644 --- a/client/src/modules/xmlhelper.ts +++ b/client/src/modules/xmlhelper.ts @@ -1,216 +1,70 @@ -import axios, { AxiosResponse } from 'axios'; -var xml2jsParser = require('xml2js').parseString; + import * as I from "../types/types"; -import Utils from './utils'; import { config } from "./config"; -import * as Communication from "./communication"; -import * as CartButtons from "./cartButtons"; -export function getXMLPromise(url: string): Promise { - return axios.get(url) - .then(function (response: void | AxiosResponse) { - - return new Promise(function (resolve: any, reject: any) { - const AxiosResponse = response; - if (AxiosResponse.status === 200 && AxiosResponse.headers["content-type"] === "text/xml;charset=utf-8") { - xml2jsParser(AxiosResponse.data, { normalizeTags: true, normalize: true, mergeAttrs: true }, function (err: any, result: any) { - if (err) - reject(err); - else { - resolve(result); - } - }); - } - }); - - }) - .catch(function (error) { - console.log(error); - }) -} - -export function getEventInfo(): I.EventInfo { - const venueXML = config.state.inVenueXML!; - const sectionArr = venueXML.master_config[0].section_inventory[0].section; - const eventObj: I.Event = venueXML.event[0]; - const event = venueXML.event[0]; - const venue_config = venueXML.venue_config[0]; - const dateObj: Date = new Date(parseInt(event.year[0]), parseInt(event.month[0])-1, parseInt(event.day[0]), parseInt(event.hour[0]), parseInt(event.minute[0])); - const start: string[] = [ dateObj.toLocaleString(["de-DE"], { weekday: "long", day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", timeZoneName: "short" }) ]; - const weekday = [ Utils.getDayName(dateObj, "de-DE") ]; - const seats_available = sectionArr.map(item => parseInt(item.available[0])).reduce((prev, curr) => prev + curr); - - - const eventExtend: I.EventExtend = { - venue_config_capacity: venue_config.capacity, - venue_config_code: venue_config.code, - venue_config_desc: venue_config.desc, - venue_config_id: venue_config.id, - venue_config_nav_image: venue_config.nav_image, - venue_config_nav_image_height: venue_config.nav_image_height, - venue_config_nav_image_width: venue_config.nav_image_width, - start: start, - weekday: weekday, - seats_available: seats_available, - }; - - let eventInfo: I.EventInfo = { ...eventObj, ...eventExtend }; - - return eventInfo; -} - -export function isValidSeatSelection() { - const inputsWithValue = config.state.inputsWithValue!; - console.log("checking seat selection"); - console.log(inputsWithValue); - jQuery("#modalCart-overlay").hide(); - - if (!config.state.selectedSeatsArr.length) - return; - - CartButtons.showHideBtnCartLoading("show"); - - jQuery("#modalCart i").hide(); - jQuery("#modalCart .uabb-button-text").addClass("dot-pulse"); - - 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, - }, - from: "child", - event: "child_needCheckoutResponse", - date: Date.now() - }; - Communication.sendMessage(message, "parent"); -} - -export function generateCheckoutUrl(): string | undefined { +export function processSMAP(): void { const inputsWithValue = config.state.inputsWithValue!; - console.log(inputsWithValue); - if (!config.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 (config.state.selectedSeatsArr.map(function (arr) { - return arr.join(","); - })).join("|"); -} - -export function getSectionDescBySectionID(sectionID: string): string | undefined { - const venueXML = config.state.inVenueXML!; - const sectionArr = venueXML.master_config[0].section_config[0].section; - - const sectionDesc = sectionArr.find(arr => { - return sectionID === arr.id[0]; - })?.desc[0]; - - return sectionDesc; -} - -export function processSMAP() { - const inputsWithValue = config.state.inputsWithValue!; if (!inputsWithValue.smap) return; - const smapArr = inputsWithValue.smap.split("").map(Number); + const smapArr: number[] = inputsWithValue.smap.split("").map(Number); if (!smapArr[0]) jQuery("#eventInfoCapacity").hide(); } -export function getVenuePricescalePropertyByPricescaleID(property: I.Pricescale2Properties, pricescaleID: string) { - const venueXML = config.state.inVenueXML!; +export function getSectionDescBySectionID(inSectionID: string): string | undefined { + const venueXML: I.VenueXML = config.state.inVenueXML!; + const sectionArr: I.Section[] = venueXML.master_config[0].section_config[0].section; + + return sectionArr.find(arr => inSectionID === arr.id[0])?.desc[0]; +} + +export function getVenuePricescalePropertyByPricescaleID(inProperty: I.Pricescale2Properties, inPricescaleID: string): string | undefined { + const venueXML: I.VenueXML = config.state.inVenueXML!; const venuePricescaleArr: I.Pricescale2[] = venueXML.venue[0].pricescales[0].pricescale; - return venuePricescaleArr.find(obj => { - if (obj.id[0] === pricescaleID) - return obj; - - return undefined; - })?.[property][0]; + return venuePricescaleArr.find(obj => obj.id[0] === inPricescaleID ? obj : undefined)?.[inProperty][0]; } export function getBuyerTypeCodeByBuyerTypeID(inBuyerTypeID: string): string | undefined { - const venueXML = config.state.inVenueXML!; - const venueBuyerTypeArr = venueXML.venue[0].buyer_types[0].buyer_type; - return venueBuyerTypeArr.find(arr => { - return inBuyerTypeID === arr.id[0]; - })?.code[0]; + const venueXML: I.VenueXML = config.state.inVenueXML!; + const venueBuyerTypeArr: I.BuyerType2[] = venueXML.venue[0].buyer_types[0].buyer_type; + + return venueBuyerTypeArr.find(arr => inBuyerTypeID === arr.id[0])?.code[0]; } -export 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); - - return undefined; +export function getPriceByBuyerTypeID(inBuyertypeID: string, inPricescaleObj: I.Pricescale5): number | undefined { + const price = inPricescaleObj?.buyer_type.find(arr => arr.id[0] === inBuyertypeID)?.price[0]; + return price ? parseFloat(price) : undefined; } export function getVenuePriceStructurePropertyByPricescaleID(inID: string): I.Pricescale5 | undefined { - const venueXML = config.state.inVenueXML!; + const venueXML: I.VenueXML = config.state.inVenueXML!; const venuePricescaleArr: I.Pricescale5[] = venueXML.price_structure[0].pricescale; - return venuePricescaleArr.find(obj => { - return obj.id[0] === inID; - }); -} - -export function generatePricescaleCSS(): string { - const venueXML = config.state.inVenueXML!; - const venuePricescalesArr: I.Pricescale2[] = venueXML.venue[0].pricescales[0].pricescale; - let cssArr: string[] = []; - - venuePricescalesArr.forEach(element => { - const ID: string = element.id[0]; - let color: string = `#${element.color[0]} !important`; // Update: Colors are always defined: fallback colors exist in system so every XML provides them - cssArr.push(`._${ID} { background-color: ${color}; }`); - }); - - return (cssArr.join("\r\n")); + return venuePricescaleArr.find(obj => obj.id[0] === inID); } export function getBuyerTypesByPricescaleID(inPricescaleID: string): I.TypeBuyerTypeArr[] | undefined { const buyerTypesArr: I.BuyerType3[] | undefined = findBuyerTypesArrByPricescaleID(inPricescaleID); + return buyerTypesArr ? buyerTypesArr.map(arr => [arr.id[0], arr.price[0], getBuyerTypeDesc(arr)]) : undefined; +} - if (buyerTypesArr) { - const buyerTypes: I.TypeBuyerType = buyerTypesArr.map(arr => { - const buyerTypeDesc: string | undefined = getBuyerTypeDesc(arr); - return [arr.id[0], arr.price[0], buyerTypeDesc]; - }); - - return buyerTypes; - } - else - return undefined; +export function generateSelectedSeatIndexes(): string { + return (config.state.selectedSeatsArr.map(arr => arr.join(","))).join("|"); } function findBuyerTypesArrByPricescaleID(inPricescaleID: string): I.BuyerType3[] | undefined { const venueXML: I.VenueXML = config.state.inVenueXML!; const venuePricescaleArr: I.Pricescale5[] = venueXML.price_structure[0].pricescale; - - return venuePricescaleArr.find(obj => - obj.id[0] === inPricescaleID) - ?.buyer_type; + + return venuePricescaleArr.find(obj => obj.id[0] === inPricescaleID)?.buyer_type; } function getBuyerTypeDesc(inArr: I.BuyerType3): string | undefined { const venueXML: I.VenueXML = config.state.inVenueXML!; const buyerTypeArr: I.BuyerType2[] = venueXML.venue[0].buyer_types[0].buyer_type; - return buyerTypeArr.find(obj => - obj.id[0] === inArr.id[0] ? obj.desc[0] : undefined) - ?.desc[0]; + return buyerTypeArr.find(obj => obj.id[0] === inArr.id[0] ? obj.desc[0] : undefined)?.desc[0]; } \ No newline at end of file diff --git a/client/src/seatmap.ts b/client/src/seatmap.ts index 4fb0825..d0bdca1 100644 --- a/client/src/seatmap.ts +++ b/client/src/seatmap.ts @@ -15,6 +15,7 @@ import * as BookingBtn from "./modules/bookingButton"; import * as Panzoom from "./modules/panzoom"; import * as CartButtons from "./modules/cartButtons"; import * as jBoxHelper from "./modules/jBoxHelper"; +import * as Parser from './modules/parser'; window.addEventListener('load', () => { // Inject JSC (jQuery Seat Charts) @@ -79,11 +80,11 @@ function messageHandler(inE: any) { const venueXML = config.state.inVenueXML!; // Generate pricescale css classes - const css = XMLHelper.generatePricescaleCSS(); + const css = UI.generatePricescaleCSS(); Utils.inject(css, "cssCustom", "body"); // Fill event info - const eventInfo = XMLHelper.getEventInfo(); + const eventInfo = Parser.getEventInfo(); UI.setEventInfo(eventInfo); // Fill select dropdown @@ -141,7 +142,7 @@ function messageHandler(inE: any) { else { Cart.removeCartItems(); Cart.generateCartItems(); - const url = XMLHelper.generateCheckoutUrl(); + const url = Cart.generateCheckoutUrl(); Events.addRedirectCheckout(url); UI.fadeInCartModal(); CartButtons.showHideBtnCartLoading("hide");