This commit is contained in:
Daniil Chemerkin 2025-02-26 18:19:01 +00:00
parent 8ed49191a0
commit a462947bc3
14 changed files with 169 additions and 124 deletions

View File

@ -306,10 +306,10 @@
"point3_color": "Head line", "point3_color": "Head line",
"point4": "A long index finger indicates a natural leader", "point4": "A long index finger indicates a natural leader",
"point5": "<color> defines the quality of your life and what you will achieve", "point5": "<color> defines the quality of your life and what you will achieve",
"point5_color": "Life line", "point5_color": "Live line",
"point6": "A short middle finger reveals a free spirit", "point6": "A short middle finger reveals a free spirit",
"point7": "<color> represents your material achievement and career goals", "point7": "<color> represents your material achievement and career goals",
"point7_color": "Fate line", "point7_color": "Money line",
"point8": "A long ring finger reveals that a person tends to take risks", "point8": "A long ring finger reveals that a person tends to take risks",
"point9": "A short little finger indicates the person's lack of self-confidence" "point9": "A short little finger indicates the person's lack of self-confidence"
}, },

View File

@ -221,10 +221,10 @@
"point3_color": "Head line", "point3_color": "Head line",
"point4": "A long index finger indicates a natural leader", "point4": "A long index finger indicates a natural leader",
"point5": "<color> defines the quality of your life and what you will achieve", "point5": "<color> defines the quality of your life and what you will achieve",
"point5_color": "Life line", "point5_color": "Live line",
"point6": "A short middle finger reveals a free spirit", "point6": "A short middle finger reveals a free spirit",
"point7": "<color> represents your material achievement and career goals", "point7": "<color> represents your material achievement and career goals",
"point7_color": "Fate line", "point7_color": "Money line",
"point8": "A long ring finger reveals that a person tends to take risks", "point8": "A long ring finger reveals that a person tends to take risks",
"point9": "A short little finger indicates the person's lack of self-confidence" "point9": "A short little finger indicates the person's lack of self-confidence"
}, },

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

View File

@ -23,6 +23,13 @@
gap: 12px; gap: 12px;
margin-bottom: 12px; margin-bottom: 12px;
&>img[src$=".svg"] {
shape-rendering: geometricPrecision;
text-rendering: geometricPrecision;
image-rendering: smooth;
-webkit-font-smoothing: antialiased;
}
&:nth-child(even) { &:nth-child(even) {
flex-direction: row-reverse; flex-direction: row-reverse;
} }
@ -40,12 +47,12 @@
grid-template-columns: 16px 1fr; grid-template-columns: 16px 1fr;
gap: 2px; gap: 2px;
& > .text { &>.text {
font-size: 16px; font-size: 16px;
line-height: 125%; line-height: 125%;
color: #000; color: #000;
& > span { &>span {
color: #cc8551; color: #cc8551;
font-weight: 600; font-weight: 600;
font-size: 18px; font-size: 18px;
@ -55,4 +62,4 @@
.photo-ready { .photo-ready {
max-width: 90px; max-width: 90px;
} }

View File

@ -11,6 +11,7 @@ import { actions } from "@/store";
// import StarSVG from "../../images/SVG/Star"; // import StarSVG from "../../images/SVG/Star";
import { usePreloadImages } from "@/hooks/preload/images"; import { usePreloadImages } from "@/hooks/preload/images";
import { DotLottieReact } from "@lottiefiles/dotlottie-react"; import { DotLottieReact } from "@lottiefiles/dotlottie-react";
import { useMetricABFlags } from "@/services/metric/metricService";
function FindHappiness() { function FindHappiness() {
const navigate = useNavigate(); const navigate = useNavigate();
@ -18,6 +19,9 @@ function FindHappiness() {
const location = useLocation(); const location = useLocation();
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2); const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
usePreloadImages(["/male-gender.webp", "/female-gender.webp"]); usePreloadImages(["/male-gender.webp", "/female-gender.webp"]);
const { flags, ready } = useMetricABFlags();
const imageType = flags?.welcomePageImage?.[0];
const image = imageType === "v1" ? "/hand-with-lines-v1.png" : "/hand-with-lines.png";
useEffect(() => { useEffect(() => {
const feature = location.pathname.replace( const feature = location.pathname.replace(
@ -29,6 +33,8 @@ function FindHappiness() {
} }
}, [dispatch, location.pathname]); }, [dispatch, location.pathname]);
if (!ready) return null;
return ( return (
<> <>
{/* <div className={styles["blocks-container"]}> {/* <div className={styles["blocks-container"]}>
@ -58,8 +64,12 @@ function FindHappiness() {
/> />
<img <img
className={styles.image} className={styles.image}
src={`${compatibilityV2Prefix}/hand-with-lines.png`} src={`${compatibilityV2Prefix}${image}`}
alt="Hand with lines" alt="Hand with lines"
style={{
minHeight: imageType === "v1" ? "auto" : "341px",
maxWidth: imageType === "v1" ? "330px" : "250px"
}}
/> />
<Title variant="h2" className={styles.title}> <Title variant="h2" className={styles.title}>
{translate("/find-your-happiness.title")} {translate("/find-your-happiness.title")}

View File

@ -190,7 +190,8 @@ function ScannedPhoto() {
); );
const onEndLoading = useCallback(() => { const onEndLoading = useCallback(() => {
if (isIOSPath && !!authCode) { const isIOS = /iPhone/i.test(navigator.userAgent);
if (isIOSPath && !!authCode && isIOS) {
return navigate(routes.client.compatibilityV2TryApp()); return navigate(routes.client.compatibilityV2TryApp());
} }
navigate(routes.client.compatibilityV2Email()); navigate(routes.client.compatibilityV2Email());

View File

@ -16,7 +16,7 @@ function PalmPhoto() {
const linesRef = useRef<SVGPathElement[]>([]); const linesRef = useRef<SVGPathElement[]>([]);
const fingers = useSelector(selectors.selectCompatibilityV2Fingers); const fingers = useSelector(selectors.selectCompatibilityV2Fingers);
const lines = useSelector(selectors.selectCompatibilityV2Lines); const lines = useSelector(selectors.selectCompatibilityV2Lines);
const [textPositions, setTextPositions] = useState<Array<{ x: number, y: number }>>([]); // const [textPositions, setTextPositions] = useState<Array<{ x: number, y: number }>>([]);
useEffect(() => { useEffect(() => {
if (isImageLoaded && imageRef.current) { if (isImageLoaded && imageRef.current) {
@ -43,63 +43,63 @@ function PalmPhoto() {
return line?.getTotalLength(); return line?.getTotalLength();
}; };
useEffect(() => { // useEffect(() => {
if (!imageWidth || !imageHeight || !lines.length) return; // if (!imageWidth || !imageHeight || !lines.length) return;
const textWidth = 90; // const textWidth = 90;
const textHeight = 17; // const textHeight = 17;
const padding = 10; // const padding = 10;
const newPositions: Array<{ x: number, y: number }> = []; // const newPositions: Array<{ x: number, y: number }> = [];
lines.forEach((line, index) => { // lines.forEach((line, index) => {
const points = line.points; // const points = line.points;
const positions = []; // const positions = [];
for (let i = 0; i < points.length - 1; i++) { // for (let i = 0; i < points.length - 1; i++) {
const x = (points[i].x + points[i + 1].x) / 2; // const x = (points[i].x + points[i + 1].x) / 2;
const y = (points[i].y + points[i + 1].y) / 2; // const y = (points[i].y + points[i + 1].y) / 2;
positions.push({ x, y }); // positions.push({ x, y });
} // }
positions.unshift({ x: points[0].x, y: points[0].y }); // positions.unshift({ x: points[0].x, y: points[0].y });
positions.push({ x: points[points.length - 1].x, y: points[points.length - 1].y }); // positions.push({ x: points[points.length - 1].x, y: points[points.length - 1].y });
let positionFound = false; // let positionFound = false;
for (const pos of positions) { // for (const pos of positions) {
let hasOverlap = false; // let hasOverlap = false;
for (const existingPos of newPositions) { // for (const existingPos of newPositions) {
if ( // if (
pos.x * imageWidth + padding < existingPos.x + textWidth && // pos.x * imageWidth + padding < existingPos.x + textWidth &&
pos.x * imageWidth + padding + textWidth > existingPos.x && // pos.x * imageWidth + padding + textWidth > existingPos.x &&
pos.y * imageHeight - padding < existingPos.y + textHeight && // pos.y * imageHeight - padding < existingPos.y + textHeight &&
pos.y * imageHeight - padding + textHeight > existingPos.y // pos.y * imageHeight - padding + textHeight > existingPos.y
) { // ) {
hasOverlap = true; // hasOverlap = true;
break; // break;
} // }
} // }
if (!hasOverlap) { // if (!hasOverlap) {
newPositions.push({ // newPositions.push({
x: pos.x * imageWidth + 10, // x: pos.x * imageWidth + 10,
y: pos.y * imageHeight - 5 // y: pos.y * imageHeight - 5
}); // });
positionFound = true; // positionFound = true;
break; // break;
} // }
} // }
if (!positionFound) { // if (!positionFound) {
newPositions.push({ // newPositions.push({
x: points[0].x * imageWidth + textWidth + padding * (index + 1), // x: points[0].x * imageWidth + textWidth + padding * (index + 1),
y: points[0].y * imageHeight - textHeight - padding * (index + 1) // y: points[0].y * imageHeight - textHeight - padding * (index + 1)
}); // });
} // }
}); // });
setTextPositions(newPositions); // setTextPositions(newPositions);
}, [lines, imageWidth, imageHeight]); // }, [lines, imageWidth, imageHeight]);
return ( return (
<div className={styles.container}> <div className={styles.container}>
@ -168,8 +168,11 @@ function PalmPhoto() {
{lines.map((line, index) => ( {lines.map((line, index) => (
<g key={`line-label-${index}`}> <g key={`line-label-${index}`}>
<text <text
x={textPositions[index]?.x || 0} // x={textPositions[index]?.x || 0}
y={textPositions[index]?.y || 0} // y={textPositions[index]?.y || 0}
x={imageWidth - 10}
y={index * 20 + 20}
textAnchor="end"
fill="#066FDE" fill="#066FDE"
className={`scanned-photo__line-text scanned-photo__line-text_${line?.name}`} className={`scanned-photo__line-text scanned-photo__line-text_${line?.name}`}
> >

View File

@ -23,6 +23,13 @@
gap: 12px; gap: 12px;
margin-bottom: 12px; margin-bottom: 12px;
&>img[src$=".svg"] {
shape-rendering: geometricPrecision;
text-rendering: geometricPrecision;
image-rendering: smooth;
-webkit-font-smoothing: antialiased;
}
&:nth-child(even) { &:nth-child(even) {
flex-direction: row-reverse; flex-direction: row-reverse;
} }
@ -40,12 +47,12 @@
grid-template-columns: 16px 1fr; grid-template-columns: 16px 1fr;
gap: 2px; gap: 2px;
& > .text { &>.text {
font-size: 16px; font-size: 16px;
line-height: 125%; line-height: 125%;
color: #000; color: #000;
& > span { &>span {
color: #cc8551; color: #cc8551;
font-weight: 600; font-weight: 600;
font-size: 18px; font-size: 18px;
@ -55,4 +62,4 @@
.photo-ready { .photo-ready {
max-width: 90px; max-width: 90px;
} }

View File

@ -10,6 +10,7 @@ import { useEffect } from "react";
import { actions } from "@/store"; import { actions } from "@/store";
// import StarSVG from "../../images/SVG/Star"; // import StarSVG from "../../images/SVG/Star";
import { usePreloadImages } from "@/hooks/preload/images"; import { usePreloadImages } from "@/hooks/preload/images";
import { useMetricABFlags } from "@/services/metric/metricService";
function FindHappiness() { function FindHappiness() {
const navigate = useNavigate(); const navigate = useNavigate();
@ -17,6 +18,10 @@ function FindHappiness() {
const location = useLocation(); const location = useLocation();
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1); const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
usePreloadImages(["/male-gender.webp", "/female-gender.webp"]); usePreloadImages(["/male-gender.webp", "/female-gender.webp"]);
const { flags, ready } = useMetricABFlags();
const imageType = flags?.welcomePageImage?.[0];
const image = imageType === "v1" ? "/hand-with-lines-v1.png" : "/hand-with-lines.png";
useEffect(() => { useEffect(() => {
const feature = location.pathname.replace( const feature = location.pathname.replace(
@ -28,6 +33,8 @@ function FindHappiness() {
} }
}, [dispatch, location.pathname]); }, [dispatch, location.pathname]);
if (!ready) return null;
return ( return (
<> <>
{/* <div className={styles["blocks-container"]}> {/* <div className={styles["blocks-container"]}>
@ -50,8 +57,12 @@ function FindHappiness() {
</div> */} </div> */}
<img <img
className={styles.image} className={styles.image}
src={`${palmistryV1Prefix}/hand-with-lines.png`} src={`${palmistryV1Prefix}${image}`}
alt="Hand with lines" alt="Hand with lines"
style={{
minHeight: imageType === "v1" ? "auto" : "341px",
maxWidth: imageType === "v1" ? "330px" : "250px"
}}
/> />
<Title variant="h2" className={styles.title}> <Title variant="h2" className={styles.title}>
{translate("/find-your-happiness.title")} {translate("/find-your-happiness.title")}

View File

@ -96,7 +96,8 @@ function ScannedPhoto() {
}, [currentElementIndex, drawElements.length]); }, [currentElementIndex, drawElements.length]);
const handleNext = () => { const handleNext = () => {
if (isIOSPath && !!authCode) { const isIOS = /iPhone/i.test(navigator.userAgent);
if (isIOSPath && !!authCode && isIOS) {
return navigate(routes.client.palmistryV1TryApp()); return navigate(routes.client.palmistryV1TryApp());
} }
return navigate(routes.client.palmistryV1Email()) return navigate(routes.client.palmistryV1Email())

View File

@ -16,7 +16,7 @@ function PalmPhoto() {
const linesRef = useRef<SVGPathElement[]>([]); const linesRef = useRef<SVGPathElement[]>([]);
const fingers = useSelector(selectors.selectPalmistryFingers); const fingers = useSelector(selectors.selectPalmistryFingers);
const lines = useSelector(selectors.selectPalmistryLines); const lines = useSelector(selectors.selectPalmistryLines);
const [textPositions, setTextPositions] = useState<Array<{ x: number, y: number }>>([]); // const [textPositions, setTextPositions] = useState<Array<{ x: number, y: number }>>([]);
useEffect(() => { useEffect(() => {
if (isImageLoaded && imageRef.current) { if (isImageLoaded && imageRef.current) {
@ -43,63 +43,63 @@ function PalmPhoto() {
return line?.getTotalLength(); return line?.getTotalLength();
}; };
useEffect(() => { // useEffect(() => {
if (!imageWidth || !imageHeight || !lines.length) return; // if (!imageWidth || !imageHeight || !lines.length) return;
const textWidth = 90; // const textWidth = 90;
const textHeight = 17; // const textHeight = 17;
const padding = 10; // const padding = 10;
const newPositions: Array<{ x: number, y: number }> = []; // const newPositions: Array<{ x: number, y: number }> = [];
lines.forEach((line, index) => { // lines.forEach((line, index) => {
const points = line.points; // const points = line.points;
const positions = []; // const positions = [];
for (let i = 0; i < points.length - 1; i++) { // for (let i = 0; i < points.length - 1; i++) {
const x = (points[i].x + points[i + 1].x) / 2; // const x = (points[i].x + points[i + 1].x) / 2;
const y = (points[i].y + points[i + 1].y) / 2; // const y = (points[i].y + points[i + 1].y) / 2;
positions.push({ x, y }); // positions.push({ x, y });
} // }
positions.unshift({ x: points[0].x, y: points[0].y }); // positions.unshift({ x: points[0].x, y: points[0].y });
positions.push({ x: points[points.length - 1].x, y: points[points.length - 1].y }); // positions.push({ x: points[points.length - 1].x, y: points[points.length - 1].y });
let positionFound = false; // let positionFound = false;
for (const pos of positions) { // for (const pos of positions) {
let hasOverlap = false; // let hasOverlap = false;
for (const existingPos of newPositions) { // for (const existingPos of newPositions) {
if ( // if (
pos.x * imageWidth + padding < existingPos.x + textWidth && // pos.x * imageWidth + padding < existingPos.x + textWidth &&
pos.x * imageWidth + padding + textWidth > existingPos.x && // pos.x * imageWidth + padding + textWidth > existingPos.x &&
pos.y * imageHeight - padding < existingPos.y + textHeight && // pos.y * imageHeight - padding < existingPos.y + textHeight &&
pos.y * imageHeight - padding + textHeight > existingPos.y // pos.y * imageHeight - padding + textHeight > existingPos.y
) { // ) {
hasOverlap = true; // hasOverlap = true;
break; // break;
} // }
} // }
if (!hasOverlap) { // if (!hasOverlap) {
newPositions.push({ // newPositions.push({
x: pos.x * imageWidth + 10, // x: pos.x * imageWidth + 10,
y: pos.y * imageHeight - 5 // y: pos.y * imageHeight - 5
}); // });
positionFound = true; // positionFound = true;
break; // break;
} // }
} // }
if (!positionFound) { // if (!positionFound) {
newPositions.push({ // newPositions.push({
x: points[0].x * imageWidth + textWidth + padding * (index + 1), // x: points[0].x * imageWidth + textWidth + padding * (index + 1),
y: points[0].y * imageHeight - textHeight - padding * (index + 1) // y: points[0].y * imageHeight - textHeight - padding * (index + 1)
}); // });
} // }
}); // });
setTextPositions(newPositions); // setTextPositions(newPositions);
}, [lines, imageWidth, imageHeight]); // }, [lines, imageWidth, imageHeight]);
return ( return (
<div className={styles.container}> <div className={styles.container}>
@ -168,8 +168,11 @@ function PalmPhoto() {
{lines.map((line, index) => ( {lines.map((line, index) => (
<g key={`line-label-${index}`}> <g key={`line-label-${index}`}>
<text <text
x={textPositions[index]?.x || 0} // x={textPositions[index]?.x || 0}
y={textPositions[index]?.y || 0} // y={textPositions[index]?.y || 0}
x={imageWidth - 10}
y={index * 20 + 20}
textAnchor="end"
fill="#066FDE" fill="#066FDE"
className={`scanned-photo__line-text scanned-photo__line-text_${line?.name}`} className={`scanned-photo__line-text scanned-photo__line-text_${line?.name}`}
> >

View File

@ -94,21 +94,21 @@
} }
.scanned-photo__line_heart { .scanned-photo__line_heart {
stroke: #f8d90f; stroke: #EE463A;
/* animation-delay: 4.5s; */ /* animation-delay: 4.5s; */
} }
.scanned-photo__line_life { .scanned-photo__line_life {
stroke: #e51c39; stroke: #024AD6;
} }
.scanned-photo__line_head { .scanned-photo__line_head {
stroke: #00d114; stroke: #52EF67;
/* animation-delay: 1.5s; */ /* animation-delay: 1.5s; */
} }
.scanned-photo__line_fate { .scanned-photo__line_fate {
stroke: #05ced8; stroke: #EF45DC;
/* animation-delay: 3s; */ /* animation-delay: 3s; */
} }
@ -185,24 +185,25 @@
opacity: 0; opacity: 0;
animation: fadeIn 0.3s forwards; animation: fadeIn 0.3s forwards;
stroke: #000; stroke: #000;
stroke-width: 0.6px;
} }
.scanned-photo__line-text_heart { .scanned-photo__line-text_heart {
fill: #f8d90f; fill: #EE463A;
/* animation-delay: 4.5s; */ /* animation-delay: 4.5s; */
} }
.scanned-photo__line-text_life { .scanned-photo__line-text_life {
fill: #e51c39; fill: #024AD6;
} }
.scanned-photo__line-text_head { .scanned-photo__line-text_head {
fill: #00d114; fill: #52EF67;
/* animation-delay: 1.5s; */ /* animation-delay: 1.5s; */
} }
.scanned-photo__line-text_fate { .scanned-photo__line-text_fate {
fill: #05ced8; fill: #EF45DC;
/* animation-delay: 3s; */ /* animation-delay: 3s; */
} }

View File

@ -209,6 +209,7 @@ type TABFlags = {
palmOnPayment: "graphical" | "real"; palmOnPayment: "graphical" | "real";
genderPageType: "v1" | "v2"; genderPageType: "v1" | "v2";
trialChoicePageType: "v1" | "v2"; trialChoicePageType: "v1" | "v2";
welcomePageImage: "v1" | "v2";
} }
export const useMetricABFlags = () => { export const useMetricABFlags = () => {