mirror of
https://github.com/makeplane/plane.git
synced 2026-07-13 05:49:40 +02:00
Merge pull request #921 from makeplane/sync/ce-ee
sync: community changes
This commit is contained in:
@@ -15,19 +15,33 @@ type TProPiceFrequency = "month" | "year";
|
||||
|
||||
type TProPlanPrice = {
|
||||
key: string;
|
||||
price: string;
|
||||
currency: string;
|
||||
price: number;
|
||||
recurring: TProPiceFrequency;
|
||||
};
|
||||
|
||||
// constants
|
||||
export const calculateYearlyDiscount = (monthlyPrice: number, yearlyPricePerMonth: number): number => {
|
||||
const monthlyCost = monthlyPrice * 12;
|
||||
const yearlyCost = yearlyPricePerMonth * 12;
|
||||
const amountSaved = monthlyCost - yearlyCost;
|
||||
const discountPercentage = (amountSaved / monthlyCost) * 100;
|
||||
return Math.floor(discountPercentage);
|
||||
};
|
||||
|
||||
const PRO_PLAN_PRICES: TProPlanPrice[] = [
|
||||
{ key: "monthly", price: "$7", recurring: "month" },
|
||||
{ key: "yearly", price: "$5", recurring: "year" },
|
||||
{ key: "monthly", currency: "$", price: 8, recurring: "month" },
|
||||
{ key: "yearly", currency: "$", price: 6, recurring: "year" },
|
||||
];
|
||||
|
||||
export const ProPlanUpgrade: FC<ProPlanUpgradeProps> = (props) => {
|
||||
const { basePlan, features, verticalFeatureList = false, extraFeatures } = props;
|
||||
// states
|
||||
const [selectedPlan, setSelectedPlan] = useState<TProPiceFrequency>("month");
|
||||
// derived
|
||||
const monthlyPrice = PRO_PLAN_PRICES.find((price) => price.recurring === "month")?.price ?? 0;
|
||||
const yearlyPrice = PRO_PLAN_PRICES.find((price) => price.recurring === "year")?.price ?? 0;
|
||||
const yearlyDiscount = calculateYearlyDiscount(monthlyPrice, yearlyPrice);
|
||||
// env
|
||||
const PRO_PLAN_MONTHLY_PAYMENT_URL = process.env.NEXT_PUBLIC_PRO_PLAN_MONTHLY_PAYMENT_URL ?? "https://plane.so/pro";
|
||||
const PRO_PLAN_YEARLY_PAYMENT_URL = process.env.NEXT_PUBLIC_PRO_PLAN_YEARLY_PAYMENT_URL ?? "https://plane.so/pro";
|
||||
@@ -55,7 +69,7 @@ export const ProPlanUpgrade: FC<ProPlanUpgradeProps> = (props) => {
|
||||
{price.recurring === "year" && ("Yearly" as string)}
|
||||
{price.recurring === "year" && (
|
||||
<span className="bg-gradient-to-r from-[#C78401] to-[#896828] text-white rounded-full px-2 py-1 ml-1 text-xs">
|
||||
-28%
|
||||
-{yearlyDiscount}%
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
@@ -69,8 +83,8 @@ export const ProPlanUpgrade: FC<ProPlanUpgradeProps> = (props) => {
|
||||
<div className="pt-6 pb-4 text-center font-semibold">
|
||||
<div className="text-2xl">Plane Pro</div>
|
||||
<div className="text-3xl">
|
||||
{price.recurring === "month" && "$7"}
|
||||
{price.recurring === "year" && "$5"}
|
||||
{price.currency}
|
||||
{price.price}
|
||||
</div>
|
||||
<div className="text-sm text-custom-text-300">a user per month</div>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
import { useCallback, useEffect, useMemo } from "react";
|
||||
// hooks
|
||||
import { useMultipleSelectStore } from "@/hooks/store";
|
||||
//
|
||||
import useReloadConfirmations from "./use-reload-confirmation";
|
||||
|
||||
export type TEntityDetails = {
|
||||
entityID: string;
|
||||
@@ -52,6 +54,15 @@ export const useMultipleSelect = (props: Props) => {
|
||||
getEntityDetailsFromEntityID,
|
||||
} = useMultipleSelectStore();
|
||||
|
||||
useReloadConfirmations(
|
||||
selectedEntityIds && selectedEntityIds.length > 0,
|
||||
"Are you sure you want to leave? Your current bulk operation selections will be lost.",
|
||||
true,
|
||||
() => {
|
||||
clearSelection();
|
||||
}
|
||||
);
|
||||
|
||||
const groups = useMemo(() => Object.keys(entities), [entities]);
|
||||
|
||||
const entitiesList: TEntityDetails[] = useMemo(
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
//TODO: remove temp flag isActive later and use showAlert as the source of truth
|
||||
const useReloadConfirmations = (isActive = true) => {
|
||||
const [showAlert, setShowAlert] = useState(false);
|
||||
const useReloadConfirmations = (isActive = true, message?: string, defaultShowAlert = false, onLeave?: () => void) => {
|
||||
const [showAlert, setShowAlert] = useState(defaultShowAlert);
|
||||
|
||||
const alertMessage = message ?? "Are you sure you want to leave? Changes you made may not be saved.";
|
||||
|
||||
const handleBeforeUnload = useCallback(
|
||||
(event: BeforeUnloadEvent) => {
|
||||
@@ -28,8 +30,10 @@ const useReloadConfirmations = (isActive = true) => {
|
||||
const isAnchorTargetBlank = anchorElement.getAttribute("target") === "_blank";
|
||||
if (isAnchorTargetBlank) return;
|
||||
// show confirm dialog
|
||||
const leave = confirm("Are you sure you want to leave? Changes you made may not be saved.");
|
||||
if (!leave) {
|
||||
const isLeaving = confirm(alertMessage);
|
||||
if (isLeaving) {
|
||||
onLeave && onLeave();
|
||||
} else {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user