@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
JavaScript
;
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;