Merge branch 'develop' into 'main'

AW-483-484-485-fix-bugs

See merge request witapp/aura-webapp!814
This commit is contained in:
Daniil Chemerkin 2025-08-29 19:01:03 +00:00
commit 6b22791f90
38 changed files with 1077 additions and 130 deletions

View File

@ -93,6 +93,19 @@
}
}
},
"/compatibility-test": {
"title": "Тест на Совместимость",
"subtitle": "Всё начинается с вас! Выберите ваш пол.",
"points": {
"point1": "Тест займмет не более 1 мин.",
"point2": "Ты получишь разбор совместимости.",
"point3": "Решишь проблемы в отношениях за месяц.",
"point4": "Сэкономишь сотни долларов на ненадёжных прогнозах.",
"point5": "Получишь персональный анализ."
},
"already_have_account": "Уже есть аккаунт? Войти",
"button": "Начать"
},
"/birthdate": {
"title": "When Were You Born?",
"text": "Your birth date can reveal strengths and values that may help you move forward"
@ -159,7 +172,71 @@
"answer1": "Single",
"answer2": "In a Relationship",
"answer3": "Married",
"answer4": "Divorced"
"answer4": "Divorced",
"v1": {
"title": "Чтобы яснее разобрать вашу суть, укажите какие у вас отношения сейчас?",
"answer1": "Single",
"answer2": "Начало",
"answer3": "Долгие отношения",
"answer4": "Развиваются непонятно куда",
"answer5": "Разрыв/кризис"
}
},
"/relationship-status-result": {
"start": {
"title": "How can you really tell if your partner is the right one—and avoid making a mistake?",
"text": "Understanding your partners emotions is the key to a harmonious relationship. Our system predicts compatibility with up to 98% accuracy, giving you clear, detailed reports."
},
"in_relationship": {
"title": "Love is important, but why isnt love alone enough for a happy, lasting relationship?",
"text": "Daily life can either strengthen your relationship or create tension if your ideas of comfort and care dont match. Our system predicts compatibility with up to 98% accuracy, helping you understand how long-lasting and harmonious your partnership can be."
},
"developing": {
"title": "Feel like your partner just doesnt get you? Its not by chance—its about differences in your natal patterns.",
"text": "Closeness isnt just about attraction—its about understanding each others wants and emotions. Our data from 2 million people backs this up, and we know how to help."
},
"crisis": {
"title": "Why do some couples split up quickly, while others stay together for years?",
"text": "A shared future isnt just about dreams—its about common goals, values, and everyday effort. Our system predicts compatibility with up to 98% accuracy. Well show you, step by step, how to build a strong relationship."
},
"single": {
"title": "Does it feel like there are no worthy partners out there, or you keep ending up with the wrong people? It all comes down to incompatible choices.",
"text": "Our system predicts compatibility with up to 98% accuracy, helping you find the right partner and opening up new possibilities in your personal life."
}
},
"/fear-in-relationship": {
"title": "Чего вы боитесь больше всего в отношениях?",
"answer1": "Потратить жизнь не на того",
"answer2": "Остаться одиноким",
"answer3": "Пропустить свою судьбу",
"answer4": "Любовь без уважения и поддержки",
"answer5": "Не узнать правду о совместимости"
},
"/important-step": {
"title": "Ты сделал важный шаг!",
"text": "Обозначил свой главный страх в отношениях. Это шаг к тому, чтобы больше не терять время. Мы поможем избежать все ошибки."
},
"/who-matter": {
"title": "О ком вы думаете, строя отношения?",
"answer1": "О себе",
"answer2": "О детях",
"answer3": "О семье"
},
"/your-priority": {
"title": "Что сейчас для вас в приоритете?",
"answer1": "Внутренняя гармония",
"answer2": "Надёжные отношения",
"answer3": "Новые впечатления"
},
"/personalized-relationship-analysis": {
"single": {
"title": "Что такое персонализированный анализ отношений?",
"text": "У вас свои сильные стороны, ожидания и трудности. Мы создаём персональный портрет, чтобы помочь вам лучше понять себя и свои истинные потребности в отношениях.<br><br>Мы анализируем ваши ответы и показываем, что мешало вам раньше, а что наоборот поможет встретить именно «своего» человека и построить счастливую любовь."
},
"relationship": {
"title": "Что такое персонализированный анализ отношений?",
"text": "Каждая пара уникальна. У вас свои сильные стороны и свои трудности. Мы создаём персональный портрет отношений, чтобы помочь укрепить доверие, гармонию и близость именно в вашей паре.<br><br>Мы анализируем ваши ответы и показываем, что мешает вашей любви, а что наоборот поможет сделать её глубже и счастливее."
}
},
"/element-resonates": {
"title": "Which Element Empowers You the Most?",

View File

@ -56,6 +56,18 @@
}
}
},
"/compatibility-test": {
"title": "Тест на Совместимость",
"subtitle": "Всё начинается с вас! Выберите ваш пол.",
"points": {
"point1": "Тест займмет не более 1 мин.",
"point2": "Ты получишь разбор совместимости по хиромантическому анализу линий на твоей ладони.",
"point3": "Решишь проблемы в отношениях за месяц.",
"point4": "Сэкономишь сотни долларов на ненадёжных прогнозах.",
"point5": "Получишь персональный анализ."
},
"already_have_account": "Уже есть аккаунт? Войти"
},
"/birthdate": {
"title": "Когда вы родились?",
"text": "Ваша дата рождения может раскрыть сильные стороны и ценности, которые помогут вам двигаться вперёд."

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -44,7 +44,7 @@ export interface IAnswersSessionPalmistry {
export interface IAnswersSessionCompatibilityV2 {
what_aspects: 'love_relationships' | 'health_vitality' | 'career_destiny' | 'life_transitions', // Type: string, optional - 'love_relationships' | 'health_vitality' | 'career_destiny';
relationship_status: 'single' | 'in_relationship' | 'engaged' | 'divorced' | 'complicated', // Type: string, optional - 'single' | 'in_relationship';
relationship_status: 'single' | 'in_relationship' | 'engaged' | 'divorced' | 'complicated' | 'start' | 'developing' | 'crisis', // Type: string, optional - 'single' | 'in_relationship';
element_resonates: 'water' | 'fire' | 'air' | 'earth' | 'light' | 'darkness', // Type: string, optional - 'water' | 'fire' | 'air' | 'earth';
favorite_color: 'blue' | 'green' | 'orange' | 'violet' | 'red' | 'yellow' | 'turquoise', // Type: string, optional - 'blue' | 'green' | 'orange' | 'violet' | 'red' | 'yellow';
head_or_heart: 'head' | 'heart' | 'both' | 'depends', // Type: string, optional - 'head' | 'heart' | 'both';
@ -57,6 +57,9 @@ export interface IAnswersSessionCompatibilityV2 {
partner_expectations: 1 | 2 | 3 | 4 | 5; // Type: number, optional - 1 | 2 | 3 | 4 | 5;
romantic_gestures: "love" | "neutral" | "dislike"; // Type: string, optional - "love" | "neutral" | "dislike";
checking_phone: "against" | "allow" | "normally"; // Type: string, optional - "against" | "allow" | "normally";
fear_in_relationship: "wasting_life_for_wrong_person" | "stay_single" | "skip_destiny" | "love_without_respect_and_support" | "not_find_truth_about_compatibility";
who_matter: "me" | "kids" | "family";
your_priority: "inner_harmony" | "reliable_relationship" | "new_impressions";
}
export interface IAnswersSessionCompatibilityV3 {

View File

@ -1,6 +1,7 @@
.container {
width: 100%;
height: 71px;
// height: 71px;
padding: 25px 16px;
border-radius: 20px;
display: flex;
align-items: center;

View File

@ -93,7 +93,7 @@
& > .likesImages {
display: flex;
flex-direction: row;
margin-left: 4px;
margin-left: 8px;
& > .likesImage {
width: 28px;
@ -102,8 +102,8 @@
background-size: cover;
background-position: center;
background-repeat: no-repeat;
border: 2px solid rgba(255, 255, 255, 1);
margin-left: -4px;
// border: 2px solid rgba(255, 255, 255, 1);
margin-left: -8px;
}
}
}

View File

@ -0,0 +1,57 @@
import { useTranslations } from "@/hooks/translations";
import styles from "./styles.module.scss";
import { ELocalesPlacement } from "@/locales";
import Title from "@/components/Title";
import PrivacyPolicy from "@/components/pages/ABDesign/v1/components/PrivacyPolicy";
import Button from "../../components/Button";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
function CompatibilityTestPage() {
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
const navigate = useNavigate();
const handleNext = () => {
navigate(routes.client.compatibilityV2RelationshipStatus());
};
return (
<div className={styles.container}>
<Title variant="h2" className={styles.title}>
{translate("/compatibility-test.title", {
br: <br />,
})}
</Title>
<ul className={styles.points}>
{Array.from({ length: 5 }).map((_, index) => (
<li key={index}>
{translate(`/compatibility-test.points.point${index + 1}`)}
</li>
))}
</ul>
{/* <ChooseGender onSelectGender={selectGender} /> */}
{/* <div className={styles["genders-container"]}>
{localGenders.map((_gender, index) => (
<Answer
key={index}
answer={_gender}
isSelected={gender === _gender.id}
onClick={() =>
selectGender(genders.find((g) => g.id === _gender.id) ?? null)
}
/>
))}
</div> */}
<Button className={styles.button} onClick={handleNext}>
{translate("/compatibility-test.button")}
</Button>
<PrivacyPolicy
containerClassName={styles["privacy-policy"]}
haveCheckbox={false}
/>
</div>
);
}
export default CompatibilityTestPage;

View File

@ -0,0 +1,53 @@
.container {
position: relative;
min-height: calc(100dvh - 110px);
display: flex;
flex-direction: column;
align-items: center;
}
.title {
margin-top: 18px;
font-size: 28px;
font-weight: 500;
line-height: 125%;
margin-bottom: 0;
}
.privacy-policy {
max-width: 316px;
text-align: center;
position: sticky;
margin-top: auto;
}
.points {
margin-top: 46px;
color: #2c2c2c;
list-style-type: disc;
li {
font-size: 20px;
line-height: 125%;
font-weight: 300;
margin-left: 28px;
&::marker {
font-size: 14px;
}
}
}
.button.button {
background: rgba(37, 99, 235, 1);
box-shadow: 2px 5px 2.5px -1px rgba(0, 0, 0, 0.2);
border-radius: 20px;
margin-top: 64px;
margin-bottom: 26px;
}
:global(body.dark-theme) {
.points {
color: #f7f7f7;
}
}

View File

@ -0,0 +1,89 @@
import Title from "@/components/Title";
import styles from "./styles.module.scss";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import { IAnswersSessionCompatibilityV2 } from "@/api/resources/Session";
import { useMemo } from "react";
import Answer from "../../components/Answer";
import { useSelector } from "react-redux";
import { actions, selectors } from "@/store";
import { useDispatch } from "react-redux";
import { useSession } from "@/hooks/session/useSession";
import { ESourceAuthorization } from "@/api/resources/User";
import routes from "@/routes";
import { useNavigate } from "react-router-dom";
import { sleep } from "@/services/date";
import { answerTimeOut } from "../../data";
function FearInRelationship() {
const navigate = useNavigate();
const dispatch = useDispatch();
const { updateSession } = useSession();
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
const { fearInRelationship } = useSelector(
selectors.selectCompatibilityV2Answers
);
const answers: {
id: IAnswersSessionCompatibilityV2["fear_in_relationship"];
title: string;
}[] = useMemo(
() => [
{
id: "wasting_life_for_wrong_person",
title: translate("/fear-in-relationship.answer1"),
},
{
id: "stay_single",
title: translate("/fear-in-relationship.answer2"),
},
{
id: "skip_destiny",
title: translate("/fear-in-relationship.answer3"),
},
{
id: "love_without_respect_and_support",
title: translate("/fear-in-relationship.answer4"),
},
{
id: "not_find_truth_about_compatibility",
title: translate("/fear-in-relationship.answer5"),
},
],
[translate]
);
const handleClick = async (
id: IAnswersSessionCompatibilityV2["fear_in_relationship"]
) => {
dispatch(actions.compatibilityV2Answers.update({ fearInRelationship: id }));
updateSession(
{
answers: {
fear_in_relationship: id,
},
},
ESourceAuthorization["aura.compatibility.v2"]
);
if (id !== fearInRelationship) await sleep(answerTimeOut);
navigate(routes.client.compatibilityV2ImportantStep());
};
return (
<div className={styles.container}>
<Title variant="h2" className={styles.title}>
{translate("/fear-in-relationship.title")}
</Title>
{answers.map((answers, index) => (
<Answer
key={index}
answer={answers}
isSelected={fearInRelationship === answers.id}
onClick={() => handleClick(answers.id)}
/>
))}
</div>
);
}
export default FearInRelationship;

View File

@ -54,6 +54,10 @@ function GenderPage() {
flag: EUnleashFlags.v2CompatibilityReviewPage,
});
const { variant: pathToEnteringBirthdate = "hide" } = useUnleash({
flag: EUnleashFlags.v2CompatibilityPathToEnteringBirthdate,
});
const pageType = flags?.genderPageType?.[0] || genderPageType || "v2";
const genderButtonIcon = flags?.genderButtonIcon?.[0] || "hide";
@ -115,12 +119,24 @@ function GenderPage() {
if (relationshipStatusPagePlacement === "v2") {
return navigate(routes.client.compatibilityV2RelationshipStatus());
}
console.log(reviewPage);
if (reviewPage === "show") {
return navigate(routes.client.compatibilityV2Review());
}
if (pathToEnteringBirthdate === "show") {
return navigate(routes.client.compatibilityV2CompatibilityTest());
}
return navigate(routes.client.compatibilityV2Birthdate());
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [gender, navigate]);
}, [
gender,
navigate,
reviewPage,
pathToEnteringBirthdate,
relationshipStatusPagePlacement,
isReady,
]);
useEffect(() => {
if (privacyPolicyChecked && gender && isSelected) {
@ -129,6 +145,20 @@ function GenderPage() {
}
}, [gender, handleNext, isSelected, privacyPolicyChecked]);
// useEffect(() => {
// if (pathToEnteringBirthdate === "show" && !pathToEnteringBirthdateShown) {
// dispatch(
// actions.compatibilityV2.update({ pathToEnteringBirthdateShown: true })
// );
// return navigate(routes.client.compatibilityV2CompatibilityTest());
// }
// }, [
// dispatch,
// navigate,
// pathToEnteringBirthdate,
// pathToEnteringBirthdateShown,
// ]);
if (!ready || !isReady) return <Loader color={LoaderColor.Black} />;
if (relationshipStatusPagePlacement === "v1" && !noRedirectAB) {

View File

@ -0,0 +1,26 @@
import { useNavigate } from "react-router-dom";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import AnswerExplanation from "../../templates/AnswerExplanation";
import routes from "@/routes";
import styles from "./styles.module.scss";
function ImportantStep() {
const navigate = useNavigate();
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
return (
<AnswerExplanation
title={translate(`/important-step.title`)}
text={translate(`/important-step.text`)}
buttonType="next"
classNameTitle={styles.title}
classNameText={styles.text}
handleNext={() => {
navigate(routes.client.compatibilityV2WhoMatter());
}}
/>
);
}
export default ImportantStep;

View File

@ -0,0 +1,8 @@
.title {
font-weight: 700;
margin-bottom: 62px;
}
.text {
margin-bottom: 62px;
}

View File

@ -14,7 +14,10 @@ import { getZodiacSignByDate } from "@/services/zodiac-sign";
import { EUnleashFlags, useUnleash } from "@/hooks/ab/unleash/useUnleash";
import Loader, { LoaderColor } from "@/components/Loader";
import { useEffect } from "react";
import metricService, { EGoals, EMetrics } from "@/services/metric/metricService";
import metricService, {
EGoals,
EMetrics,
} from "@/services/metric/metricService";
function PalmsInformation() {
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
@ -26,33 +29,47 @@ function PalmsInformation() {
});
const { isReady, variant: zodiacImages } = useUnleash({
flag: EUnleashFlags.zodiacImages
flag: EUnleashFlags.zodiacImages,
});
const { variant: relationshipStatusPagePlacement = "v0" } = useUnleash({
flag: EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement
flag: EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement,
});
const { variant: pathToEnteringBirthdate = "hide" } = useUnleash({
flag: EUnleashFlags.v2CompatibilityPathToEnteringBirthdate,
});
const handleNext = () => {
if (relationshipStatusPagePlacement === "v1" || relationshipStatusPagePlacement === "v2") {
if (
relationshipStatusPagePlacement === "v1" ||
relationshipStatusPagePlacement === "v2" ||
pathToEnteringBirthdate === "show"
) {
return navigate(`${routes.client.compatibilityV2RelateFollowing()}/1`);
}
navigate(routes.client.compatibilityV2RelationshipStatus());
};
if (!isReady) {
return <Loader color={LoaderColor.Black} />;
}
useEffect(() => {
const ua = window.navigator.userAgent;
if (ua.includes("FBAN") || ua.includes("FBAV") || ua.includes("FBIOS")) {
metricService.reachGoal(EGoals.STAYED_IN_FB, [EMetrics.YANDEX, EMetrics.KLAVIYO])
metricService.reachGoal(EGoals.STAYED_IN_FB, [
EMetrics.YANDEX,
EMetrics.KLAVIYO,
]);
}
if (ua.includes("Instagram")) {
metricService.reachGoal(EGoals.STAYED_IN_INSTAGRAM, [EMetrics.YANDEX, EMetrics.KLAVIYO])
metricService.reachGoal(EGoals.STAYED_IN_INSTAGRAM, [
EMetrics.YANDEX,
EMetrics.KLAVIYO,
]);
}
}, [])
}, []);
if (!isReady) {
return <Loader color={LoaderColor.Black} />;
}
return (
<div className={styles["page-container"]}>
@ -78,11 +95,11 @@ function PalmsInformation() {
{translate(`/palms-information.${zodiacSign?.toLowerCase()}.title`)}
</Title>
<p className={styles.description}>
{translate(`/palms-information.${zodiacSign?.toLowerCase()}.description`)}
{translate(
`/palms-information.${zodiacSign?.toLowerCase()}.description`
)}
</p>
<Button onClick={handleNext}>
{translate("next")}
</Button>
<Button onClick={handleNext}>{translate("next")}</Button>
<Policy>
{translate("privacy_policy", {
eulaLink: (

View File

@ -0,0 +1,40 @@
import styles from "./styles.module.scss";
import AnswerExplanation from "../../templates/AnswerExplanation";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
import { useMemo } from "react";
function PersonalizedRelationshipAnalysis() {
const navigate = useNavigate();
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
const { relationshipStatus: relationshipStatusAnswer } = useSelector(
selectors.selectCompatibilityV2Answers
);
const relationshipStatus = useMemo(() => {
return relationshipStatusAnswer === "single" ? "single" : "relationship";
}, [relationshipStatusAnswer]);
return (
<AnswerExplanation
title={translate(
`/personalized-relationship-analysis.${relationshipStatus}.title`
)}
text={translate(
`/personalized-relationship-analysis.${relationshipStatus}.text`
)}
buttonType="next"
classNameTitle={styles.title}
classNameText={styles.text}
handleNext={() => {
navigate(routes.client.compatibilityV2Birthdate());
}}
/>
);
}
export default PersonalizedRelationshipAnalysis;

View File

@ -0,0 +1,7 @@
.title {
font-weight: 700;
}
.text {
margin-bottom: 38px;
}

View File

@ -14,6 +14,7 @@ import { useSession } from "@/hooks/session/useSession";
import { IAnswersSessionCompatibilityV2 } from "@/api/resources/Session";
import { ESourceAuthorization } from "@/api/resources/User";
import { EUnleashFlags, useUnleash } from "@/hooks/ab/unleash/useUnleash";
import Loader, { LoaderColor } from "@/components/Loader";
function RelationshipStatus() {
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
@ -25,14 +26,47 @@ function RelationshipStatus() {
);
const { variant: relationshipStatusPagePlacement = "v0" } = useUnleash({
flag: EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement
flag: EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement,
});
const { variant: pathToEnteringBirthdate = "hide", isReady } = useUnleash({
flag: EUnleashFlags.v2CompatibilityPathToEnteringBirthdate,
});
const isPathToEnteringBirthdate = useMemo(
() => isReady && pathToEnteringBirthdate === "show",
[isReady, pathToEnteringBirthdate]
);
const answers: {
id: IAnswersSessionCompatibilityV2["relationship_status"];
title: string;
}[] = useMemo(
() => [
}[] = useMemo(() => {
if (isPathToEnteringBirthdate) {
return [
{
id: "single",
title: translate("/relationship-status.v1.answer1"),
},
{
id: "start",
title: translate("/relationship-status.v1.answer2"),
},
{
id: "in_relationship",
title: translate("/relationship-status.v1.answer3"),
},
{
id: "developing",
title: translate("/relationship-status.v1.answer4"),
},
{
id: "crisis",
title: translate("/relationship-status.v1.answer5"),
},
];
}
return [
{
id: "single",
title: translate("/relationship-status.answer1"),
@ -53,21 +87,31 @@ function RelationshipStatus() {
// id: "complicated",
// title: translate("/relationship-status.answer5"),
// },
],
[translate]
);
];
}, [isPathToEnteringBirthdate, translate]);
const handleClick = async (id: IAnswersSessionCompatibilityV2["relationship_status"]) => {
const handleClick = async (
id: IAnswersSessionCompatibilityV2["relationship_status"]
) => {
dispatch(actions.compatibilityV2Answers.update({ relationshipStatus: id }));
updateSession({
answers: {
relationship_status: id,
updateSession(
{
answers: {
relationship_status: id,
},
},
}, ESourceAuthorization["aura.compatibility.v2"]);
ESourceAuthorization["aura.compatibility.v2"]
);
if (id !== relationshipStatus) await sleep(answerTimeOut);
if (isPathToEnteringBirthdate) {
return navigate(routes.client.compatibilityV2RelationshipStatusResult());
}
if (relationshipStatusPagePlacement === "v1") {
return navigate(`${routes.client.compatibilityV2Gender()}?noRedirectAB=true`);
return navigate(
`${routes.client.compatibilityV2Gender()}?noRedirectAB=true`
);
}
if (relationshipStatusPagePlacement === "v2") {
@ -77,10 +121,16 @@ function RelationshipStatus() {
navigate(`${routes.client.compatibilityV2RelateFollowing()}/1`);
};
if (!isReady) {
return <Loader color={LoaderColor.Black} />;
}
return (
<div className={styles.container}>
<Title variant="h2" className={styles.title}>
{translate("/relationship-status.title")}
{isPathToEnteringBirthdate
? translate("/relationship-status.v1.title")
: translate("/relationship-status.title")}
</Title>
{answers.map((answers, index) => (
<Answer

View File

@ -0,0 +1,29 @@
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import routes from "@/routes";
import { selectors } from "@/store";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import AnswerExplanation from "../../templates/AnswerExplanation";
function RelationshipStatusResult() {
const navigate = useNavigate();
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
const { relationshipStatus } = useSelector(
selectors.selectCompatibilityV2Answers
);
return (
<AnswerExplanation
title={translate(
`/relationship-status-result.${relationshipStatus}.title`
)}
text={translate(`/relationship-status-result.${relationshipStatus}.text`)}
handleNext={() => {
navigate(routes.client.compatibilityV2FearInRelationship());
}}
/>
);
}
export default RelationshipStatusResult;

View File

@ -11,15 +11,31 @@ import { images } from "../../data";
import Button from "../../components/Button";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import { EUnleashFlags, useUnleash } from "@/hooks/ab/unleash/useUnleash";
import Loader, { LoaderColor } from "@/components/Loader";
function ReviewPage() {
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
const navigate = useNavigate();
const { variant: pathToEnteringBirthdate = "hide", isReady } = useUnleash({
flag: EUnleashFlags.v2CompatibilityPathToEnteringBirthdate,
});
const handleNext = () => {
if (pathToEnteringBirthdate === "show") {
return navigate(routes.client.compatibilityV2CompatibilityTest());
}
navigate(routes.client.compatibilityV2Birthdate());
};
if (!isReady) {
return (
<div className={styles.container}>
<Loader color={LoaderColor.Black} />
</div>
);
}
return (
<div className={styles.container}>
<Title variant="h1" className={styles.title}>
@ -51,9 +67,9 @@ function ReviewPage() {
verifiedText={translate("/review.review.verified_user")}
likesText={translate("/review.review.likes")}
likesImages={[
"review/like_1.jpg",
"review/like_2.jpg",
"review/like_3.png",
images("review/like_1.png"),
images("review/like_2.png"),
images("review/like_3.png"),
]}
image={images("review/avatar.jpg")}
/>

View File

@ -6,6 +6,10 @@
min-height: 100dvh;
margin: 0 auto;
padding: 45px 24px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
& * {
font-family: Inter;

View File

@ -0,0 +1,79 @@
import Title from "@/components/Title";
import styles from "./styles.module.scss";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import { IAnswersSessionCompatibilityV2 } from "@/api/resources/Session";
import { useMemo } from "react";
import Answer from "../../components/Answer";
import { useSelector } from "react-redux";
import { actions, selectors } from "@/store";
import { useDispatch } from "react-redux";
import { useSession } from "@/hooks/session/useSession";
import { ESourceAuthorization } from "@/api/resources/User";
import routes from "@/routes";
import { useNavigate } from "react-router-dom";
import { sleep } from "@/services/date";
import { answerTimeOut } from "../../data";
function WhoMatter() {
const navigate = useNavigate();
const dispatch = useDispatch();
const { updateSession } = useSession();
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
const { whoMatter } = useSelector(selectors.selectCompatibilityV2Answers);
const answers: {
id: IAnswersSessionCompatibilityV2["who_matter"];
title: string;
}[] = useMemo(
() => [
{
id: "me",
title: translate("/who-matter.answer1"),
},
{
id: "kids",
title: translate("/who-matter.answer2"),
},
{
id: "family",
title: translate("/who-matter.answer3"),
},
],
[translate]
);
const handleClick = async (
id: IAnswersSessionCompatibilityV2["who_matter"]
) => {
dispatch(actions.compatibilityV2Answers.update({ whoMatter: id }));
updateSession(
{
answers: {
who_matter: id,
},
},
ESourceAuthorization["aura.compatibility.v2"]
);
if (id !== whoMatter) await sleep(answerTimeOut);
navigate(routes.client.compatibilityV2YourPriority());
};
return (
<div className={styles.container}>
<Title variant="h2" className={styles.title}>
{translate("/who-matter.title")}
</Title>
{answers.map((answers, index) => (
<Answer
key={index}
answer={answers}
isSelected={whoMatter === answers.id}
onClick={() => handleClick(answers.id)}
/>
))}
</div>
);
}
export default WhoMatter;

View File

@ -0,0 +1,79 @@
import Title from "@/components/Title";
import styles from "./styles.module.scss";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import { IAnswersSessionCompatibilityV2 } from "@/api/resources/Session";
import { useMemo } from "react";
import Answer from "../../components/Answer";
import { useSelector } from "react-redux";
import { actions, selectors } from "@/store";
import { useDispatch } from "react-redux";
import { useSession } from "@/hooks/session/useSession";
import { ESourceAuthorization } from "@/api/resources/User";
import routes from "@/routes";
import { useNavigate } from "react-router-dom";
import { sleep } from "@/services/date";
import { answerTimeOut } from "../../data";
function YourPriority() {
const navigate = useNavigate();
const dispatch = useDispatch();
const { updateSession } = useSession();
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
const { yourPriority } = useSelector(selectors.selectCompatibilityV2Answers);
const answers: {
id: IAnswersSessionCompatibilityV2["your_priority"];
title: string;
}[] = useMemo(
() => [
{
id: "inner_harmony",
title: translate("/your-priority.answer1"),
},
{
id: "reliable_relationship",
title: translate("/your-priority.answer2"),
},
{
id: "new_impressions",
title: translate("/your-priority.answer3"),
},
],
[translate]
);
const handleClick = async (
id: IAnswersSessionCompatibilityV2["your_priority"]
) => {
dispatch(actions.compatibilityV2Answers.update({ yourPriority: id }));
updateSession(
{
answers: {
your_priority: id,
},
},
ESourceAuthorization["aura.compatibility.v2"]
);
if (id !== yourPriority) await sleep(answerTimeOut);
navigate(routes.client.compatibilityV2PersonalizedRelationshipAnalysis());
};
return (
<div className={styles.container}>
<Title variant="h2" className={styles.title}>
{translate("/your-priority.title")}
</Title>
{answers.map((answers, index) => (
<Answer
key={index}
answer={answers}
isSelected={yourPriority === answers.id}
onClick={() => handleClick(answers.id)}
/>
))}
</div>
);
}
export default YourPriority;

View File

@ -0,0 +1,73 @@
import { useTranslations } from "@/hooks/translations";
import styles from "./styles.module.scss";
import { ELocalesPlacement } from "@/locales";
import Title from "@/components/Title";
import Button from "../../components/Button";
import { useNavigate } from "react-router-dom";
interface IAnswerExplanation {
title?: string;
text?: string;
buttonType?: "back_next" | "next";
classNameTitle?: string;
classNameText?: string;
handleBack?: () => void;
handleNext: () => void;
}
function AnswerExplanation({
title,
text,
buttonType = "back_next",
classNameTitle = "",
classNameText = "",
handleBack,
handleNext,
}: IAnswerExplanation) {
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
const navigate = useNavigate();
const handleBackClick = () => {
return handleBack ? handleBack() : navigate(-1);
};
const handleNextClick = () => {
return handleNext();
};
return (
<div className={styles.container}>
{!!title?.length && (
<Title variant="h2" className={`${styles.title} ${classNameTitle}`}>
{title}
</Title>
)}
{!!text?.length && (
<p className={`${styles.text} ${classNameText}`}>{text}</p>
)}
{buttonType === "back_next" && (
<div className={styles["buttons-container"]}>
<Button
className={`${styles.button} ${styles["back-button"]}`}
onClick={handleBackClick}
>
{translate("back")}
</Button>
<Button
className={`${styles.button} ${styles["next-button"]}`}
onClick={handleNextClick}
>
{translate("next")}
</Button>
</div>
)}
{buttonType === "next" && (
<Button className={styles.button} onClick={handleNextClick}>
{translate("next")}
</Button>
)}
</div>
);
}
export default AnswerExplanation;

View File

@ -0,0 +1,44 @@
.container {
width: 100%;
}
.title {
font-size: 28px;
font-weight: 500;
line-height: 40px;
}
.text {
font-size: 20px;
line-height: 25px;
text-align: center;
margin-bottom: 74px;
}
.buttons-container {
display: flex;
flex-direction: row;
justify-content: space-between;
padding-top: 24px;
& > .button {
width: 48%;
min-width: 0px;
font-size: 23px;
height: 44px;
min-height: 0px;
&.back-button {
background: none;
color: #2c2c2c;
border: solid #2c2c2c 2px;
}
}
}
:global(body.dark-theme) {
.buttons-container > .button.back-button {
color: #fff;
border-color: #fff;
}
}

View File

@ -37,6 +37,7 @@ export enum EUnleashFlags {
"v2CompatibilityCameraTemplate" = "v2-compatibility-camera-template",
"v2CompatibilityRelationshipStatusPagePlacement" = "v2-compatibility-relationship-status-page-placement",
"v2CompatibilityReviewPage" = "v2-compatibility-review-page",
"v2CompatibilityPathToEnteringBirthdate" = "v2-compatibility-path-to-entering-birthdate",
}
interface IUseUnleashProps<T extends EUnleashFlags> {
@ -78,6 +79,7 @@ interface IVariants {
[EUnleashFlags.v2CompatibilityCameraTemplate]: 'v0' | 'v1' | 'v2' | 'v3' | 'v4';
[EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement]: 'v0' | 'v1' | 'v2';
[EUnleashFlags.v2CompatibilityReviewPage]: 'show' | 'hide';
[EUnleashFlags.v2CompatibilityPathToEnteringBirthdate]: 'hide' | 'show';
}
/**

View File

@ -34,17 +34,28 @@ function Layout() {
]);
const { variant: relationshipStatusPagePlacement = "v0" } = useUnleash({
flag: EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement
flag: EUnleashFlags.v2CompatibilityRelationshipStatusPagePlacement,
});
const getIsBackButtonVisible = () => {
if (
relationshipStatusPagePlacement === "v1" && location.pathname.includes(routes.client.compatibilityV2RelationshipStatus())
location.pathname.includes(
routes.client.compatibilityV2RelationshipStatusResult()
)
) {
return false;
}
if (
relationshipStatusPagePlacement === "v1" && location.pathname.includes(routes.client.compatibilityV2Gender())
relationshipStatusPagePlacement === "v1" &&
location.pathname.includes(
routes.client.compatibilityV2RelationshipStatus()
)
) {
return false;
}
if (
relationshipStatusPagePlacement === "v1" &&
location.pathname.includes(routes.client.compatibilityV2Gender())
) {
return true;
}

View File

@ -1,30 +1,13 @@
import { useSchemeColorByElement } from "@/hooks/useSchemeColorByElement";
import { useRef } from "react";
import { useMemo, useRef } from "react";
import { Outlet, useLocation } from "react-router-dom";
import routes from "@/routes";
import StepperBar from "@/components/CompatibilityV2/components/StepperBar";
import styles from "./styles.module.scss";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
const stepperRoutes = [
routes.client.compatibilityV2Birthdate(),
routes.client.compatibilityV2PalmsInformation(),
// routes.client.compatibilityV2WhatAspects(),
routes.client.compatibilityV2RelationshipStatus(),
routes.client.compatibilityV2RelateFollowing(),
routes.client.compatibilityV2RomanticGestures(),
routes.client.compatibilityV2CheckingPhone(),
routes.client.compatibilityV2BirthdatePartner(),
routes.client.compatibilityV2PalmsInformationPartner(),
routes.client.compatibilityV2DateEvent(),
// routes.client.compatibilityV2ElementResonates(),
// routes.client.compatibilityV2FavoriteColor(),
routes.client.compatibilityV2HeadOrHeart(),
routes.client.compatibilityV2HeadOrHeartResult(),
routes.client.compatibilityV2Email(),
];
import { EUnleashFlags, useUnleash } from "@/hooks/ab/unleash/useUnleash";
import Loader, { LoaderColor } from "@/components/Loader";
function StepperLayout() {
const darkTheme = useSelector(selectors.selectDarkTheme);
@ -33,27 +16,86 @@ function StepperLayout() {
useSchemeColorByElement(mainRef.current, "section.page, .page, section", [
location,
]);
const { variant: pathToEnteringBirthdate = "hide", isReady } = useUnleash({
flag: EUnleashFlags.v2CompatibilityPathToEnteringBirthdate,
});
const stepperRoutes = useMemo(() => {
if (pathToEnteringBirthdate === "show") {
return [
routes.client.compatibilityV2RelationshipStatus(),
routes.client.compatibilityV2FearInRelationship(),
routes.client.compatibilityV2ImportantStep(),
routes.client.compatibilityV2WhoMatter(),
routes.client.compatibilityV2YourPriority(),
routes.client.compatibilityV2Birthdate(),
routes.client.compatibilityV2PalmsInformation(),
// routes.client.compatibilityV2WhatAspects(),
routes.client.compatibilityV2RelateFollowing(),
routes.client.compatibilityV2RomanticGestures(),
routes.client.compatibilityV2CheckingPhone(),
routes.client.compatibilityV2BirthdatePartner(),
routes.client.compatibilityV2PalmsInformationPartner(),
routes.client.compatibilityV2DateEvent(),
// routes.client.compatibilityV2ElementResonates(),
// routes.client.compatibilityV2FavoriteColor(),
routes.client.compatibilityV2HeadOrHeart(),
routes.client.compatibilityV2HeadOrHeartResult(),
routes.client.compatibilityV2Email(),
];
}
return [
routes.client.compatibilityV2Birthdate(),
routes.client.compatibilityV2PalmsInformation(),
// routes.client.compatibilityV2WhatAspects(),
routes.client.compatibilityV2RelationshipStatus(),
routes.client.compatibilityV2RelateFollowing(),
routes.client.compatibilityV2RomanticGestures(),
routes.client.compatibilityV2CheckingPhone(),
routes.client.compatibilityV2BirthdatePartner(),
routes.client.compatibilityV2PalmsInformationPartner(),
routes.client.compatibilityV2DateEvent(),
// routes.client.compatibilityV2ElementResonates(),
// routes.client.compatibilityV2FavoriteColor(),
routes.client.compatibilityV2HeadOrHeart(),
routes.client.compatibilityV2HeadOrHeartResult(),
routes.client.compatibilityV2Email(),
];
}, [pathToEnteringBirthdate]);
const getCurrentStep = () => {
let index = 0;
for (const route of stepperRoutes) {
if (location.pathname.includes(route)) {
if (location.pathname.includes(routes.client.compatibilityV2BirthdatePartner())) {
if (
location.pathname.includes(
routes.client.compatibilityV2BirthdatePartner()
)
) {
return 8;
}
if (location.pathname.includes(routes.client.compatibilityV2PalmsInformationPartner())) {
if (
location.pathname.includes(
routes.client.compatibilityV2PalmsInformationPartner()
)
) {
return 9;
}
return index + 1;
}
index++;
}
return 0;
};
if (!isReady) {
return <Loader color={LoaderColor.Black} />;
}
return (
<>
<StepperBar

View File

@ -44,13 +44,22 @@ import AddConsultant from "@/components/palmistry/AdditionalPurchases/pages/AddC
import AddGuides from "@/components/palmistry/AdditionalPurchases/pages/AddGuides";
import PaymentPage from "@/components/Payment/nmi/PaymentPage";
import TryApp from "@/components/CompatibilityV2/pages/TryApp";
import { ESiteTheme, useTheme } from "@/hooks/theme/useTheme";
import { EUnleashFlags, useUnleash } from "@/hooks/ab/unleash/useUnleash";
import Loader, { LoaderColor } from "@/components/Loader";
import { useTheme } from "@/hooks/theme/useTheme";
import ScanHand from "@/components/CompatibilityV2/pages/ScanHand";
import { ELocalesPlacement } from "@/locales";
import { useFunnel } from "@/hooks/funnel/useFunnel";
import Review from "@/components/CompatibilityV2/pages/Review";
import {
getSystemColorScheme,
subscribeToSystemThemeChange,
} from "@/utils/Theme";
import CompatibilityTestPage from "@/components/CompatibilityV2/pages/CompatibilityTest";
import RelationshipStatusResult from "@/components/CompatibilityV2/pages/RelationshipStatusResult";
import FearInRelationship from "@/components/CompatibilityV2/pages/FearInRelationship";
import ImportantStep from "@/components/CompatibilityV2/pages/ImportantStep";
import WhoMatter from "@/components/CompatibilityV2/pages/WhoMatter";
import YourPriority from "@/components/CompatibilityV2/pages/YourPriority";
import PersonalizedRelationshipAnalysis from "@/components/CompatibilityV2/pages/PersonalizedRelationshipAnalysis";
const removePrefix = (path: string) => path.replace(compatibilityV2Prefix, "");
@ -59,10 +68,6 @@ function CompatibilityV2Routes() {
const dispatch = useDispatch();
const { setTheme } = useTheme();
const { isReady, variant: darkThemeCompatibilityV2Variant } = useUnleash({
flag: EUnleashFlags.darkThemeCompatibilityV2,
});
const { funnelData } = useFunnel({
funnel: ELocalesPlacement.CompatibilityV2,
paymentPlacement: "",
@ -140,28 +145,17 @@ function CompatibilityV2Routes() {
}
useEffect(() => {
if (darkThemeCompatibilityV2Variant === "enabled") {
setTheme(ESiteTheme.Dark);
}
return () => {
setTheme(ESiteTheme.Light);
};
}, [darkThemeCompatibilityV2Variant]);
const systemColorScheme = getSystemColorScheme();
setTheme(systemColorScheme);
if (!isReady) {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100dvh",
}}
>
<Loader color={LoaderColor.Black} />
</div>
);
}
const unsubscribe = subscribeToSystemThemeChange((theme) => {
setTheme(theme);
});
return () => {
unsubscribe?.();
};
}, [setTheme]);
return (
<Routes>
@ -261,6 +255,12 @@ function CompatibilityV2Routes() {
>
<Route path="*" element={<Gender />} />
</Route>
<Route
path={removePrefix(
routes.client.compatibilityV2CompatibilityTest()
)}
element={<CompatibilityTestPage />}
/>
<Route
path={removePrefix(routes.client.compatibilityV2GenderPartner())}
element={<GenderPartner />}
@ -271,7 +271,39 @@ function CompatibilityV2Routes() {
>
<Route path="*" element={<FindHappiness />} />
</Route>
<Route
path={removePrefix(
routes.client.compatibilityV2RelationshipStatusResult()
)}
element={<RelationshipStatusResult />}
/>
<Route
path={removePrefix(
routes.client.compatibilityV2PersonalizedRelationshipAnalysis()
)}
element={<PersonalizedRelationshipAnalysis />}
/>
<Route element={<StepperLayout />}>
<Route
path={removePrefix(
routes.client.compatibilityV2FearInRelationship()
)}
element={<FearInRelationship />}
/>
<Route
path={removePrefix(
routes.client.compatibilityV2ImportantStep()
)}
element={<ImportantStep />}
/>
<Route
path={removePrefix(routes.client.compatibilityV2WhoMatter())}
element={<WhoMatter />}
/>
<Route
path={removePrefix(routes.client.compatibilityV2YourPriority())}
element={<YourPriority />}
/>
<Route
path={removePrefix(routes.client.compatibilityV2Birthdate())}
element={<Birthdate />}

View File

@ -224,6 +224,7 @@ const routes = {
palmistryOnboardingV1: () => [palmistryV1Prefix, "onboarding"].join("/"),
// CompatibilityV2
compatibilityV2Welcome: () => [compatibilityV2Prefix, "welcome"].join("/"),
compatibilityV2CompatibilityTest: () => [compatibilityV2Prefix, "compatibility-test"].join("/"),
compatibilityV2Gender: () => [compatibilityV2Prefix, "gender"].join("/"),
compatibilityV2GenderPartner: () => [compatibilityV2Prefix, "gender-partner"].join("/"),
compatibilityV2Birthdate: () => [compatibilityV2Prefix, "birthdate"].join("/"),
@ -233,6 +234,11 @@ const routes = {
compatibilityV2DateEvent: () => [compatibilityV2Prefix, "date-event"].join("/"),
compatibilityV2WhatAspects: () => [compatibilityV2Prefix, "what-aspects"].join("/"),
compatibilityV2RelationshipStatus: () => [compatibilityV2Prefix, "relationship-status"].join("/"),
compatibilityV2RelationshipStatusResult: () => [compatibilityV2Prefix, "relationship-status-result"].join("/"),
compatibilityV2FearInRelationship: () => [compatibilityV2Prefix, "fear-in-relationship"].join("/"),
compatibilityV2ImportantStep: () => [compatibilityV2Prefix, "important-step"].join("/"),
compatibilityV2WhoMatter: () => [compatibilityV2Prefix, "who-matter"].join("/"),
compatibilityV2YourPriority: () => [compatibilityV2Prefix, "your-priority"].join("/"),
compatibilityV2ElementResonates: () => [compatibilityV2Prefix, "element-resonates"].join("/"),
compatibilityV2FavoriteColor: () => [compatibilityV2Prefix, "favorite-color"].join("/"),
compatibilityV2HeadOrHeart: () => [compatibilityV2Prefix, "head-or-heart"].join("/"),
@ -240,6 +246,7 @@ const routes = {
compatibilityV2RelateFollowing: () => [compatibilityV2Prefix, "relate-following"].join("/"),
compatibilityV2RomanticGestures: () => [compatibilityV2Prefix, "romantic-gestures"].join("/"),
compatibilityV2CheckingPhone: () => [compatibilityV2Prefix, "checking-phone"].join("/"),
compatibilityV2PersonalizedRelationshipAnalysis: () => [compatibilityV2Prefix, "personalized-relationship-analysis"].join("/"),
compatibilityV2LetScan: () => [compatibilityV2Prefix, "let-scan"].join("/"),
compatibilityV2ScanInstruction: () => [compatibilityV2Prefix, "scan-instruction"].join("/"),
compatibilityV2Camera: () => [compatibilityV2Prefix, "camera"].join("/"),

View File

@ -2,7 +2,9 @@ import { IPalmistryFinger, IPalmistryLine } from "@/api/resources/Palmistry";
import { createSlice, createSelector } from "@reduxjs/toolkit";
import type { PayloadAction } from "@reduxjs/toolkit";
export type ICompatibilityV2FingerLocal = IPalmistryFinger & { fingerName?: string }
export type ICompatibilityV2FingerLocal = IPalmistryFinger & {
fingerName?: string;
};
interface ICompatibilityV2 {
lines: IPalmistryLine[];
@ -35,7 +37,8 @@ export const selectCompatibilityV2Lines = createSelector(
(compatibilityV2) => compatibilityV2
);
export const selectCompatibilityV2Fingers = createSelector(
(state: { compatibilityV2: ICompatibilityV2 }) => state.compatibilityV2.fingers,
(state: { compatibilityV2: ICompatibilityV2 }) =>
state.compatibilityV2.fingers,
(compatibilityV2) => compatibilityV2
);
export const selectCompatibilityV2Photo = createSelector(
@ -43,7 +46,8 @@ export const selectCompatibilityV2Photo = createSelector(
(compatibilityV2) => compatibilityV2
);
export const selectCompatibilityV2FromRedesign = createSelector(
(state: { compatibilityV2: ICompatibilityV2 }) => state.compatibilityV2.fromRedesign,
(state: { compatibilityV2: ICompatibilityV2 }) =>
state.compatibilityV2.fromRedesign,
(compatibilityV2) => compatibilityV2
);
export default compatibilityV2Slice.reducer;

View File

@ -2,41 +2,48 @@ import { createSlice, createSelector } from "@reduxjs/toolkit";
import type { PayloadAction } from "@reduxjs/toolkit";
export interface ICompatibilityV2Answers {
whatAspects: string;
relationshipStatus: string;
elementResonates: string;
favoriteColor: string;
headOrHeart: string;
dateEvent: string;
romanticGestures: string;
checkingPhone: string;
whatAspects: string;
relationshipStatus: string;
elementResonates: string;
favoriteColor: string;
headOrHeart: string;
dateEvent: string;
romanticGestures: string;
checkingPhone: string;
fearInRelationship: string;
whoMatter: string;
yourPriority: string;
}
const initialState: ICompatibilityV2Answers = {
whatAspects: "",
relationshipStatus: "",
elementResonates: "",
favoriteColor: "",
headOrHeart: "",
dateEvent: "",
romanticGestures: "",
checkingPhone: "",
whatAspects: "",
relationshipStatus: "",
elementResonates: "",
favoriteColor: "",
headOrHeart: "",
dateEvent: "",
romanticGestures: "",
checkingPhone: "",
fearInRelationship: "",
whoMatter: "",
yourPriority: "",
};
const compatibilityV2AnswersSlice = createSlice({
name: "compatibilityV2Answers",
initialState,
reducers: {
update(state, action: PayloadAction<Partial<ICompatibilityV2Answers>>) {
return { ...state, ...action.payload };
},
name: "compatibilityV2Answers",
initialState,
reducers: {
update(state, action: PayloadAction<Partial<ICompatibilityV2Answers>>) {
return { ...state, ...action.payload };
},
extraReducers: (builder) => builder.addCase("reset", () => initialState),
},
extraReducers: (builder) => builder.addCase("reset", () => initialState),
});
export const { actions } = compatibilityV2AnswersSlice;
export const selectCompatibilityV2Answers = createSelector(
(state: { compatibilityV2Answers: ICompatibilityV2Answers }) => state.compatibilityV2Answers,
(compatibilityV2Answers) => compatibilityV2Answers
(state: { compatibilityV2Answers: ICompatibilityV2Answers }) =>
state.compatibilityV2Answers,
(compatibilityV2Answers) => compatibilityV2Answers
);
export default compatibilityV2AnswersSlice.reducer;

View File

@ -88,39 +88,56 @@ import palmistry, {
selectPalmistryFingers,
selectPalmistryFromRedesign,
selectPalmistryLines,
selectPalmistryPhoto
selectPalmistryPhoto,
} from "./palmistry";
import compatibilityV2, {
actions as compatibilityV2Actions,
selectCompatibilityV2Fingers,
selectCompatibilityV2FromRedesign,
selectCompatibilityV2Lines,
selectCompatibilityV2Photo
selectCompatibilityV2Photo,
} from "./compatibilityV2";
import retainingFunnel, {
actions as retainingFunnelActions,
selectRetainingFunnel,
selectCancellingSubscriptionId
selectCancellingSubscriptionId,
} from "./retainingFunnel";
import compatibilityV3, {
actions as compatibilityV3Actions,
selectCompatibilityV3Fingers,
selectCompatibilityV3FromRedesign,
selectCompatibilityV3Lines,
selectCompatibilityV3Photo
selectCompatibilityV3Photo,
} from "./compatibilityV3";
import compatibilityV4, {
actions as compatibilityV4Actions,
selectCompatibilityV4Fingers,
selectCompatibilityV4FromRedesign,
selectCompatibilityV4Lines,
selectCompatibilityV4Photo
selectCompatibilityV4Photo,
} from "./compatibilityV4";
import { selectPaywallsIsMustUpdate, selectPaywalls } from "./paywalls";
import privacyPolicy, { actions as privacyPolicyActions, selectPrivacyPolicy } from "./privacyPolicy";
import personalVideo, { actions as personalVideoActions, selectPersonalVideo } from "./personalVideo";
import chats, { actions as chatsActions, selectAnswers, selectCurrentStep } from "./chats";
import chat, { actions as chatActions, selectCurrentAssistant, selectCurrentChatId, selectDateEndChatting, selectIsAutoRefill, selectIsPayedFirstPurchase } from "./chat";
import privacyPolicy, {
actions as privacyPolicyActions,
selectPrivacyPolicy,
} from "./privacyPolicy";
import personalVideo, {
actions as personalVideoActions,
selectPersonalVideo,
} from "./personalVideo";
import chats, {
actions as chatsActions,
selectAnswers,
selectCurrentStep,
} from "./chats";
import chat, {
actions as chatActions,
selectCurrentAssistant,
selectCurrentChatId,
selectDateEndChatting,
selectIsAutoRefill,
selectIsPayedFirstPurchase,
} from "./chat";
const preloadedState = loadStore();
export const actions = {

31
src/utils/Theme/index.ts Normal file
View File

@ -0,0 +1,31 @@
import { ESiteTheme } from "@/hooks/theme/useTheme";
export function getSystemColorScheme(): ESiteTheme {
if (typeof window !== "undefined" && window.matchMedia) {
return window.matchMedia("(prefers-color-scheme: dark)").matches
? ESiteTheme.Dark
: ESiteTheme.Light;
}
return ESiteTheme.Light;
}
export function subscribeToSystemThemeChange(
callback: (theme: ESiteTheme) => void
) {
if (typeof window === "undefined" || !window.matchMedia) {
return;
}
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handleChange = (e: MediaQueryListEvent) => {
callback(e.matches ? ESiteTheme.Dark : ESiteTheme.Light);
};
mediaQuery.addEventListener("change", handleChange);
return () => {
mediaQuery.removeEventListener("change", handleChange);
};
}