/** Subscription/pricing-tier card — takes a `Plan` (billing cycle, features), not a physical product like ProductCard's `options`. */ export type PaymentCardProps = { /** The plan to render. */ plan: Plan; /** true hides the CTA button unless `isRenewal` is also true, no matter what `plan.buttonText` says. */ isActive?: boolean; /** Adds an "Upgrade Your Plan" badge and primary outline; ignored when `isActive` is set. */ isNextUpgrade?: boolean; /** Picks which of `plan.monthlyPrice` / `plan.yearlyPrice` is shown. */ billingCycle: "monthly" | "yearly"; /** Called with `plan.plan_id` when the CTA button is clicked. */ onSelect?: (planId: number) => void; /** `type` is always "button" in practice — PaymentCard never wires hover on the outer card, only the CTA button. */ onHover?: (planId: number, type: "card" | "button", state: boolean) => void; /** The plan_id whose button should spin, not a boolean — matched via `===` against each plan's plan_id. */ buttonLoading?: number; /** Replaces the card content with skeletons. */ isLoading?: boolean; /** Keeps the CTA button visible on the active plan. */ isRenewal?: boolean; }; /** Plan data rendered by PaymentCard — `billing`/`tax` are pre-formatted display strings shown under the price, not derived from monthlyPrice/yearlyPrice. */ export type Plan = { /** Identifier passed to `onSelect` / `onHover` and matched against `buttonLoading`. */ plan_id: number; /** Plan title. */ name: string; /** Muted line under the price. */ description: string; /** Price in rupees shown for the monthly cycle; the price block is hidden when both prices are 0. */ monthlyPrice: number; /** Price in rupees shown for the yearly cycle; the price block is hidden when both prices are 0. */ yearlyPrice: number; /** Display string beside the price, e.g. "/month". */ billing: string; /** Display string under `billing`, e.g. "+ GST". */ tax: string; /** Check-marked feature list, one row per entry. */ features: string[]; /** Icon rendered in the tinted tile above the name. */ icon: React.ReactNode; /** CTA label; with no text the button is hidden unless `isRenewal`. */ buttonText: string; /** "link" still gets the same filled bg/color override as "solid" — only "outline" is excluded from it. */ buttonVariant: "solid" | "outline" | "link"; /** Adds a "Most Popular" badge and scales the card up slightly; lower priority than active and upgrade badges. */ popular?: boolean; /** CTA text while this plan's button is loading. */ buttonLoadingText?: string; /** Success-coloured line under the price, e.g. a discount note. */ priceDescription?: string; };