This commit is contained in:
Daniil Chemerkin 2025-03-04 20:33:01 +00:00
parent 5d22f50213
commit 752e8eb5d9
28 changed files with 32947 additions and 20 deletions

View File

@ -585,5 +585,19 @@
"capricorn": "Capricorn",
"aquarius": "Aquarius",
"pisces": "Pisces"
},
"/choose-place": {
"title": "Your Compatibility<br>Reading is READY",
"subtitle": "<count><br>страниц подробного<br>разбора.",
"subtitle_count": "57",
"description1": "Ты можешь купить его на всегда или БЕСПЛАТНО прочитать у нас в приложении.",
"description2": "Ваш разбор по Совместимости действителен 10 минут, после чего он будет удален.",
"button1": "Buy",
"button2": "Read for FREE<br>in the App"
},
"/code-instruction": {
"instruction_point_1": "1. Copy Your Access Code",
"instruction_point_2": "2. Download the App and Enter Your Access Code",
"not_share_description": "Enter your access code in the app to access Your Personalized Reading. Do not share your code with anyone."
}
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 159 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 157 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 159 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 191 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 182 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 167 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 148 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 176 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 147 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 181 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 175 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 182 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 148 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 127 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 136 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 175 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 157 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 137 KiB

View File

@ -0,0 +1,69 @@
import Title from "@/components/Title"
import styles from "./styles.module.scss"
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import Answer from "../../components/Answer";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
function ChoosePlace() {
const navigate = useNavigate();
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV3);
const [selectedAnswer, setSelectedAnswer] = useState<string | null>(null);
const answers = [
{
id: "site",
title: translate("/choose-place.button1"),
},
{
id: "app",
title: translate("/choose-place.button2", {
br: <br />,
}),
}
]
const handleAnswerClick = (answerId: string) => {
setSelectedAnswer(answerId);
if (answerId === "site") {
return navigate(routes.client.compatibilityV3Email());
}
return navigate(routes.client.compatibilityV3CodeInstruction());
}
return (
<div className={styles.container}>
<Title className={styles.title} variant="h2">
{translate("/choose-place.title", {
br: <br />,
})}
</Title>
<Title className={styles.subtitle} variant="h3">
{translate("/choose-place.subtitle", {
count: <span className={styles.count}>
{translate("/choose-place.subtitle_count")}
</span>,
br: <br />,
})}
</Title>
<p className={styles.description1}>
{translate("/choose-place.description1")}
</p>
<p className={styles.description2}>
{translate("/choose-place.description2")}
</p>
{answers.map((answer) => (
<Answer
key={answer.id}
answer={answer}
isSelected={selectedAnswer === answer.id}
onClick={() => handleAnswerClick(answer.id)}
/>
))}
</div>
)
}
export default ChoosePlace

View File

@ -0,0 +1,45 @@
.title {
font-family: SF Pro Text;
font-weight: 500;
font-size: 28px;
line-height: 35px;
text-align: center;
white-space: pre-line;
margin-top: 70px;
}
.subtitle {
margin-top: 62px;
font-family: SF Pro Text;
font-weight: 400;
font-size: 23px;
line-height: 28.75px;
text-align: center;
white-space: pre-line;
color: #2C2C2C;
&>.count {
font-family: SF Pro Text;
font-weight: 700;
font-size: 39px;
line-height: 48.75px;
text-align: center;
}
}
.description1 {
font-family: SF Pro Text;
font-weight: 300;
font-size: 20px;
line-height: 25px;
color: #2C2C2C;
margin-top: 62px;
}
.description2 {
font-family: SF Pro Text;
font-weight: 400;
font-size: 14px;
line-height: 17.5px;
margin-top: 8px;
}

View File

@ -0,0 +1,41 @@
import metricService, { EGoals, EMetrics } from "@/services/metric/metricService";
import { images } from "../../data"
import YourAccessCode from "../TryApp/components/YourAccessCode"
import styles from "./styles.module.scss"
import { copyToClipboard } from "@/services/data";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
function CodeInstruction() {
const code = useSelector(selectors.selectAuthCode);
const { translate } = useTranslations(ELocalesPlacement.CompatibilityV3);
const downloadApp = async () => {
metricService.reachGoal(EGoals.DOWNLOAD_APP, [EMetrics.YANDEX]);
await copyToClipboard(code);
// TODO
window.location.href =
"https://apps.apple.com/us/app/aura-astrology-horoscope/id1601978549";
};
return (
<div className={styles.container}>
<p className={styles.instructionPoint} style={{
marginBottom: "16px",
marginTop: "8px"
}}>{translate("/code-instruction.instruction_point_1")}</p>
<YourAccessCode />
<p className={styles.instructionPoint} style={{
marginTop: "56px"
}}>{translate("/code-instruction.instruction_point_2")}</p>
<img className={styles.downloadApp} src={images("download-app.png")} alt="Download app" onClick={downloadApp} />
<p className={styles.notShareDescription}>
{translate("/code-instruction.not_share_description")}
</p>
</div>
)
}
export default CodeInstruction

View File

@ -0,0 +1,32 @@
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: calc(100dvh - 134px);
}
.instructionPoint {
width: 100%;
font-weight: 600;
font-size: 19px;
line-height: 22.99px;
text-align: center;
margin-top: 32px;
}
.downloadApp {
width: 100%;
max-width: 236px;
margin-top: 16px;
cursor: pointer;
}
.notShareDescription {
font-weight: 500;
font-size: 15px;
line-height: 18.15px;
text-align: center;
max-width: 300px;
margin-top: 46px;
}

View File

@ -16,6 +16,7 @@ import { useAuthentication } from "@/hooks/authentication/use-authentication";
import { ESourceAuthorization } from "@/api/resources/User";
import { ELottieKeys, useLottie } from "@/hooks/lottie/useLottie";
import { DotLottieReact } from "@lottiefiles/dotlottie-react";
import { useMetricABFlags } from "@/services/metric/metricService";
// const drawElementChangeDelay = 1500;
// const startDelay = 500;
@ -57,6 +58,9 @@ function ScannedPhoto() {
const { relationshipStatus } = useSelector(selectors.selectCompatibilityV3Answers)
const { flags } = useMetricABFlags();
const tryAppVariant = flags?.tryApp?.[0] || "v1";
const loadingProfilePoints: IPoint[] = useMemo(() => {
const prefix = relationshipStatus === "single" ? "without-partner" : "with-partner";
return [
@ -190,7 +194,10 @@ function ScannedPhoto() {
const onEndLoading = useCallback(() => {
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
if (isIOSPath && !!authCode && isIOS) {
return navigate(routes.client.compatibilityV3TryApp());
if (tryAppVariant === "v0") {
return navigate(routes.client.compatibilityV3TryApp());
}
return navigate(routes.client.compatibilityV3ChoosePlace());
}
navigate(routes.client.compatibilityV3Email());
}, [isIOSPath, authCode, navigate]);

View File

@ -45,6 +45,8 @@ import AddGuides from "@/components/palmistry/AdditionalPurchases/pages/AddGuide
import PaymentPage from "@/components/Payment/nmi/PaymentPage";
import { EPlacementKeys } from "@/api/resources/Paywall";
import TryApp from "@/components/CompatibilityV3/pages/TryApp";
import ChoosePlace from "@/components/CompatibilityV3/pages/ChoosePlace";
import CodeInstruction from "@/components/CompatibilityV3/pages/CodeInstruction";
const removePrefix = (path: string) => path.replace(compatibilityV3Prefix, "");
@ -294,6 +296,14 @@ function CompatibilityV3Routes() {
path={removePrefix(routes.client.compatibilityV3ScannedPhoto())}
element={<ScannedPhoto />}
/>
<Route
path={removePrefix(routes.client.compatibilityV3ChoosePlace())}
element={<ChoosePlace />}
/>
<Route
path={removePrefix(routes.client.compatibilityV3CodeInstruction())}
element={<CodeInstruction />}
/>
<Route
path={removePrefix(routes.client.compatibilityV3SaveOff())}
element={<SaveOff />}

View File

@ -267,6 +267,10 @@ const routes = {
compatibilityV3ScanInstruction: () => [compatibilityV3Prefix, "scan-instruction"].join("/"),
compatibilityV3Camera: () => [compatibilityV3Prefix, "camera"].join("/"),
compatibilityV3ScannedPhoto: () => [compatibilityV3Prefix, "scanned-photo"].join("/"),
compatibilityV3ChoosePlace: () => [compatibilityV3Prefix, "choose-place"].join("/"),
compatibilityV3CodeInstruction: () => [compatibilityV3Prefix, "code-instruction"].join("/"),
compatibilityV3Email: () => [compatibilityV3Prefix, "email"].join("/"),
compatibilityV3TrialChoice: () => [compatibilityV3Prefix, "trial-choice"].join("/"),
compatibilityV3TrialChoiceVideo: () => [compatibilityV3Prefix, "trial-choice-video"].join("/"),

View File

@ -215,6 +215,7 @@ type TABFlags = {
cameraRequestModal: "with" | "without";
yourReading: "v1" | "v2";
genderButtonIcon: "show" | "hide";
tryApp: "v0" | "v1";
}
export const useMetricABFlags = () => {