feat(payment): implement first recharge offer functionality and UI updates

This commit is contained in:
2026-07-02 14:39:09 +08:00
parent 7b35fd18c5
commit d4de1370e8
20 changed files with 607 additions and 50 deletions
@@ -6,6 +6,12 @@ import type { VipOfferPlanView } from "./components/subscription-vip-offer-secti
export type SubscriptionType = "vip" | "topup";
export interface FirstRechargeOfferView {
badgeText: string;
title: string;
subtitle: string;
}
export function isVipPlan(plan: PaymentPlan): boolean {
return plan.vipDays !== null;
}
@@ -54,6 +60,9 @@ export function toVipOfferPlanView(plan: PaymentPlan): VipOfferPlanView {
price: formatOfferAmount(plan.amountCents),
currency: formatOfferCurrency(plan.currency),
originalPrice: formatOfferAmount(plan.originalAmountCents),
isFirstRechargeOffer: plan.isFirstRechargeOffer,
firstRechargeDiscountPercent: plan.firstRechargeDiscountPercent,
promotionType: plan.promotionType,
};
}
@@ -63,6 +72,10 @@ export function toCoinsOfferPlanView(plan: PaymentPlan): CoinsOfferPlanView {
coins: plan.dolAmount ?? 0,
price: formatOfferAmount(plan.amountCents),
currency: formatCoinCurrency(plan.currency),
originalPrice: formatOfferAmount(plan.originalAmountCents),
isFirstRechargeOffer: plan.isFirstRechargeOffer,
firstRechargeDiscountPercent: plan.firstRechargeDiscountPercent,
promotionType: plan.promotionType,
};
}
@@ -123,3 +136,25 @@ export function getDefaultSubscriptionPlanId(input: {
if (input.selectedPlan !== null) return null;
return input.coinPlans[0]?.id ?? null;
}
export function getFirstRechargeOfferView(input: {
isFirstRecharge: boolean;
discountPercent?: number | null;
vipPlans: readonly VipOfferPlanView[];
coinPlans: readonly CoinsOfferPlanView[];
}): FirstRechargeOfferView | null {
const promotedPlan = [...input.vipPlans, ...input.coinPlans].find(
(plan) => plan.isFirstRechargeOffer,
);
if (!input.isFirstRecharge && !promotedPlan) return null;
const discountPercent =
promotedPlan?.firstRechargeDiscountPercent ?? input.discountPercent ?? 50;
const badgeText = `${discountPercent}% OFF`;
return {
badgeText,
title: "New User First Recharge",
subtitle:
"Your first recharge price is already applied. No code needed.",
};
}