feat: add information of subscription plan on stripe page, fix private bug
This commit is contained in:
parent
8db05c3fd4
commit
f355ff391c
@ -124,6 +124,18 @@ function App(): JSX.Element {
|
|||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route element={<Layout setIsSpecialOfferOpen={setIsSpecialOfferOpen} />}>
|
<Route element={<Layout setIsSpecialOfferOpen={setIsSpecialOfferOpen} />}>
|
||||||
|
<Route
|
||||||
|
path={routes.client.paymentResult()}
|
||||||
|
element={<PaymentResultPage />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path={routes.client.paymentSuccess()}
|
||||||
|
element={<PaymentSuccessPage />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path={routes.client.paymentFail()}
|
||||||
|
element={<PaymentFailPage />}
|
||||||
|
/>
|
||||||
<Route element={<AuthorizedUserOutlet />}>
|
<Route element={<AuthorizedUserOutlet />}>
|
||||||
<Route path={routes.client.root()} element={<MainPage />} />
|
<Route path={routes.client.root()} element={<MainPage />} />
|
||||||
<Route path={routes.client.birthday()} element={<BirthdayPage />} />
|
<Route path={routes.client.birthday()} element={<BirthdayPage />} />
|
||||||
@ -162,32 +174,20 @@ function App(): JSX.Element {
|
|||||||
<Route path={routes.client.static()} element={<StaticPage />} />
|
<Route path={routes.client.static()} element={<StaticPage />} />
|
||||||
<Route path={routes.client.priceList()} element={<PriceListPage />} />
|
<Route path={routes.client.priceList()} element={<PriceListPage />} />
|
||||||
{/* <Route
|
{/* <Route
|
||||||
path={routes.client.wallpaper()}
|
path={routes.client.wallpaper()}
|
||||||
element={<ProtectWallpaperPage />}
|
element={<ProtectWallpaperPage />}
|
||||||
/> */}
|
/> */}
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route element={<PrivateOutlet />}>
|
||||||
|
<Route element={<AuthorizedUserOutlet />}>
|
||||||
<Route
|
<Route
|
||||||
path={routes.client.subscription()}
|
path={routes.client.subscription()}
|
||||||
element={<SubscriptionPage />}
|
element={<SubscriptionPage />}
|
||||||
/>
|
/>
|
||||||
<Route element={<PrivateOutlet />}>
|
|
||||||
<Route element={<AuthorizedUserOutlet />}>
|
|
||||||
<Route
|
<Route
|
||||||
path={routes.client.paymentMethod()}
|
path={routes.client.paymentMethod()}
|
||||||
element={<PaymentPage />}
|
element={<PaymentPage />}
|
||||||
/>
|
/>
|
||||||
<Route
|
|
||||||
path={routes.client.paymentResult()}
|
|
||||||
element={<PaymentResultPage />}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path={routes.client.paymentSuccess()}
|
|
||||||
element={<PaymentSuccessPage />}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path={routes.client.paymentFail()}
|
|
||||||
element={<PaymentFailPage />}
|
|
||||||
/>
|
|
||||||
<Route
|
<Route
|
||||||
path={routes.client.paymentStripe()}
|
path={routes.client.paymentStripe()}
|
||||||
element={<StripePage />}
|
element={<StripePage />}
|
||||||
|
|||||||
@ -14,10 +14,10 @@ import routes from "@/routes";
|
|||||||
import "./styles.css";
|
import "./styles.css";
|
||||||
import Header from "../Header";
|
import Header from "../Header";
|
||||||
import { StripeButton } from "./methods/Stripe";
|
import { StripeButton } from "./methods/Stripe";
|
||||||
import { PayPalButton } from "./methods/PayPal/Button";
|
// import { PayPalButton } from "./methods/PayPal/Button";
|
||||||
import { useAuth } from "@/auth";
|
// import { useAuth } from "@/auth";
|
||||||
import { useApi } from "@/api";
|
// import { useApi } from "@/api";
|
||||||
import { PayPalReceiptPayload } from "@/api/resources/UserSubscriptionReceipts";
|
// import { PayPalReceiptPayload } from "@/api/resources/UserSubscriptionReceipts";
|
||||||
import { ISubscriptionPlan } from "@/api/resources/SubscriptionPlans";
|
import { ISubscriptionPlan } from "@/api/resources/SubscriptionPlans";
|
||||||
|
|
||||||
const getPrice = (activeSubPlan: ISubscriptionPlan | null) => {
|
const getPrice = (activeSubPlan: ISubscriptionPlan | null) => {
|
||||||
@ -32,8 +32,8 @@ const getPrice = (activeSubPlan: ISubscriptionPlan | null) => {
|
|||||||
function PaymentPage(): JSX.Element {
|
function PaymentPage(): JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { applePay } = usePayment();
|
const { applePay } = usePayment();
|
||||||
const api = useApi();
|
// const api = useApi();
|
||||||
const { token } = useAuth();
|
// const { token } = useAuth();
|
||||||
const [openErrorModal, setOpenErrorModal] = useState(false);
|
const [openErrorModal, setOpenErrorModal] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const isLoading = applePay === null;
|
const isLoading = applePay === null;
|
||||||
@ -46,23 +46,23 @@ function PaymentPage(): JSX.Element {
|
|||||||
navigate(routes.client.paymentStripe());
|
navigate(routes.client.paymentStripe());
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigateToPayPal = async () => {
|
// const navigateToPayPal = async () => {
|
||||||
const { subscription_receipt } = await api.createSubscriptionReceipt({
|
// const { subscription_receipt } = await api.createSubscriptionReceipt({
|
||||||
token,
|
// token,
|
||||||
itemInterval: "year",
|
// itemInterval: "year",
|
||||||
way: "paypal",
|
// way: "paypal",
|
||||||
subscription_receipt: {
|
// subscription_receipt: {
|
||||||
sub_plan_id: activeSubPlan?.id || "",
|
// sub_plan_id: activeSubPlan?.id || "",
|
||||||
},
|
// },
|
||||||
} as PayPalReceiptPayload);
|
// } as PayPalReceiptPayload);
|
||||||
const url = subscription_receipt.data.links?.find(
|
// const url = subscription_receipt.data.links?.find(
|
||||||
(link) => link.rel === "approve"
|
// (link) => link.rel === "approve"
|
||||||
)?.href;
|
// )?.href;
|
||||||
if (!url?.length) {
|
// if (!url?.length) {
|
||||||
return setOpenErrorModal(true);
|
// return setOpenErrorModal(true);
|
||||||
}
|
// }
|
||||||
window.location.href = url;
|
// window.location.href = url;
|
||||||
};
|
// };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -84,7 +84,7 @@ function PaymentPage(): JSX.Element {
|
|||||||
{t("choose_payment")}
|
{t("choose_payment")}
|
||||||
</Title>
|
</Title>
|
||||||
<div className="payment-buttons-container">
|
<div className="payment-buttons-container">
|
||||||
<PayPalButton onClick={navigateToPayPal} />
|
{/* <PayPalButton onClick={navigateToPayPal} /> */}
|
||||||
<StripeButton onClick={navigateToStripe} />
|
<StripeButton onClick={navigateToStripe} />
|
||||||
</div>
|
</div>
|
||||||
<p className="payment-warining">
|
<p className="payment-warining">
|
||||||
|
|||||||
@ -9,7 +9,11 @@ import {
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
|
|
||||||
export default function CheckoutForm() {
|
interface ICheckoutFormProps {
|
||||||
|
children?: JSX.Element | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function CheckoutForm({ children }: ICheckoutFormProps) {
|
||||||
const stripe = useStripe();
|
const stripe = useStripe();
|
||||||
const elements = useElements();
|
const elements = useElements();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -46,6 +50,7 @@ export default function CheckoutForm() {
|
|||||||
id="payment-form"
|
id="payment-form"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
|
{children ? children : null}
|
||||||
<PaymentElement />
|
<PaymentElement />
|
||||||
<MainButton color="blue" disabled={isProcessing} id="submit">
|
<MainButton color="blue" disabled={isProcessing} id="submit">
|
||||||
<span id="button-text">
|
<span id="button-text">
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { useSelector } from "react-redux";
|
|||||||
import { selectors } from "@/store";
|
import { selectors } from "@/store";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import routes from "@/routes";
|
import routes from "@/routes";
|
||||||
|
import SubPlanInformation from "../SubPlanInformation";
|
||||||
|
|
||||||
export function StripePage(): JSX.Element {
|
export function StripePage(): JSX.Element {
|
||||||
const api = useApi();
|
const api = useApi();
|
||||||
@ -55,7 +56,9 @@ export function StripePage(): JSX.Element {
|
|||||||
) : null}
|
) : null}
|
||||||
{stripePromise && clientSecret && (
|
{stripePromise && clientSecret && (
|
||||||
<Elements stripe={stripePromise} options={{ clientSecret }}>
|
<Elements stripe={stripePromise} options={{ clientSecret }}>
|
||||||
<CheckoutForm />
|
<CheckoutForm>
|
||||||
|
{activeSubPlan && <SubPlanInformation subPlan={activeSubPlan} />}
|
||||||
|
</CheckoutForm>
|
||||||
</Elements>
|
</Elements>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
17
src/components/SubPlanInformation/TotalToday/index.tsx
Normal file
17
src/components/SubPlanInformation/TotalToday/index.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import styles from "./styles.module.css";
|
||||||
|
import Title from "@/components/Title";
|
||||||
|
|
||||||
|
interface ITotalTodayProps {
|
||||||
|
total: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function TotalToday({ total }: ITotalTodayProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<Title className={styles.text} variant="h3">{"Total today:"}</Title>
|
||||||
|
<Title className={styles.text} variant="h3">{total}</Title>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TotalToday;
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #e7f5ee;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #000;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
28
src/components/SubPlanInformation/index.tsx
Normal file
28
src/components/SubPlanInformation/index.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import styles from "./styles.module.css";
|
||||||
|
import { ISubscriptionPlan } from "@/api/resources/SubscriptionPlans";
|
||||||
|
import TotalToday from "./TotalToday";
|
||||||
|
|
||||||
|
interface ISubPlanInformationProps {
|
||||||
|
subPlan: ISubscriptionPlan;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPrice = (plan: ISubscriptionPlan): string => {
|
||||||
|
return `$${(plan.trial?.price_cents || 0) / 100}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
function SubPlanInformation({
|
||||||
|
subPlan,
|
||||||
|
}: ISubPlanInformationProps): JSX.Element {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<TotalToday total={getPrice(subPlan)} />
|
||||||
|
<p className={styles.description}>
|
||||||
|
{t("auweb.pay.information").replaceAll("%@", getPrice(subPlan))}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SubPlanInformation;
|
||||||
16
src/components/SubPlanInformation/styles.module.css
Normal file
16
src/components/SubPlanInformation/styles.module.css
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 300px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666666;
|
||||||
|
text-align: left;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 16px;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user