App Store review 1.2.2 ("fails to register the plan"): follow Offerlyst's approved
managed-pricing setup. The plan is read from the Partner API on every app load,
shops without a plan (new install or reinstall) go to Shopify's plan selection
page, and app_subscriptions/update keeps it in sync. Billing API code removed.
Reviewer's checkout video: Shopify's checkout shows pickup by location name, so
the delivery label rename never reached the shopper. New checkout-time extension
shows the chosen date and time on the thank-you page (all plans) and next to
pickup/shipping options (Plus). Checkout display copy now matches.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
41 lines
2.0 KiB
TypeScript
41 lines
2.0 KiB
TypeScript
/**
|
|
* Feature gates per billing plan. "free" = Starter or no active subscription.
|
|
* Prices live in the Partner Dashboard (managed pricing); keep plan handles and copy in sync with it.
|
|
*/
|
|
export interface Features {
|
|
maxLocations: number;
|
|
monthlyBookings: number | null;
|
|
productRules: boolean;
|
|
inventoryAware: boolean;
|
|
peakDays: boolean;
|
|
waitlist: boolean;
|
|
freshness: boolean;
|
|
smsWhatsapp: boolean;
|
|
runSheets: boolean;
|
|
drivingDistance: boolean;
|
|
}
|
|
|
|
const PLANS: Record<string, Features> = {
|
|
free: { maxLocations: 1, monthlyBookings: 50, productRules: true, inventoryAware: false, peakDays: false, waitlist: false, freshness: false, smsWhatsapp: false, runSheets: false, drivingDistance: false },
|
|
Growth: { maxLocations: 3, monthlyBookings: null, productRules: true, inventoryAware: true, peakDays: true, waitlist: true, freshness: true, smsWhatsapp: false, runSheets: true, drivingDistance: false },
|
|
Pro: { maxLocations: 50, monthlyBookings: null, productRules: true, inventoryAware: true, peakDays: true, waitlist: true, freshness: true, smsWhatsapp: true, runSheets: true, drivingDistance: true },
|
|
};
|
|
|
|
export function features(plan: string): Features {
|
|
return PLANS[plan] ?? PLANS.free;
|
|
}
|
|
|
|
/** Maps managed-pricing plan handles or names (Partner Dashboard: starter / growth / pro) to a plan key. */
|
|
export function planFromSubscription(text: string | null | undefined): string {
|
|
const n = (text || "").toLowerCase();
|
|
if (n.includes("pro")) return "Pro";
|
|
if (n.includes("growth")) return "Growth";
|
|
return "free";
|
|
}
|
|
|
|
export const PLAN_COPY = [
|
|
{ id: "free", name: "Starter", price: "Free", points: ["1 location", "50 scheduled orders a month", "Capacity holds and cutoffs", "Email reminders"] },
|
|
{ id: "Growth", name: "Growth", price: "$19/month", points: ["Up to 3 locations", "Unlimited orders", "Festival rush control and waitlist", "Fresh-stock windows", "Driver run sheets"] },
|
|
{ id: "Pro", name: "Pro", price: "$49/month", points: ["Up to 50 locations", "SMS and WhatsApp reminders", "Driving-distance zones", "Everything in Growth"] },
|
|
];
|