w-aura/src/components/pages/PaymentWithEmailPage/index.tsx
2024-04-05 18:42:11 +04:00

280 lines
8.3 KiB
TypeScript

import EmailInput from "@/components/EmailEnterPage/EmailInput";
import styles from "./styles.module.css";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { actions, selectors } from "@/store";
import { useDispatch, useSelector } from "react-redux";
import MainButton from "@/components/MainButton";
import Loader, { LoaderColor } from "@/components/Loader";
import { useAuth } from "@/auth";
import { ApiError, extractErrorMessage, useApi } from "@/api";
import { getClientTimezone } from "@/locales";
import ErrorText from "@/components/ErrorText";
import Title from "@/components/Title";
import NameInput from "@/components/EmailEnterPage/NameInput";
import {
ResponseGet,
ResponsePost,
ResponsePostExistPaymentData,
} from "@/api/resources/SinglePayment";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import PaymentForm from "./PaymentForm";
import { getPriceCentsToDollars } from "@/services/price";
import { createSinglePayment } from "@/services/singlePayment";
function PaymentWithEmailPage() {
const { t, i18n } = useTranslation();
const tokenFromStore = useSelector(selectors.selectToken);
const { signUp, user: userFromStore } = useAuth();
const api = useApi();
const navigate = useNavigate();
const timezone = getClientTimezone();
const dispatch = useDispatch();
const birthday = useSelector(selectors.selectBirthday);
const { gender } = useSelector(selectors.selectQuestionnaire);
const locale = i18n.language;
const [email, setEmail] = useState("");
const [name, setName] = useState("");
const [isValidEmail, setIsValidEmail] = useState(false);
const [isValidName, setIsValidName] = useState(true);
const [isDisabled, setIsDisabled] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [isLoadingPage, setIsLoadingPage] = useState(false);
const [isAuth, setIsAuth] = useState(false);
const [apiError, setApiError] = useState<ApiError | null>(null);
const [error, setError] = useState<boolean>(false);
const [paymentIntent, setPaymentIntent] = useState<
ResponsePost | ResponsePostExistPaymentData | null
>(null);
const [currentProduct, setCurrentProduct] = useState<ResponseGet>();
const returnUrl = `${window.location.protocol}//${window.location.host}/payment/result/?type=epe`;
useEffect(() => {
if (isValidName && isValidEmail) {
setIsDisabled(false);
} else {
setIsDisabled(true);
}
}, [isValidEmail, email, isValidName, name]);
const handleValidEmail = (email: string) => {
dispatch(actions.form.addEmail(email));
setEmail(email);
setIsValidEmail(true);
};
const handleValidName = (name: string) => {
setName(name);
setIsValidName(true);
};
const authorization = async () => {
try {
setIsLoading(true);
const auth = await api.auth({ email, timezone, locale });
const {
auth: { token, user },
} = auth;
signUp(token, user);
const payload = {
user: {
profile_attributes: {
birthday,
full_name: name,
},
},
token,
};
const updatedUser = await api.updateUser(payload).catch((error) => {
console.log("Error: ", error);
});
if (updatedUser?.user) {
dispatch(actions.user.update(updatedUser.user));
}
if (name) {
dispatch(
actions.user.update({
username: name,
})
);
}
dispatch(actions.status.update("registred"));
setIsAuth(true);
const userUpdated = await api.getUser({ token });
return { user: userUpdated?.user, token };
} catch (error) {
console.error(error);
if (error instanceof ApiError) {
setApiError(error as ApiError);
} else {
setError(true);
}
}
};
const getCurrentProduct = async (token: string) => {
const productsSinglePayment = await api.getSinglePaymentProducts({
token,
});
const currentProduct = productsSinglePayment.find(
(product) => product.key === "moons.pdf.aura"
);
return currentProduct;
};
const handleClick = async () => {
const authData = await authorization();
if (!authData) {
return;
}
const { user, token } = authData;
const currentProduct = await getCurrentProduct(token);
if (!currentProduct) {
setError(true);
return;
}
setCurrentProduct(currentProduct);
const { productId, key } = currentProduct;
const paymentInfo = {
productId,
key,
};
const paymentIntent = await createSinglePayment(
user,
paymentInfo,
token,
email,
name,
birthday,
returnUrl,
api,
gender
);
setPaymentIntent(paymentIntent);
setIsLoading(false);
if ("payment" in paymentIntent) {
if (paymentIntent.payment.status === "paid")
return navigate(routes.client.epeSuccessPayment());
return navigate(routes.client.epeFailPayment());
}
};
const handleAuthUser = useCallback(async () => {
if (!tokenFromStore.length || !userFromStore) {
return;
}
setIsLoadingPage(true);
const currentProduct = await getCurrentProduct(tokenFromStore);
if (!currentProduct) {
setError(true);
return;
}
setCurrentProduct(currentProduct);
const { productId, key } = currentProduct;
const paymentInfo = {
productId,
key,
};
const paymentIntent = await createSinglePayment(
userFromStore,
paymentInfo,
tokenFromStore,
userFromStore.email,
userFromStore.profile.full_name,
userFromStore.profile.birthday,
returnUrl,
api,
gender
);
setPaymentIntent(paymentIntent);
setIsLoadingPage(false);
setIsLoading(false);
if ("payment" in paymentIntent) {
if (paymentIntent.payment.status === "paid")
return navigate(routes.client.epeSuccessPayment());
return navigate(routes.client.epeFailPayment());
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
handleAuthUser();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div className={`${styles.page} page`}>
{isLoadingPage && <Loader color={LoaderColor.Black} />}
{!isLoadingPage &&
paymentIntent &&
"paymentIntent" in paymentIntent &&
!!tokenFromStore.length && (
<>
<Title variant="h1" className={styles.title}>
{getPriceCentsToDollars(currentProduct?.amount || 0)}$
</Title>
<PaymentForm
stripePublicKey={paymentIntent.paymentIntent.data.public_key}
clientSecret={paymentIntent.paymentIntent.data.client_secret}
returnUrl={returnUrl}
/>
</>
)}
{(!tokenFromStore || !paymentIntent) && !isLoadingPage && (
<>
<NameInput
value={name}
placeholder="Your name"
onValid={handleValidName}
onInvalid={() => setIsValidName(true)}
/>
<EmailInput
name="email"
value={email}
placeholder={t("your_email")}
onValid={handleValidEmail}
onInvalid={() => setIsValidEmail(false)}
/>
<MainButton
className={styles.button}
onClick={handleClick}
disabled={isDisabled}
>
{isLoading && <Loader color={LoaderColor.White} />}
{!isLoading &&
!(!apiError && !error && !isLoading && isAuth) &&
t("_continue")}
{!apiError && !error && !isLoading && isAuth && (
<img
className={styles["success-icon"]}
src="/SuccessIcon.png"
alt="Success Icon"
/>
)}
</MainButton>
</>
)}
{(error || apiError) && (
<Title variant="h3" style={{ color: "red", margin: 0 }}>
Something went wrong
</Title>
)}
{apiError && (
<ErrorText
size="medium"
isShown={Boolean(apiError)}
message={apiError ? extractErrorMessage(apiError) : null}
/>
)}
</div>
);
}
export default PaymentWithEmailPage;