occsn-checkout
Version:
Occasion checkout experience boilerplate component built using React-Redux and Mitragyna
1,535 lines (1,355 loc) • 108 kB
JavaScript
/*!
* 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