UNPKG

@open-tender/cloud

Version:

A library of hooks, reducers, utility functions, and types for use with Open Tender applications that utilize our cloud-based Order API.

529 lines (528 loc) 24.3 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.selectMenuSlug = exports.selectCartIds = exports.selectOrderLimits = exports.selectCanOrder = exports.selectCartCounts = exports.selectCartTotal = exports.selectCartQuantity = exports.selectOrder = exports.selectTimezone = exports.selectAlert = exports.updateOrder = exports.setCurrentVendor = exports.checkout = exports.setTable = exports.setServiceType = exports.setRevenueCenter = exports.setRequestedAt = exports.setPrepType = exports.setOrderType = exports.setOrderServiceType = exports.setOrderId = exports.setMenuVars = exports.setDeviceType = exports.setCurrentItem = exports.setCurrentCategory = exports.setCurbside = exports.setCart = exports.setAlert = exports.setAddress = exports.resetRevenueCenter = exports.resetOrderType = exports.resetMessages = exports.resetLocation = exports.resetCart = exports.resetAlert = exports.removeMessage = exports.removeItemFromCart = exports.incrementItemInCart = exports.decrementItemInCart = exports.addMessage = exports.addItemToCart = exports.resetOrder = exports.reorderPastOrder = exports.editOrder = exports.refreshRevenueCenter = exports.revertMenu = exports.fetchLocationBySlug = exports.fetchLocation = exports.fetchRevenueCenter = exports.OrderActionType = void 0; exports.orderReducer = exports.selectCurrentCategory = exports.selectAutoSelect = exports.selectMenuVars = exports.selectCurrentItem = exports.selectMessages = exports.selectCurrentVendor = exports.selectCart = exports.selectRevenueCenter = void 0; const tslib_1 = require("tslib"); const toolkit_1 = require("@reduxjs/toolkit"); const types_1 = require("./types"); const utils_1 = require("@open-tender/utils"); const checkout_1 = require("./checkout"); const menu_1 = require("./menu"); const menuItems_1 = require("./menuItems"); const initialState = { address: null, alert: null, cart: [], cartCounts: {}, currentCategory: null, currentItem: null, currentVendor: null, deviceType: null, error: null, isCurbside: false, isOutpost: false, loading: 'idle', messages: [], orderId: null, prepType: null, orderType: null, requestedAt: 'asap', revenueCenter: null, serviceType: null, table: null }; var OrderActionType; (function (OrderActionType) { OrderActionType["FetchRevenueCenter"] = "order/fetchRevenueCenter"; OrderActionType["FetchLocation"] = "order/fetchLocation"; OrderActionType["RevertMenu"] = "order/revertMenu"; OrderActionType["RefreshRevenueCenter"] = "order/refreshRevenueCenter"; OrderActionType["EditOrder"] = "order/editOrder"; OrderActionType["ReorderPastOrder"] = "order/reorderPastOrder"; })(OrderActionType = exports.OrderActionType || (exports.OrderActionType = {})); exports.fetchRevenueCenter = (0, toolkit_1.createAsyncThunk)(OrderActionType.FetchRevenueCenter, (requestData, { dispatch, getState, rejectWithValue }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const { api } = getState().config; if (!api) return; try { const revenueCenter = yield api.getRevenueCenter(requestData.revenueCenterId, requestData.requestedAt); dispatch((0, exports.setRevenueCenter)(revenueCenter)); return revenueCenter; } catch (err) { return rejectWithValue(err); } })); exports.fetchLocation = (0, toolkit_1.createAsyncThunk)(OrderActionType.FetchLocation, ({ revenueCenterId, cartTotal }, { dispatch, getState, rejectWithValue }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const { api } = getState().config; if (!api) return; try { const revenueCenter = yield api.getLocation(revenueCenterId, cartTotal); dispatch((0, exports.setRevenueCenter)(revenueCenter)); return revenueCenter; } catch (err) { return rejectWithValue(err); } })); exports.fetchLocationBySlug = (0, toolkit_1.createAsyncThunk)(OrderActionType.FetchLocation, ({ slug, cartTotal }, { dispatch, getState, rejectWithValue }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const { api } = getState().config; if (!api) return; try { const revenueCenter = yield api.getLocationBySlug(slug, cartTotal); dispatch((0, exports.setRevenueCenter)(revenueCenter)); return revenueCenter; } catch (err) { return rejectWithValue(err); } })); exports.revertMenu = (0, toolkit_1.createAsyncThunk)(OrderActionType.RevertMenu, (requestData, { dispatch, getState, rejectWithValue }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const { api } = getState().config; if (!api) return; try { const revenueCenter = yield api.getLocation(requestData.revenueCenterId); dispatch((0, exports.setMenuVars)({ revenueCenter, serviceType: requestData.serviceType, requestedAt: requestData.requestedAt })); return revenueCenter; } catch (err) { return rejectWithValue(err); } })); exports.refreshRevenueCenter = (0, toolkit_1.createAsyncThunk)(OrderActionType.RefreshRevenueCenter, ({ revenueCenterId, serviceType, requestedAt, reset }, { getState, rejectWithValue }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const { api } = getState().config; if (!api) return; try { const revenueCenter = yield api.getLocation(revenueCenterId); if (reset) requestedAt = null; const firstTimes = (0, utils_1.makeFirstTimes)(revenueCenter, serviceType, requestedAt); const { status } = revenueCenter; if (!firstTimes || status !== 'OPEN') { return { type: 'closed', args: { status, preventClose: true } }; } else { return { type: 'adjustRequestedAt', args: { firstTimes, revenueCenter, preventClose: true } }; } } catch (err) { return rejectWithValue(err); } })); exports.editOrder = (0, toolkit_1.createAsyncThunk)(OrderActionType.EditOrder, (order, { dispatch, getState, rejectWithValue }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const { api } = getState().config; if (!api) return; const alert = { type: 'working', args: { text: 'Building your order...' } }; dispatch((0, exports.setAlert)(alert)); try { const { order_id: orderId, order_type: orderType, service_type: serviceType, requested_at: requestedAt, revenue_center, address } = order; const revenueCenterId = revenue_center === null || revenue_center === void 0 ? void 0 : revenue_center.revenue_center_id; const revenueCenter = yield api.getLocation(revenueCenterId); const menuItems = yield api.getMenuItems(revenueCenterId, serviceType); const { cart, cartCounts } = (0, utils_1.rehydrateCart)(menuItems, order.cart); dispatch((0, menuItems_1.setMenuItems)(menuItems)); const form = (0, utils_1.rehydrateCheckoutForm)(order); dispatch((0, checkout_1.updateForm)(form)); // dispatch(toggleSidebar()) const isOutpost = revenueCenter.is_outpost; const payload = { orderId, orderType, serviceType, isOutpost, revenueCenter, requestedAt, address, cart: cart, cartCounts }; dispatch((0, exports.setAlert)({ type: 'closeAndSidebar' })); return payload; } catch (err) { dispatch((0, exports.resetAlert)()); dispatch((0, exports.addMessage)('Something went wrong. Please contact support.')); return rejectWithValue(null); } })); exports.reorderPastOrder = (0, toolkit_1.createAsyncThunk)(OrderActionType.ReorderPastOrder, ({ revenueCenterId, serviceType, items }, { dispatch, getState, rejectWithValue }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const { api } = getState().config; if (!api) return; const alert = { type: 'working', args: { text: 'Building your order...' } }; dispatch((0, exports.setAlert)(alert)); try { const revenueCenter = yield api.getLocation(revenueCenterId); const requestedAt = (0, utils_1.makeFirstRequestedAt)(revenueCenter, serviceType, null); if (!requestedAt) { const { status } = revenueCenter; const alert = { type: 'closed', args: { status, isCancel: true } }; dispatch((0, exports.setAlert)(alert)); return {}; } else { dispatch((0, menu_1.resetMenuVars)()); dispatch((0, exports.resetRevenueCenter)()); const menuItems = yield api.getMenuItems(revenueCenterId, serviceType); const { cart, cartCounts } = (0, utils_1.rehydrateCart)(menuItems, items); dispatch((0, menuItems_1.setMenuItems)(menuItems)); const orderType = revenueCenter.revenue_center_type; const payload = { revenueCenter, requestedAt, serviceType, cart, cartCounts }; const alert = { type: 'requestedAt', args: { openSidebar: true, focusFirst: true, skipClose: true, isReorder: true, revenueCenter, serviceType, orderType, requestedAt } }; dispatch((0, exports.setAlert)(alert)); return payload; } } catch (err) { dispatch((0, exports.resetAlert)()); dispatch((0, exports.addMessage)('Something went wrong. Please contact support.')); return rejectWithValue(null); } })); const orderSlice = (0, toolkit_1.createSlice)({ name: types_1.ReducerType.Order, initialState, reducers: { resetOrder: () => initialState, resetOrderType: state => { state.orderId = null; state.orderType = null; state.serviceType = null; state.prepType = null; state.isOutpost = false; state.isCurbside = false; state.revenueCenter = null; state.table = null; state.requestedAt = null; }, resetRevenueCenter: state => { state.revenueCenter = null; }, resetLocation: state => { state.revenueCenter = null; }, resetCart: state => { state.cart = null; state.cartCounts = null; }, resetMessages: state => { state.messages = []; }, resetAlert: state => { state.alert = null; }, updateOrder: (state, action) => { return Object.assign(Object.assign({}, state), action.payload); }, checkout: state => state, setAlert: (state, action) => { state.alert = action.payload; }, setOrderId: (state, action) => { state.orderId = action.payload; }, setOrderType: (state, action) => { state.orderType = action.payload; }, setServiceType: (state, action) => { state.serviceType = action.payload; }, setOrderServiceType: (state, action) => { return Object.assign(Object.assign({}, state), action.payload); }, setCurbside: (state, action) => { state.isCurbside = action.payload; }, setDeviceType: (state, action) => { state.deviceType = action.payload; }, setCurrentVendor: (state, action) => { state.currentVendor = action.payload; }, setMenuVars: (state, action) => { const { revenueCenter } = action.payload; return Object.assign(Object.assign(Object.assign({}, state), action.payload), { orderType: revenueCenter.revenue_center_type, isOutpost: revenueCenter.is_outpost }); }, setAddress: (state, action) => { state.address = action.payload; }, setRequestedAt: (state, action) => { const messages = state.messages.filter(i => !i.message.includes('Requested time')); state.requestedAt = action.payload; state.messages = messages; }, setRevenueCenter: (state, action) => { const revenueCenter = action.payload; const previousRequestedAt = state.requestedAt; const requestedAt = (0, utils_1.makeFirstRequestedAt)(revenueCenter, state.serviceType, previousRequestedAt); let messages; if (previousRequestedAt && requestedAt !== previousRequestedAt) { const otherMessages = state.messages.filter(i => !i.message.includes('Requested time')); const tz = utils_1.timezoneMap[revenueCenter.timezone]; const requestedAtText = (0, utils_1.makeRequestedAtStr)(requestedAt, tz); const msg = { message: `Requested time updated to ${requestedAtText}`, id: (0, utils_1.makeRandomNumberString)() }; messages = [msg, ...otherMessages]; } else { messages = state.messages; } state.revenueCenter = revenueCenter; state.requestedAt = requestedAt !== null && requestedAt !== void 0 ? requestedAt : null; state.messages = messages; }, setTable: (state, action) => { state.table = action.payload; }, setPrepType: (state, action) => { state.prepType = action.payload; }, setCart: (state, action) => { const cartCounts = (0, utils_1.calcCartCounts)(action.payload); state.cart = action.payload; state.cartCounts = cartCounts; }, setCurrentCategory: (state, action) => { state.currentCategory = action.payload; }, setCurrentItem: (state, action) => { state.currentItem = action.payload; }, addItemToCart: (state, action) => { const currentCart = state.cart !== null ? state.cart : []; const { cart, cartCounts } = (0, utils_1.addItem)([...currentCart], action.payload); state.cart = cart; state.cartCounts = cartCounts; }, removeItemFromCart: (state, action) => { const { index } = action.payload; const currentCart = state.cart !== null ? state.cart : []; const { cart, cartCounts } = (0, utils_1.removeItem)([...currentCart], index); state.cart = cart; state.cartCounts = cartCounts; }, incrementItemInCart: (state, action) => { const { index } = action.payload; const currentCart = state.cart !== null ? state.cart : []; const { cart, cartCounts } = (0, utils_1.incrementItem)([...currentCart], index); state.cart = cart; state.cartCounts = cartCounts; }, decrementItemInCart: (state, action) => { const { index } = action.payload; const currentCart = state.cart !== null ? state.cart : []; const { cart, cartCounts } = (0, utils_1.decrementItem)([...currentCart], index); state.cart = cart; state.cartCounts = cartCounts; }, addMessage: (state, action) => { const existing = state.messages.map(i => i.message); if (existing.includes(action.payload)) { // do nothing return; } state.messages = [ ...state.messages, { message: action.payload, id: (0, utils_1.makeRandomNumberString)() } ]; }, removeMessage: (state, action) => { state.messages = state.messages.filter(i => i.id !== action.payload); } }, extraReducers: builder => { builder .addCase(exports.fetchRevenueCenter.fulfilled, state => { state.loading = 'idle'; state.error = null; }) .addCase(exports.fetchRevenueCenter.pending, state => { state.loading = 'pending'; }) .addCase(exports.fetchRevenueCenter.rejected, (state, action) => { state.error = action.payload; state.loading = 'idle'; }) .addCase(exports.fetchLocation.fulfilled, state => { state.loading = 'idle'; state.error = null; }) .addCase(exports.fetchLocation.pending, state => { state.loading = 'pending'; }) .addCase(exports.fetchLocation.rejected, (state, action) => { state.error = action.payload; state.loading = 'idle'; }) .addCase(exports.revertMenu.fulfilled, state => { state.loading = 'idle'; state.error = null; }) .addCase(exports.revertMenu.pending, state => { state.loading = 'pending'; }) .addCase(exports.revertMenu.rejected, (state, action) => { state.error = action.payload; state.loading = 'idle'; }) .addCase(exports.refreshRevenueCenter.fulfilled, (state, action) => { state.alert = action.payload; state.loading = 'idle'; state.error = null; }) .addCase(exports.refreshRevenueCenter.pending, state => { state.loading = 'pending'; }) .addCase(exports.refreshRevenueCenter.rejected, (state, action) => { state.error = action.payload; state.loading = 'idle'; }) .addCase(exports.editOrder.fulfilled, (state, action) => { return Object.assign(Object.assign(Object.assign({}, state), action.payload), { loading: 'idle', error: null }); }) .addCase(exports.editOrder.pending, state => { state.loading = 'pending'; }) .addCase(exports.editOrder.rejected, state => { state.loading = 'idle'; }) .addCase(exports.reorderPastOrder.fulfilled, (state, action) => { return Object.assign(Object.assign(Object.assign({}, state), action.payload), { loading: 'idle', error: null }); }) .addCase(exports.reorderPastOrder.pending, state => { state.loading = 'pending'; }) .addCase(exports.reorderPastOrder.rejected, state => { state.loading = 'idle'; }); } }); _a = orderSlice.actions, exports.resetOrder = _a.resetOrder, exports.addItemToCart = _a.addItemToCart, exports.addMessage = _a.addMessage, exports.decrementItemInCart = _a.decrementItemInCart, exports.incrementItemInCart = _a.incrementItemInCart, exports.removeItemFromCart = _a.removeItemFromCart, exports.removeMessage = _a.removeMessage, exports.resetAlert = _a.resetAlert, exports.resetCart = _a.resetCart, exports.resetLocation = _a.resetLocation, exports.resetMessages = _a.resetMessages, exports.resetOrderType = _a.resetOrderType, exports.resetRevenueCenter = _a.resetRevenueCenter, exports.setAddress = _a.setAddress, exports.setAlert = _a.setAlert, exports.setCart = _a.setCart, exports.setCurbside = _a.setCurbside, exports.setCurrentCategory = _a.setCurrentCategory, exports.setCurrentItem = _a.setCurrentItem, exports.setDeviceType = _a.setDeviceType, exports.setMenuVars = _a.setMenuVars, exports.setOrderId = _a.setOrderId, exports.setOrderServiceType = _a.setOrderServiceType, exports.setOrderType = _a.setOrderType, exports.setPrepType = _a.setPrepType, exports.setRequestedAt = _a.setRequestedAt, exports.setRevenueCenter = _a.setRevenueCenter, exports.setServiceType = _a.setServiceType, exports.setTable = _a.setTable, exports.checkout = _a.checkout, exports.setCurrentVendor = _a.setCurrentVendor, exports.updateOrder = _a.updateOrder; const selectAlert = (state) => state.order.alert; exports.selectAlert = selectAlert; const selectTimezone = (state) => { var _a; return state.order.revenueCenter ? utils_1.timezoneMap[(_a = state.order.revenueCenter.timezone) !== null && _a !== void 0 ? _a : 'US/Central'] : (0, utils_1.getUserTimezone)(); }; exports.selectTimezone = selectTimezone; const selectOrder = (state) => state.order; exports.selectOrder = selectOrder; const selectCartQuantity = (state) => { return state.order.cart ? state.order.cart.reduce((t, i) => (t += i.quantity), 0) : 0; }; exports.selectCartQuantity = selectCartQuantity; const selectCartTotal = (state) => { return state.order.cart ? state.order.cart.reduce((t, i) => (t += i.totalPrice || 0), 0.0) : 0.0; }; exports.selectCartTotal = selectCartTotal; const selectCartCounts = (state) => state.order.cartCounts || {}; exports.selectCartCounts = selectCartCounts; const selectCanOrder = (state) => state.order.revenueCenter && state.order.serviceType && state.order.requestedAt; exports.selectCanOrder = selectCanOrder; exports.selectOrderLimits = (0, toolkit_1.createSelector)((state) => { const { revenueCenter, serviceType } = state.order; const { cartGuest, spendingLimit } = state.groupOrder; return { revenueCenter, serviceType, cartGuest, spendingLimit }; }, ({ revenueCenter, serviceType, cartGuest, spendingLimit }) => { if (!revenueCenter || !serviceType) { return { orderMinimum: null, orderMaximum: null }; } const { order_maximum, order_minimum } = revenueCenter; const orderMax = cartGuest && spendingLimit ? parseFloat(spendingLimit) : order_maximum ? parseFloat(order_maximum[serviceType]) : 0; const orderMaximum = orderMax; const orderMinimum = order_minimum ? parseFloat(order_minimum[serviceType]) : 0; return { orderMinimum: orderMinimum > 0 ? orderMinimum : null, orderMaximum: orderMaximum > 0 ? orderMaximum : null }; }); exports.selectCartIds = (0, toolkit_1.createSelector)((state) => { return state.order.cart; }, cart => (cart ? cart.map(i => i.id) : [])); const selectMenuSlug = (state) => { const { revenueCenter } = state.order; return revenueCenter ? `/menu/${revenueCenter.slug}` : '/'; }; exports.selectMenuSlug = selectMenuSlug; const selectRevenueCenter = (state) => state.order.revenueCenter; exports.selectRevenueCenter = selectRevenueCenter; const selectCart = (state) => state.order.cart; exports.selectCart = selectCart; const selectCurrentVendor = (state) => state.order.currentVendor; exports.selectCurrentVendor = selectCurrentVendor; const selectMessages = (state) => state.order.messages; exports.selectMessages = selectMessages; const selectCurrentItem = (state) => state.order.currentItem; exports.selectCurrentItem = selectCurrentItem; exports.selectMenuVars = (0, toolkit_1.createSelector)((state) => { const { revenueCenter, serviceType, requestedAt } = state.order; return { revenueCenter, serviceType, requestedAt }; }, ({ revenueCenter, serviceType, requestedAt }) => { return { revenueCenterId: (revenueCenter === null || revenueCenter === void 0 ? void 0 : revenueCenter.revenue_center_id) || null, serviceType: serviceType, requestedAt: requestedAt }; }); const selectAutoSelect = (state) => { var _a, _b; const autoSelect = (_b = (_a = state.config) === null || _a === void 0 ? void 0 : _a.settings) === null || _b === void 0 ? void 0 : _b.autoSelect; const { orderType, serviceType } = state.order; return autoSelect && orderType && serviceType ? autoSelect[orderType][serviceType] : false; }; exports.selectAutoSelect = selectAutoSelect; const selectCurrentCategory = (state) => state.order.currentCategory; exports.selectCurrentCategory = selectCurrentCategory; exports.orderReducer = orderSlice.reducer;