develop
@ -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."
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 159 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 159 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 191 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 167 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 176 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 181 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 137 KiB |
69
src/components/CompatibilityV3/pages/ChoosePlace/index.tsx
Normal 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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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]);
|
||||
|
||||
@ -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 />}
|
||||
|
||||
@ -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("/"),
|
||||
|
||||
@ -215,6 +215,7 @@ type TABFlags = {
|
||||
cameraRequestModal: "with" | "without";
|
||||
yourReading: "v1" | "v2";
|
||||
genderButtonIcon: "show" | "hide";
|
||||
tryApp: "v0" | "v1";
|
||||
}
|
||||
|
||||
export const useMetricABFlags = () => {
|
||||
|
||||