317 lines
10 KiB
TypeScript
317 lines
10 KiB
TypeScript
import { useTranslation } from "react-i18next";
|
|
import MainButton from "../MainButton";
|
|
import Title from "../Title";
|
|
import styles from "./styles.module.css";
|
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
import NameInput from "./nameInput";
|
|
import DatePicker from "./DatePicker";
|
|
import { IDate, getDateAsString } from "@/services/date";
|
|
import { AICompatCategories, useApi, useApiCall } from "@/api";
|
|
import { useNavigate } from "react-router-dom";
|
|
import routes from "@/routes";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import { actions, selectors } from "@/store";
|
|
import { EPathsFromHome } from "@/store/siteConfig";
|
|
import {
|
|
getCategoryIdByZodiacSign,
|
|
getZodiacSignByDate,
|
|
} from "@/services/zodiac-sign";
|
|
import { Asset } from "@/api/resources/Assets";
|
|
import { getRandomArbitrary } from "@/services/random-value";
|
|
import Onboarding, { EDirectionOnboarding } from "../Onboarding";
|
|
import TextWithFinger from "../TextWithFinger";
|
|
|
|
function CompatibilityPage(): JSX.Element {
|
|
const { t, i18n } = useTranslation();
|
|
const navigate = useNavigate();
|
|
const dispatch = useDispatch();
|
|
const [isDisabled, setIsDisabled] = useState(true);
|
|
const [isDisabledName, setIsDisabledName] = useState(true);
|
|
const [isDisabledDate, setIsDisabledDate] = useState(true);
|
|
const [isChangeDate, setIsChangeDate] = useState(false);
|
|
const [currentOnboarding, setCurrentOnboarding] = useState(0);
|
|
const [name, setName] = useState<string>("");
|
|
const [selectedDate, setSelectedDate] = useState<string | IDate>("");
|
|
const [compatCategory, setCompatCategory] = useState(1);
|
|
const homeConfig = useSelector(selectors.selectHome);
|
|
const showNavbarFooter = homeConfig.isShowNavbar;
|
|
const birthdate = useSelector(selectors.selectBirthdate);
|
|
const onboardingCompatibility = useSelector(
|
|
selectors.selectOnboardingCompatibility
|
|
);
|
|
const zodiacSign = getZodiacSignByDate(birthdate);
|
|
const [asset, setAsset] = useState<Asset>();
|
|
const api = useApi();
|
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
const dateRef = useRef<HTMLInputElement>(null);
|
|
const categoriesRef = useRef<HTMLInputElement>(null);
|
|
const mainButtonRef = useRef<HTMLInputElement>(null);
|
|
const locale = i18n.language;
|
|
|
|
const assetsData = useCallback(async () => {
|
|
const { asset_categories } = await api.getAssetCategories({ locale });
|
|
const categoryId = getCategoryIdByZodiacSign(zodiacSign, asset_categories);
|
|
const { assets } = await api.getAssets({
|
|
category: String(categoryId || "1"),
|
|
});
|
|
return assets;
|
|
}, [api, locale, zodiacSign]);
|
|
|
|
const {
|
|
data: assets,
|
|
// isPending
|
|
} = useApiCall<Asset[]>(assetsData);
|
|
|
|
useEffect(() => {
|
|
if (assets) {
|
|
setAsset(assets[getRandomArbitrary(0, assets?.length || 0)]);
|
|
}
|
|
}, [assets]);
|
|
|
|
const handleNext = () => {
|
|
if (isDisabled) return;
|
|
dispatch(
|
|
actions.onboardingConfig.update({
|
|
compatibility: {
|
|
isShown: true,
|
|
},
|
|
})
|
|
);
|
|
dispatch(
|
|
actions.compatibility.update({
|
|
rightUser: {
|
|
name,
|
|
birthDate: selectedDate,
|
|
},
|
|
categoryId: compatCategory,
|
|
})
|
|
);
|
|
navigate(routes.client.compatibilityResult());
|
|
};
|
|
|
|
const handleCross = () => {
|
|
if (homeConfig.pathFromHome === EPathsFromHome.compatibility) {
|
|
dispatch(
|
|
actions.siteConfig.update({
|
|
home: {
|
|
pathFromHome: EPathsFromHome.compatibility,
|
|
isShowNavbar: false,
|
|
},
|
|
})
|
|
);
|
|
return navigate(routes.client.breath());
|
|
}
|
|
if (homeConfig.pathFromHome === EPathsFromHome.breath) {
|
|
dispatch(
|
|
actions.siteConfig.update({
|
|
home: {
|
|
pathFromHome: EPathsFromHome.compatibility,
|
|
isShowNavbar: true,
|
|
},
|
|
})
|
|
);
|
|
return navigate(routes.client.home());
|
|
}
|
|
return navigate(routes.client.home());
|
|
};
|
|
|
|
const loadData = useCallback(() => {
|
|
return api
|
|
.getAiCompatCategories({ locale })
|
|
.then((resp: AICompatCategories.Response) => resp.compat_categories);
|
|
}, [api, locale]);
|
|
const { data } = useApiCall<AICompatCategories.CompatCategory[]>(loadData);
|
|
|
|
const handleValidName = (name: string) => {
|
|
setIsDisabledName(!name.length);
|
|
setName(name);
|
|
checkAllDisabled();
|
|
};
|
|
|
|
const handleValidDate = (date: string | IDate) => {
|
|
setIsDisabledDate(date === "");
|
|
setIsChangeDate(date !== getDateAsString(new Date()));
|
|
setSelectedDate(date);
|
|
checkAllDisabled();
|
|
};
|
|
|
|
const checkAllDisabled = () => {
|
|
setIsDisabled(isDisabledName || isDisabledDate);
|
|
};
|
|
|
|
const changeCompatCategory = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
setCompatCategory(parseInt(event.target.value));
|
|
};
|
|
|
|
return (
|
|
<section
|
|
className={`${styles.page} page`}
|
|
style={{
|
|
paddingBottom: showNavbarFooter ? "48px" : "16px",
|
|
backgroundImage: `url(${asset?.url.replace("http://", "https://")})`,
|
|
}}
|
|
>
|
|
<div className={styles.blurring}></div>
|
|
{!showNavbarFooter && (
|
|
<div className={styles.cross} onClick={handleCross}></div>
|
|
)}
|
|
{/* <Title variant="h1" className={styles.title}>
|
|
{t("compatibility")}
|
|
</Title> */}
|
|
<div className={styles.content}>
|
|
<Title variant="h2" className={styles.iam}>
|
|
{t("iAm")}
|
|
</Title>
|
|
<Title variant="h3" className={styles.plus}>
|
|
+
|
|
</Title>
|
|
<div className={styles["inputs-container"]}>
|
|
{!onboardingCompatibility.isShown && <>
|
|
{currentOnboarding === 0 && (
|
|
<Onboarding
|
|
targetRef={inputRef}
|
|
isShow={currentOnboarding === 0}
|
|
direction={EDirectionOnboarding.BOTTOM}
|
|
showBackground={true}
|
|
>
|
|
<TextWithFinger
|
|
text={t("au.web_onbording.name")}
|
|
direction={EDirectionOnboarding.BOTTOM}
|
|
crossClickHandler={() => setCurrentOnboarding(1)}
|
|
/>
|
|
</Onboarding>
|
|
)}
|
|
{currentOnboarding === 1 && (
|
|
<Onboarding
|
|
targetRef={dateRef}
|
|
isShow={currentOnboarding === 1}
|
|
direction={EDirectionOnboarding.BOTTOM}
|
|
showBackground={true}
|
|
>
|
|
<>
|
|
<button
|
|
className={styles["compatibility-onboarding__button"]}
|
|
disabled={!isChangeDate}
|
|
onClick={() => setCurrentOnboarding(2)}
|
|
>
|
|
Done
|
|
</button>
|
|
<TextWithFinger
|
|
text={t("au.web_onbording.date")}
|
|
direction={EDirectionOnboarding.BOTTOM}
|
|
showCross={false}
|
|
/>
|
|
</>
|
|
</Onboarding>
|
|
)}
|
|
{currentOnboarding === 3 && (
|
|
<Onboarding
|
|
targetRef={mainButtonRef}
|
|
isShow={currentOnboarding === 3}
|
|
direction={EDirectionOnboarding.TOP}
|
|
showBackground={true}
|
|
>
|
|
<TextWithFinger
|
|
text={""}
|
|
direction={EDirectionOnboarding.TOP}
|
|
showCross={false}
|
|
/>
|
|
</Onboarding>
|
|
)}
|
|
</>}
|
|
<div
|
|
className={styles["input-container__name-container"]}
|
|
style={{ zIndex: currentOnboarding === 0 ? 99 : 1 }}
|
|
ref={inputRef}
|
|
>
|
|
<NameInput
|
|
name="name"
|
|
value={name}
|
|
placeholder={t("name")}
|
|
onKeyDown={(e) => {
|
|
if (!name.length) return;
|
|
if (e.key === "Enter") {
|
|
setCurrentOnboarding(1);
|
|
(e.target as HTMLInputElement).blur();
|
|
dateRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
}
|
|
}}
|
|
onValid={handleValidName}
|
|
onInvalid={() => setIsDisabledName(true)}
|
|
/>
|
|
</div>
|
|
<div
|
|
className={styles["input-container__date-container"]}
|
|
style={{ zIndex: currentOnboarding === 1 ? 99 : 1 }}
|
|
ref={dateRef}
|
|
>
|
|
<DatePicker onDateChange={handleValidDate} />
|
|
</div>
|
|
</div>
|
|
{currentOnboarding === 2 && !onboardingCompatibility.isShown && (
|
|
<Onboarding
|
|
targetRef={categoriesRef}
|
|
isShow={currentOnboarding === 2}
|
|
direction={EDirectionOnboarding.TOP}
|
|
showBackground={true}
|
|
>
|
|
<TextWithFinger
|
|
text={t("au.web_onbording.category")}
|
|
direction={EDirectionOnboarding.TOP}
|
|
showCross={true}
|
|
crossClickHandler={() => setCurrentOnboarding(3)}
|
|
/>
|
|
</Onboarding>
|
|
)}
|
|
{data && data.length && (
|
|
<div
|
|
className={styles["compatibility-categories"]}
|
|
style={{ zIndex: currentOnboarding === 2 ? 99 : 1 }}
|
|
ref={categoriesRef}
|
|
>
|
|
{data.map((item, index) => (
|
|
<div
|
|
className="compatibility-categories__item"
|
|
key={index}
|
|
onClick={() => setCurrentOnboarding(3)}
|
|
>
|
|
<input
|
|
className={`${styles["compatibility-categories__input"]} ${
|
|
compatCategory === item.id
|
|
? styles["compatibility-categories__input--checked"]
|
|
: ""
|
|
}`}
|
|
type="radio"
|
|
name="compatCategory"
|
|
id={String(item.id)}
|
|
value={item.id}
|
|
checked={compatCategory === item.id}
|
|
onChange={changeCompatCategory}
|
|
/>
|
|
<label htmlFor={String(item.id)}>{item.name}</label>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
<div
|
|
style={{
|
|
position: "relative",
|
|
zIndex: currentOnboarding === 3 ? 99 : 1,
|
|
}}
|
|
ref={mainButtonRef}
|
|
>
|
|
<MainButton
|
|
className={styles["check-btn"]}
|
|
onClick={handleNext}
|
|
disabled={isDisabled}
|
|
>
|
|
{t("check")}
|
|
</MainButton>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
export default CompatibilityPage;
|