[WEB-4253] improvement: plan card enhancements (#7168)

* [WEB-4253] improvement: plan card enhancements

* improvement: pricing changes
This commit is contained in:
Prateek Shourya
2025-06-05 14:37:26 +05:30
committed by GitHub
parent 1113f9fc19
commit 986f29d1f2
4 changed files with 91 additions and 15 deletions

View File

@@ -72,23 +72,23 @@ export const PLANE_COMMUNITY_PRODUCTS: Record<string, IPaymentProduct> = {
prices: [
{
id: `price_yearly_${EProductSubscriptionEnum.BUSINESS}`,
unit_amount: 0,
unit_amount: 15600,
recurring: "year",
currency: "usd",
workspace_amount: 0,
workspace_amount: 15600,
product: EProductSubscriptionEnum.BUSINESS,
},
{
id: `price_monthly_${EProductSubscriptionEnum.BUSINESS}`,
unit_amount: 0,
unit_amount: 1500,
recurring: "month",
currency: "usd",
workspace_amount: 0,
workspace_amount: 1500,
product: EProductSubscriptionEnum.BUSINESS,
},
],
payment_quantity: 1,
is_active: false,
is_active: true,
},
[EProductSubscriptionEnum.ENTERPRISE]: {
id: EProductSubscriptionEnum.ENTERPRISE,
@@ -141,8 +141,8 @@ export const SUBSCRIPTION_REDIRECTION_URLS: Record<EProductSubscriptionEnum, Rec
year: "https://app.plane.so/upgrade/pro/self-hosted?plan=year",
},
[EProductSubscriptionEnum.BUSINESS]: {
month: TALK_TO_SALES_URL,
year: TALK_TO_SALES_URL,
month: "https://app.plane.so/upgrade/business/self-hosted?plan=month",
year: "https://app.plane.so/upgrade/business/self-hosted?plan=year",
},
[EProductSubscriptionEnum.ENTERPRISE]: {
month: TALK_TO_SALES_URL,

View File

@@ -11,10 +11,12 @@ import { useTranslation } from "@plane/i18n";
import { TBillingFrequency } from "@plane/types";
import { getButtonStyling } from "@plane/ui";
import { cn, getSubscriptionName } from "@plane/utils";
// components
import { DiscountInfo } from "@/components/license/modal/card/discount-info";
// constants
import { getUpgradeButtonStyle } from "@/components/workspace/billing/subscription";
import { TPlanDetail } from "@/constants/plans";
// components
// local imports
import { PlanFrequencyToggle } from "./frequency-toggle";
type TPlanDetailProps = {
@@ -64,11 +66,17 @@ export const PlanDetail: FC<TPlanDetailProps> = observer((props) => {
</div>
<div className="flex gap-x-2 items-start text-custom-text-300 pb-1 transition-all duration-300 animate-slide-up">
{isSubscriptionActive && displayPrice !== undefined && (
<span className="text-custom-text-100 text-2xl font-semibold transition-all duration-300">
{"$" + displayPrice}
</span>
<div className="flex items-center gap-1 text-2xl text-custom-text-100 font-semibold transition-all duration-300">
<DiscountInfo
currency="$"
frequency={billingFrequency ?? "month"}
price={displayPrice}
subscriptionType={subscriptionType}
className="mr-1.5"
/>
</div>
)}
<div className="pt-2">
<div className="pt-1">
{pricingDescription && <div className="transition-all duration-300">{pricingDescription}</div>}
{pricingSecondaryDescription && (
<div className="text-xs text-custom-text-400 transition-all duration-300">

View File

@@ -6,8 +6,10 @@ import { EProductSubscriptionEnum } from "@plane/constants";
import { IPaymentProduct, TSubscriptionPrice } from "@plane/types";
import { getButtonStyling, Loader } from "@plane/ui";
import { cn } from "@plane/utils";
// helpers
// components
import { getUpgradeButtonStyle } from "@/components/workspace/billing/subscription";
// local imports
import { DiscountInfo } from "./discount-info";
export type TCheckoutParams = {
planVariant: EProductSubscriptionEnum;
@@ -56,8 +58,13 @@ export const PlanCheckoutButton: FC<Props> = observer((props) => {
</Loader>
) : (
<span className="animate-fade-in">
{price.currency}
{price.price}
<DiscountInfo
currency={price.currency}
frequency={price.recurring}
price={price.price}
subscriptionType={planVariant}
className="mr-1.5"
/>
</span>
)}
</div>

View File

@@ -0,0 +1,61 @@
import { useTheme } from "next-themes";
// plane imports
import { EProductSubscriptionEnum } from "@plane/constants";
import { TBillingFrequency } from "@plane/types";
import { cn } from "@plane/utils";
type TDiscountInfoProps = {
className?: string;
currency: string;
frequency: TBillingFrequency;
price: number;
subscriptionType: EProductSubscriptionEnum;
};
const PLANS_WITH_DISCOUNT = [EProductSubscriptionEnum.PRO];
const getActualPrice = (frequency: TBillingFrequency, subscriptionType: EProductSubscriptionEnum): number | null => {
switch (subscriptionType) {
case EProductSubscriptionEnum.PRO:
return frequency === "month" ? 10 : 8;
default:
return null;
}
};
export const DiscountInfo = ({ className, currency, frequency, price, subscriptionType }: TDiscountInfoProps) => {
const { resolvedTheme } = useTheme();
// derived values
const actualPrice = getActualPrice(frequency, subscriptionType);
if (!PLANS_WITH_DISCOUNT.includes(subscriptionType)) {
return (
<>
{currency}
{price}
</>
);
}
return (
<>
{actualPrice != price && (
<span className={cn("relative", className)}>
<img
src={
resolvedTheme === "dark"
? "https://images.plane.so/pricing/hero/scribble-white.svg"
: "https://images.plane.so/pricing/hero/scribble-black.svg"
}
alt="image"
className="absolute top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2 w-full scale-x-125"
/>
{currency}
{actualPrice}
</span>
)}
{currency}
{price}
</>
);
};