diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json
index 0745e73..c9009a7 100644
--- a/public/locales/de/translation.json
+++ b/public/locales/de/translation.json
@@ -20,6 +20,7 @@
"hour": "Stunde",
"minutes": "Minuten",
"minute": "Minute",
+ "daysLong": "Tagen",
"days": "Tage",
"day": "Tag",
"separator": "und"
@@ -507,13 +508,38 @@
]
},
"paymentPlan": {
- "title": "Zahlungsplan",
- "buttonUpdateBillingDetails": "Zahlungsdetails aktualisieren",
- "plan": "Plan",
- "contentsOfSubscription": {
- "title": "Inhalt des Abonnements",
- "maxEmployees": "Maximale Anzahl von Mitarbeitern",
- "calendarMaxFutureBookingDays": "Maximale Anzahl von Tagen im Voraus"
- }
+ "title": "Features & Preisübersicht",
+ "buttonMonthly": "Monatlich",
+ "buttonYearly": "Jährlich",
+ "buttonManagePlan": "Zahlungsplan verwalten",
+ "buttonBuyPlan": "Jetzt buchen",
+ "monthly": "monatlich",
+ "businessPlan": "Unternehmensplan",
+ "cancelledOn": "Gekündigt am {{date}} Uhr",
+ "changeToAnnualPayment": "Wechseln Sie zur jährlichen Zahlung und ",
+ "saveAmount": "sparen Sie {{amount}} €",
+ "popconfirmChangePlan": {
+ "title": "Zahlungsplan wechseln",
+ "description": "Sind Sie sicher, dass Sie Ihren Plan ändern wollen?"
+ },
+ "alertDemoEndsIn": {
+ "demoEndsIn": "Die Testversion endet in",
+ "selectPlanToAccessFullFeatures": "Wählen Sie einen Plan, um auf alle Funktionen zuzugreifen."
+ },
+ "alertPlanCancelled": "Ihr Plan wurde gekündigt. Am Ende des Abrechnungszeitraums müssen Sie einen neuen Plan auswählen, um unsere Dienste weiterhin nutzen zu können.",
+ "features": [
+ {
+ "text": "Unbegrenzte {{bold}}",
+ "bold": "Terminanzahl"
+ },
+ {
+ "text": "Bis zu {{bold}}",
+ "bold": "20 Mitarbeiter"
+ },
+ {
+ "text": "Buchungen bis zu {{bold}} im Voraus",
+ "bold": "7 Wochen"
+ }
+ ]
}
}
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index 12aaf72..b1d7a5a 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -20,6 +20,7 @@
"hour": "hour",
"minutes": "minutes",
"minute": "minute",
+ "daysLong": "days",
"days": "days",
"day": "day",
"separator": "and"
@@ -516,13 +517,38 @@
]
},
"paymentPlan": {
- "title": "Payment plan",
- "buttonUpdateBillingDetails": "Update billing details",
- "plan": "Plan",
- "contentsOfSubscription": {
- "title": "Contents of subscription",
- "maxEmployees": "Max. employees",
- "calendarMaxFutureBookingDays": "Max. future booking days"
- }
+ "title": "Features & Pricing",
+ "buttonMonthly": "Monthly",
+ "buttonYearly": "Yearly",
+ "buttonManagePlan": "Manage plan",
+ "buttonBuyPlan": "Buy now",
+ "monthly": "monthly",
+ "businessPlan": "Business Plan",
+ "cancelledOn": "Cancelled on {{date}} o'clock",
+ "changeToAnnualPayment": "Switch to annual payment and ",
+ "saveAmount": "save {{amount}} €",
+ "popconfirmChangePlan": {
+ "title": "Change plan",
+ "description": "Are you sure you want to change your plan?"
+ },
+ "alertDemoEndsIn": {
+ "demoEndsIn": "Demo ends in",
+ "selectPlanToAccessFullFeatures": "Select a plan to access all features."
+ },
+ "alertPlanCancelled": "Your plan has been cancelled. At the end of the billing period, you need to select a new plan to continue using our services.",
+ "features": [
+ {
+ "text": "Unlimited {{bold}}",
+ "bold": "number of appointments"
+ },
+ {
+ "text": "Up to {{bold}}",
+ "bold": "20 employees"
+ },
+ {
+ "text": "Bookings up to {{bold}} in advance",
+ "bold": "7 weeks"
+ }
+ ]
}
}
diff --git a/src/Components/SideMenu/index.js b/src/Components/SideMenu/index.js
index d3a9128..9d317cf 100644
--- a/src/Components/SideMenu/index.js
+++ b/src/Components/SideMenu/index.js
@@ -174,17 +174,10 @@ export function SideMenuContent({
}
}, [location.pathname]);
- const calculateExpiry = () => {
- const currentDate = new Date();
- const expiryDate = new Date(sideBarContext.paymentPlanTrialEnd);
-
- const diffTime = Math.abs(expiryDate - currentDate);
- const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
-
- return diffDays;
- };
-
- const accountPlanExpiry = calculateExpiry();
+ const daysLeft = Math.floor(
+ (new Date(sideBarContext.paymentPlanTrialEnd) - new Date()) /
+ (1000 * 60 * 60 * 24)
+ );
return (
{t("sideMenu.paymentPlanTrailingDaysLeft", {
- daysLeft: accountPlanExpiry,
+ daysLeft: daysLeft,
dayUnit:
- accountPlanExpiry > 1
+ daysLeft > 1
? t("common.unit.days")
: t("common.unit.day"),
})}
diff --git a/src/Pages/PaymentPlan/index.js b/src/Pages/PaymentPlan/index.js
index 6729865..fb3b667 100644
--- a/src/Pages/PaymentPlan/index.js
+++ b/src/Pages/PaymentPlan/index.js
@@ -10,25 +10,26 @@ import {
Grid,
Skeleton,
notification,
+ Popconfirm,
+ Tag,
} from "antd";
-import { useAppContext } from "../../Contexts/AppContext";
import {
AppStyle,
FormatDatetime,
myFetch,
showUnkownErrorNotification,
} from "../../utils";
-import { useTranslation } from "react-i18next";
+import { Trans, useTranslation } from "react-i18next";
import { CheckOutlined, CloseOutlined } from "@ant-design/icons";
import { useEffect, useState } from "react";
import { ReactComponent as RocketLaunch } from "./rocket_launch_FILL1_wght400_GRAD0_opsz24.svg";
import { ReactComponent as Check } from "./task_alt_FILL0_wght400_GRAD0_opsz24.svg";
+import CountUp from "react-countup";
const { useBreakpoint } = Grid;
export default function PaymentPlan() {
const { t } = useTranslation();
- const appContext = useAppContext();
const [notificationApi, notificationContextHolder] =
notification.useNotification();
@@ -62,8 +63,7 @@ export default function PaymentPlan() {
setSelectedBillingPeriod(data.payment_plan_interval);
}
})
- .catch((error) => {
- console.log(error);
+ .catch(() => {
setIsRequesting(false);
showUnkownErrorNotification(notificationApi, t);
});
@@ -71,19 +71,31 @@ export default function PaymentPlan() {
useEffect(() => fetchPaymentPlan(), []);
- const showAlert = () => {
+ const showAlertTrialEnds = () => {
if (
!isRequesting &&
requestData.payment_plan === 0 &&
requestData.payment_plan_trial_end &&
!requestData.payment_plan_canceled_at
) {
+ const daysLeft = Math.floor(
+ (new Date(requestData.payment_plan_trial_end) - new Date()) /
+ (1000 * 60 * 60 * 24)
+ );
+
return (
- Ihre Demo endet in 7 Tagen. Jetzt einen Plan auswählen, um
- den vollen Funktionsumfang zu nutzen.
+ {t("paymentPlan.alertDemoEndsIn.demoEndsIn")}{" "}
+
+ {daysLeft}{" "}
+ {daysLeft === 1
+ ? t("common.unit.day")
+ : t("common.unit.daysLong")}
+
+ .{" "}
+ {t("paymentPlan.alertDemoEndsIn.selectPlanToAccessFullFeatures")}
}
type="warning"
@@ -95,34 +107,104 @@ export default function PaymentPlan() {
}
};
+ const showAlertPlanCancelled = () => {
+ if (!isRequesting && requestData.payment_plan_canceled_at) {
+ return (
+
+ {t("paymentPlan.alertPlanCancelled", {
+ date: FormatDatetime(requestData.payment_plan_canceled_at),
+ })}
+
+ }
+ type="warning"
+ showIcon
+ closable
+ style={{ marginBottom: 12 }}
+ />
+ );
+ }
+ };
+
+ const percentageDiscount =
+ requestData.prices.length > 0
+ ? Math.round(
+ 100 -
+ (100 / (requestData.prices[0].unit_amount * 12)) *
+ requestData.prices[1].unit_amount
+ )
+ : 0;
+
+ const handleButtonBuyPlan = () => {
+ setRequestingCheckout(true);
+
+ myFetch({
+ method: "POST",
+ url: "/payment/checkout",
+ body: {
+ lookupKey: `za-basic-${
+ selectedBillingPeriod === 0 ? "monthly" : "yearly"
+ }`,
+ },
+ notificationApi,
+ t,
+ })
+ .then((data) => {
+ if (data.url) {
+ window.location.href = data.url;
+ return;
+ }
+
+ if (data.status === "ok") {
+ fetchPaymentPlan();
+ setRequestingCheckout(false);
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ setRequestingCheckout(false);
+ });
+ };
+
+ const ButtonBuyPlan = ({ onClick }) => {
+ return (
+
+ );
+ };
+
return (
<>
{notificationContextHolder}
- {showAlert()}
+ {showAlertTrialEnds()}
+ {showAlertPlanCancelled()}
-
+
-
-
-
- Unbegrenzte Terminanzahl
-
-
-
-
-
- Bis zu 20 Mitarbeiter
-
-
-
-
-
- Buchungen bis zu 6 Wochen im Voraus
-
-
+ {t("paymentPlan.features", { returnObjects: true }).map(
+ (feature, index) => (
+
+
+
+ }}
+ />
+
+
+ )
+ )}
@@ -140,12 +222,12 @@ export default function PaymentPlan() {
(requestData.payment_plan_canceled_at === undefined ? (
) : (
-
+
))
}
onClick={() => setSelectedBillingPeriod(0)}
>
- Monatlich
+ {t("paymentPlan.buttonMonthly")}
)}
@@ -160,12 +242,29 @@ export default function PaymentPlan() {
(requestData.payment_plan_canceled_at === undefined ? (
) : (
-
+
))
}
onClick={() => setSelectedBillingPeriod(1)}
>
- Jährlich
+
+ {t("paymentPlan.buttonYearly")}
+
+ {requestData.payment_plan_interval !== 1 && (
+
+ -
+ 10
+ ? percentageDiscount - 10
+ : 0
+ }
+ end={percentageDiscount}
+ />{" "}
+ %
+
+ )}
+
)}
@@ -197,74 +296,56 @@ export default function PaymentPlan() {
level={screenBreakpoint.xs ? 3 : 2}
style={{ color: "#fff" }}
>
- Unternehmensplan
+ {t("paymentPlan.businessPlan")}
{isRequesting ? (
) : (
-
+ requestData.payment_plan_interval ? (
+
+ ) : requestData.payment_plan === 0 ? (
+ handleButtonBuyPlan()} />
+ ) : (
+ handleButtonBuyPlan()}
+ >
+
+
+ )}
+ >
)}
@@ -296,18 +377,40 @@ export default function PaymentPlan() {
- /monatlich
+ /{t("paymentPlan.monthly")}
- {selectedBillingPeriod === requestData.payment_plan &&
+ {selectedBillingPeriod === requestData.payment_plan_interval &&
requestData.payment_plan_canceled_at !== undefined && (
- Gekündigt am{" "}
- {FormatDatetime(requestData.payment_plan_canceled_at)} Uhr
+ {t("paymentPlan.cancelledOn", {
+ date: FormatDatetime(
+ requestData.payment_plan_canceled_at
+ ),
+ })}
+
+
+ )}
+
+ {selectedBillingPeriod === 1 &&
+ requestData.payment_plan_interval !== 1 && (
+
+
+ {t("paymentPlan.changeToAnnualPayment")}
+
+ {t("paymentPlan.saveAmount", {
+ amount:
+ requestData.prices[0].unit_amount * 12 -
+ requestData.prices[1].unit_amount,
+ })}
+
)}