@coursebuilder/core
Version:
Core package for Course Builder
276 lines (275 loc) • 9 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/lib/pricing/pricing-state-machine.ts
var pricing_state_machine_exports = {};
__export(pricing_state_machine_exports, {
defaultPricingOptions: () => defaultPricingOptions,
pricingMachine: () => pricingMachine
});
module.exports = __toCommonJS(pricing_state_machine_exports);
var import_xstate = require("xstate");
var defaultPricingOptions = {
withImage: true,
withTitle: true,
withGuaranteeBadge: true,
isLiveEvent: false,
isCohort: false,
isPPPEnabled: true,
teamQuantityLimit: 100,
allowTeamPurchase: true,
cancelUrl: `${process.env.NEXT_PUBLIC_URL}/`
};
var pricingMachine = (0, import_xstate.setup)({
types: {
context: {},
input: {},
events: {}
},
actors: {
loadFormattedPrices: (0, import_xstate.fromPromise)(async ({ input }) => {
if (!input)
return Promise.resolve(null);
return await fetch(`${process.env.NEXT_PUBLIC_URL}/api/coursebuilder/prices-formatted`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
productId: input.productId,
quantity: input.quantity || 1,
couponId: input.couponId,
merchantCoupon: input.merchantCoupon,
autoApplyPPP: input.autoApplyPPP || false
})
}).then(async (res) => {
return await res.json() || null;
});
}),
loadPurchases: (0, import_xstate.fromPromise)(async ({ input }) => {
if (!input.userId) {
return Promise.resolve({
isPreviouslyPurchased: false
});
}
return await fetch(`${process.env.NEXT_PUBLIC_URL}/api/coursebuilder/purchases?userId=${input.userId}`).then(async (res) => {
const userPurchases = await res.json();
if (userPurchases?.length === 0)
return {
isPreviouslyPurchased: false
};
const purchasesForProduct = userPurchases?.filter((purchase) => purchase?.product?.id === input.productId && purchase?.status === "Valid");
if (purchasesForProduct && purchasesForProduct.length > 0) {
return {
isPreviouslyPurchased: true,
purchases: purchasesForProduct
};
} else {
return {
isPreviouslyPurchased: false
};
}
}).catch((e) => {
console.error("Error loading purchases", e);
return {
isPreviouslyPurchased: false
};
});
})
},
guards: {
canToggleTeamPurchase: function({ context, event }) {
console.log("GUARD!", context.isPPPActive);
return !context.isPPPActive;
},
isPPPAvailable: function({ context, event }) {
return Boolean(context.formattedPrice?.availableCoupons.some((coupon) => coupon?.type === "ppp"));
},
canUpdateQuantity: (0, import_xstate.and)([
({ context, event }) => {
return context.isTeamPurchaseActive && !context.isPPPActive || context.isBuyingMoreSeats;
}
])
}
}).createMachine({
context: ({ input }) => ({
product: input.product,
formattedPrice: null,
quantity: input.quantity || 1,
isPPPActive: false,
isTeamPurchaseActive: false,
isCohort: input.product.type === "cohort",
couponId: input.couponId || null,
activeMerchantCoupon: null,
autoApplyPPP: input.autoApplyPPP || false,
isBuyingMoreSeats: false,
options: input.options ? {
...defaultPricingOptions,
...input.options
} : defaultPricingOptions,
userId: input.userId,
isPreviouslyPurchased: false,
allowPurchase: true,
pricingData: input.pricingData || {
formattedPrice: null,
purchaseToUpgrade: null,
quantityAvailable: -1
},
purchases: null,
organizationId: input.organizationId
}),
id: "Pricing Display",
initial: "Loading Pricing Data",
states: {
"Loading Pricing Data": {
invoke: [
{
id: "load-purchases",
src: "loadPurchases",
input: ({ context }) => ({
userId: context.userId,
productId: context.product.id
}),
onDone: {
actions: (0, import_xstate.assign)({
isPreviouslyPurchased: ({ event }) => event.output.isPreviouslyPurchased,
purchases: ({ event }) => event.output.purchases
})
}
},
{
id: "load-prices",
input: ({ context: { product, quantity, couponId, country, activeMerchantCoupon, autoApplyPPP } }) => ({
productId: product.id,
quantity,
couponId,
country,
merchantCoupon: activeMerchantCoupon,
autoApplyPPP
}),
src: "loadFormattedPrices",
onDone: {
target: "Ready To Buy",
actions: (0, import_xstate.assign)({
formattedPrice: ({ event }) => event.output
})
}
}
],
on: {
UPDATE_QUANTITY: {
target: "Debouncing Quantity",
actions: (0, import_xstate.assign)({
quantity: ({ event }) => Math.max(event.quantity, 1)
}),
guard: {
type: "canUpdateQuantity"
}
}
}
},
"Debouncing Quantity": {
after: {
350: {
target: "Loading Pricing Data"
}
},
on: {
UPDATE_QUANTITY: {
target: "Debouncing Quantity",
actions: (0, import_xstate.assign)({
quantity: ({ event }) => Math.max(event.quantity, 1)
}),
guard: {
type: "canUpdateQuantity"
}
}
}
},
"Ready To Buy": {
on: {
TOGGLE_TEAM_PURCHASE: {
target: "Loading Pricing Data",
actions: [
(0, import_xstate.assign)({
activeMerchantCoupon: void 0,
isPPPActive: false,
isTeamPurchaseActive: ({ context }) => !context.isTeamPurchaseActive,
quantity: ({ context }) => {
if (context.isTeamPurchaseActive) {
return 1;
} else {
const defaultTeamSize = 5;
if (context.options.isLiveEvent) {
if (context.pricingData.quantityAvailable === -1) {
return defaultTeamSize;
} else {
return Math.max(1, Math.min(context.pricingData.quantityAvailable, defaultTeamSize));
}
} else {
return Math.min(context.options.teamQuantityLimit, defaultTeamSize);
}
}
}
})
],
guard: {
type: "canToggleTeamPurchase"
}
},
TOGGLE_BUYING_MORE_SEATS: {
actions: (0, import_xstate.assign)({
isBuyingMoreSeats: ({ context }) => !context.isBuyingMoreSeats,
isTeamPurchaseActive: () => true
})
},
SET_MERCHANT_COUPON: {
target: "Loading Pricing Data",
actions: (0, import_xstate.assign)({
activeMerchantCoupon: ({ event }) => event.merchantCoupon,
autoApplyPPP: false,
isPPPActive: ({ event }) => event.merchantCoupon?.type === "ppp",
isTeamPurchaseActive: ({ event, context }) => event.merchantCoupon?.type === "ppp" ? false : context.isTeamPurchaseActive,
quantity: ({ context, event }) => event.merchantCoupon?.type === "ppp" ? 1 : context.quantity
})
},
UPDATE_QUANTITY: {
target: "Debouncing Quantity",
actions: (0, import_xstate.assign)({
quantity: ({ event }) => Math.max(event.quantity, 1)
}),
guard: {
type: "canUpdateQuantity"
}
},
PURCHASE_INITIATED: {
target: "Purchasing"
}
}
},
Purchasing: {
type: "final"
}
}
});
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
defaultPricingOptions,
pricingMachine
});
//# sourceMappingURL=pricing-state-machine.cjs.map