From 037e1078ec1186e915d64f49f1b59793c9fdf54f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B5=D0=BD=D0=B8=D1=81=20=D0=9A=D0=B0=D1=82=D0=B0?= =?UTF-8?q?=D0=B5=D0=B2?= Date: Tue, 23 Jan 2024 00:15:05 +0000 Subject: [PATCH] feat: questionnaire --- src/api/resources/UserSubscriptionReceipts.ts | 1 + src/components/App/index.tsx | 4 +- .../methods/Stripe/CheckoutForm.tsx | 29 ++++--- src/components/PaymentPage/results/index.tsx | 80 ++++++++++++++++++- .../PaymentPage/results/styles.module.css | 15 ++++ .../StripePage/ApplePayButton/index.tsx | 23 +++++- src/components/StripePage/index.tsx | 40 ++-------- src/components/pages/WorksForUs/index.tsx | 12 +-- 8 files changed, 149 insertions(+), 55 deletions(-) create mode 100644 src/components/PaymentPage/results/styles.module.css diff --git a/src/api/resources/UserSubscriptionReceipts.ts b/src/api/resources/UserSubscriptionReceipts.ts index b5f5960..5ac1ec4 100644 --- a/src/api/resources/UserSubscriptionReceipts.ts +++ b/src/api/resources/UserSubscriptionReceipts.ts @@ -66,6 +66,7 @@ export interface SubscriptionReceipt { autorenewable: boolean; error: string; links?: IPayPalLink[]; + stripe_status?: string; }; } diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 0f7ed0e..d5420a9 100755 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -232,7 +232,9 @@ function App(): JSX.Element { } - /> + > + } /> + } diff --git a/src/components/PaymentPage/methods/Stripe/CheckoutForm.tsx b/src/components/PaymentPage/methods/Stripe/CheckoutForm.tsx index 305ceae..d5d8ceb 100644 --- a/src/components/PaymentPage/methods/Stripe/CheckoutForm.tsx +++ b/src/components/PaymentPage/methods/Stripe/CheckoutForm.tsx @@ -13,9 +13,13 @@ import { useNavigate } from "react-router-dom"; interface ICheckoutFormProps { children?: JSX.Element | null; + subscriptionReceiptId?: string; } -export default function CheckoutForm({ children }: ICheckoutFormProps) { +export default function CheckoutForm({ + children, + subscriptionReceiptId, +}: ICheckoutFormProps) { const stripe = useStripe(); const elements = useElements(); const dispatch = useDispatch(); @@ -28,7 +32,6 @@ export default function CheckoutForm({ children }: ICheckoutFormProps) { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); - if (!stripe || !elements) { return; } @@ -39,7 +42,7 @@ export default function CheckoutForm({ children }: ICheckoutFormProps) { const { error } = await stripe.confirmPayment({ elements, confirmParams: { - return_url: `https://${window.location.host}/payment/result`, + return_url: `https://${window.location.host}/payment/result/${subscriptionReceiptId}`, }, }); if (error) { @@ -48,14 +51,12 @@ export default function CheckoutForm({ children }: ICheckoutFormProps) { dispatch(actions.status.update("subscribed")); navigate(routes.client.paymentSuccess()); } - } catch(error) { - console.log('error -> ', error); + } catch (error) { + console.log("error -> ", error); setMessage("Oops! Something went wrong."); - } finally { + } finally { setIsProcessing(false); - } - - + } }; return ( @@ -66,12 +67,18 @@ export default function CheckoutForm({ children }: ICheckoutFormProps) { > {children ? children : null} setFormReady(true)} /> - + {isProcessing ? "Processing..." : "Pay now"} - {message} + + {message} + ); } diff --git a/src/components/PaymentPage/results/index.tsx b/src/components/PaymentPage/results/index.tsx index 4871444..1f77ee2 100644 --- a/src/components/PaymentPage/results/index.tsx +++ b/src/components/PaymentPage/results/index.tsx @@ -1,15 +1,91 @@ import { useNavigate } from "react-router-dom"; import routes from "@/routes"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { useSearchParams } from "react-router-dom"; import { useDispatch } from "react-redux"; import { actions } from "@/store"; +// import { SubscriptionReceipts, useApi, useApiCall } from "@/api"; +// import { useAuth } from "@/auth"; +import styles from "./styles.module.css"; +import Loader from "@/components/Loader"; function PaymentResultPage(): JSX.Element { + // const api = useApi(); + // const { token } = useAuth(); const navigate = useNavigate(); const dispatch = useDispatch(); const [searchParams] = useSearchParams(); const status = searchParams.get("redirect_status"); + status; + // const { id } = useParams(); + // const requestTimeOutRef = useRef(); + const [isLoading] = useState(true); + // const [subscriptionReceipt, setSubscriptionReceipt] = + // useState(); + + // const loadData = useCallback(async () => { + // if (!id) { + // return null; + // } + // const getSubscriptionReceiptStatus = async () => { + // const { subscription_receipt } = await api.getSubscriptionReceipt({ + // token, + // id, + // }); + // const { stripe_status } = subscription_receipt.data; + // if (stripe_status === "incomplete") { + // requestTimeOutRef.current = setTimeout( + // getSubscriptionReceiptStatus, + // 3000 + // ); + // } + // setSubscriptionReceipt(subscription_receipt); + // return { subscription_receipt }; + // }; + // return getSubscriptionReceiptStatus(); + // }, [api, id, token]); + + // useApiCall(loadData); + + // useEffect(() => { + // if (!subscriptionReceipt) { + // if (id?.length) return; + // return () => { + // if (requestTimeOutRef.current) { + // clearTimeout(requestTimeOutRef.current); + // } + // navigate(routes.client.paymentFail()); + // }; + // } + // const { stripe_status } = subscriptionReceipt.data; + // if (stripe_status === "succeeded") { + // dispatch(actions.status.update("subscribed")); + // setIsLoading(false); + // return () => { + // if (requestTimeOutRef.current) { + // clearTimeout(requestTimeOutRef.current); + // } + // navigate(routes.client.paymentSuccess()); + // }; + // } else if (stripe_status === "payment_failed") { + // setIsLoading(false); + + // return () => { + // if (requestTimeOutRef.current) { + // clearTimeout(requestTimeOutRef.current); + // } + // navigate(routes.client.paymentFail()); + // }; + // } + // }, [dispatch, id, navigate, subscriptionReceipt]); + + // useEffect(() => { + // return () => { + // if (requestTimeOutRef.current) { + // clearTimeout(requestTimeOutRef.current); + // } + // }; + // }, []); useEffect(() => { if (status === "succeeded") { @@ -19,7 +95,7 @@ function PaymentResultPage(): JSX.Element { return navigate(routes.client.paymentFail()); }, [navigate, status, dispatch]); - return <>; + return
{isLoading && }
; } export default PaymentResultPage; diff --git a/src/components/PaymentPage/results/styles.module.css b/src/components/PaymentPage/results/styles.module.css new file mode 100644 index 0000000..343746f --- /dev/null +++ b/src/components/PaymentPage/results/styles.module.css @@ -0,0 +1,15 @@ +.page { + position: relative; + height: fit-content; + min-height: calc(100vh - 103px); + flex: auto; + /* max-height: -webkit-fill-available; */ + color: #fff; + overflow-y: scroll; + padding-bottom: 180px; + display: flex; + flex-direction: column; + gap: 20px; + align-items: center; + justify-content: center; +} diff --git a/src/components/StripePage/ApplePayButton/index.tsx b/src/components/StripePage/ApplePayButton/index.tsx index acf9c2d..0039355 100644 --- a/src/components/StripePage/ApplePayButton/index.tsx +++ b/src/components/StripePage/ApplePayButton/index.tsx @@ -7,15 +7,25 @@ import { import { PaymentRequest } from "@stripe/stripe-js"; import { ISubscriptionPlan } from "@/api/resources/SubscriptionPlans"; import styles from "./styles.module.css"; +import { useDispatch } from "react-redux"; +import { useNavigate } from "react-router-dom"; +import routes from "@/routes"; interface ApplePayButtonProps { activeSubPlan: ISubscriptionPlan | null; client_secret: string; + subscriptionReceiptId?: string; } -function ApplePayButton({ activeSubPlan, client_secret }: ApplePayButtonProps) { +function ApplePayButton({ + activeSubPlan, + client_secret, + subscriptionReceiptId, +}: ApplePayButtonProps) { const stripe = useStripe(); const elements = useElements(); + const dispatch = useDispatch(); + const navigate = useNavigate(); const [paymentRequest, setPaymentRequest] = useState( null ); @@ -63,13 +73,22 @@ function ApplePayButton({ activeSubPlan, client_secret }: ApplePayButtonProps) { return; } + navigate(`${routes.client.paymentResult()}/${subscriptionReceiptId}`); // Show a success message to your customer // There's a risk of the customer closing the window before callback // execution. Set up a webhook or plugin to listen for the // payment_intent.succeeded event that handles any business critical // post-payment actions. }); - }, [activeSubPlan, client_secret, elements, stripe]); + }, [ + activeSubPlan, + client_secret, + dispatch, + elements, + navigate, + stripe, + subscriptionReceiptId, + ]); return ( <> diff --git a/src/components/StripePage/index.tsx b/src/components/StripePage/index.tsx index b4046a2..012fc84 100644 --- a/src/components/StripePage/index.tsx +++ b/src/components/StripePage/index.tsx @@ -28,21 +28,12 @@ export function StripePage(): JSX.Element { useState | null>(null); const [subPlans, setSubPlans] = useState(null); const [clientSecret, setClientSecret] = useState(""); + const [subscriptionReceiptId, setSubscriptionReceiptId] = + useState(""); const [isLoading, setIsLoading] = useState(true); if (!activeSubPlan) { navigate(routes.client.priceList()); } - // const timeoutRef = useRef(); - - // const appleReceipt = async () => { - // const { subscription_receipt } = await api.createSubscriptionReceipt({ - // token, - // receiptData: "", - // autorenewable: true, - // sandbox: true, - // }); - // console.log(subscription_receipt); - // }; useEffect(() => { (async () => { @@ -59,26 +50,6 @@ export function StripePage(): JSX.Element { })(); }, [activeSubPlan, api, locale, navigate]); - // useEffect(() => { - // timeoutRef.current = setTimeout(async () => { - // const { subscription_receipt } = await api.createSubscriptionReceipt({ - // token, - // way: "stripe", - // subscription_receipt: { - // sub_plan_id: activeSubPlan?.id || "stripe.7", - // }, - // }); - // const { client_secret } = subscription_receipt.data; - // setClientSecret(client_secret); - // setIsLoading(false); - // }, 4000); - // return () => { - // if (timeoutRef.current) { - // clearTimeout(timeoutRef.current); - // } - // }; - // }, [api, token]); - useEffect(() => { (async () => { const { subscription_receipt } = await api.createSubscriptionReceipt({ @@ -88,7 +59,9 @@ export function StripePage(): JSX.Element { sub_plan_id: activeSubPlan?.id || "stripe.7", }, }); + const { id } = subscription_receipt; const { client_secret } = subscription_receipt.data; + setSubscriptionReceiptId(id); setClientSecret(client_secret); setIsLoading(false); })(); @@ -109,16 +82,17 @@ export function StripePage(): JSX.Element {

{email}

)} - {stripePromise && clientSecret && ( + {stripePromise && clientSecret && subscriptionReceiptId && ( {activeSubPlan && ( )} - + )} diff --git a/src/components/pages/WorksForUs/index.tsx b/src/components/pages/WorksForUs/index.tsx index 397f040..5f0764a 100644 --- a/src/components/pages/WorksForUs/index.tsx +++ b/src/components/pages/WorksForUs/index.tsx @@ -1,14 +1,14 @@ -import Title from "@/components/Title"; +// import Title from "@/components/Title"; import styles from "./styles.module.css"; import MainButton from "@/components/MainButton"; import { useNavigate } from "react-router-dom"; import routes from "@/routes"; -import { useSelector } from "react-redux"; -import { selectors } from "@/store"; +// import { useSelector } from "react-redux"; +// import { selectors } from "@/store"; function WorksForUsPage() { const navigate = useNavigate(); - const { relationshipProblem } = useSelector(selectors.selectQuestionnaire); + // const { relationshipProblem } = useSelector(selectors.selectQuestionnaire); const handleBack = () => { navigate(-1); @@ -22,7 +22,7 @@ function WorksForUsPage() {
The starry key
- {relationshipProblem === "very_unhappy" && ( + {/* {relationshipProblem === "very_unhappy" && ( We’ve got you covered! We’ll start with small, personalized insights into you and your partner’s personality traits. @@ -40,7 +40,7 @@ function WorksForUsPage() { <br /> Let's find out what's working (and what isn’t) and go from there. - )} + )} */}

Now, we need some information about{" "} Your Partner’s Profile to create