UNPKG

occsn-checkout

Version:

Occasion checkout experience boilerplate component built using React-Redux and Mitragyna

1,535 lines (1,355 loc) 108 kB
/*! * occsn-checkout v0.0.16 * (c) 2018-present Peak Labs LLC DBA Occasion App * Released under the MIT License. */ 'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var ActiveResource = _interopDefault(require('active-resource')); var Occasion = _interopDefault(require('occasion-sdk')); var mirrorCreator = _interopDefault(require('mirror-creator')); var React = require('react'); var React__default = _interopDefault(React); var PropTypes = _interopDefault(require('prop-types')); var ReactHtmlParser = _interopDefault(require('react-html-parser')); var reactstrap = require('reactstrap'); var classnames = _interopDefault(require('classnames')); var _ = _interopDefault(require('underscore')); var mitragyna = require('mitragyna'); var moment = _interopDefault(require('moment')); var FullCalendar = _interopDefault(require('fullcalendar-reactwrapper')); require('fullcalendar-reactwrapper/dist/css/fullcalendar.min.css'); var reactRedux = require('react-redux'); var s = _interopDefault(require('underscore.string')); var Currency = _interopDefault(require('react-currency-formatter')); var Decimal = _interopDefault(require('decimal.js-light')); var Q = _interopDefault(require('q')); var SpreedlyAPI = _interopDefault(require('spreedly')); var SquareAPI = _interopDefault(require('square')); var Immutable = _interopDefault(require('immutable')); var redux = require('redux'); var reduxDevtoolsExtension = require('redux-devtools-extension'); var thunkMiddleware = _interopDefault(require('redux-thunk')); require('bootstrap/dist/css/bootstrap.css'); function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _next(value) { step("next", value); } function _throw(err) { step("throw", err); } _next(); }); }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } var options = { token: window.OCCSN.api_key, immutable: true }; var url = window.OCCSN.host_url; if (url != undefined) { options.baseUrl = ActiveResource.prototype.Links.__constructLink(url, 'api', 'v1'); } var occsn = Occasion.Client(options); var actionTypes = mirrorCreator(['OCCSN_BOOK_ORDER_REQUEST', 'OCCSN_BOOK_ORDER_REQUEST_COMPLETE', 'OCCSN_CONSTRUCT_ORDER_REQUEST', 'OCCSN_FIND_REDEEMABLE_REQUEST', 'OCCSN_FIND_REDEEMABLE_REQUEST_COMPLETE', 'OCCSN_LOAD_PRODUCT_REQUEST', 'OCCSN_SAVE_ORDER_REQUEST', 'OCCSN_SAVE_ORDER_REQUEST_COMPLETE', 'OCCSN_SET_ORDER', 'OCCSN_SET_PRODUCT', 'OCCSN_SET_SKIP_ATTENDEES']); function constructOrder(product) { return function (dispatch) { dispatch(constructOrderRequest()); return occsn.Order.construct({ product: product, status: 'initialized' }).then(function (order) { dispatch(setOrder(order)); }); }; } function constructOrderRequest() { return { type: actionTypes.OCCSN_CONSTRUCT_ORDER_REQUEST }; } function bookOrder(order) { return ( /*#__PURE__*/ function () { var _ref = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee(dispatch) { return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: dispatch(bookOrderRequest()); _context.prev = 1; _context.next = 4; return order.update({ status: 'reserved' }); case 4: order = _context.sent; _context.next = 10; break; case 7: _context.prev = 7; _context.t0 = _context["catch"](1); order = _context.t0; case 10: dispatch(setOrder(order)); dispatch(bookOrderRequestComplete()); case 12: case "end": return _context.stop(); } } }, _callee, this, [[1, 7]]); })); return function (_x) { return _ref.apply(this, arguments); }; }() ); } function bookOrderRequest() { return { type: actionTypes.OCCSN_BOOK_ORDER_REQUEST }; } function bookOrderRequestComplete(order) { return { type: actionTypes.OCCSN_BOOK_ORDER_REQUEST_COMPLETE, order: order }; } function findRedeemable(product, code, onSuccess, onError) { return function (dispatch) { dispatch(findRedeemableRequest()); return product.redeemables().findBy({ code: code }).then(onSuccess, onError).finally(function () { dispatch(findRedeemableRequestComplete()); }); }; } function findRedeemableRequest() { return { type: actionTypes.OCCSN_FIND_REDEEMABLE_REQUEST }; } function findRedeemableRequestComplete() { return { type: actionTypes.OCCSN_FIND_REDEEMABLE_REQUEST_COMPLETE }; } function loadProduct(id) { return function (dispatch) { dispatch(loadProductRequest()); var query = occsn.Product.includes({ merchant: 'currency', venue: 'state' }).find(id); return query.then(function (product) { dispatch(setProduct(product)); dispatch(constructOrder(product)); }); }; } function loadProductRequest() { return { type: actionTypes.OCCSN_LOAD_PRODUCT_REQUEST }; } function saveOrder(order) { return ( /*#__PURE__*/ function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee2(dispatch) { return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: dispatch(saveOrderRequest()); _context2.next = 3; return order.save(); case 3: order = _context2.sent; dispatch(setOrder(order)); dispatch(saveOrderRequestComplete()); case 6: case "end": return _context2.stop(); } } }, _callee2, this); })); return function (_x2) { return _ref2.apply(this, arguments); }; }() ); } function saveOrderRequest() { return { type: actionTypes.OCCSN_SAVE_ORDER_REQUEST }; } function saveOrderRequestComplete() { return { type: actionTypes.OCCSN_SAVE_ORDER_REQUEST_COMPLETE }; } function setOrder(order) { return { type: actionTypes.OCCSN_SET_ORDER, order: order }; } function setProduct(product) { return { type: actionTypes.OCCSN_SET_PRODUCT, product: product }; } function setSkipAttendees(skipAttendees) { return { type: actionTypes.OCCSN_SET_SKIP_ATTENDEES, skipAttendees: skipAttendees }; } var Header = /*#__PURE__*/ function (_PureComponent) { _inherits(Header, _PureComponent); function Header() { _classCallCheck(this, Header); return _possibleConstructorReturn(this, (Header.__proto__ || Object.getPrototypeOf(Header)).apply(this, arguments)); } _createClass(Header, [{ key: "render", value: function render() { var product = this.props.product; var merchant = product.merchant(); var venue = product.venue(); return React__default.createElement("section", null, product.image.url ? React__default.createElement("section", { style: { maxHeight: '360px', overflow: 'hidden' } }, React__default.createElement("img", { style: { width: '100%' }, src: product.image.url })) : null, React__default.createElement(reactstrap.Jumbotron, null, React__default.createElement(reactstrap.Row, null, React__default.createElement(reactstrap.Col, { className: "venue", sm: "3" }, React__default.createElement("h3", null, venue.name), React__default.createElement("p", null, venue.address, ", ", venue.city, ", ", venue.state().code, " ", venue.zip)), React__default.createElement(reactstrap.Col, { sm: "9" }, React__default.createElement("h2", null, merchant.name), React__default.createElement("hr", null), React__default.createElement("section", { className: "product" }, React__default.createElement("h1", null, product.title), React__default.createElement("span", null, ReactHtmlParser(product.description))))))); } }]); return Header; }(React.PureComponent); _defineProperty(Header, "propTypes", { product: PropTypes.instanceOf(occsn.Product) }); var actionTypes$1 = mirrorCreator(['OCCSN_LOAD_PRODUCT_TIME_SLOTS_REQUEST', 'OCCSN_SET_ACTIVE_TIME_SLOTS_COLLECTION', 'OCCSN_SET_TIME_SLOTS_FROM_CALENDAR']); function loadProductCalendar(product) { return function (dispatch) { dispatch(loadProductTimeSlotsRequest()); return product.constructCalendar(product.firstTimeSlotStartsAt.clone().startOf('month')).then(function (timeSlots) { dispatch(setActiveTimeSlotsCollection(timeSlots)); }); }; } function loadProductTimeSlots(product) { return function (dispatch) { dispatch(loadProductTimeSlotsRequest()); var query = product.timeSlots().includes({ product: 'merchant' }).where({ status: 'bookable' }).all(); return query.then(function (timeSlots) { dispatch(setActiveTimeSlotsCollection(timeSlots)); }); }; } function loadProductTimeSlotsRequest() { return { type: actionTypes$1.OCCSN_LOAD_PRODUCT_TIME_SLOTS_REQUEST }; } function setActiveTimeSlotsCollection(timeSlots) { return { type: actionTypes$1.OCCSN_SET_ACTIVE_TIME_SLOTS_COLLECTION, timeSlots: timeSlots }; } function setTimeSlotsFromCalendar(timeSlots) { return { type: actionTypes$1.OCCSN_SET_TIME_SLOTS_FROM_CALENDAR, timeSlots: timeSlots }; } var TimeSlotsSelector = /*#__PURE__*/ function (_React$Component) { _inherits(TimeSlotsSelector, _React$Component); function TimeSlotsSelector() { var _this; _classCallCheck(this, TimeSlotsSelector); _this = _possibleConstructorReturn(this, (TimeSlotsSelector.__proto__ || Object.getPrototypeOf(TimeSlotsSelector)).call(this)); _.bindAll(_assertThisInitialized(_this), ['selectTimeSlot']); _this.state = { toolTips: {} }; return _this; } _createClass(TimeSlotsSelector, [{ key: "selectTimeSlot", value: function selectTimeSlot(timeSlot) { var _this$props = this.props, onSelect = _this$props.onSelect, subject = _this$props.subject; var newSubject = subject.assignAttributes({ timeSlots: [timeSlot] }); onSelect(newSubject); } }, { key: "toggleToolTip", value: function toggleToolTip(id) { var _this2 = this; return function () { var toolTips = _this2.state.toolTips; toolTips[id] = !toolTips[id]; _this2.setState({ toolTips: toolTips }); }; } }, { key: "render", value: function render() { var _this3 = this; var _this$props2 = this.props, calendar = _this$props2.calendar, disabled = _this$props2.disabled, timeSlots = _this$props2.timeSlots, showAvailability = _this$props2.showAvailability, subject = _this$props2.subject; var formatProps = this.context.formatProps; var customControlInputClassNames = classnames('custom-control-input', { 'is-invalid': !subject.errors().forField('timeSlots').empty() }); var timeSlotFormat; if (calendar) { timeSlotFormat = formatProps.calendarTimeSlotsSelector || 'LT'; } else { timeSlotFormat = formatProps.calendarTimeSlotsSelector || 'LLLL'; } return React__default.createElement("section", { className: "time-slots-selector" }, React__default.createElement("section", { className: "time-slots-selector-buttons" }, timeSlots.map(function (timeSlot) { return React__default.createElement("span", null, React__default.createElement(reactstrap.Button, { className: subject.timeSlots().target().include(timeSlot) ? 'active' : '', color: "primary", disabled: disabled, id: 'timeSlot-' + timeSlot.id.replace(/~/g, ''), key: timeSlot.id, onClick: function onClick() { return _this3.selectTimeSlot(timeSlot); }, outline: true }, timeSlot.startsAt.format(timeSlotFormat)), showAvailability ? React__default.createElement(reactstrap.Tooltip, { placement: "bottom", isOpen: _this3.state.toolTips[timeSlot.id], target: 'timeSlot-' + timeSlot.id.replace(/~/g, ''), toggle: _this3.toggleToolTip(timeSlot.id) }, timeSlot.spotsAvailable, " open spots") : null); }).toArray()), React__default.createElement("section", { className: "time-slots-selector-errors custom-control" }, React__default.createElement("div", { className: customControlInputClassNames }), React__default.createElement(mitragyna.ErrorsFor, { component: reactstrap.FormFeedback, field: "timeSlots" }))); } }]); return TimeSlotsSelector; }(React__default.Component); _defineProperty(_defineProperty(TimeSlotsSelector, "propTypes", { calendar: PropTypes.bool, disabled: PropTypes.bool, onSelect: PropTypes.func.isRequired, subject: PropTypes.instanceOf(occsn.Order).isRequired, showAvailability: PropTypes.bool, timeSlots: PropTypes.shape({ __collection: PropTypes.arrayOf(PropTypes.instanceOf(occsn.TimeSlot)) }).isRequired }), "contextTypes", { formatProps: PropTypes.object }); var Calendar = /*#__PURE__*/ function (_PureComponent) { _inherits(Calendar, _PureComponent); function Calendar() { var _this; _classCallCheck(this, Calendar); _this = _possibleConstructorReturn(this, (Calendar.__proto__ || Object.getPrototypeOf(Calendar)).call(this)); _.bindAll(_assertThisInitialized(_this), 'dateClicked'); return _this; } _createClass(Calendar, [{ key: "dateClicked", value: function dateClicked(selectedDate) { var _this$props = this.props, calendarTimeSlots = _this$props.calendarTimeSlots, onDateSelect = _this$props.onDateSelect; var timeSlotsForDay = calendarTimeSlots.detect(function (date) { return date.day.clone().utc().isSame(selectedDate, 'day'); }).timeSlots; if (!timeSlotsForDay.empty()) onDateSelect(timeSlotsForDay); } }, { key: "render", value: function render() { var _this2 = this; var calendarTimeSlots = this.props.calendarTimeSlots; var events = calendarTimeSlots.map(function (day) { return day.timeSlots.map(function (timeSlot) { return { start: timeSlot.startsAt.format(), allDay: true, rendering: 'background' }; }).toArray(); }).flatten().toArray(); return React__default.createElement("section", { className: "calendar" }, React__default.createElement(FullCalendar, { header: false, dayClick: this.dateClicked, defaultDate: calendarTimeSlots.first().day, events: events, fixedWeekCount: 5, ref: function ref(r) { return _this2.fullCalendar = r; } })); } }]); return Calendar; }(React.PureComponent); _defineProperty(Calendar, "propTypes", { calendarTimeSlots: PropTypes.shape({ __collection: PropTypes.arrayOf(PropTypes.shape({ day: PropTypes.instanceOf(moment), timeSlots: PropTypes.shape({ __collection: PropTypes.arrayOf(PropTypes.instanceOf(occsn.TimeSlot)) }) })) }).isRequired, onDateSelect: PropTypes.func.isRequired }); var Paginator = /*#__PURE__*/ function (_PureComponent) { _inherits(Paginator, _PureComponent); function Paginator() { var _this; _classCallCheck(this, Paginator); _this = _possibleConstructorReturn(this, (Paginator.__proto__ || Object.getPrototypeOf(Paginator)).call(this)); _.bindAll(_assertThisInitialized(_this), 'nextClicked', 'prevClicked'); return _this; } _createClass(Paginator, [{ key: "nextClicked", value: function nextClicked() { var _this$props = this.props, onChange = _this$props.onChange, timeSlotsCollection = _this$props.timeSlotsCollection; timeSlotsCollection.nextPage().then(function (nextTimeSlotsCollection) { onChange(nextTimeSlotsCollection); }); } }, { key: "prevClicked", value: function prevClicked() { var _this$props2 = this.props, onChange = _this$props2.onChange, timeSlotsCollection = _this$props2.timeSlotsCollection; timeSlotsCollection.prevPage().then(function (prevTimeSlotsCollection) { onChange(prevTimeSlotsCollection); }); } }, { key: "render", value: function render() { var _this$props3 = this.props, className = _this$props3.className, timeSlotsCollection = _this$props3.timeSlotsCollection; return React__default.createElement("section", { className: "time-slots-paginator" }, React__default.createElement(reactstrap.Pagination, { className: className }, React__default.createElement(reactstrap.PaginationItem, { disabled: !timeSlotsCollection.hasPrevPage() }, React__default.createElement(reactstrap.PaginationLink, { previous: true, onClick: this.prevClicked })), React__default.createElement(reactstrap.PaginationItem, { disabled: !timeSlotsCollection.hasNextPage() }, React__default.createElement(reactstrap.PaginationLink, { next: true, onClick: this.nextClicked })))); } }]); return Paginator; }(React.PureComponent); _defineProperty(Paginator, "propTypes", { className: PropTypes.string.isRequired, onChange: PropTypes.func.isRequired, timeSlotsCollection: PropTypes.shape({ __collection: PropTypes.arrayOf(PropTypes.any) }).isRequired }); function stateToProps(state) { return { data: { product: state.$$appStore.get('product'), activeTimeSlotsCollection: state.$$calendarStore.get('activeTimeSlotsCollection'), timeSlotsFromCalendar: state.$$calendarStore.get('timeSlotsFromCalendar') } }; } // Bind relevant action creators and map them to properties function dispatchToProps(dispatch) { return { actions: { loadProductCalendar: function loadProductCalendar$$1(product) { return dispatch(loadProductCalendar(product)); }, loadProductTimeSlots: function loadProductTimeSlots$$1(product) { return dispatch(loadProductTimeSlots(product)); }, saveOrder: function saveOrder$$1(order) { return dispatch(saveOrder(order)); }, setOrder: function setOrder$$1(order) { return dispatch(setOrder(order)); }, setActiveTimeSlotsCollection: function setActiveTimeSlotsCollection$$1(timeSlots) { return dispatch(setActiveTimeSlotsCollection(timeSlots)); }, setTimeSlotsFromCalendar: function setTimeSlotsFromCalendar$$1(timeSlots) { return dispatch(setTimeSlotsFromCalendar(timeSlots)); } } }; } var TimeSlotsContainer = /*#__PURE__*/ function (_React$Component) { _inherits(TimeSlotsContainer, _React$Component); function TimeSlotsContainer() { var _this; _classCallCheck(this, TimeSlotsContainer); _this = _possibleConstructorReturn(this, (TimeSlotsContainer.__proto__ || Object.getPrototypeOf(TimeSlotsContainer)).call(this)); _.bindAll(_assertThisInitialized(_this), 'onDateSelect', 'onTimeSelect'); return _this; } _createClass(TimeSlotsContainer, [{ key: "componentDidMount", value: function componentDidMount() { var _this$props = this.props, actions = _this$props.actions, data = _this$props.data, order = _this$props.order; switch (data.product.timeSlotView) { case 'calendar': actions.loadProductCalendar(data.product); break; case 'list': if (data.product.requiresTimeSlotSelection) actions.loadProductTimeSlots(data.product); break; } if (data.product.sellsSessions) { actions.setActiveTimeSlotsCollection(order.timeSlots().target().clone()); } } }, { key: "onDateSelect", value: function onDateSelect(timeSlotsFromCalendar) { var actions = this.props.actions; var callbackProps = this.context.callbackProps; if (callbackProps.onDateSelect) callbackProps.onDateSelect(timeSlotsFromCalendar); actions.setTimeSlotsFromCalendar(timeSlotsFromCalendar); } }, { key: "onTimeSelect", value: function onTimeSelect(order) { var actions = this.props.actions; var callbackProps = this.context.callbackProps; if (callbackProps.onTimeSelect) callbackProps.onTimeSelect(order); actions.setOrder(order); actions.saveOrder(order); } }, { key: "render", value: function render() { var data = this.props.data; return React__default.createElement("section", { className: "time-slots" }, data.activeTimeSlotsCollection.empty() ? this.renderLoadingScreen() : this.renderTimeSlotsScreen()); } }, { key: "renderLoadingScreen", value: function renderLoadingScreen() { var componentProps = this.context.componentProps; var loadingComponent; if (componentProps.timeSlotsLoading) { loadingComponent = React__default.createElement(componentProps.timeSlotsLoading); } return React__default.createElement("section", { className: "time-slots-loading" }, loadingComponent); } }, { key: "renderTimeSlotsScreen", value: function renderTimeSlotsScreen() { var _this$props2 = this.props, actions = _this$props2.actions, data = _this$props2.data, order = _this$props2.order; switch (data.product.timeSlotView) { case 'calendar': return React__default.createElement("section", { className: "calendar-view" }, React__default.createElement(reactstrap.Row, null, React__default.createElement(reactstrap.Col, { xs: "9" }, React__default.createElement("h3", null, data.activeTimeSlotsCollection.first().day.format('MMMM YYYY'))), React__default.createElement(reactstrap.Col, { xs: "3" }, React__default.createElement(Paginator, { className: "float-right", onChange: actions.setActiveTimeSlotsCollection, timeSlotsCollection: data.activeTimeSlotsCollection }))), React__default.createElement(Calendar, { onDateSelect: this.onDateSelect, calendarTimeSlots: data.activeTimeSlotsCollection }), React__default.createElement("a", { name: "time-slots-selector", id: "time-slots-selector-anchor" }), data.timeSlotsFromCalendar.first() ? React__default.createElement("h3", { className: "calendar-date-selected" }, data.timeSlotsFromCalendar.first().startsAt.format('dddd, MMMM Do')) : null, React__default.createElement(TimeSlotsSelector, { calendar: true, onSelect: this.onTimeSelect, showAvailability: data.product.showOccurrenceAvailability, subject: order, timeSlots: data.timeSlotsFromCalendar })); case 'list': return React__default.createElement("section", { className: "list-view" }, data.product.sellsSessions ? React__default.createElement("p", null, "Sessions are purchased together") : null, React__default.createElement("a", { name: "time-slots-selector", id: "time-slots-selector-anchor" }), React__default.createElement(TimeSlotsSelector, { disabled: data.product.sellsSessions, onSelect: this.onTimeSelect, showAvailability: data.product.showOccurrenceAvailability, subject: order, timeSlots: data.activeTimeSlotsCollection }), !data.product.sellsSessions ? React__default.createElement(reactstrap.Row, null, React__default.createElement(reactstrap.Col, { xs: { offset: "9" } }), React__default.createElement(reactstrap.Col, { xs: "3" }, React__default.createElement(Paginator, { className: "float-right", onChange: actions.setActiveTimeSlotsCollection, timeSlotsCollection: data.activeTimeSlotsCollection }))) : null); } } }]); return TimeSlotsContainer; }(React__default.Component); // See https://github.com/reactjs/react-redux/blob/master/docs/api.md#examples _defineProperty(_defineProperty(TimeSlotsContainer, "propTypes", { actions: PropTypes.object.isRequired, data: PropTypes.object.isRequired, order: PropTypes.instanceOf(occsn.Order), onSelect: PropTypes.func }), "contextTypes", { callbackProps: PropTypes.object, componentProps: PropTypes.object }); var TimeSlotsContainer$1 = reactRedux.connect(stateToProps, dispatchToProps)(TimeSlotsContainer); var Attendee = /*#__PURE__*/ function (_PureComponent) { _inherits(Attendee, _PureComponent); function Attendee() { _classCallCheck(this, Attendee); return _possibleConstructorReturn(this, (Attendee.__proto__ || Object.getPrototypeOf(Attendee)).apply(this, arguments)); } _createClass(Attendee, [{ key: "render", value: function render() { var _this$props = this.props, indexOf = _this$props.indexOf, questions = _this$props.questions; return React__default.createElement(reactstrap.Card, { className: "attendee-container" }, React__default.createElement(reactstrap.CardBody, { className: "attendee" }, React__default.createElement(reactstrap.CardTitle, { className: "attendee-title" }, "Attendee ", indexOf + 1), questions.map(function (q) { return React__default.createElement(reactstrap.FormGroup, { className: "attendee-input-container" }, React__default.createElement(reactstrap.Label, { "for": 'attendee-' + indexOf + '-' + q }, s.humanize(q)), React__default.createElement(mitragyna.Field, { type: "text", name: q, id: 'attendee-' + indexOf + '-' + q, component: reactstrap.Input, invalidClassName: "is-invalid" })); }).toArray())); } }]); return Attendee; }(React.PureComponent); _defineProperty(Attendee, "propTypes", { indexOf: PropTypes.number.isRequired, questions: PropTypes.shape({ __collection: PropTypes.arrayOf(PropTypes.string) }).isRequired, subject: PropTypes.instanceOf(occsn.Attendee).isRequired }); var Attendees = /*#__PURE__*/ function (_React$Component) { _inherits(Attendees, _React$Component); function Attendees() { var _this; _classCallCheck(this, Attendees); _this = _possibleConstructorReturn(this, (Attendees.__proto__ || Object.getPrototypeOf(Attendees)).call(this)); _.bindAll(_assertThisInitialized(_this), 'toggleSkipAttendees'); return _this; } _createClass(Attendees, [{ key: "toggleSkipAttendees", value: function toggleSkipAttendees(e) { var setSkipAttendees = this.props.setSkipAttendees; setSkipAttendees(e.target.checked); } }, { key: "render", value: function render() { var _this$props = this.props, questions = _this$props.questions, skipAttendees = _this$props.skipAttendees, subject = _this$props.subject; return React__default.createElement("section", { className: "attendees" }, React__default.createElement("div", { className: "skip-attendees" }, React__default.createElement(reactstrap.FormGroup, { check: true }, React__default.createElement(reactstrap.Label, { check: true, "for": "toggleAttendees" }, React__default.createElement(reactstrap.Input, { type: "checkbox", id: "toggleAttendees", name: "toggleAttendees", checked: skipAttendees, onChange: this.toggleSkipAttendees }), "Skip attendees for now"))), !skipAttendees ? React__default.createElement(mitragyna.Collection, { component: Attendee, componentProps: { questions: questions }, reflection: "attendees", subject: subject.attendees() }) : null); } }]); return Attendees; }(React__default.Component); _defineProperty(Attendees, "propTypes", { questions: PropTypes.shape({ __collection: PropTypes.arrayOf(PropTypes.string) }).isRequired, setSkipAttendees: PropTypes.func, skipAttendees: PropTypes.bool, subject: PropTypes.instanceOf(occsn.Order) }); var Customer = /*#__PURE__*/ function (_PureComponent) { _inherits(Customer, _PureComponent); function Customer() { _classCallCheck(this, Customer); return _possibleConstructorReturn(this, (Customer.__proto__ || Object.getPrototypeOf(Customer)).apply(this, arguments)); } _createClass(Customer, [{ key: "render", value: function render() { return React__default.createElement("section", { className: "customer" }, React__default.createElement(reactstrap.FormGroup, { className: "customer-email-form-group" }, React__default.createElement(reactstrap.Label, { "for": "email" }, "Email*"), React__default.createElement(mitragyna.Field, { className: "customer-email-field", type: "email", name: "email", id: "email", component: reactstrap.Input, invalidClassName: "is-invalid" }), React__default.createElement(mitragyna.ErrorsFor, { className: "customer-email-errors", component: reactstrap.FormFeedback, field: "email" })), React__default.createElement(reactstrap.FormGroup, { className: "customer-first-name-form-group" }, React__default.createElement(reactstrap.Label, { "for": "firstName" }, "First Name*"), React__default.createElement(mitragyna.Field, { className: "customer-first-name-field", type: "text", name: "firstName", id: "firstName", component: reactstrap.Input, invalidClassName: "is-invalid" }), React__default.createElement(mitragyna.ErrorsFor, { className: "customer-first-name-errors", component: reactstrap.FormFeedback, field: "firstName" })), React__default.createElement(reactstrap.FormGroup, { className: "customer-last-name-form-group" }, React__default.createElement(reactstrap.Label, { "for": "lastName" }, "Last Name*"), React__default.createElement(mitragyna.Field, { className: "customer-last-name-field", type: "text", name: "lastName", id: "lastName", component: reactstrap.Input, invalidClassName: "is-invalid" }), React__default.createElement(mitragyna.ErrorsFor, { className: "customer-last-name-errors", component: reactstrap.FormFeedback, field: "lastName" })), React__default.createElement(reactstrap.FormGroup, { className: "customer-zip-form-group" }, React__default.createElement(reactstrap.Label, { "for": "zip" }, "Zip Code*"), React__default.createElement(mitragyna.Field, { className: "customer-zip-field", type: "text", name: "zip", id: "zip", component: reactstrap.Input, invalidClassName: "is-invalid" }), React__default.createElement(mitragyna.ErrorsFor, { className: "customer-zip-errors", component: reactstrap.FormFeedback, field: "zip" }))); } }]); return Customer; }(React.PureComponent); _defineProperty(Customer, "propTypes", { subject: PropTypes.instanceOf(occsn.Customer) }); var MissingAnswers = /*#__PURE__*/ function (_PureComponent) { _inherits(MissingAnswers, _PureComponent); function MissingAnswers() { var _this; _classCallCheck(this, MissingAnswers); _this = _possibleConstructorReturn(this, (MissingAnswers.__proto__ || Object.getPrototypeOf(MissingAnswers)).call(this)); _.bindAll(_assertThisInitialized(_this), 'empty', 'missingRequiredAnswers'); return _this; } _createClass(MissingAnswers, [{ key: "missingRequiredAnswers", value: function missingRequiredAnswers(override) { var order = this.props.order; if (override) order = override; return order.answers().target().select(function (a) { return a.question().required && (a.question().optionable && !a.option() || !a.question().optionable && !a.value) || a.question().formControl == 'waiver' && !a.value; }); } }, { key: "empty", value: function empty() { return this.missingRequiredAnswers().empty(); } }, { key: "render", value: function render() { if (this.empty()) { return null; } else { return React__default.createElement(reactstrap.Alert, { color: "secondary", className: "missing-answers" }, React__default.createElement("p", { className: "missing-answers-text" }, "Please complete the following fields:"), React__default.createElement("ul", { className: "missing-answers-list" }, this.missingRequiredAnswers().map(function (a) { return React__default.createElement("li", { className: "missing-answer" }, a.question().title); }).toArray())); } } }]); return MissingAnswers; }(React.PureComponent); _defineProperty(MissingAnswers, "propTypes", { order: PropTypes.instanceOf(occsn.Order) }); var Pricing = /*#__PURE__*/ function (_PureComponent) { _inherits(Pricing, _PureComponent); function Pricing() { _classCallCheck(this, Pricing); return _possibleConstructorReturn(this, (Pricing.__proto__ || Object.getPrototypeOf(Pricing)).apply(this, arguments)); } _createClass(Pricing, [{ key: "render", value: function render() { var order = this.props.order; var rows = []; var currency = order.product().merchant().currency().name; var displaySubtotal = false; if (!_.isNull(order.coupon())) { displaySubtotal = true; rows.push(React__default.createElement("p", { className: "coupon-discount" }, React__default.createElement("span", null, "Coupon Discount: "), React__default.createElement(Currency, { currency: currency, quantity: order.couponAmount.neg().toNumber() }))); } if (Decimal(order.taxPercentage).toNumber() > 0.0) { displaySubtotal = true; rows.push(React__default.createElement("p", { className: "tax" }, React__default.createElement("span", null, "Tax (", order.taxPercentage, "%): "), React__default.createElement(Currency, { currency: currency, quantity: order.tax }))); } if (displaySubtotal) { rows.unshift(React__default.createElement("p", { className: "subtotal" }, React__default.createElement("span", null, "Subtotal: "), React__default.createElement(Currency, { currency: currency, quantity: order.subtotal }))); } rows.push(React__default.createElement("p", { className: "total" }, "Total: ", React__default.createElement(Currency, { currency: currency, quantity: order.price }))); if (order.giftCardAmount && !order.giftCardAmount.isZero()) { rows.push(React__default.createElement("p", { className: "gift-card-amount" }, React__default.createElement("span", null, "Gift Cards: "), React__default.createElement(Currency, { currency: currency, quantity: order.giftCardAmount.neg().toNumber() })), React__default.createElement("p", { className: "outstanding-balance" }, React__default.createElement("span", null, "Balance due today: "), React__default.createElement(Currency, { currency: currency, quantity: order.outstandingBalance.toNumber() }))); } return React__default.createElement("section", { className: "total-due" }, React__default.createElement("section", { className: "pricing" }, React__default.createElement("section", { className: "pricing-list" }, rows))); } }]); return Pricing; }(React.PureComponent); _defineProperty(Pricing, "propTypes", { order: PropTypes.instanceOf(occsn.Order) }); var PaymentServiceProvider = /*#__PURE__*/ function (_PureComponent) { _inherits(PaymentServiceProvider, _PureComponent); function PaymentServiceProvider() { var _this; _classCallCheck(this, PaymentServiceProvider); _this = _possibleConstructorReturn(this, (PaymentServiceProvider.__proto__ || Object.getPrototypeOf(PaymentServiceProvider)).call(this)); _this.reset(); _.bindAll(_assertThisInitialized(_this), 'buildPaymentMethod', 'initializeForm', 'tokenizePaymentMethodData', 'reset'); return _this; } _createClass(PaymentServiceProvider, [{ key: "componentDidMount", value: function componentDidMount() { this.initializeForm(); } }, { key: "buildPaymentMethod", value: function buildPaymentMethod() { this.reset(); this.tokenizePaymentMethodData(); return this.paymentMethodDeferred.promise; } // Initializes the iFrame form that the 3rd party PSP provides for their PCI-compliant service }, { key: "initializeForm", value: function initializeForm() { throw 'initializeForm must be defined by subclasses'; } // Sends the data contained the payment method form to the 3rd party PSP }, { key: "tokenizePaymentMethodData", value: function tokenizePaymentMethodData() { throw 'tokenizePaymentMethodData must be defined by subclasses'; } }, { key: "reset", value: function reset() { this.paymentMethodDeferred = Q.defer(); } }]); return PaymentServiceProvider; }(React.PureComponent); _defineProperty(PaymentServiceProvider, "propTypes", { order: PropTypes.instanceOf(occsn.Order) }); var Cash = /*#__PURE__*/ function (_PaymentServiceProvid) { _inherits(Cash, _PaymentServiceProvid); function Cash() { _classCallCheck(this, Cash); return _possibleConstructorReturn(this, (Cash.__proto__ || Object.getPrototypeOf(Cash)).apply(this, arguments)); } _createClass(Cash, [{ key: "initializeForm", value: function initializeForm() {} }, { key: "render", value: function render() { return React__default.createElement("section", { className: "cash-container" }, React__default.createElement(reactstrap.Alert, { color: "warning", className: "cash" }, "No payment required at this time. Payment will be collected at the venue.")); } }]); return Cash; }(PaymentServiceProvider); var Spreedly = /*#__PURE__*/ function (_PaymentServiceProvid) { _inherits(Spreedly, _PaymentServiceProvid); function Spreedly() { var _this; _classCallCheck(this, Spreedly); _this = _possibleConstructorReturn(this, (Spreedly.__proto__ || Object.getPrototypeOf(Spreedly)).call(this)); _.bindAll(_assertThisInitialized(_this), 'handleChange'); _this.state = { month: null, full_name: null, year: null }; return _this; } // Initializes the iFrame using the global SpreedlyAPI object imported as a separate script // @note Called on componentDidMount // @see PaymentServiceProvider#componentDidMount _createClass(Spreedly, [{ key: "initializeForm", value: function initializeForm() { var _this2 = this; SpreedlyAPI.init(global.OCCSN.spreedly_key, { "numberEl": "spreedly-number", "cvvEl": "spreedly-cvv" }); var defaultInputStyle = 'display: block;' + ' width: 80%;' + ' padding: 0.375rem 0.75rem;' + ' font-size: 1rem;' + ' line-height: 1.5;' + ' color: #495057;' + ' background-color: #fff;' + ' background-clip: padding-box;' + ' border: 1px solid #ced4da;' + ' border-radius: 0.25rem;' + ' transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out'; var focusInputStyle = 'color: #495057;' + ' background-color: #fff;' + ' border-color: #80bdff;' + ' outline: 0;' + ' box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25)'; SpreedlyAPI.on("ready", function () { SpreedlyAPI.setFieldType("number", "text"); SpreedlyAPI.setNumberFormat("prettyFormat"); SpreedlyAPI.setPlaceholder("number", "•••• •••• •••• ••••"); SpreedlyAPI.setPlaceholder("cvv", "•••"); SpreedlyAPI.setStyle("number", defaultInputStyle); SpreedlyAPI.setStyle("cvv", defaultInputStyle); }); SpreedlyAPI.on('fieldEvent', function (name, type, activeEl, inputProperties) { if (type == 'focus') { SpreedlyAPI.setStyle(name, focusInputStyle); } if (type == 'blur') { SpreedlyAPI.setStyle(name, defaultInputStyle); } }); SpreedlyAPI.on('errors', function (errors) { console.log(errors); _this2.paymentMethodDeferred.reject(_.map(errors, function (error) { return ['creditCard.' + s.camelize(error.attribute, true), error.key.replace('errors.', ''), error.message]; })); }); SpreedlyAPI.on('paymentMethod', function (token) { _this2.paymentMethodDeferred.resolve(occsn.CreditCard.build({ id: token })); }); } // Triggers paymentMethod event }, { key: "tokenizePaymentMethodData", value: function tokenizePaymentMethodData() { SpreedlyAPI.tokenizeCreditCard(this.state); } }, { key: "handleChange", value: function handleChange(name, e) { this.setState(_defineProperty({}, name, e.target.value)); } }, { key: "render", value: function render() { var _this3 = this; var order = this.props.order; return React__default.createElement("section", { className: "spreedly-container" }, React__default.createElement(reactstrap.FormGroup, { className: "spreedly-full-name" }, React__default.createElement("label", null, "Name On Card"), React__default.createElement(reactstrap.Input, { type: "text", id: "full_name", name: "full_name", placeholder: "Name On Card", onChange: function onChange(e) { return _this3.handleChange('full_name', e); }, className: order.errors().forField('creditCard.firstName').empty() && order.errors().forField('creditCard.lastName').empty() ? '' : 'is-invalid' }), React__default.createElement(mitragyna.ErrorsFor, { className: "spreedly-first-name-errors", component: reactstrap.FormFeedback, field: "creditCard.firstName" }), React__default.createElement(mitragyna.ErrorsFor, { className: "spreedly-last-name-errors", component: reactstrap.FormFeedback, field: "creditCard.lastName" })), React__default.createElement(reactstrap.FormGroup, { className: "spreedly-card-number" }, React__default.createElement(reactstrap.Label, null, "Credit Card Number"), React__default.createElement("div", { "class": "custom-file" }, React__default.createElement("div", { className: "custom-file-input is-invalid", style: { opacity: 1 } }, React__default.createElement("div", { id: "spreedly-number", style: { height: '48px' } })), React__default.createElement(mitragyna.ErrorsFor, { className: "spreedly-card-number-errors", component: reactstrap.FormFeedback, field: "creditCard.number" }))), React__default.createElement(reactstrap.FormGroup, { className: "spreedly-expiration-cvv" }, React__default.createElement(reactstrap.Row, null, React__default.createElement(reactstrap.Col, { className: "spreedly-expiration", xs: "6" }, React__default.createElement(reactstrap.Label, null, "Expiration Date"), React__default.createElement(reactstrap.Row, null, React__default.createElement(reactstrap.Col, { xs: "6" }, React__default.createElement(reactstrap.Input, { type: "text", id: "month", name: "month", maxlength: "2", placeholder: "MM", onChange: function onChange(e) { return _this3.handleChange('month', e); }, className: order.errors().forField('creditCard.year').empty() ? '' : 'is-invalid' }), React__default.createElement(mitragyna.ErrorsFor, { className: "spreedly-expiration-month-errors", component: reactstrap.FormFeedback, field: "creditCard.month" })), React__default.createElement(reactstrap.Col, { xs: "6" }, React__default.createElement(reactstrap.Input, { type: "text", id: "year", name: "year", maxlength: "4", placeholder: "YYYY", onChange: function onChange(e) { return _this3.handleChange('year', e); }, className: order.errors().forField('creditCard.year').empty() ? '' : 'is-invalid' }), React__default.createElement(mitragyna.ErrorsFor, { className: "spreedly-expiration-year-errors", component: reactstrap.FormFeedback, field: "creditCard.year" })))), React__default.createElement(reactstrap.Col, { className: "spreedly-cvv", xs: "3" }, React__default.createElement(reactstrap.Label, null, "CVV"), React__default.createElement("div", { id: "spreedly-cvv", style: { height: '48px' } }))))); } }]); return Spreedly; }(PaymentServiceProvider); var Square = /*#__PURE__*/ function (_PaymentServiceProvid) { _inherits(Square, _PaymentServiceProvid); function Square() { _classCallCheck(this, Square); return _possibleConstructorRe