payment plan

master
alex 2024-02-17 20:57:16 +01:00
parent c46ee6e5ea
commit 7ca71a8b1e
6 changed files with 75 additions and 114 deletions

View File

@ -118,11 +118,7 @@
}, },
"support": "Unterstützung", "support": "Unterstützung",
"feedback": "Feedback", "feedback": "Feedback",
"accountPlan": { "paymentPlan": "Zahlungsplan"
"infoDaysLeft": "{{daysLeft}} {{dayUnit}} verbleibend",
"buttonExtend": "Plan verlängern",
"buttonManage": "Plan verwalten"
}
}, },
"employees": { "employees": {
"pageTitle": "Mitarbeiter", "pageTitle": "Mitarbeiter",

View File

@ -118,11 +118,7 @@
}, },
"support": "Support", "support": "Support",
"feedback": "Feedback", "feedback": "Feedback",
"accountPlan": { "paymentPlan": "Payment plan"
"infoDaysLeft": "{{daysLeft}} {{dayUnit}} left",
"buttonExtend": "Extend plan",
"buttonManage": "Manage plan"
}
}, },
"employees": { "employees": {
"pageTitle": "Employees", "pageTitle": "Employees",

View File

@ -8,10 +8,11 @@ import {
ShopOutlined, ShopOutlined,
TeamOutlined, TeamOutlined,
UserOutlined, UserOutlined,
WalletOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { Button, Card, Divider, Flex, Menu, Typography } from "antd"; import { Divider, Menu } from "antd";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import { BreakpointLgWidth, Constants, isDevelopmentEnv } from "../../utils"; import { BreakpointLgWidth, Constants, isDevelopmentEnv } from "../../utils";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useSideBarContext } from "../../Contexts/SideBarContext"; import { useSideBarContext } from "../../Contexts/SideBarContext";
@ -31,6 +32,8 @@ export function SideMenuContent({
const navigate = useNavigate(); const navigate = useNavigate();
console.log("selectedKeys", selectedKeys);
const getFirstMenuItems = () => { const getFirstMenuItems = () => {
let items = [ let items = [
{ {
@ -117,6 +120,12 @@ export function SideMenuContent({
); );
} }
items.push({
label: t("sideMenu.paymentPlan"),
icon: <WalletOutlined />,
key: Constants.ROUTE_PATHS.PAYMENT_PLAN,
});
items.push({ items.push({
label: sideBarContext.username, label: sideBarContext.username,
icon: <UserOutlined />, icon: <UserOutlined />,
@ -153,17 +162,6 @@ export function SideMenuContent({
} }
}, [location.pathname]); }, [location.pathname]);
const calculateExpiry = () => {
const currentDate = new Date();
const expiryDate = new Date(sideBarContext.accountPlanExpiry);
const diffTime = Math.abs(expiryDate - currentDate);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return diffDays;
};
const accountPlanExpiry = calculateExpiry();
return ( return (
<div <div
style={{ style={{
@ -218,7 +216,31 @@ export function SideMenuContent({
<div> <div>
<Divider style={{ margin: 0 }} /> <Divider style={{ margin: 0 }} />
{sideBarContext.accountPlanExpiry !== undefined && <Menu
selectable={true}
selectedKeys={[selectedKeys]}
mode="vertical"
onClick={(item) => navigate(item.key)}
items={getSecondMenuItems()}
/>
</div>
</div>
);
}
/*
const calculateExpiry = () => {
const currentDate = new Date();
const expiryDate = new Date(sideBarContext.accountPlanExpiry);
const diffTime = Math.abs(expiryDate - currentDate);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return diffDays;
};
const accountPlanExpiry = calculateExpiry();
{sideBarContext.accountPlanExpiry !== undefined &&
accountPlanExpiry > 0 && ( accountPlanExpiry > 0 && (
<Card <Card
style={{ backgroundColor: "#6878d6", margin: 8 }} style={{ backgroundColor: "#6878d6", margin: 8 }}
@ -250,15 +272,4 @@ export function SideMenuContent({
</Button> </Button>
</Card> </Card>
)} )}
*/
<Menu
selectable={true}
selectedKeys={[selectedKeys]}
mode="vertical"
onClick={(item) => navigate(item.key)}
items={getSecondMenuItems()}
/>
</div>
</div>
);
}

View File

@ -131,11 +131,12 @@ function AccountDetails({ t, form }) {
); );
} }
function ChoosenProduct({ t, paymentPlan }) { export function ChoosenProduct({ t, paymentPlan, extra }) {
return ( return (
<Card <Card
title={t("authentication.signUp.choosenProduct.title")} title={t("authentication.signUp.choosenProduct.title")}
style={{ marginBottom: 16 }} style={{ marginBottom: 16 }}
extra={extra}
> >
<Typography.Title level={2}> <Typography.Title level={2}>
{Constants.APP_NAME} - {Constants.PAYMENT_PLAN[paymentPlan].name} {Constants.APP_NAME} - {Constants.PAYMENT_PLAN[paymentPlan].name}

View File

@ -1,70 +1,51 @@
import { Button, Card, Descriptions } from "antd"; import { Button, notification } from "antd";
import { useAppContext } from "../../Contexts/AppContext"; import { useAppContext } from "../../Contexts/AppContext";
import { Constants, myFetch } from "../../utils"; import { myFetch, showUnkownErrorNotification } from "../../utils";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { CreditCardOutlined } from "@ant-design/icons"; import { CreditCardOutlined } from "@ant-design/icons";
import { useState } from "react"; import { useState } from "react";
import { ChoosenProduct } from "../Authentication/SignUp";
export default function PaymentPlan() { export default function PaymentPlan() {
const { t } = useTranslation(); const { t } = useTranslation();
const appContext = useAppContext(); const appContext = useAppContext();
const [notificationApi, notificationContextHolder] =
notification.useNotification();
const [isRequestingBillingDetails, setIsRequestingBillingDetails] = const [isRequestingBillingDetails, setIsRequestingBillingDetails] =
useState(false); useState(false);
return ( return (
<Card <>
title={t("paymentPlan.title")} {notificationContextHolder}
extra={
<Button
type="link"
icon={<CreditCardOutlined />}
loading={isRequestingBillingDetails}
onClick={() => {
setIsRequestingBillingDetails(true);
myFetch({ <ChoosenProduct
method: "GET", t={t}
url: "/payment/portal", paymentPlan={appContext.paymentPlan}
}) extra={
.then((response) => { <Button
console.log("response", response); type="link"
icon={<CreditCardOutlined />}
loading={isRequestingBillingDetails}
onClick={() => {
setIsRequestingBillingDetails(true);
window.location.href = response.url; myFetch({
method: "GET",
url: "/payment/portal",
}) })
.catch((error) => { .then((response) => (window.location.href = response.url))
console.error("error", error); .catch(() => {
setIsRequestingBillingDetails(false); setIsRequestingBillingDetails(false);
}); showUnkownErrorNotification(notificationApi, t);
}} });
> }}
{t("paymentPlan.buttonUpdateBillingDetails")} >
</Button> {t("paymentPlan.buttonUpdateBillingDetails")}
} </Button>
> }
<Descriptions> />
<Descriptions.Item label={t("paymentPlan.plan")}> </>
{Constants.PAYMENT_PLAN[appContext.paymentPlan].name}
</Descriptions.Item>
<Descriptions.Item
label={t("paymentPlan.contentsOfSubscription.title")}
>
<>
{t("paymentPlan.contentsOfSubscription.maxEmployees")}{" "}
{Constants.PAYMENT_PLAN[appContext.paymentPlan].maxEmployees}
<br />
{t(
"paymentPlan.contentsOfSubscription.calendarMaxFutureBookingDays"
)}
:{" "}
{
Constants.PAYMENT_PLAN[appContext.paymentPlan]
.calendarMaxFutureBookingDays
}
<br />
</>
</Descriptions.Item>
</Descriptions>
</Card>
); );
} }

View File

@ -62,7 +62,7 @@ export const Constants = {
CALENDAR: "calendar", CALENDAR: "calendar",
CALENDAR_AUTH: "calendar/auth", CALENDAR_AUTH: "calendar/auth",
}, },
PAYMENT_PLAN: "payment-plan", PAYMENT_PLAN: "/payment-plan",
FEEDBACK: "/feedback", FEEDBACK: "/feedback",
SUPPORT: "/support", SUPPORT: "/support",
USER_PROFILE: "/user-profile", USER_PROFILE: "/user-profile",
@ -115,35 +115,11 @@ export const Constants = {
name: "Basic", name: "Basic",
maxEmployees: 15, maxEmployees: 15,
calendarMaxFutureBookingDays: 60, calendarMaxFutureBookingDays: 60,
price: {
en: {
totalNet: "9,99 €", // netto
vat: "1,90 €",
totalAmount: "11,89 €", // brutto
},
de: {
totalNet: "9,99 €",
vat: "1,90 €",
totalAmount: "11,89 €",
},
},
}, },
{ {
name: "Premium", name: "Premium",
maxEmployees: 50, // temporary maxEmployees: 50, // temporary
calendarMaxFutureBookingDays: 365, // temporary calendarMaxFutureBookingDays: 365, // temporary
price: {
en: {
totalNet: "24,99 €",
vat: "4,75 €",
totalAmount: "29,74 €",
},
de: {
totalNet: "24,99 €",
vat: "4,75 €",
totalAmount: "29,74 €",
},
},
}, },
], ],
}; };