w-aura/src/components/Compatibility/index.tsx
Daniil Chemerkin 21c8ff7e9b Develop
2024-08-17 00:33:17 +00:00

396 lines
13 KiB
TypeScript

import { useTranslations } from "@/hooks/translations";
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 from "../Onboarding";
import TextWithFinger from "../TextWithFinger";
import { EDirectionOnboarding } from "@/types";
function CompatibilityPage(): JSX.Element {
const { translate, i18n } = useTranslations();
const navigate = useNavigate();
const dispatch = useDispatch();
const homeConfig = useSelector(selectors.selectHome);
const showNavbarFooter = homeConfig.isShowNavbar;
const birthdate = useSelector(selectors.selectBirthdate);
const onboardingCompatibility = useSelector(
selectors.selectOnboardingCompatibility
).isShown;
const [isDisabled, setIsDisabled] = useState(true);
const [isDisabledName, setIsDisabledName] = useState(true);
const [isDisabledSelfName, setIsDisabledSelfName] = useState(true);
isDisabledSelfName;
const [isDisabledDate, setIsDisabledDate] = useState(true);
const [isChangeDate, setIsChangeDate] = useState(false);
const [currentOnboarding, setCurrentOnboarding] = useState(0);
const [name, setName] = useState<string>("");
const [selfName, setSelfName] = useState<string>("");
const [selectedDate, setSelectedDate] = useState<string | IDate>("");
const [compatCategory, setCompatCategory] = useState(1);
const zodiacSign = getZodiacSignByDate(birthdate);
const [asset, setAsset] = useState<Asset>();
const api = useApi();
const inputSelfNameRef = useRef<HTMLInputElement>(null);
const inputNameRef = 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,
selfName,
})
);
dispatch(
actions.compatibilities.update({
name,
birthDate: getDateAsString(selectedDate),
})
);
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 handleValidSelfName = (name: string) => {
setIsDisabledSelfName(!name.length);
setSelfName(name);
checkAllDisabled();
};
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 = () => {
// isDisabledSelfName
setIsDisabled(isDisabledName || isDisabledDate);
};
const changeCompatCategory = (event: React.ChangeEvent<HTMLInputElement>) => {
setCompatCategory(parseInt(event.target.value));
};
const scrollToElementOnboarding = (
nextOnboarding: number,
ref: HTMLElement | null
) => {
setCurrentOnboarding(nextOnboarding);
ref?.scrollIntoView({ behavior: "smooth" });
};
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>
)}
<div className={styles.content}>
{onboardingCompatibility && (
<Title variant="h2" className={styles.iam}>
{translate("iAm")}
</Title>
)}
{!onboardingCompatibility && (
<div
className={styles["input-container__name-container"]}
style={{ zIndex: currentOnboarding === 0 ? 100 : 1 }}
ref={inputSelfNameRef}
>
<NameInput
name="selfName"
value={selfName}
placeholder={translate("au.name.my_name")}
onKeyDown={(e) => {
if (!selfName.length) return;
if (e.key === "Enter") {
(e.target as HTMLInputElement).blur();
}
}}
onValid={handleValidSelfName}
onInvalid={() => setIsDisabledSelfName(true)}
onBlur={() => {
if (!selfName.length) return;
setCurrentOnboarding(1);
inputNameRef.current?.scrollIntoView({ behavior: "smooth" });
}}
/>
</div>
)}
<Title variant="h3" className={styles.plus}>
+
</Title>
<div className={styles["inputs-container"]}>
{!onboardingCompatibility && (
<>
{currentOnboarding === 0 && (
<Onboarding
targetRef={inputSelfNameRef.current as HTMLDivElement}
isShow={currentOnboarding === 0}
direction={EDirectionOnboarding.BOTTOM}
showBackground={true}
>
<TextWithFinger
text={translate("au.onboarding.my_name")}
direction={EDirectionOnboarding.BOTTOM}
crossClickHandler={() => {
if (!selfName.length) return;
scrollToElementOnboarding(1, inputNameRef.current);
}}
/>
</Onboarding>
)}
{currentOnboarding === 1 && (
<Onboarding
targetRef={inputNameRef.current as HTMLDivElement}
isShow={currentOnboarding === 1}
direction={EDirectionOnboarding.BOTTOM}
showBackground={true}
>
<TextWithFinger
text={translate("au.web_onbording.name")}
direction={EDirectionOnboarding.BOTTOM}
crossClickHandler={() => {
if (!name.length) return;
scrollToElementOnboarding(2, dateRef.current);
}}
/>
</Onboarding>
)}
{currentOnboarding === 2 && (
<Onboarding
targetRef={dateRef.current as HTMLDivElement}
isShow={currentOnboarding === 2}
direction={EDirectionOnboarding.BOTTOM}
showBackground={true}
>
<>
<button
className={styles["compatibility-onboarding__button"]}
disabled={!isChangeDate}
onClick={() => setCurrentOnboarding(3)}
>
Done
</button>
<TextWithFinger
text={translate("au.web_onbording.date")}
direction={EDirectionOnboarding.BOTTOM}
showCross={false}
/>
</>
</Onboarding>
)}
{currentOnboarding === 4 && (
<Onboarding
targetRef={mainButtonRef.current as HTMLDivElement}
isShow={currentOnboarding === 4}
direction={EDirectionOnboarding.TOP}
showBackground={true}
>
<TextWithFinger
text={""}
direction={EDirectionOnboarding.TOP}
showCross={false}
/>
</Onboarding>
)}
</>
)}
<div
className={styles["input-container__name-container"]}
style={{ zIndex: currentOnboarding === 1 ? 99 : 1 }}
ref={inputNameRef}
>
<NameInput
name="name"
value={name}
placeholder={translate("au.name.person")}
onKeyDown={(e) => {
if (!name.length) return;
if (e.key === "Enter") {
(e.target as HTMLInputElement).blur();
}
}}
onValid={handleValidName}
onInvalid={() => setIsDisabledName(true)}
onBlur={() => {
if (!name.length) return;
setCurrentOnboarding(2);
dateRef.current?.scrollIntoView({ behavior: "smooth" });
}}
/>
</div>
<div
className={styles["input-container__date-container"]}
style={{ zIndex: currentOnboarding === 2 ? 99 : 1 }}
ref={dateRef}
>
<DatePicker onDateChange={handleValidDate} />
</div>
</div>
{currentOnboarding === 3 && !onboardingCompatibility && (
<Onboarding
targetRef={categoriesRef.current as HTMLDivElement}
isShow={currentOnboarding === 3}
direction={EDirectionOnboarding.TOP}
showBackground={true}
>
<TextWithFinger
text={translate("au.web_onbording.category")}
direction={EDirectionOnboarding.TOP}
showCross={true}
crossClickHandler={() => setCurrentOnboarding(4)}
/>
</Onboarding>
)}
{data && data.length && (
<div
className={styles["compatibility-categories"]}
style={{ zIndex: currentOnboarding === 3 ? 99 : 1 }}
ref={categoriesRef}
>
{data.map((item, index) => (
<div
className="compatibility-categories__item"
key={index}
onClick={() => setCurrentOnboarding(4)}
>
<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 === 4 ? 99 : 1,
}}
ref={mainButtonRef}
>
<MainButton
className={styles["check-btn"]}
onClick={handleNext}
disabled={isDisabled}
>
{translate("check")}
</MainButton>
</div>
</div>
</section>
);
}
export default CompatibilityPage;