w-aura/src/components/CompatibilityV2/pages/ScanHand/index.tsx
2025-04-01 13:07:55 +00:00

175 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Title from "@/components/Title";
import Header from "../../components/Header";
import { images } from "../../data";
import styles from "./styles.module.scss";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import { useEffect, useState, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";
import { actions, selectors } from "@/store";
import Loader, { LoaderColor } from "@/components/Loader";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import { IPalmistryFinger } from "@/api/resources/Palmistry";
import { ICompatibilityV2FingerLocal } from "@/store/compatibilityV2";
import { useApi } from "@/api";
import { DataURIToBlob } from "@/services/data";
function ScanHand() {
const api = useApi();
const dispatch = useDispatch();
const navigate = useNavigate();
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
const [isLoading, setIsLoading] = useState(false);
const imageRef = useRef<HTMLImageElement>(null);
const gender = (useSelector(selectors.selectQuestionnaire)?.gender || "female");
const handleNext = () => {
navigate(`${routes.client.compatibilityV2ScannedPhoto()}?fromScanHand=true`)
}
useEffect(() => {
const timer = setTimeout(() => {
handleHandOn()
}, 6000);
return () => clearTimeout(timer);
}, []);
const convertImageToBase64 = (img: HTMLImageElement): Promise<string> => {
return new Promise((resolve, reject) => {
const canvas = document.createElement('canvas');
const padding = 100;
canvas.width = img.width * 1.4 + padding * 2;
canvas.height = img.height * 1.4;
const ctx = canvas.getContext('2d');
if (!ctx) {
reject(new Error('Не удалось получить контекст canvas'));
return;
}
ctx.fillStyle = '#272727';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, padding, 0, img.width * 1.4, canvas.height);
const base64String = canvas.toDataURL('image/png');
resolve(base64String);
});
};
const fingersNames = {
thumb: translate("thumb"),
index_finger: translate("index_finger"),
middle_finger: translate("middle_finger"),
ring_finger: translate("ring_finger"),
pinky: translate("pinky"),
};
const setFingersNames = (
fingers: IPalmistryFinger[]
): ICompatibilityV2FingerLocal[] => {
if (!fingers) return [];
return fingers.map((finger) => {
return {
...finger,
fingerName: fingersNames[finger.name as keyof typeof fingersNames],
};
});
};
const getLines = async (file: File | Blob) => {
const formData = new FormData();
formData.append("file", file);
try {
const result = await api.getPalmistryLines({ formData, gender: gender as "male" | "female" });
const fingers = setFingersNames(result?.fingers);
dispatch(
actions.compatibilityV2.update({
lines: result?.lines,
fingers,
})
);
return result;
} catch (error) {
dispatch(
actions.compatibilityV2.update({
lines: [],
fingers: [],
})
);
return null;
}
};
const handleHandOn = async () => {
if (isLoading || !imageRef.current) return;
setIsLoading(true);
try {
const photo = await convertImageToBase64(imageRef.current);
const file = DataURIToBlob(photo);
await getLines(file);
URL.revokeObjectURL(URL.createObjectURL(file));
dispatch(
actions.compatibilityV2.update({
photo,
})
);
handleNext()
} catch (error) {
console.error('Ошибка при конвертации изображения:', error);
} finally {
setIsLoading(false);
}
}
return (
<div
className={styles.container}
>
<Header
className={styles.header}
classNameTitle={styles["header-title"]}
isBackButtonVisible={true}
/>
<div
className={styles.content}
onClick={handleHandOn}
onTouchStart={(e) => {
e.preventDefault();
handleHandOn();
}}
>
{!isLoading && <>
<div className={styles.gradientContainer}>
<div className={styles.animationContainer}>
<div className={styles.line} />
</div>
</div>
<img className={styles.imageGif} src={images("scan-hand/Palm-tach-A.gif")} alt="Palm-tach-A" />
<Title variant="h2" className={styles.title}>
{translate("/scan-hand.title")}
</Title>
</>}
<img
ref={imageRef}
className={styles.imageHand}
src={images(`scan-hand/${gender}-Palm-A.png`)}
alt="hand"
draggable={false}
/>
{isLoading &&
<Loader color={LoaderColor.White} />
}
</div>
</div>
)
}
export default ScanHand