mirror of
https://github.com/makeplane/plane.git
synced 2026-02-09 15:49:06 -06:00
[WEB-4253] improvement: plan card enhancements (#7168)
* [WEB-4253] improvement: plan card enhancements * improvement: pricing changes
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
61
web/core/components/license/modal/card/discount-info.tsx
Normal file
61
web/core/components/license/modal/card/discount-info.tsx
Normal 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}
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user