AW-483-484-485-fix-bugs

This commit is contained in:
Daniil Chemerkin 2025-08-19 20:56:55 +00:00
parent f34c0cc64f
commit 7455a3d0fd
32 changed files with 1728 additions and 938 deletions

View File

@ -591,6 +591,24 @@
"/scan-hand": { "/scan-hand": {
"title": "Place your palm against the phone screen." "title": "Place your palm against the phone screen."
}, },
"/review": {
"title": "<color> found their soulmate",
"title_color": "25M+",
"stars": "4.9",
"reviews": "<count> reviews",
"reviews_count": "125,000+",
"soulmates_count": "600+",
"soulmates_today": "Soulmates today",
"trusted": "Trusted worldwide",
"trusted_count": "15M",
"review": {
"username": "Mary Jones",
"verified_user": "Verified User • 2 weeks ago",
"text": "\"Я не ожидала такого результата - приложение дало точные подсказки, которые помогли мне разобраться в чувствах и принять важное решение. Это действительно работает.\"",
"likes": "1.2K"
},
"button": "Continue"
},
"period": { "period": {
"day_one": "{{count}} day", "day_one": "{{count}} day",
"day_other": "{{count}} days", "day_other": "{{count}} days",

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,85 @@
import Title from "@/components/Title";
import styles from "./styles.module.scss";
import Stars from "../Stars";
interface IReview2Props {
image: string;
username: string;
text: string;
verifiedText: string;
likesText: string;
likesImages: string[];
}
function Review2({
image,
username,
text,
verifiedText,
likesText,
likesImages,
}: IReview2Props) {
return (
<div className={styles.container}>
<div className={styles.header}>
<div
className={styles.avatar}
style={{ backgroundImage: `url(${image})` }}
/>
<div className={styles.headerContent}>
<div className={styles.headerContentTitle}>
<Title variant="h3" className={styles.username}>
{username}
</Title>
<Stars starVariant="1" />
</div>
<div className={styles.headerContentText}>
<svg
width="14"
height="14"
viewBox="0 0 14 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.39495 1.13343C5.2326 1.27179 5.15142 1.34097 5.06472 1.39908C4.86599 1.53228 4.64279 1.62473 4.40808 1.67107C4.30569 1.69129 4.19937 1.69977 3.98673 1.71673C3.45248 1.75937 3.18535 1.78069 2.96249 1.85941C2.44702 2.04147 2.04157 2.44693 1.8595 2.96239C1.78078 3.18525 1.75947 3.45239 1.71683 3.98664C1.69986 4.19927 1.69138 4.30559 1.67116 4.40799C1.62482 4.6427 1.53237 4.86589 1.39917 5.06463C1.34107 5.15133 1.27189 5.2325 1.13353 5.39485C0.785899 5.80279 0.612079 6.00672 0.510159 6.21999C0.274405 6.71325 0.274405 7.28659 0.510159 7.77985C0.612085 7.99312 0.785899 8.19705 1.13353 8.60499C1.27187 8.76732 1.34107 8.84852 1.39917 8.93519C1.53237 9.13392 1.62482 9.35712 1.67116 9.59185C1.69138 9.69425 1.69986 9.80059 1.71683 10.0132C1.75947 10.5475 1.78078 10.8146 1.8595 11.0375C2.04157 11.5529 2.44702 11.9584 2.96249 12.1405C3.18535 12.2191 3.45248 12.2405 3.98673 12.2831C4.19937 12.3001 4.30569 12.3086 4.40808 12.3288C4.64279 12.3751 4.86599 12.4676 5.06472 12.6008C5.15142 12.6589 5.23259 12.7281 5.39495 12.8664C5.80288 13.2141 6.00681 13.3879 6.22008 13.4898C6.71335 13.7255 7.28668 13.7255 7.77995 13.4898C7.99321 13.3879 8.19715 13.2141 8.60508 12.8664C8.76741 12.7281 8.84861 12.6589 8.93528 12.6008C9.13401 12.4676 9.35721 12.3751 9.59195 12.3288C9.69435 12.3086 9.80068 12.3001 10.0133 12.2831C10.5475 12.2405 10.8147 12.2191 11.0375 12.1405C11.553 11.9584 11.9585 11.5529 12.1405 11.0375C12.2192 10.8146 12.2405 10.5475 12.2832 10.0132C12.3001 9.80059 12.3087 9.69425 12.3289 9.59185C12.3752 9.35712 12.4677 9.13392 12.6009 8.93519C12.6589 8.84852 12.7281 8.76732 12.8665 8.60499C13.2141 8.19705 13.3879 7.99312 13.4899 7.77985C13.7256 7.28659 13.7256 6.71325 13.4899 6.21999C13.3879 6.00672 13.2141 5.80279 12.8665 5.39485C12.7281 5.2325 12.6589 5.15133 12.6009 5.06463C12.4677 4.86589 12.3752 4.6427 12.3289 4.40799C12.3087 4.30559 12.3001 4.19927 12.2832 3.98664C12.2405 3.45239 12.2192 3.18525 12.1405 2.96239C11.9585 2.44693 11.553 2.04147 11.0375 1.85941C10.8147 1.78069 10.5475 1.75937 10.0133 1.71673C9.80068 1.69977 9.69435 1.69129 9.59195 1.67107C9.35721 1.62473 9.13401 1.53228 8.93528 1.39908C8.84861 1.34097 8.76741 1.27179 8.60508 1.13343C8.19715 0.785807 7.99321 0.611994 7.77995 0.510067C7.28668 0.274314 6.71335 0.274314 6.22008 0.510067C6.00681 0.611987 5.80288 0.785807 5.39495 1.13343ZM9.91568 5.57535C10.1275 5.36345 10.1275 5.01992 9.91568 4.80803C9.70381 4.59614 9.36021 4.59614 9.14835 4.80803L5.91488 8.04152L4.85165 6.97832C4.63977 6.76645 4.29623 6.76645 4.08434 6.97832C3.87245 7.19019 3.87245 7.53372 4.08434 7.74565L5.5312 9.19252C5.74308 9.40439 6.08661 9.40439 6.29855 9.19252L9.91568 5.57535Z"
fill="#3BC350"
/>
</svg>
<p className={styles.verifiedText}>{verifiedText}</p>
</div>
</div>
</div>
<p className={styles.text}>{text}</p>
<div className={styles.footer}>
<svg
width="17"
height="15"
viewBox="0 0 17 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.4059 0.0314703C11.2691 0.205562 11.8303 1.05258 11.6576 1.92304L11.5812 2.3047C11.4053 3.1986 11.0799 4.04897 10.625 4.82234H15.4062C16.2861 4.82234 17 5.54214 17 6.42934C17 7.0487 16.6514 7.58772 16.14 7.85555C16.502 8.15017 16.7344 8.60213 16.7344 9.10767C16.7344 9.89108 16.1766 10.5439 15.4428 10.6845C15.5889 10.9289 15.6719 11.2135 15.6719 11.5182C15.6719 12.2313 15.2104 12.8372 14.5729 13.0448C14.5961 13.1553 14.6094 13.2725 14.6094 13.393C14.6094 14.2802 13.8955 15 13.0156 15H9.77832C9.14746 15 8.5332 14.8125 8.00859 14.461L6.73027 13.6006C5.84375 13.0046 5.3125 12.0003 5.3125 10.9256V9.64334V8.03634V7.20271C5.3125 6.22511 5.7541 5.30444 6.50781 4.69177L6.75352 4.49424C7.6334 3.78448 8.23438 2.7868 8.45352 1.6753L8.52988 1.29363C8.70254 0.423176 9.54258 -0.142621 10.4059 0.0314703ZM1.0625 5.358H3.1875C3.7752 5.358 4.25 5.83676 4.25 6.42934V13.9287C4.25 14.5212 3.7752 15 3.1875 15H1.0625C0.474805 15 0 14.5212 0 13.9287V6.42934C0 5.83676 0.474805 5.358 1.0625 5.358Z"
fill="#475466"
/>
</svg>
<p className={styles.likes}>{likesText}</p>
<div className={styles.likesImages}>
{likesImages.map((image, index) => (
<img
className={styles.likesImage}
src={image}
alt={`${index + 1} like avatar`}
key={index}
/>
))}
</div>
</div>
</div>
);
}
export default Review2;

View File

@ -0,0 +1,109 @@
.container {
width: 100%;
padding: 18px 17px 9px;
background: rgba(255, 255, 255, 1);
border: 1px solid rgba(228, 231, 236, 1);
border-radius: 12px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: 26px;
& > .text {
font-family: Inter;
font-weight: 400;
font-size: 14px;
line-height: 100%;
color: rgba(15, 23, 40, 1);
margin-top: 12px;
}
}
.header {
display: grid;
grid-template-columns: 50px 1fr;
gap: 8px;
width: 100%;
& > .avatar {
width: 50px;
height: 50px;
border-radius: 50%;
// object-fit: cover;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
& > .headerContent {
display: flex;
flex-direction: column;
gap: 8px;
& > .headerContentTitle {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
& > .username {
font-family: Inter;
font-weight: 600;
font-style: Semi Bold;
font-size: 14px;
line-height: 20px;
color: rgba(15, 23, 40, 1);
margin: 0;
}
}
& > .headerContentText {
display: flex;
flex-direction: row;
gap: 4px;
& > .verifiedText {
font-family: Inter;
font-weight: 400;
font-size: 12px;
line-height: 16px;
color: rgba(71, 84, 102, 1);
}
}
}
}
.footer {
display: flex;
flex-direction: row;
gap: 6px;
width: 100%;
margin-top: 24px;
align-items: center;
& > .likes {
font-family: Inter;
font-weight: 400;
font-size: 12px;
line-height: 16px;
color: rgba(71, 84, 102, 1);
}
& > .likesImages {
display: flex;
flex-direction: row;
margin-left: 4px;
& > .likesImage {
width: 28px;
height: 28px;
border-radius: 50%;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
border: 2px solid rgba(255, 255, 255, 1);
margin-left: -4px;
}
}
}

View File

@ -0,0 +1,33 @@
import { useTranslations } from "@/hooks/translations";
import WreathSVG from "../../images/SVG/Wreath";
import Stars from "../Stars";
import styles from "./styles.module.scss";
import { ELocalesPlacement } from "@/locales";
function ReviewsCount() {
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
return (
<div className={styles.container}>
<WreathSVG />
<div className={styles.content}>
<div className={styles.stars}>
<Stars starVariant="1" />
{translate("/review.stars")}
</div>
<div className={styles.reviews}>
{translate("/review.reviews", {
count: (
<span className={styles.reviews_count}>
{translate("/review.reviews_count")}
</span>
),
})}
</div>
</div>
<WreathSVG className={styles.wreath_2} />
</div>
);
}
export default ReviewsCount;

View File

@ -0,0 +1,52 @@
.wreath_2 {
transform: scaleX(-1);
}
.container {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: fit-content;
gap: 4px;
& > .content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 4px;
& > .stars {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 4px;
font-family: Inter;
font-weight: 600;
font-style: Semi Bold;
font-size: 18px;
line-height: 28px;
letter-spacing: 0%;
text-align: center;
color: rgba(15, 23, 40, 1);
}
& > .reviews {
font-family: Inter;
font-weight: 400;
font-style: Regular;
font-size: 12px;
line-height: 16px;
letter-spacing: 0%;
text-align: center;
color: rgba(71, 84, 102, 1);
& > .reviews_count {
font-weight: 700;
}
}
}
}

View File

@ -1,16 +1,20 @@
import StarSVG from "../../images/SVG/Star"; import StarSVG, { StarSVG1 } from "../../images/SVG/Star";
import styles from "./styles.module.scss"; import styles from "./styles.module.scss";
interface IStarsProps { interface IStarsProps {
stars?: number; stars?: number;
starVariant?: "0" | "1";
} }
function Stars({ stars = 5 }: IStarsProps) { function Stars({ stars = 5, starVariant = "0" }: IStarsProps) {
return ( return (
<div className={styles.container}> <div className={styles.container}>
{Array.from({ length: stars }).map((_, index) => ( {Array.from({ length: stars }).map((_, index) => {
<StarSVG key={index} /> if (starVariant === "1") {
))} return <StarSVG1 key={index} />;
}
return <StarSVG key={index} />;
})}
</div> </div>
); );
} }

View File

@ -0,0 +1,21 @@
import styles from "./styles.module.scss";
interface IStatisticsItemProps {
title: string;
text: string;
image: React.ReactNode;
}
function StatisticsItem({ title, text, image }: IStatisticsItemProps) {
return (
<div className={styles.statistics_item}>
<div className={styles.statistics_item_header}>
<div className={styles.statistics_item_image}>{image}</div>
<div className={styles.statistics_item_title}>{title}</div>
</div>
<p className={styles.statistics_item_text}>{text}</p>
</div>
);
}
export default StatisticsItem;

View File

@ -0,0 +1,48 @@
.statistics_item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
gap: 4px;
& > .statistics_item_header {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 8px;
& > .statistics_item_image {
width: 32px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
background: rgba(255, 255, 255, 1);
border-radius: 8px;
border: 1px solid rgba(228, 231, 236, 1);
}
& > .statistics_item_title {
font-family: Inter;
font-weight: 600;
font-style: Semi Bold;
font-size: 20px;
line-height: 28px;
letter-spacing: 0%;
text-align: center;
color: rgba(15, 23, 40, 1);
}
}
& > .statistics_item_text {
display: block;
font-family: Inter;
font-weight: 400;
font-size: 12px;
line-height: 16px;
text-align: center;
color: rgba(71, 84, 102, 1);
padding-left: 16px;
}
}

View File

@ -0,0 +1,16 @@
export default function HeartSVG() {
return (
<svg
width="14"
height="13"
viewBox="0 0 14 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1.30156 7.21409L6.24258 11.827C6.44766 12.0184 6.71836 12.125 7 12.125C7.28164 12.125 7.55234 12.0184 7.75742 11.827L12.6984 7.21409C13.5297 6.44026 14 5.35471 14 4.21995V4.06135C14 2.15002 12.6191 0.520337 10.7352 0.205884C9.48828 -0.00192878 8.21953 0.405493 7.32812 1.2969L7 1.62502L6.67188 1.2969C5.78047 0.405493 4.51172 -0.00192878 3.26484 0.205884C1.38086 0.520337 0 2.15002 0 4.06135V4.21995C0 5.35471 0.470312 6.44026 1.30156 7.21409Z"
fill="#475466"
/>
</svg>
);
}

View File

@ -0,0 +1,16 @@
export default function SoulmatesSVG() {
return (
<svg
width="18"
height="14"
viewBox="0 0 18 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.1875 0C4.76766 0 5.32406 0.230468 5.7343 0.640704C6.14453 1.05094 6.375 1.60734 6.375 2.1875C6.375 2.76766 6.14453 3.32406 5.7343 3.7343C5.32406 4.14453 4.76766 4.375 4.1875 4.375C3.60734 4.375 3.05094 4.14453 2.6407 3.7343C2.23047 3.32406 2 2.76766 2 2.1875C2 1.60734 2.23047 1.05094 2.6407 0.640704C3.05094 0.230468 3.60734 0 4.1875 0ZM14.25 0C14.8302 0 15.3866 0.230468 15.7968 0.640704C16.207 1.05094 16.4375 1.60734 16.4375 2.1875C16.4375 2.76766 16.207 3.32406 15.7968 3.7343C15.3866 4.14453 14.8302 4.375 14.25 4.375C13.6698 4.375 13.1134 4.14453 12.7032 3.7343C12.293 3.32406 12.0625 2.76766 12.0625 2.1875C12.0625 1.60734 12.293 1.05094 12.7032 0.640704C13.1134 0.230468 13.6698 0 14.25 0ZM0.25 8.16758C0.25 6.55703 1.55703 5.25 3.16758 5.25H4.33516C4.76992 5.25 5.18281 5.3457 5.55469 5.51523C5.51914 5.71211 5.50273 5.91719 5.50273 6.125C5.50273 7.16953 5.96211 8.10742 6.68672 8.75C6.68125 8.75 6.67578 8.75 6.66758 8.75H0.832422C0.5125 8.75 0.25 8.4875 0.25 8.16758ZM11.3324 8.75C11.327 8.75 11.3215 8.75 11.3133 8.75C12.0406 8.10742 12.4973 7.16953 12.4973 6.125C12.4973 5.91719 12.4781 5.71484 12.4453 5.51523C12.8172 5.34297 13.2301 5.25 13.6648 5.25H14.8324C16.443 5.25 17.75 6.55703 17.75 8.16758C17.75 8.49023 17.4875 8.75 17.1676 8.75H11.3324ZM6.375 6.125C6.375 5.42881 6.65156 4.76113 7.14384 4.26884C7.63613 3.77656 8.30381 3.5 9 3.5C9.69619 3.5 10.3639 3.77656 10.8562 4.26884C11.3484 4.76113 11.625 5.42881 11.625 6.125C11.625 6.82119 11.3484 7.48887 10.8562 7.98116C10.3639 8.47344 9.69619 8.75 9 8.75C8.30381 8.75 7.63613 8.47344 7.14384 7.98116C6.65156 7.48887 6.375 6.82119 6.375 6.125ZM3.75 13.2699C3.75 11.2574 5.38242 9.625 7.39492 9.625H10.6051C12.6176 9.625 14.25 11.2574 14.25 13.2699C14.25 13.6719 13.9246 14 13.5199 14H4.48008C4.07812 14 3.75 13.6746 3.75 13.2699Z"
fill="#475466"
/>
</svg>
);
}

View File

@ -17,3 +17,22 @@ function StarSVG() {
} }
export default StarSVG; export default StarSVG;
function StarSVG1() {
return (
<svg
width="16"
height="15"
viewBox="0 0 16 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.80587 1.24219C8.66095 0.941406 8.3547 0.75 8.01837 0.75C7.68204 0.75 7.37853 0.941406 7.23087 1.24219L5.47267 4.85977L1.54611 5.43945C1.21798 5.48867 0.944543 5.71836 0.843371 6.03281C0.742199 6.34727 0.82423 6.69453 1.05939 6.92695L3.90861 9.74609L3.23595 13.7301C3.18126 14.0582 3.31798 14.3918 3.58868 14.5859C3.85939 14.7801 4.21759 14.8047 4.5129 14.6488L8.02111 12.7758L11.5293 14.6488C11.8246 14.8047 12.1828 14.7828 12.4535 14.5859C12.7242 14.3891 12.8609 14.0582 12.8063 13.7301L12.1309 9.74609L14.9801 6.92695C15.2152 6.69453 15.3 6.34727 15.1961 6.03281C15.0922 5.71836 14.8215 5.48867 14.4934 5.43945L10.5641 4.85977L8.80587 1.24219Z"
fill="#FACC15"
/>
</svg>
);
}
export { StarSVG1 };

View File

@ -0,0 +1,59 @@
function WreathSVG(props: React.SVGProps<SVGSVGElement>) {
return (
<svg
width="46"
height="67"
viewBox="0 0 46 67"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M18.2206 22.9101C18.2206 22.9101 21.2785 20.5574 20.8671 16.0748C20.4498 11.5935 17.3969 9.13641 17.3969 9.13641C17.3969 9.13641 13.8919 11.9766 14.2973 16.3445C14.6996 20.7144 18.2206 22.9101 18.2206 22.9101Z"
fill="#475466"
/>
<path
d="M24.0256 26.6616C24.0256 26.6616 28.1101 27.385 31.3343 24.4053C34.5578 21.4282 33.8496 16.973 33.8496 16.973C33.8496 16.973 29.9386 16.7584 26.6282 19.8149C23.321 22.8695 24.0256 26.6616 24.0256 26.6616Z"
fill="#475466"
/>
<path
d="M23.1981 31.4942C20.3174 34.9552 21.5088 38.626 21.5088 38.626C21.5088 38.626 25.6571 38.8088 28.4618 35.4383C31.2653 32.0619 29.9821 27.7382 29.9821 27.7382C29.9821 27.7382 26.0789 28.0331 23.1981 31.4942Z"
fill="#475466"
/>
<path
d="M31.4122 37.03C31.4122 37.03 27.5505 37.6944 25.0097 41.4068C22.4668 45.127 23.9963 48.6654 23.9963 48.6654C23.9963 48.6654 28.1388 48.4577 30.6172 44.8365C33.093 41.2147 31.4122 37.03 31.4122 37.03Z"
fill="#475466"
/>
<path
d="M28.6623 59.3529C28.6623 59.3529 32.5735 57.9594 33.9038 53.7794C35.2323 49.5962 32.4129 46.0745 32.4129 46.0745C32.4129 46.0745 28.9061 47.8219 27.5416 52.1115C26.1803 56.3993 28.6623 59.3529 28.6623 59.3529Z"
fill="#475466"
/>
<path
d="M25.3809 16.3474C25.3809 16.3474 29.2307 16.0882 31.3719 12.1308C33.5158 8.1741 32.3419 4.4361 32.3419 4.4361C32.3419 4.4361 27.8521 4.85392 25.761 8.71404C23.6732 12.5722 25.3809 16.3474 25.3809 16.3474Z"
fill="#475466"
/>
<path
d="M15.8727 31.9006C15.8727 31.9006 18.099 28.7489 16.3836 24.591C14.6636 20.4292 11.0249 18.9807 11.0249 18.9807C11.0249 18.9807 8.51345 22.7284 10.1866 26.7842C11.859 30.8426 15.8727 31.9006 15.8727 31.9006Z"
fill="#475466"
/>
<path
d="M16.4016 41.887C16.4016 41.887 17.8701 38.3196 15.275 34.6468C12.6754 30.97 8.80465 30.3686 8.80465 30.3686C8.80465 30.3686 7.18715 34.5812 9.71777 38.1628C12.2542 41.7431 16.4016 41.887 16.4016 41.887Z"
fill="#475466"
/>
<path
d="M18.8811 50.6773C18.8811 50.6773 19.2077 46.8342 15.6174 44.1211C12.0259 41.4021 8.1565 42.0011 8.1565 42.0011C8.1565 42.0011 7.89177 46.5059 11.3882 49.1559C14.8866 51.7981 18.8811 50.6773 18.8811 50.6773Z"
fill="#475466"
/>
<path
d="M20.0077 54.3533C16.119 52.0865 12.3459 53.1409 12.3459 53.1409C12.3459 53.1409 12.6199 57.6428 16.4076 59.8529C20.2004 62.0644 24.0307 60.4731 24.0307 60.4731C24.0307 60.4731 23.8972 56.6175 20.0077 54.3533Z"
fill="#475466"
/>
<path
d="M25.1598 18.9823L23.5342 17.5789C23.3828 17.7573 8.47456 35.6316 29.4192 65.7051L31.1791 64.4786C11.2389 35.8423 24.5813 19.6562 25.1598 18.9823Z"
fill="#475466"
/>
</svg>
);
}
export default WreathSVG;

View File

@ -0,0 +1,13 @@
<svg width="46" height="67" viewBox="0 0 46 67" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.2206 22.9101C18.2206 22.9101 21.2785 20.5574 20.8671 16.0748C20.4498 11.5935 17.3969 9.13641 17.3969 9.13641C17.3969 9.13641 13.8919 11.9766 14.2973 16.3445C14.6996 20.7144 18.2206 22.9101 18.2206 22.9101Z" fill="#475466"/>
<path d="M24.0256 26.6616C24.0256 26.6616 28.1101 27.385 31.3343 24.4053C34.5578 21.4282 33.8496 16.973 33.8496 16.973C33.8496 16.973 29.9386 16.7584 26.6282 19.8149C23.321 22.8695 24.0256 26.6616 24.0256 26.6616Z" fill="#475466"/>
<path d="M23.1981 31.4942C20.3174 34.9552 21.5088 38.626 21.5088 38.626C21.5088 38.626 25.6571 38.8088 28.4618 35.4383C31.2653 32.0619 29.9821 27.7382 29.9821 27.7382C29.9821 27.7382 26.0789 28.0331 23.1981 31.4942Z" fill="#475466"/>
<path d="M31.4122 37.03C31.4122 37.03 27.5505 37.6944 25.0097 41.4068C22.4668 45.127 23.9963 48.6654 23.9963 48.6654C23.9963 48.6654 28.1388 48.4577 30.6172 44.8365C33.093 41.2147 31.4122 37.03 31.4122 37.03Z" fill="#475466"/>
<path d="M28.6623 59.3529C28.6623 59.3529 32.5735 57.9594 33.9038 53.7794C35.2323 49.5962 32.4129 46.0745 32.4129 46.0745C32.4129 46.0745 28.9061 47.8219 27.5416 52.1115C26.1803 56.3993 28.6623 59.3529 28.6623 59.3529Z" fill="#475466"/>
<path d="M25.3809 16.3474C25.3809 16.3474 29.2307 16.0882 31.3719 12.1308C33.5158 8.1741 32.3419 4.4361 32.3419 4.4361C32.3419 4.4361 27.8521 4.85392 25.761 8.71404C23.6732 12.5722 25.3809 16.3474 25.3809 16.3474Z" fill="#475466"/>
<path d="M15.8727 31.9006C15.8727 31.9006 18.099 28.7489 16.3836 24.591C14.6636 20.4292 11.0249 18.9807 11.0249 18.9807C11.0249 18.9807 8.51345 22.7284 10.1866 26.7842C11.859 30.8426 15.8727 31.9006 15.8727 31.9006Z" fill="#475466"/>
<path d="M16.4016 41.887C16.4016 41.887 17.8701 38.3196 15.275 34.6468C12.6754 30.97 8.80465 30.3686 8.80465 30.3686C8.80465 30.3686 7.18715 34.5812 9.71777 38.1628C12.2542 41.7431 16.4016 41.887 16.4016 41.887Z" fill="#475466"/>
<path d="M18.8811 50.6773C18.8811 50.6773 19.2077 46.8342 15.6174 44.1211C12.0259 41.4021 8.1565 42.0011 8.1565 42.0011C8.1565 42.0011 7.89177 46.5059 11.3882 49.1559C14.8866 51.7981 18.8811 50.6773 18.8811 50.6773Z" fill="#475466"/>
<path d="M20.0077 54.3533C16.119 52.0865 12.3459 53.1409 12.3459 53.1409C12.3459 53.1409 12.6199 57.6428 16.4076 59.8529C20.2004 62.0644 24.0307 60.4731 24.0307 60.4731C24.0307 60.4731 23.8972 56.6175 20.0077 54.3533Z" fill="#475466"/>
<path d="M25.1598 18.9823L23.5342 17.5789C23.3828 17.7573 8.47456 35.6316 29.4192 65.7051L31.1791 64.4786C11.2389 35.8423 24.5813 19.6562 25.1598 18.9823Z" fill="#475466"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -7,7 +7,9 @@ import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales"; import { ELocalesPlacement } from "@/locales";
import { useCallback, useEffect, useLayoutEffect, useState } from "react"; import { useCallback, useEffect, useLayoutEffect, useState } from "react";
import { sleep } from "@/services/date"; import { sleep } from "@/services/date";
import metricService, { useMetricABFlags } from "@/services/metric/metricService"; import metricService, {
useMetricABFlags,
} from "@/services/metric/metricService";
import { genders } from "@/components/pages/ABDesign/v1/data/genders"; import { genders } from "@/components/pages/ABDesign/v1/data/genders";
import { Navigate, useNavigate, useSearchParams } from "react-router-dom"; import { Navigate, useNavigate, useSearchParams } from "react-router-dom";
import routes, { compatibilityV2Prefix } from "@/routes"; import routes, { compatibilityV2Prefix } from "@/routes";
@ -41,11 +43,15 @@ function GenderPage() {
const { flags, ready } = useMetricABFlags(); const { flags, ready } = useMetricABFlags();
const { isReady, variant: genderPageType } = useUnleash({ const { isReady, variant: genderPageType } = useUnleash({
flag: EUnleashFlags.genderPageType flag: EUnleashFlags.genderPageType,
}); });
const { variant: relationshipStatusPagePlacement = "v0" } = useUnleash({ const { variant: relationshipStatusPagePlacement = "v0" } = useUnleash({
flag: EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement flag: EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement,
});
const { variant: reviewPage = "hide" } = useUnleash({
flag: EUnleashFlags.v2CompatibilityReviewPage,
}); });
const pageType = flags?.genderPageType?.[0] || genderPageType || "v2"; const pageType = flags?.genderPageType?.[0] || genderPageType || "v2";
@ -53,14 +59,16 @@ function GenderPage() {
const localGenders = genders.map((gender) => ({ const localGenders = genders.map((gender) => ({
id: gender.id, id: gender.id,
title: <> title: (
{genderButtonIcon === "show" && <>
{genderButtonIcon === "show" && (
<span className={styles.genderIcon}> <span className={styles.genderIcon}>
{gender.id === "male" ? "🙋‍♂️" : "🙋‍♀️"} {gender.id === "male" ? "🙋‍♂️" : "🙋‍♀️"}
</span> </span>
} )}
{translate(gender.id, undefined, ELocalesPlacement.V1)} {translate(gender.id, undefined, ELocalesPlacement.V1)}
</>, </>
),
})); }));
useLayoutEffect(() => { useLayoutEffect(() => {
@ -107,6 +115,9 @@ function GenderPage() {
if (relationshipStatusPagePlacement === "v2") { if (relationshipStatusPagePlacement === "v2") {
return navigate(routes.client.compatibilityV2RelationshipStatus()); return navigate(routes.client.compatibilityV2RelationshipStatus());
} }
if (reviewPage === "show") {
return navigate(routes.client.compatibilityV2Review());
}
return navigate(routes.client.compatibilityV2Birthdate()); return navigate(routes.client.compatibilityV2Birthdate());
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [gender, navigate]); }, [gender, navigate]);
@ -121,28 +132,43 @@ function GenderPage() {
if (!ready || !isReady) return <Loader color={LoaderColor.Black} />; if (!ready || !isReady) return <Loader color={LoaderColor.Black} />;
if (relationshipStatusPagePlacement === "v1" && !noRedirectAB) { if (relationshipStatusPagePlacement === "v1" && !noRedirectAB) {
return <Navigate to={routes.client.compatibilityV2RelationshipStatus()} /> return <Navigate to={routes.client.compatibilityV2RelationshipStatus()} />;
} }
switch (pageType) { switch (pageType) {
case "v0": case "v0":
return ( return (
<GenderV0 localGenders={localGenders} gender={gender} selectGender={selectGender} /> <GenderV0
) localGenders={localGenders}
gender={gender}
selectGender={selectGender}
/>
);
case "v1": case "v1":
return ( return (
<GenderV1 localGenders={localGenders} gender={gender} selectGender={selectGender} /> <GenderV1
) localGenders={localGenders}
gender={gender}
selectGender={selectGender}
/>
);
case "v2": case "v2":
return ( return (
<GenderV2 localGenders={localGenders} gender={gender} selectGender={selectGender} /> <GenderV2
) localGenders={localGenders}
gender={gender}
selectGender={selectGender}
/>
);
default: default:
return ( return (
<GenderV0 localGenders={localGenders} gender={gender} selectGender={selectGender} /> <GenderV0
localGenders={localGenders}
gender={gender}
selectGender={selectGender}
/>
); );
} }
} }
export default GenderPage; export default GenderPage;

View File

@ -0,0 +1,73 @@
import Title from "@/components/Title";
import styles from "./styles.module.scss";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import ReviewsCount from "../../components/ReviewsCount";
import StatisticsItem from "../../components/StatisticsItem";
import SoulmatesSVG from "../../images/SVG/Soulmates";
import HeartSVG from "../../images/SVG/Heart";
import Review2 from "../../components/Review2";
import { images } from "../../data";
import Button from "../../components/Button";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
function ReviewPage() {
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
const navigate = useNavigate();
const handleNext = () => {
navigate(routes.client.compatibilityV2Birthdate());
};
return (
<div className={styles.container}>
<Title variant="h1" className={styles.title}>
{translate("/review.title", {
color: (
<span className={styles.title_color}>
{translate("/review.title_color")}
</span>
),
})}
</Title>
<div className={styles.content}>
<ReviewsCount />
<div className={styles.statistics}>
<StatisticsItem
title={translate("/review.soulmates_count")}
text={translate("/review.soulmates_today")}
image={<SoulmatesSVG />}
/>
<StatisticsItem
title={translate("/review.trusted_count")}
text={translate("/review.trusted")}
image={<HeartSVG />}
/>
</div>
<Review2
username={translate("/review.review.username")}
text={translate("/review.review.text")}
verifiedText={translate("/review.review.verified_user")}
likesText={translate("/review.review.likes")}
likesImages={[
"review/like_1.jpg",
"review/like_2.jpg",
"review/like_3.png",
]}
image={images("review/avatar.jpg")}
/>
<img
className={styles.partners}
src={images("review/partners.png")}
alt="partners"
/>
</div>
<Button className={styles.button} onClick={handleNext}>
{translate("/review.button")}
</Button>
</div>
);
}
export default ReviewPage;

View File

@ -0,0 +1,75 @@
.container {
position: relative;
width: 100%;
max-width: 560px;
height: fit-content;
min-height: 100dvh;
margin: 0 auto;
padding: 45px 24px;
& * {
font-family: Inter;
}
}
.title {
font-weight: 900;
font-size: 36px;
line-height: 45px;
// letter-spacing: -1.4px;
text-align: left;
margin: 0;
margin-left: 22px;
& > .title_color {
background: linear-gradient(90deg, #ff0099 0%, #3c15ff 96.54%);
color: transparent;
background-clip: text;
}
}
.content {
background: rgba(248, 249, 251, 1);
width: 100%;
padding: 14px 24px 24px;
border-radius: 16px;
margin-top: 12px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
& > .statistics {
width: 100%;
padding-inline: 4px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-top: 36px;
}
& > .partners {
width: 100%;
margin-top: 23px;
}
}
.button.button {
width: 100%;
max-width: 288px;
margin-top: 14px;
margin-inline: auto;
min-height: 56px;
background: rgba(37, 99, 235, 1);
border-radius: 12px;
border: 1px solid rgba(229, 231, 235, 1);
box-shadow: none;
font-family: Inter;
font-weight: 500;
font-size: 16px;
line-height: 100%;
text-align: center;
position: sticky;
bottom: calc(0dvh + 32px);
}

View File

@ -5,14 +5,18 @@ import { actions, selectors } from "@/store";
// import Title from "@/components/Title"; // import Title from "@/components/Title";
import PriceList from "@/components/pages/ABDesign/v1/components/PriceList"; import PriceList from "@/components/pages/ABDesign/v1/components/PriceList";
import { addCurrency, ELocalesPlacement } from "@/locales"; import { addCurrency, ELocalesPlacement } from "@/locales";
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useRef, useState } from "react";
import Button from "../../components/Button"; import Button from "../../components/Button";
import routes from "@/routes"; import routes from "@/routes";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import Loader from "@/components/Loader"; import Loader from "@/components/Loader";
import { useTranslations } from "@/hooks/translations"; import { useTranslations } from "@/hooks/translations";
// import { useMetricABFlags } from "@/services/metric/metricService"; // import { useMetricABFlags } from "@/services/metric/metricService";
import metricService, { EGoals, EMetrics, useMetricABFlags } from "@/services/metric/metricService"; import metricService, {
EGoals,
EMetrics,
useMetricABFlags,
} from "@/services/metric/metricService";
import TrialChoiceV1 from "./v1"; import TrialChoiceV1 from "./v1";
import { usePreloadImages } from "@/hooks/preload/images"; import { usePreloadImages } from "@/hooks/preload/images";
import { getZodiacSignByDate } from "@/services/zodiac-sign"; import { getZodiacSignByDate } from "@/services/zodiac-sign";
@ -21,23 +25,29 @@ import { getFormattedPrice } from "@/utils/price.utils.tsx";
import { useFunnel } from "@/hooks/funnel/useFunnel"; import { useFunnel } from "@/hooks/funnel/useFunnel";
function TrialChoice() { function TrialChoice() {
const { translate, getPeriodText } = useTranslations(ELocalesPlacement.CompatibilityV2); const { translate, getPeriodText } = useTranslations(
ELocalesPlacement.CompatibilityV2
);
const navigate = useNavigate(); const navigate = useNavigate();
const dispatch = useDispatch(); const dispatch = useDispatch();
const bottomRef = useRef<HTMLDivElement>(null);
const { const {
isPending, isPending,
products, products,
currency, currency,
trialInterval, trialInterval,
trialPeriod, trialPeriod,
getProperty getProperty,
} = useFunnel({ } = useFunnel({
funnel: ELocalesPlacement.CompatibilityV2, funnel: ELocalesPlacement.CompatibilityV2,
paymentPlacement: "main" paymentPlacement: "main",
}) });
const { gender, partnerGender, birthdate, partnerBirthdate } = useSelector(selectors.selectQuestionnaire) const { gender, partnerGender, birthdate, partnerBirthdate } = useSelector(
selectors.selectQuestionnaire
);
const zodiacSign = getZodiacSignByDate(birthdate); const zodiacSign = getZodiacSignByDate(birthdate);
const zodiacSignPartner = getZodiacSignByDate(partnerBirthdate); const zodiacSignPartner = getZodiacSignByDate(partnerBirthdate);
@ -55,8 +65,8 @@ function TrialChoice() {
"/v2/compatibility/life-line.svg", "/v2/compatibility/life-line.svg",
"/v2/compatibility/fate-line.svg", "/v2/compatibility/fate-line.svg",
"/v2/compatibility/hand-little-finger.svg", "/v2/compatibility/hand-little-finger.svg",
"/v2/compatibility/partners.png" "/v2/compatibility/partners.png",
]) ]);
const { flags, ready } = useMetricABFlags(); const { flags, ready } = useMetricABFlags();
const trialChoicePageType = flags?.trialChoicePageType?.[0]; const trialChoicePageType = flags?.trialChoicePageType?.[0];
@ -66,40 +76,55 @@ function TrialChoice() {
// const isLongText = flags?.text?.[0] === "on"; // const isLongText = flags?.text?.[0] === "on";
const [isDisabled, setIsDisabled] = useState(true); const [isDisabled, setIsDisabled] = useState(true);
const [isDisabledButtonClicked, setIsDisabledButtonClicked] = useState(false);
const selectedPrice = useSelector(selectors.selectSelectedPrice); const selectedPrice = useSelector(selectors.selectSelectedPrice);
const email = useSelector(selectors.selectEmail); const email = useSelector(selectors.selectEmail);
const homeConfig = useSelector(selectors.selectHome); const homeConfig = useSelector(selectors.selectHome);
const { variant: trialPriceVariant = 'v0', isReady: isReadyTrialPrice } = useUnleash({ const { variant: trialPriceVariant = "v0", isReady: isReadyTrialPrice } =
useUnleash({
flag: EUnleashFlags.compatibilityV2TrialTextPrice, flag: EUnleashFlags.compatibilityV2TrialTextPrice,
}); });
const { variant: trialButtonVariant = "v0", isReady: isReadyTrialButton } =
useUnleash({
flag: EUnleashFlags.compatibilityV2TrialButton,
});
const maxProduct = useMemo(() => { const maxProduct = useMemo(() => {
if (!products?.length) return null; if (!products?.length) return null;
return products.reduce( return products.reduce((max, product) => {
(max, product) => { return Number(product.trialPrice || 0) > Number(max.trialPrice || 0)
return Number(product.trialPrice || 0) > Number(max.trialPrice || 0) ? product : max ? product
}, : max;
products[0] }, products[0]);
);
}, [products]); }, [products]);
const maxTrialPrice = useMemo(() => { const maxTrialPrice = useMemo(() => {
if (!maxProduct) return ""; if (!maxProduct) return "";
return addCurrency( return addCurrency(getFormattedPrice(maxProduct.trialPrice || 0), currency);
getFormattedPrice(maxProduct.trialPrice || 0),
currency
);
}, [maxProduct, currency]); }, [maxProduct, currency]);
const handlePriceItem = () => { const handlePriceItem = () => {
metricService.reachGoal(EGoals.SELECT_TRIAL, [EMetrics.YANDEX, EMetrics.KLAVIYO]); metricService.reachGoal(EGoals.SELECT_TRIAL, [
EMetrics.YANDEX,
EMetrics.KLAVIYO,
]);
metricService.reachGoal(EGoals.AURA_SELECT_TRIAL, [EMetrics.KLAVIYO]); metricService.reachGoal(EGoals.AURA_SELECT_TRIAL, [EMetrics.KLAVIYO]);
setIsDisabled(false); setIsDisabled(false);
}; };
const handleNext = () => { const handleNext = () => {
if (isDisabled && trialButtonVariant === "v1") {
setIsDisabledButtonClicked(true);
bottomRef.current?.scrollIntoView({
behavior: "smooth",
block: "end",
});
return;
}
if (isDisabled) { if (isDisabled) {
return; return;
} }
@ -112,11 +137,16 @@ function TrialChoice() {
}; };
useEffect(() => { useEffect(() => {
metricService.reachGoal(EGoals.TRIAL_CHOICE_PAGE_VISIT, [EMetrics.YANDEX, EMetrics.KLAVIYO]); metricService.reachGoal(EGoals.TRIAL_CHOICE_PAGE_VISIT, [
metricService.reachGoal(EGoals.AURA_TRIAL_CHOICE_PAGE_VISIT, [EMetrics.KLAVIYO]); EMetrics.YANDEX,
EMetrics.KLAVIYO,
]);
metricService.reachGoal(EGoals.AURA_TRIAL_CHOICE_PAGE_VISIT, [
EMetrics.KLAVIYO,
]);
}, []); }, []);
if (!ready || !isReadyTrialPrice) { if (!ready || !isReadyTrialPrice || !isReadyTrialButton) {
return ( return (
<div className={styles.container}> <div className={styles.container}>
<Loader className={styles.loader} /> <Loader className={styles.loader} />
@ -127,7 +157,7 @@ function TrialChoice() {
if (trialChoicePageType === "v1") { if (trialChoicePageType === "v1") {
return <TrialChoiceV1 />; return <TrialChoiceV1 />;
} }
let trialPriceTextVariant = 'v0'; let trialPriceTextVariant = "v0";
switch (trialPriceVariant) { switch (trialPriceVariant) {
case "v0": case "v0":
trialPriceTextVariant = "v0"; trialPriceTextVariant = "v0";
@ -146,10 +176,14 @@ function TrialChoice() {
break; break;
} }
return ( return (
<div className={styles.container}> <div className={styles.container}>
{!(isPending || !isReadyTrialPrice || !maxProduct) && ( {!(
isPending ||
!isReadyTrialPrice ||
!maxProduct ||
!isReadyTrialButton
) && (
<> <>
<EmailSubstrate className={styles["email-substrate"]} email={email} /> <EmailSubstrate className={styles["email-substrate"]} email={email} />
{/* {!isLongText && ( {/* {!isLongText && (
@ -157,43 +191,59 @@ function TrialChoice() {
{getText("text.0")} {getText("text.0")}
</Title> </Title>
)} */} )} */}
<p className={styles.text}>{ <p className={styles.text}>
translate('/trial-choice.description', { {translate("/trial-choice.description", {
maxTrialPrice, maxTrialPrice,
trialPeriod1: getPeriodText(trialPeriod, trialInterval || 0), trialPeriod1: getPeriodText(trialPeriod, trialInterval || 0),
trialPeriod2: getPeriodText(trialPeriod, trialInterval || 0), trialPeriod2: getPeriodText(trialPeriod, trialInterval || 0),
br: <br /> br: <br />,
}) })}
}</p> </p>
<div className={styles["price-container"]}> <div className={styles["price-container"]}>
<PriceList <PriceList
products={products} products={products}
activeItem={selectedPrice} activeItem={selectedPrice}
classNameItem={styles["price-item"]} classNameItem={`${styles["price-item"]} ${
isDisabledButtonClicked && isDisabled
? styles["price-item-disabled"]
: ""
}`}
classNameItemActive={`${styles["price-item-active"]}`} classNameItemActive={`${styles["price-item-active"]}`}
classNamePricesContainer={styles["prices-container"]} classNamePricesContainer={styles["prices-container"]}
currency={currency} currency={currency}
click={handlePriceItem} click={handlePriceItem}
/> />
<p className={styles["auxiliary-text"]}> <p className={styles["auxiliary-text"]}>
{translate(`${getProperty("text.1")?.value}.${trialPriceTextVariant}`, { {translate(
`${getProperty("text.1")?.value}.${trialPriceTextVariant}`,
{
price: maxTrialPrice, price: maxTrialPrice,
br: <br /> br: <br />,
})} }
)}
</p> </p>
</div> </div>
<Button <Button
className={styles.button} className={`${styles.button} ${
disabled={isDisabled} trialButtonVariant === "v1" ? styles["button-v1"] : ""
} ${
isDisabled && trialButtonVariant === "v1"
? styles["button-v1-disabled"]
: ""
}`}
disabled={isDisabled && trialButtonVariant !== "v1"}
onClick={handleNext} onClick={handleNext}
> >
{translate("next")} {translate("next")}
</Button> </Button>
<div ref={bottomRef} />
</> </>
)} )}
{(isPending || !isReadyTrialPrice) && <Loader className={styles.loader} />} {(isPending || !isReadyTrialPrice || !isReadyTrialButton) && (
<Loader className={styles.loader} />
)}
</div> </div>
); );
} }

View File

@ -53,14 +53,24 @@
background-color: transparent; background-color: transparent;
color: #224e90; color: #224e90;
} }
&.price-item-disabled {
color: #fb6c6c;
border-color: #fb6c6c;
}
} }
:global(.dark-theme) .price-item { :global(.dark-theme) .price-item {
border: solid #F7F7F7 1px; border: solid #f7f7f7 1px;
&.price-item-active { &.price-item-active {
border: solid #4F8DE5 3px !important; border: solid #4f8de5 3px !important;
color: #4F8DE5; color: #4f8de5;
}
&.price-item-disabled {
color: #fb6c6c;
border-color: #fb6c6c;
} }
} }
@ -83,7 +93,7 @@
} }
:global(.dark-theme) .auxiliary-text { :global(.dark-theme) .auxiliary-text {
color: #4F8DE5; color: #4f8de5;
} }
.cursor { .cursor {
@ -106,18 +116,29 @@
margin-top: 20px; margin-top: 20px;
transition: background 0.2s ease, color 0.2s ease; transition: background 0.2s ease, color 0.2s ease;
&:disabled { &:not(.button-v1):disabled {
border: solid #224e90 1px; border: solid #224e90 1px;
background: none; background: none;
color: #120d0d; color: #120d0d;
opacity: 1; opacity: 1;
} }
&.button-v1 {
position: sticky;
bottom: calc(0dvh + 16px);
&.button-v1-disabled {
opacity: 0.85;
}
}
} }
:global(.dark-theme) .button:disabled { :global(.dark-theme) {
border: solid #4F8DE5 1px; .button:not(.button-v1):disabled {
border: solid #4f8de5 1px;
background: none; background: none;
color: #F7F7F7; color: #f7f7f7;
}
} }
.text { .text {

View File

@ -189,6 +189,10 @@ function PaymentPage({
} }
if (!isPending && paymentUrl?.length) { if (!isPending && paymentUrl?.length) {
metricService.userParams({
isStripe: true,
});
const fbPixels = JSON.parse(localStorage.getItem("fb_pixels") || "[]").join( const fbPixels = JSON.parse(localStorage.getItem("fb_pixels") || "[]").join(
"," ","
); );

View File

@ -72,3 +72,19 @@
src: url(./assets/media/open-sans-bold.woff2) src: url(./assets/media/open-sans-bold.woff2)
format("woff2"); format("woff2");
} }
@font-face {
font-display: swap;
font-family: Inter;
font-style: normal;
font-weight: 100 900;
src: url(./assets/media/InterVariable.woff2) format("woff2-variations");
}
@font-face {
font-display: swap;
font-family: Inter;
font-style: italic;
font-weight: 100 900;
src: url(./assets/media/InterVariable-Italic.woff2) format("woff2-variations");
}

View File

@ -30,11 +30,13 @@ export enum EUnleashFlags {
"compatibilityV2TrialTextPrice" = "v2-compatibility-trial-text-price", "compatibilityV2TrialTextPrice" = "v2-compatibility-trial-text-price",
"compatibilityV3TrialTextPrice" = "v3-compatibility-trial-text-price", "compatibilityV3TrialTextPrice" = "v3-compatibility-trial-text-price",
"compatibilityV4TrialTextPrice" = "v4-compatibility-trial-text-price", "compatibilityV4TrialTextPrice" = "v4-compatibility-trial-text-price",
"compatibilityV2TrialButton" = "v2-compatibility-trial-button",
"palmistryV1TrialTextPrice" = "v1-palmistry-trial-text-price", "palmistryV1TrialTextPrice" = "v1-palmistry-trial-text-price",
"v2CompatibilityScanResultNumbers" = "v2-compatibility-scan-result-numbers", "v2CompatibilityScanResultNumbers" = "v2-compatibility-scan-result-numbers",
"v2CompatibilityScanInstructionImage" = "v2-compatibility-scan-instruction-image", "v2CompatibilityScanInstructionImage" = "v2-compatibility-scan-instruction-image",
"v2CompatibilityCameraTemplate" = "v2-compatibility-camera-template", "v2CompatibilityCameraTemplate" = "v2-compatibility-camera-template",
"v2CompatibilityRelationshipStatusPagePlacement" = "v2-compatibility-relationship-status-page-placement", "v2CompatibilityRelationshipStatusPagePlacement" = "v2-compatibility-relationship-status-page-placement",
"v2CompatibilityReviewPage" = "v2-compatibility-review-page",
} }
interface IUseUnleashProps<T extends EUnleashFlags> { interface IUseUnleashProps<T extends EUnleashFlags> {
@ -69,11 +71,13 @@ interface IVariants {
[EUnleashFlags.compatibilityV2TrialTextPrice]: "v0" | "v1" | "v2" | "v3"; [EUnleashFlags.compatibilityV2TrialTextPrice]: "v0" | "v1" | "v2" | "v3";
[EUnleashFlags.compatibilityV3TrialTextPrice]: "v0" | "v1" | "v2" | "v3"; [EUnleashFlags.compatibilityV3TrialTextPrice]: "v0" | "v1" | "v2" | "v3";
[EUnleashFlags.compatibilityV4TrialTextPrice]: "v0" | "v1" | "v2" | "v3"; [EUnleashFlags.compatibilityV4TrialTextPrice]: "v0" | "v1" | "v2" | "v3";
[EUnleashFlags.compatibilityV2TrialButton]: "v0" | "v1";
[EUnleashFlags.palmistryV1TrialTextPrice]: "v0" | "v1" | "v2" | "v3"; [EUnleashFlags.palmistryV1TrialTextPrice]: "v0" | "v1" | "v2" | "v3";
[EUnleashFlags.v2CompatibilityScanResultNumbers]: 'off' | 'on'; [EUnleashFlags.v2CompatibilityScanResultNumbers]: 'off' | 'on';
[EUnleashFlags.v2CompatibilityScanInstructionImage]: 'v0' | 'v1'; [EUnleashFlags.v2CompatibilityScanInstructionImage]: 'v0' | 'v1';
[EUnleashFlags.v2CompatibilityCameraTemplate]: 'v0' | 'v1' | 'v2' | 'v3' | 'v4'; [EUnleashFlags.v2CompatibilityCameraTemplate]: 'v0' | 'v1' | 'v2' | 'v3' | 'v4';
[EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement]: 'v0' | 'v1' | 'v2'; [EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement]: 'v0' | 'v1' | 'v2';
[EUnleashFlags.v2CompatibilityReviewPage]: 'show' | 'hide';
} }
/** /**

View File

@ -113,8 +113,8 @@ export type TTranslationPlacements = Partial<
export const getTranslationsJSON = async (language: string): Promise<TTranslationPlacements> => { export const getTranslationsJSON = async (language: string): Promise<TTranslationPlacements> => {
const api = createApi(); const api = createApi();
const isDev = false//window.location.hostname === "localhost" // const isDev = false//window.location.hostname === "localhost"
// const isDev = window.location.hostname === "localhost" const isDev = window.location.hostname === "localhost"
let defaultLanguage = getDefaultLocaleByLanguage(language).toLowerCase(); let defaultLanguage = getDefaultLocaleByLanguage(language).toLowerCase();
if (defaultLanguage === "pt") { if (defaultLanguage === "pt") {
defaultLanguage = "pt-pt" defaultLanguage = "pt-pt"

View File

@ -50,6 +50,7 @@ import Loader, { LoaderColor } from "@/components/Loader";
import ScanHand from "@/components/CompatibilityV2/pages/ScanHand"; import ScanHand from "@/components/CompatibilityV2/pages/ScanHand";
import { ELocalesPlacement } from "@/locales"; import { ELocalesPlacement } from "@/locales";
import { useFunnel } from "@/hooks/funnel/useFunnel"; import { useFunnel } from "@/hooks/funnel/useFunnel";
import Review from "@/components/CompatibilityV2/pages/Review";
const removePrefix = (path: string) => path.replace(compatibilityV2Prefix, ""); const removePrefix = (path: string) => path.replace(compatibilityV2Prefix, "");
@ -241,6 +242,10 @@ function CompatibilityV2Routes() {
path={removePrefix(routes.client.compatibilityV2ScanHand())} path={removePrefix(routes.client.compatibilityV2ScanHand())}
element={<ScanHand />} element={<ScanHand />}
/> />
<Route
path={removePrefix(routes.client.compatibilityV2Review())}
element={<Review />}
/>
<Route element={<Layout />}> <Route element={<Layout />}>
<Route <Route
element={ element={

View File

@ -256,6 +256,7 @@ const routes = {
compatibilityV2SaveOff: () => [compatibilityV2Prefix, "save-off"].join("/"), compatibilityV2SaveOff: () => [compatibilityV2Prefix, "save-off"].join("/"),
compatibilityV2SecretDiscount: () => [compatibilityV2Prefix, "secret-discount"].join("/"), compatibilityV2SecretDiscount: () => [compatibilityV2Prefix, "secret-discount"].join("/"),
compatibilityV2Onboarding: () => [compatibilityV2Prefix, "onboarding"].join("/"), compatibilityV2Onboarding: () => [compatibilityV2Prefix, "onboarding"].join("/"),
compatibilityV2Review: () => [compatibilityV2Prefix, "review"].join("/"),
// CompatibilityV3 // CompatibilityV3
compatibilityV3Welcome: () => [compatibilityV3Prefix, "welcome"].join("/"), compatibilityV3Welcome: () => [compatibilityV3Prefix, "welcome"].join("/"),
compatibilityV3Gender: () => [compatibilityV3Prefix, "gender"].join("/"), compatibilityV3Gender: () => [compatibilityV3Prefix, "gender"].join("/"),

View File

@ -45,7 +45,7 @@ export enum EGoals {
AURA_PAYMENT_METHODS_OPENED = "AuraPaymentMethodsOpened", AURA_PAYMENT_METHODS_OPENED = "AuraPaymentMethodsOpened",
AURA_TRIAL_CHOICE_PAGE_VISIT = "AuraTrialChoicePageVisit", AURA_TRIAL_CHOICE_PAGE_VISIT = "AuraTrialChoicePageVisit",
AURA_TRIAL_PAYMENT_PAGE_VISIT = "AuraTrialPaymentPageVisit", AURA_TRIAL_PAYMENT_PAGE_VISIT = "AuraTrialPaymentPageVisit",
ROSE_VIDEO_CREATION_START = 'RoseVideoCreationStart', ROSE_VIDEO_CREATION_START = "RoseVideoCreationStart",
ROSE_LOADING_START = "RoseLoadingStart", ROSE_LOADING_START = "RoseLoadingStart",
ROSE_VIDEO_CREATED = "RoseVideoCreated", ROSE_VIDEO_CREATED = "RoseVideoCreated",
ROSE_LOADING_END = "RoseLoadingEnd", ROSE_LOADING_END = "RoseLoadingEnd",
@ -76,15 +76,15 @@ export enum EGoals {
} }
export enum EFlags { export enum EFlags {
isNextPageMentioned = 'Go to page mentionedIn', isNextPageMentioned = "Go to page mentionedIn",
aboutUsAnswers = 'Key for aboutUsAnswers' aboutUsAnswers = "Key for aboutUsAnswers",
} }
export enum EMetrics { export enum EMetrics {
YANDEX = "Yandex", YANDEX = "Yandex",
KLAVIYO = "Klaviyo", KLAVIYO = "Klaviyo",
FACEBOOK = "Facebook", FACEBOOK = "Facebook",
GOOGLE_ANALYTICS = "GoogleAnalytics" GOOGLE_ANALYTICS = "GoogleAnalytics",
} }
interface IUserParams { interface IUserParams {
@ -95,36 +95,37 @@ interface IUserParams {
hasPersonalVideo: boolean; hasPersonalVideo: boolean;
gender: string; gender: string;
age: number; age: number;
isStripe: boolean;
} }
const environments = import.meta.env const environments = import.meta.env;
const metricCounterNumber = Number(environments.AURA_YANDEX_COUNTER_NUMBER) const metricCounterNumber = Number(environments.AURA_YANDEX_COUNTER_NUMBER);
const gaMeasurementId = environments.AURA_GA_MEASUREMENT_ID const gaMeasurementId = environments.AURA_GA_MEASUREMENT_ID;
const checkIsAvailableYandexMetric = () => { const checkIsAvailableYandexMetric = () => {
const isProduction = environments.MODE === "production"; const isProduction = environments.MODE === "production";
if (!isProduction) { if (!isProduction) {
console.log("ANALYTIC IS NOT WORKING: Not production") console.log("ANALYTIC IS NOT WORKING: Not production");
return false; return false;
}; }
if (typeof window.ym !== "function") { if (typeof window.ym !== "function") {
console.error("Yandex.Metric not found") console.error("Yandex.Metric not found");
return false return false;
}
return true
} }
return true;
};
const checkIsAvailableYandexMetricAB = () => { const checkIsAvailableYandexMetricAB = () => {
const isProduction = environments.MODE === "production"; const isProduction = environments.MODE === "production";
if (!isProduction) { if (!isProduction) {
console.log("ANALYTIC IS NOT WORKING: Not production") console.log("ANALYTIC IS NOT WORKING: Not production");
return false; return false;
}; }
if (typeof window.ymab !== "function") { if (typeof window.ymab !== "function") {
console.error("Yandex.Metric not found") console.error("Yandex.Metric not found");
return false return false;
}
return true
} }
return true;
};
const checkIsAvailableGoogleAnalytics = () => { const checkIsAvailableGoogleAnalytics = () => {
// const isProduction = environments.MODE === "production"; // const isProduction = environments.MODE === "production";
@ -133,15 +134,15 @@ const checkIsAvailableGoogleAnalytics = () => {
// return false; // return false;
// }; // };
if (typeof window.gtag !== "function") { if (typeof window.gtag !== "function") {
console.error("Google Analytics not found") console.error("Google Analytics not found");
return false return false;
}
return true
} }
return true;
};
const setUserID = (userId: string) => { const setUserID = (userId: string) => {
if (checkIsAvailableYandexMetric()) { if (checkIsAvailableYandexMetric()) {
window.ym(metricCounterNumber, "setUserID", userId) window.ym(metricCounterNumber, "setUserID", userId);
Clarity.identify(userId); Clarity.identify(userId);
} }
@ -150,18 +151,18 @@ const setUserID = (userId: string) => {
// window.gtag('set', 'user_properties', { // window.gtag('set', 'user_properties', {
// user_id: userId // user_id: userId
// }); // });
window.gtag('config', gaMeasurementId, { window.gtag("config", gaMeasurementId, {
user_id: userId user_id: userId,
}); });
} }
if (!window.klaviyo) return console.error("Klaviyo.Metric not found"); if (!window.klaviyo) return console.error("Klaviyo.Metric not found");
window.klaviyo.push(['identify', userId]); window.klaviyo.push(["identify", userId]);
} };
const userParams = (parameters: Partial<IUserParams>) => { const userParams = (parameters: Partial<IUserParams>) => {
if (checkIsAvailableYandexMetric()) { if (checkIsAvailableYandexMetric()) {
window.ym(metricCounterNumber, "userParams", parameters) window.ym(metricCounterNumber, "userParams", parameters);
} }
Object.entries(parameters).forEach(([key, value]) => { Object.entries(parameters).forEach(([key, value]) => {
@ -176,17 +177,21 @@ const userParams = (parameters: Partial<IUserParams>) => {
// }), {}); // }), {});
// window.gtag('set', 'user_properties', gaUserProperties); // window.gtag('set', 'user_properties', gaUserProperties);
window.gtag('config', gaMeasurementId, { window.gtag("config", gaMeasurementId, {
send_page_view: false, send_page_view: false,
...parameters ...parameters,
}); });
} }
if (!window.klaviyo) return console.error("Klaviyo.Metric not found"); if (!window.klaviyo) return console.error("Klaviyo.Metric not found");
window.klaviyo.push(['identify', parameters]); window.klaviyo.push(["identify", parameters]);
} };
const reachGoal = (goal: EGoals, usingMetrics: EMetrics[], options?: unknown) => { const reachGoal = (
goal: EGoals,
usingMetrics: EMetrics[],
options?: unknown
) => {
console.log("goal: ", goal); console.log("goal: ", goal);
const isProduction = environments.MODE === "production"; const isProduction = environments.MODE === "production";
const source = getSourceByPathname(); const source = getSourceByPathname();
@ -195,24 +200,25 @@ const reachGoal = (goal: EGoals, usingMetrics: EMetrics[], options?: unknown) =>
if (usingMetrics.includes(EMetrics.YANDEX)) { if (usingMetrics.includes(EMetrics.YANDEX)) {
if (typeof window.ym !== "function") { if (typeof window.ym !== "function") {
console.error("Yandex.Metric not found") console.error("Yandex.Metric not found");
} else if (isProduction) { } else if (isProduction) {
window.ym(metricCounterNumber, "reachGoal", goal) window.ym(metricCounterNumber, "reachGoal", goal);
Clarity.event(goal); Clarity.event(goal);
console.log("goalYM&Clarity: ", goal); console.log("goalYM&Clarity: ", goal);
} }
if (!checkIsAvailableGoogleAnalytics()) { if (!checkIsAvailableGoogleAnalytics()) {
console.error("Google Analytics not found") console.error("Google Analytics not found");
} else { } else {
const eventName = goal === EGoals.PAYMENT_SUCCESS ? "purchase" : goal; const eventName = goal === EGoals.PAYMENT_SUCCESS ? "purchase" : goal;
window.gtag('event', eventName, { window.gtag("event", eventName, {
source, source,
...(options as Record<string, unknown>) ...(options as Record<string, unknown>),
}); });
console.log("goalGA: ", goal); console.log("goalGA: ", goal);
} }
} }
if (!isProduction) return console.log("ANALYTIC IS NOT WORKING: Not production"); if (!isProduction)
return console.log("ANALYTIC IS NOT WORKING: Not production");
// if (usingMetrics.includes(EMetrics.GOOGLE_ANALYTICS)) { // if (usingMetrics.includes(EMetrics.GOOGLE_ANALYTICS)) {
// if (typeof window.gtag !== "function") { // if (typeof window.gtag !== "function") {
@ -225,22 +231,26 @@ const reachGoal = (goal: EGoals, usingMetrics: EMetrics[], options?: unknown) =>
if (usingMetrics.includes(EMetrics.KLAVIYO)) { if (usingMetrics.includes(EMetrics.KLAVIYO)) {
if (!window.klaviyo) { if (!window.klaviyo) {
console.error("Klaviyo.Metric not found") console.error("Klaviyo.Metric not found");
} else { } else {
window.klaviyo.push(['track', goal]); window.klaviyo.push(["track", goal]);
console.log("goalKLAVIYO: ", goal); console.log("goalKLAVIYO: ", goal);
} }
} }
if (usingMetrics.includes(EMetrics.FACEBOOK)) { if (usingMetrics.includes(EMetrics.FACEBOOK)) {
if (typeof window.fbq !== "function") { if (typeof window.fbq !== "function") {
console.error("Facebook.Metric not found") console.error("Facebook.Metric not found");
} else { } else {
window.fbq('track', goal === EGoals.ENTERED_EMAIL ? EGoals.LEAD : goal, options) window.fbq(
"track",
goal === EGoals.ENTERED_EMAIL ? EGoals.LEAD : goal,
options
);
console.log("goalFB: ", goal); console.log("goalFB: ", goal);
} }
} }
} };
type THitOptions = { type THitOptions = {
callback: () => void; callback: () => void;
@ -248,15 +258,15 @@ type THitOptions = {
params: { params: {
order_price: number; order_price: number;
currency: string; currency: string;
}, };
referer: string; referer: string;
title: string; title: string;
} };
const hit = (url?: string, options?: THitOptions) => { const hit = (url?: string, options?: THitOptions) => {
if (!checkIsAvailableYandexMetric()) return; if (!checkIsAvailableYandexMetric()) return;
window.ym(metricCounterNumber, "hit", url, options); window.ym(metricCounterNumber, "hit", url, options);
} };
const initMetric = () => { const initMetric = () => {
if (!checkIsAvailableYandexMetric()) return; if (!checkIsAvailableYandexMetric()) return;
@ -268,16 +278,21 @@ const initMetric = () => {
webvisor: true, webvisor: true,
}); });
console.log("Metric initialized"); console.log("Metric initialized");
} };
const initMetricAB = () => { const initMetricAB = () => {
if (!checkIsAvailableYandexMetricAB()) return; if (!checkIsAvailableYandexMetricAB()) return;
window.ymab(`metrika.${metricCounterNumber}`, "setConfig", {
window.ymab(`metrika.${metricCounterNumber}`, 'setConfig', { enableJS: true, enableWatch: true }); enableJS: true,
window.ymab(`metrika.${metricCounterNumber}`, 'init'/*, {clientFeatures}, {callback}*/); enableWatch: true,
});
window.ymab(
`metrika.${metricCounterNumber}`,
"init" /*, {clientFeatures}, {callback}*/
);
console.log("Metric initialized"); console.log("Metric initialized");
} };
type TABFlags = { type TABFlags = {
showTimerTrial: "show" | "hide"; showTimerTrial: "show" | "hide";
@ -293,12 +308,19 @@ type TABFlags = {
yourReading: "v1" | "v2"; yourReading: "v1" | "v2";
genderButtonIcon: "show" | "hide"; genderButtonIcon: "show" | "hide";
tryApp: "v0" | "v1"; tryApp: "v0" | "v1";
} };
export const useMetricABFlags = () => { export const useMetricABFlags = () => {
return useExperiments<typeof EFlags & TABFlags>({ return useExperiments<typeof EFlags & TABFlags>({
clientId: `metrika.${metricCounterNumber}` clientId: `metrika.${metricCounterNumber}`,
}) });
} };
export default { setUserID, userParams, reachGoal, hit, initMetric, initMetricAB } export default {
setUserID,
userParams,
reachGoal,
hit,
initMetric,
initMetricAB,
};