implemented cart button
This commit is contained in:
@@ -7,12 +7,19 @@ import * as JSC from "./modules/jsc";
|
||||
import { config } from "./modules/config";
|
||||
import Utils from './modules/utils';
|
||||
import { PanzoomObject } from "@panzoom/panzoom";
|
||||
import jBox from 'jbox';
|
||||
require('jbox/dist/jBox.all.css');
|
||||
|
||||
let inputsWithValue: I.InputsWithValue;
|
||||
let seatmap: any;
|
||||
let panzoom: PanzoomObject | undefined;
|
||||
let venueXML: I.VenueXML;
|
||||
let inVenueXML: I.VenueXML;
|
||||
let seatmapXML: any;
|
||||
let state: I.State = {
|
||||
priceOverall: "",
|
||||
selectedSeatsArr: [],
|
||||
selectedSeatsObj: {}
|
||||
}
|
||||
|
||||
function messagesHandler(inE: any) {
|
||||
if (typeof (inE.data) !== 'string')
|
||||
@@ -29,19 +36,19 @@ function messagesHandler(inE: any) {
|
||||
break;
|
||||
}
|
||||
case "parent_init_sendVenueXML": {
|
||||
venueXML = data.message.map_response;
|
||||
inVenueXML = data.message.map_response;
|
||||
|
||||
// generate pricescale css classes
|
||||
const css = generatePricescaleCSS(venueXML);
|
||||
const css = generatePricescaleCSS(inVenueXML);
|
||||
Utils.inject(css, "cssCustom", "body");
|
||||
console.log(css);
|
||||
|
||||
// fill event info
|
||||
const eventInfo = XMLHelper.getEventInfo(venueXML);
|
||||
const eventInfo = XMLHelper.getEventInfo(inVenueXML);
|
||||
UI.setEventInfo(eventInfo, inputsWithValue);
|
||||
|
||||
// fill select dropdown
|
||||
const seatmapListing: I.Seatmap[] = XMLHelper.getSeatmapListing(venueXML);
|
||||
const seatmapListing: I.Seatmap[] = XMLHelper.getSeatmapListing(inVenueXML);
|
||||
console.log(seatmapListing);
|
||||
UI.setOptionSelect(seatmapListing, "dropdownSeatmap");
|
||||
|
||||
@@ -63,23 +70,63 @@ function messagesHandler(inE: any) {
|
||||
const map: string[] = JSC.generateMap(seatmapXML);
|
||||
const rows: number[] = JSC.getRows(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);
|
||||
|
||||
JSC.setUnavailableSeats(seatmapXML, seatmap);
|
||||
selectSeatsInCart();
|
||||
UI.convertLegendToDropdown("dropdownLegend");
|
||||
dropdownLegendOnChange("#dropdownLegend");
|
||||
panzoom = UI.addPanzoom("#containerSeatmapInner", ".panzoomZoomIn", ".panzoomZoomOut", "#panzoomResetZoom");
|
||||
UI.controlLoftloader("hide");
|
||||
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:
|
||||
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 {
|
||||
const venuePricescalesArr: I.Pricescale2[] = inVenueXML.venue[0].pricescales[0].pricescale;
|
||||
let cssArr: string[] = [];
|
||||
@@ -87,10 +134,12 @@ function generatePricescaleCSS(inVenueXML: I.VenueXML): string {
|
||||
venuePricescalesArr.forEach(element => {
|
||||
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`;
|
||||
if (color === "")
|
||||
color = Utils.generateRandomColor();
|
||||
// if (color === "") {
|
||||
// console.log("no default color");
|
||||
// color = Utils.generateRandomColor();
|
||||
// }
|
||||
|
||||
cssArr.push(`._${ID} { background-color: ${color}; }`);
|
||||
});
|
||||
@@ -102,9 +151,18 @@ window.addEventListener('load', function () {
|
||||
Utils.inject(config.urlJSCStaging, "js", "head");
|
||||
Utils.inject(config.urlCSSJSCStaging, "css", "body");
|
||||
Utils.inject(config.urlCSSChildStaging, "css", "body");
|
||||
Utils.inject(config.urlCSSjQueryUI, "css", "body");
|
||||
Communication.listenToMessages(messagesHandler);
|
||||
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");
|
||||
if (dropdownSeatmap) {
|
||||
dropdownSeatmap.addEventListener("change", function (this: HTMLSelectElement) {
|
||||
@@ -114,10 +172,31 @@ window.addEventListener('load', function () {
|
||||
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) {
|
||||
const dropdownLegend = jQuery(inSelector).get(0);
|
||||
dropdownLegend.addEventListener("change", function (this: HTMLSelectElement) {
|
||||
@@ -139,7 +218,6 @@ function dropdownLegendOnChange(inSelector: string) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function changeDropdownLegendBGColor(inSelector: string, inValue: string, inClassName: string) {
|
||||
let bgColor: string = "#fafafa";
|
||||
let color: string = "#5c5c5c";
|
||||
@@ -154,6 +232,124 @@ function changeDropdownLegendBGColor(inSelector: string, inValue: string, inClas
|
||||
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 {
|
||||
|
||||
// console.log(inSeatmapInitMap);
|
||||
@@ -189,19 +385,33 @@ function addSeatmap(inSelector: string, inMap: string[], inRows: number[], inSea
|
||||
legend: inLegend,
|
||||
click: function () {
|
||||
if (this.status() == 'available') {
|
||||
console.log("available");
|
||||
console.log(this);
|
||||
//do some stuff, i.e. add to the cart
|
||||
const selectedSeat: I.JSCSelectedSeat = this.settings;
|
||||
console.log("seat selected");
|
||||
console.log(selectedSeat);
|
||||
|
||||
addSeatToState(inVenueXML, selectedSeat);
|
||||
|
||||
calcOverallPrice(inVenueXML);
|
||||
setBtnCartText();
|
||||
console.log(state.selectedSeatsArr);
|
||||
|
||||
return 'selected';
|
||||
}
|
||||
else if (this.status() == 'selected') {
|
||||
console.log("selected");
|
||||
//seat has been vacated
|
||||
const selectedSeat: I.JSCSelectedSeat = this.settings;
|
||||
console.log("seat unselected");
|
||||
|
||||
removeSeatFromState(selectedSeat);
|
||||
|
||||
calcOverallPrice(inVenueXML);
|
||||
setBtnCartText();
|
||||
console.log(state.selectedSeatsArr);
|
||||
|
||||
return 'available';
|
||||
}
|
||||
else if (this.status() == 'unavailable') {
|
||||
console.log("unavailable");
|
||||
//seat has been already booked
|
||||
|
||||
return 'unavailable';
|
||||
}
|
||||
else {
|
||||
@@ -211,18 +421,4 @@ function addSeatmap(inSelector: string, inMap: string[], inRows: number[], inSea
|
||||
});
|
||||
|
||||
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'));
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user