import { ApiError, SinglePayment, useApi } from "@/api"; import { User } from "@/api/resources/User"; import { AuthToken } from "@/api/types"; import { productUrls } from "@/data/products"; import routes from "@/routes"; import { getZodiacSignByDate } from "@/services/zodiac-sign"; import { selectors } from "@/store"; import { useCallback, useMemo, useState } from "react"; import { useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; interface ICreateSinglePaymentProps { user: User; token: AuthToken; targetProductKey: string; returnUrl: string; } interface IErrorSinglePayment { error?: string; } export const useSinglePayment = () => { const api = useApi(); const navigate = useNavigate(); const [paymentIntent, setPaymentIntent] = useState(); const [product, setProduct] = useState(); const [error, setError] = useState( {} as IErrorSinglePayment ); const [isLoading, setIsLoading] = useState(false); const { gender } = useSelector(selectors.selectQuestionnaire); const birthday = useSelector(selectors.selectBirthday); const getCurrentProduct = useCallback( async (token: AuthToken, targetProductKey: string) => { const productsSinglePayment = await api.getSinglePaymentProducts({ token, }); const currentProduct = productsSinglePayment.find( (product) => product.key === targetProductKey ); return currentProduct; }, [api] ); const handlerPaymentIntentResult = useCallback( (paymentIntent: SinglePayment.ResponsePost, type: string) => { if (!("payment" in paymentIntent)) return; let status = "failed"; if (paymentIntent.payment.status === "paid") { status = "succeeded"; } return navigate( `${routes.client.paymentResult()}?redirect_status=${status}&redirect_type=${type}` ); }, [navigate] ); const checkProductPurchased = useCallback( async (email: string, productKey: string, token: AuthToken) => { try { const purchased = await api.checkProductPurchased({ email, productKey, token, }); if ("active" in purchased && purchased.active) { return true; } return false; } catch (error) { console.error(error); return false; } }, [api] ); const createSinglePayment = useCallback( async ({ user, token, targetProductKey, returnUrl, }: ICreateSinglePaymentProps) => { setIsLoading(true); const product = await getCurrentProduct(token, targetProductKey); if (!product) { setError({ error: "Product not found" }); setIsLoading(false); return; } setProduct(product); const isPurchased = await checkProductPurchased( user?.email || "", targetProductKey, token ); if (isPurchased && productUrls[targetProductKey]?.length) { return navigate(productUrls[targetProductKey]); } let _gender = "male"; if (gender.length) { _gender = gender; } if (user.profile.gender?.length) { _gender = user.profile.gender; } const paymentIntent = await api.createSinglePayment({ token, data: { user: { id: `${user?.id}`, email: user?.email, name: user.username || "", sign: user?.profile?.sign?.sign || getZodiacSignByDate(user.profile.birthday || birthday || ""), age: user?.profile?.age?.years || 1, gender: _gender, }, partner: { sign: null, age: null, }, paymentInfo: { productId: product?.productId || "", key: product?.key || "", }, return_url: returnUrl, }, }).catch((error: ApiError) => { if (error.responseData && "message" in error.responseData) { setError({ error: error.responseData.message }); } else { setError({ error: error.message }); } setIsLoading(false); return; }); if (typeof paymentIntent !== "object") { return; } if ("message" in paymentIntent) { setError({ error: paymentIntent.message }); setIsLoading(false); return; } handlerPaymentIntentResult(paymentIntent, targetProductKey); setPaymentIntent(paymentIntent); setIsLoading(false); return paymentIntent; }, [ api, birthday, checkProductPurchased, gender, getCurrentProduct, handlerPaymentIntentResult, navigate, ] ); return useMemo( () => ({ product, paymentIntent, createSinglePayment, isLoading, error, }), [product, paymentIntent, createSinglePayment, isLoading, error] ); };