273 lines
8.2 KiB
TypeScript
273 lines
8.2 KiB
TypeScript
import { useDispatch, useSelector } from "react-redux";
|
|
import { useTranslation } from "react-i18next";
|
|
import { useNavigate, useParams } from "react-router-dom";
|
|
import { actions, selectors } from "@/store";
|
|
import MainButton from "../MainButton";
|
|
import Policy from "../Policy";
|
|
import PaymentTable, { Currency, Locale } from "../PaymentTable";
|
|
import CallToAction from "../CallToAction";
|
|
import routes from "@/routes";
|
|
import styles from "./styles.module.css";
|
|
// import Header from "../Header";
|
|
// import SpecialWelcomeOffer from "../SpecialWelcomeOffer";
|
|
import { useEffect, useState } from "react";
|
|
import { ApiError, extractErrorMessage, useApi } from "@/api";
|
|
import { useAuth } from "@/auth";
|
|
import { getClientLocale, getClientTimezone } from "@/locales";
|
|
import Loader from "../Loader";
|
|
import Title from "../Title";
|
|
import ErrorText from "../ErrorText";
|
|
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
|
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
|
|
|
const currency = Currency.USD;
|
|
const locale = getClientLocale() as Locale;
|
|
|
|
const getPrice = (product: IPaywallProduct | null) => {
|
|
if (!product?.trialPrice) {
|
|
return 0;
|
|
}
|
|
return (product.trialPrice === 100 ? 99 : product.trialPrice || 0) / 100;
|
|
};
|
|
|
|
function SubscriptionPage(): JSX.Element {
|
|
const api = useApi();
|
|
const timezone = getClientTimezone();
|
|
const { signUp } = useAuth();
|
|
const { t } = useTranslation();
|
|
const navigate = useNavigate();
|
|
const dispatch = useDispatch();
|
|
// const [isOpenModal, setIsOpenModal] = useState(false);
|
|
const [email, setEmail] = useState("");
|
|
const [emailError, setEmailError] = useState<null | string>(
|
|
"Email is invalid"
|
|
);
|
|
const [name, setName] = useState("");
|
|
const [nameError, setNameError] = useState<null | string>("Name is invalid");
|
|
const [isSubmit, setIsSubmit] = useState(false);
|
|
const [isAuth, setIsAuth] = useState(false);
|
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
const [apiError, setApiError] = useState<ApiError | null>(null);
|
|
const [error, setError] = useState<boolean>(false);
|
|
const { subPlan } = useParams();
|
|
const birthday = useSelector(selectors.selectBirthday);
|
|
console.log(nameError);
|
|
|
|
const { products } = usePaywall({
|
|
placementKey: EPlacementKeys["aura.placement.main"],
|
|
});
|
|
const activeProductFromStore = useSelector(selectors.selectActiveProduct);
|
|
const [activeProduct, setActiveProduct] = useState<IPaywallProduct | null>(
|
|
activeProductFromStore
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (subPlan) {
|
|
const targetProduct = products.find(
|
|
(product) =>
|
|
String(
|
|
product?.trialPrice
|
|
? Math.floor((product?.trialPrice + 1) / 100)
|
|
: product.key.replace(".", "")
|
|
) === subPlan
|
|
);
|
|
if (targetProduct) {
|
|
setActiveProduct(targetProduct);
|
|
}
|
|
}
|
|
}, [products, subPlan]);
|
|
|
|
const paymentItems = [
|
|
{
|
|
title: activeProduct?.name || "Per 7-Day Trial For",
|
|
price: getPrice(activeProduct),
|
|
description: activeProduct?.description?.length
|
|
? activeProduct.description
|
|
: t("au.2week_plan.web"),
|
|
},
|
|
];
|
|
|
|
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 } },
|
|
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"));
|
|
dispatch(
|
|
actions.payment.update({
|
|
activeProduct,
|
|
})
|
|
);
|
|
setIsLoading(false);
|
|
setIsAuth(true);
|
|
setTimeout(() => {
|
|
navigate(routes.client.paymentMethod());
|
|
}, 1000);
|
|
} catch (error) {
|
|
console.error(error);
|
|
if (error instanceof ApiError) {
|
|
setApiError(error as ApiError);
|
|
} else {
|
|
setError(true);
|
|
}
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleClick = async () => {
|
|
setIsSubmit(true);
|
|
|
|
if (
|
|
!isValidEmail(email)
|
|
// || !isValidName(name)
|
|
) {
|
|
return;
|
|
}
|
|
await authorization();
|
|
};
|
|
// const handleCross = () => setIsOpenModal(true);
|
|
const policyLink = (
|
|
<a href="https://aura.wit.life/" target="_blank" rel="noopener noreferrer">
|
|
{t("subscription_policy")}
|
|
</a>
|
|
);
|
|
|
|
const isValidEmail = (email: string) => {
|
|
return /\S+@\S+\.\S+/.test(email);
|
|
};
|
|
|
|
const isValidName = (name: string) => {
|
|
return !!(name.length > 0 && name.length < 30);
|
|
};
|
|
|
|
const handleChangeEmail = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
const email = event.target.value;
|
|
if (!isValidEmail(email)) {
|
|
setEmailError("Email is invalid");
|
|
} else {
|
|
setEmailError(null);
|
|
}
|
|
setEmail(email);
|
|
};
|
|
|
|
const handleChangeName = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
const name = event.target.value;
|
|
if (!isValidName(name)) {
|
|
setNameError("Name is invalid");
|
|
} else {
|
|
setNameError(null);
|
|
}
|
|
setName(name);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
{/* <SpecialWelcomeOffer open={isOpenModal} onClose={handleClick} /> */}
|
|
{/* <Header classCross={styles.cross} clickCross={handleCross} /> */}
|
|
{/* <UserHeader email={email} /> */}
|
|
<section className={`${styles.page} page`}>
|
|
<CallToAction />
|
|
{/* <Countdown start={10} /> */}
|
|
<PaymentTable
|
|
items={paymentItems}
|
|
currency={currency}
|
|
locale={locale}
|
|
/>
|
|
<div className={styles["inputs-container"]}>
|
|
<div className={styles["inputs-container__input-container"]}>
|
|
<input
|
|
className={`${styles["inputs-container__input"]}`}
|
|
// ${
|
|
// nameError && isSubmit && styles["inputs-container__input-error"]
|
|
// }
|
|
type="name"
|
|
name="name"
|
|
id="name"
|
|
value={name}
|
|
onChange={handleChangeName}
|
|
placeholder="Your name"
|
|
/>
|
|
{/* {isSubmit && !!nameError && (
|
|
<span className={styles["inputs-container__label-error"]}>
|
|
{nameError}
|
|
</span>
|
|
)} */}
|
|
</div>
|
|
<div className={styles["inputs-container__input-container"]}>
|
|
<input
|
|
className={`${styles["inputs-container__input"]} ${
|
|
emailError &&
|
|
isSubmit &&
|
|
styles["inputs-container__input-error"]
|
|
}`}
|
|
type="email"
|
|
name="email"
|
|
id="email"
|
|
value={email}
|
|
onChange={handleChangeEmail}
|
|
placeholder="Your email"
|
|
/>
|
|
{isSubmit && !!emailError && (
|
|
<span className={styles["inputs-container__label-error"]}>
|
|
{emailError}
|
|
</span>
|
|
)}
|
|
</div>
|
|
{isLoading && isSubmit && isValidEmail(email) && (
|
|
// isValidName(name) &&
|
|
<Loader />
|
|
)}
|
|
{(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}
|
|
/>
|
|
)}
|
|
{!apiError && !error && !isLoading && isAuth && (
|
|
<img src="/SuccessIcon.png" alt="Success Icon" />
|
|
)}
|
|
</div>
|
|
<div className={styles["subscription-action"]}>
|
|
<MainButton onClick={handleClick}>
|
|
Start ${getPrice(activeProduct || null)}
|
|
</MainButton>
|
|
</div>
|
|
<Policy>
|
|
<>
|
|
{t("auweb.agree.text1")}
|
|
{t("subscription_text", { policyLink })}
|
|
</>
|
|
</Policy>
|
|
</section>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default SubscriptionPage;
|