Fix trial upsell modal logic
This commit is contained in:
parent
76f497d2c8
commit
8fc463313d
2 changed files with 89 additions and 6 deletions
59
apps/main/src/components/TrialUpsellModal.test.ts
Normal file
59
apps/main/src/components/TrialUpsellModal.test.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { shouldShowTrialUpsell } from "./TrialUpsellModal";
|
||||
|
||||
describe("shouldShowTrialUpsell", () => {
|
||||
it("does not show when trial has more than 7 days remaining", () => {
|
||||
expect(
|
||||
shouldShowTrialUpsell({
|
||||
isTrialExpired: false,
|
||||
activeSubscriptionPlan: null,
|
||||
isTemporaryUser: false,
|
||||
daysRemaining: 14,
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("shows when trial is within reminder window and user has no subscription", () => {
|
||||
expect(
|
||||
shouldShowTrialUpsell({
|
||||
isTrialExpired: false,
|
||||
activeSubscriptionPlan: null,
|
||||
isTemporaryUser: false,
|
||||
daysRemaining: 3,
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("does not show when trial is expired", () => {
|
||||
expect(
|
||||
shouldShowTrialUpsell({
|
||||
isTrialExpired: true,
|
||||
activeSubscriptionPlan: null,
|
||||
isTemporaryUser: false,
|
||||
daysRemaining: null,
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("does not show when organization already has a paid subscription", () => {
|
||||
expect(
|
||||
shouldShowTrialUpsell({
|
||||
isTrialExpired: false,
|
||||
activeSubscriptionPlan: "team",
|
||||
isTemporaryUser: false,
|
||||
daysRemaining: 2,
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("does not show for temporary users", () => {
|
||||
expect(
|
||||
shouldShowTrialUpsell({
|
||||
isTrialExpired: false,
|
||||
activeSubscriptionPlan: null,
|
||||
isTemporaryUser: true,
|
||||
daysRemaining: 2,
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -15,9 +15,29 @@ import { useMaybeUser } from "../providers/UserStoreProvider";
|
|||
|
||||
const MODAL_INTERVAL_MS = 15 * 60 * 1000; // 15 minutes
|
||||
const LAST_SHOWN_KEY = "trial-upsell-modal-last-shown";
|
||||
const TRIAL_UPSELL_REMINDER_DAYS = 7;
|
||||
|
||||
export const shouldShowTrialUpsell = (input: {
|
||||
isTrialExpired: boolean;
|
||||
activeSubscriptionPlan: "solo" | "team" | "annual" | null;
|
||||
isTemporaryUser: boolean;
|
||||
daysRemaining: number | null;
|
||||
}) => {
|
||||
const { isTrialExpired, activeSubscriptionPlan, isTemporaryUser, daysRemaining } = input;
|
||||
|
||||
if (isTrialExpired || activeSubscriptionPlan || isTemporaryUser) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (daysRemaining === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return daysRemaining > 0 && daysRemaining <= TRIAL_UPSELL_REMINDER_DAYS;
|
||||
};
|
||||
|
||||
/**
|
||||
* Auto-opening modal that shows every 15 minutes to remind users about trial expiration.
|
||||
* Auto-opening modal that reminds users near trial expiration.
|
||||
*/
|
||||
export function TrialUpsellModal() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
|
@ -26,11 +46,15 @@ export function TrialUpsellModal() {
|
|||
const user = useMaybeUser();
|
||||
const { mutate: createCheckout, isPending: checkoutPending } = useCreateCheckoutSession();
|
||||
|
||||
const shouldShowModal =
|
||||
!!organizationData &&
|
||||
!organizationData.is_trial_expired &&
|
||||
!organizationData.active_subscription_plan &&
|
||||
!user?.is_temporary;
|
||||
const shouldShowModal = Boolean(
|
||||
organizationData &&
|
||||
shouldShowTrialUpsell({
|
||||
isTrialExpired: organizationData.is_trial_expired,
|
||||
activeSubscriptionPlan: organizationData.active_subscription_plan,
|
||||
isTemporaryUser: Boolean(user?.is_temporary),
|
||||
daysRemaining,
|
||||
})
|
||||
);
|
||||
|
||||
const requiredPlan = organizationData?.required_plan ?? "solo";
|
||||
const checkoutPlan = requiredPlan === "team" ? "team" : "solo";
|
||||
|
|
|
|||
Loading…
Reference in a new issue