w-aura/src/hooks/payment/useSinglePayment.ts
2024-04-18 21:54:57 +00:00

182 lines
5.0 KiB
TypeScript

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<SinglePayment.ResponsePost>();
const [product, setProduct] = useState<SinglePayment.ResponseGet>();
const [error, setError] = useState<IErrorSinglePayment>(
{} 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<SinglePayment.ResponsePost>) => {
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]
);
};