diff --git a/src/api/useApiCall.ts b/src/api/useApiCall.ts index f82f06a..8da2382 100644 --- a/src/api/useApiCall.ts +++ b/src/api/useApiCall.ts @@ -11,10 +11,13 @@ interface HookResult { type ApiMethod = () => Promise type ApiCallState = 'idle' | 'pending' | 'success' | 'error' -export function useApiCall(apiMethod: ApiMethod): HookResult { +export function useApiCall( + apiMethod: ApiMethod, + startState: ApiCallState = 'idle' +): HookResult { const [data, setData] = useState(null) const [error, setError] = useState(null) - const [state, setState] = useState('idle') + const [state, setState] = useState(startState) const isPending = state === 'pending' useEffect(() => { diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index ecb9088..f834438 100755 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -113,7 +113,6 @@ import AddConsultationPage from "../pages/AdditionalPurchases/pages/AddConsultat import StepsManager from "@/components/palmistry/steps-manager/steps-manager"; import Advisors from "../pages/Advisors"; import AdvisorChatPage from "../pages/AdvisorChat"; -import PaymentWithEmailPage from "../pages/PaymentWithEmailPage"; import SuccessPaymentPage from "../pages/PaymentWithEmailPage/ResultPayment/SuccessPaymentPage"; import FailPaymentPage from "../pages/PaymentWithEmailPage/ResultPayment/FailPaymentPage"; import { useSchemeColorByElement } from "@/hooks/useSchemeColorByElement"; @@ -121,6 +120,7 @@ import GetInformationPartnerPage from "../pages/GetInformationPartner"; import BirthPlacePage from "../pages/BirthPlacePage"; import LoadingPage from "../pages/LoadingPage"; import { EProductKeys, productUrls } from "@/data/products"; +import SinglePaymentPage from "../pages/SinglePaymentPage"; const isProduction = import.meta.env.MODE === "production"; @@ -146,7 +146,7 @@ function App(): JSX.Element { } else { dispatch(actions.userConfig.addIsForceShortPath(false)); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const isForceShortPath = useSelector(selectors.selectIsForceShortPath); @@ -276,10 +276,10 @@ function App(): JSX.Element { force: routes.client.epeBirthdate(), }, purchasedProduct: { - no: routes.client.singlePaymentShortPath("moons.pdf.aura"), + no: routes.client.epePayment(), }, }} - requiredParameters={[]} + requiredParameters={[isForceShortPath || gender]} /> } > @@ -297,7 +297,7 @@ function App(): JSX.Element { no: routes.client.epeGender(), }, purchasedProduct: { - no: routes.client.singlePaymentShortPath("moons.pdf.aura"), + no: routes.client.epePayment(), }, }} requiredParameters={[isForceShortPath || gender]} @@ -309,6 +309,54 @@ function App(): JSX.Element { element={} /> + + } + > + + } + /> + + + } + > + + } + /> + } > @@ -373,7 +421,7 @@ function App(): JSX.Element { no: routes.client.advisorChatGender(), }, purchasedProduct: { - no: routes.client.singlePaymentShortPath("chat.aura"), + no: routes.client.advisorChatPayment(), }, }} requiredParameters={[isForceShortPath || gender]} @@ -395,7 +443,7 @@ function App(): JSX.Element { force: routes.client.advisorChatBirthdate(), }, purchasedProduct: { - no: routes.client.singlePaymentShortPath("chat.aura"), + no: routes.client.advisorChatPayment(), }, }} requiredParameters={[birthdate, isForceShortPath || gender]} @@ -417,7 +465,7 @@ function App(): JSX.Element { force: routes.client.advisorChatBirthdate(), }, purchasedProduct: { - no: routes.client.singlePaymentShortPath("chat.aura"), + no: routes.client.advisorChatPayment(), }, }} requiredParameters={[birthdate, isForceShortPath || gender]} @@ -429,6 +477,68 @@ function App(): JSX.Element { element={} /> + + + } + > + + } + /> + + + + } + > + + } + /> + + } @@ -443,15 +553,14 @@ function App(): JSX.Element { productKey={EProductKeys["chat.aura"]} redirectUrls={{ user: { - no: routes.client.advisorChatGender(), - force: routes.client.advisorChatBirthdate(), + no: routes.client.advisorChatEmail(), }, data: { no: routes.client.advisorChatGender(), force: routes.client.advisorChatBirthdate(), }, purchasedProduct: { - no: routes.client.singlePaymentShortPath("chat.aura"), + no: routes.client.advisorChatPayment(), }, }} requiredParameters={[ @@ -470,7 +579,7 @@ function App(): JSX.Element { {/* Advisor short path */} {/* Single Payment Page Short Path */} - } > } /> - + */} {/* Single Payment Page Short Path */} {/* Test Routes Start */} @@ -989,9 +1098,10 @@ function ShortPathOutlet(props: IShortPathOutletProps): JSX.Element { error: "Something went wrong", }; } - }, [api, productKey, token, user?.email]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [token]); - const { data, isPending } = useApiCall(loadData); + const { data, isPending } = useApiCall(loadData, "pending"); if (isPending) { return ; diff --git a/src/components/BirthdayPage/index.tsx b/src/components/BirthdayPage/index.tsx index 27f4c3e..38ecc3a 100644 --- a/src/components/BirthdayPage/index.tsx +++ b/src/components/BirthdayPage/index.tsx @@ -19,7 +19,7 @@ function BirthdayPage(): JSX.Element { const [isDisabled, setIsDisabled] = useState(true); let nextRoute = routes.client.didYouKnow(); if (window.location.href.includes("/epe/")) { - nextRoute = routes.client.singlePaymentShortPath("moons.pdf.aura"); + nextRoute = routes.client.epeEmail(); } if (window.location.href.includes("/advisor-chat/")) { nextRoute = routes.client.advisorChatBirthtime(); diff --git a/src/components/EmailEnterPage/index.tsx b/src/components/EmailEnterPage/index.tsx index c262d42..13d7228 100755 --- a/src/components/EmailEnterPage/index.tsx +++ b/src/components/EmailEnterPage/index.tsx @@ -17,7 +17,15 @@ import routes from "@/routes"; import NameInput from "./NameInput"; import { ISubscriptionPlan } from "@/api/resources/SubscriptionPlans"; -function EmailEnterPage(): JSX.Element { +interface IEmailEnterPage { + redirectUrl?: string; + isRequiredName?: boolean; +} + +function EmailEnterPage({ + redirectUrl = routes.client.emailConfirm(), + isRequiredName = false, +}: IEmailEnterPage): JSX.Element { const api = useApi(); const { signUp } = useAuth(); const { t, i18n } = useTranslation(); @@ -28,7 +36,7 @@ function EmailEnterPage(): JSX.Element { const birthday = useSelector(selectors.selectBirthday); const [isDisabled, setIsDisabled] = useState(true); const [isValidEmail, setIsValidEmail] = useState(false); - const [isValidName, setIsValidName] = useState(true); + const [isValidName, setIsValidName] = useState(!isRequiredName); const [isLoading, setIsLoading] = useState(false); const [isAuth, setIsAuth] = useState(false); const [apiError, setApiError] = useState(null); @@ -41,9 +49,11 @@ function EmailEnterPage(): JSX.Element { const timezone = getClientTimezone(); const locale = i18n.language; const { subPlan } = useParams(); - const { gender, flowChoice, birthPlace } = useSelector( - selectors.selectQuestionnaire - ); + const { + gender, + birthPlace, + // flowChoice + } = useSelector(selectors.selectQuestionnaire); useEffect(() => { if (subPlan) { @@ -117,9 +127,9 @@ function EmailEnterPage(): JSX.Element { user: { profile_attributes: { birthday, - gender, + gender: gender.length ? gender : "male", full_name: name, - relationship_status: flowChoice, + // relationship_status: !!flowChoice.length ? flowChoice : null, }, birthplace_attributes: { address: birthPlace }, }, @@ -147,7 +157,7 @@ function EmailEnterPage(): JSX.Element { setIsLoading(false); setIsAuth(true); setTimeout(() => { - navigate(routes.client.emailConfirm()); + navigate(redirectUrl); }, 1000); } catch (error) { console.error(error); @@ -170,7 +180,7 @@ function EmailEnterPage(): JSX.Element { value={name} placeholder="Your name" onValid={handleValidName} - onInvalid={() => setIsValidName(true)} + onInvalid={() => setIsValidName(!isRequiredName)} /> { - navigate(routes.client.singlePaymentShortPath("chat.aura")); + navigate(routes.client.advisorChatEmail()); }; return ( diff --git a/src/components/pages/SinglePaymentPage/index.tsx b/src/components/pages/SinglePaymentPage/index.tsx new file mode 100644 index 0000000..195b814 --- /dev/null +++ b/src/components/pages/SinglePaymentPage/index.tsx @@ -0,0 +1,81 @@ +import Title from "@/components/Title"; +import styles from "./styles.module.css"; +import PaymentForm from "../PaymentWithEmailPage/PaymentForm"; +import { getPriceCentsToDollars } from "@/services/price"; +import { useSinglePayment } from "@/hooks/payment/useSinglePayment"; +import routes from "@/routes"; +import { useAuth } from "@/auth"; +import Loader, { LoaderColor } from "@/components/Loader"; +import { useCallback, useEffect } from "react"; +import { EProductKeys } from "@/data/products"; + +interface ISinglePaymentPage { + productId: EProductKeys; + isForce?: boolean; +} + +function SinglePaymentPage({ productId, isForce = false }: ISinglePaymentPage) { + const { + product, + paymentIntent, + isLoading: isLoadingSinglePayment, + error: errorSinglePayment, + createSinglePayment, + } = useSinglePayment(); + const { user: userFromStore, token: tokenFromStore } = useAuth(); + + const returnUrl = `${window.location.protocol}//${ + window.location.host + }${routes.client.paymentResult()}`; + + const createPayment = useCallback(async () => { + if (!tokenFromStore.length || !userFromStore) { + return; + } + await createSinglePayment({ + user: userFromStore, + token: tokenFromStore, + targetProductKey: productId || "", + returnUrl, + }); + }, [ + createSinglePayment, + productId, + returnUrl, + tokenFromStore, + userFromStore, + ]); + + useEffect(() => { + createPayment(); + }, [createPayment]); + + return ( +
+ {isLoadingSinglePayment && } + {!isLoadingSinglePayment && + paymentIntent && + "paymentIntent" in paymentIntent && + !!tokenFromStore.length && ( + <> + + {getPriceCentsToDollars(product?.amount || 0)}$ + + + + )} + {errorSinglePayment?.error && ( + + Something went wrong:{" "} + {errorSinglePayment?.error?.length && errorSinglePayment?.error} + + )} +
+ ); +} + +export default SinglePaymentPage; \ No newline at end of file diff --git a/src/components/pages/SinglePaymentPage/styles.module.css b/src/components/pages/SinglePaymentPage/styles.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/routes.ts b/src/routes.ts index 9e57abc..00f0928 100755 --- a/src/routes.ts +++ b/src/routes.ts @@ -128,6 +128,7 @@ const routes = { // Email - Pay - Email epeGender: () => [host, "epe", "gender"].join("/"), epeBirthdate: () => [host, "epe", "birthdate"].join("/"), + epeEmail: () => [host, "epe", "email"].join("/"), epePayment: () => [host, "epe", "payment"].join("/"), epeSuccessPayment: () => [host, "epe", "success-payment"].join("/"), epeFailPayment: () => [host, "epe", "fail-payment"].join("/"), @@ -138,6 +139,7 @@ const routes = { advisorChatBirthtime: () => [host, "advisor-chat", "birthtime"].join("/"), advisorChatBirthPlace: () => [host, "advisor-chat", "birth-place"].join("/"), + advisorChatEmail: () => [host, "advisor-chat", "email"].join("/"), advisorChatPayment: () => [host, "advisor-chat", "payment"].join("/"), advisorChatSuccessPayment: () => [host, "advisor-chat", "success-payment"].join("/"),