diff --git a/package-lock.json b/package-lock.json
index f5caf0c..383d54d 100755
--- a/package-lock.json
+++ b/package-lock.json
@@ -28,6 +28,7 @@
"react-circular-progressbar": "^2.1.0",
"react-dom": "^18.2.0",
"react-ga4": "^2.1.0",
+ "react-helmet": "^6.1.0",
"react-i18next": "^12.3.1",
"react-pdf": "8.0.2",
"react-player": "^2.16.0",
@@ -44,6 +45,7 @@
"@types/node": "^20.5.1",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
+ "@types/react-helmet": "^6.1.11",
"@types/react-router-dom": "^5.3.3",
"@types/react-slick": "^0.23.13",
"@typescript-eslint/eslint-plugin": "^5.59.6",
@@ -1563,6 +1565,15 @@
"@types/react": "*"
}
},
+ "node_modules/@types/react-helmet": {
+ "version": "6.1.11",
+ "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.11.tgz",
+ "integrity": "sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/react-router": {
"version": "5.1.20",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz",
@@ -4080,6 +4091,20 @@
"resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-2.1.0.tgz",
"integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ=="
},
+ "node_modules/react-helmet": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
+ "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
+ "dependencies": {
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.7.2",
+ "react-fast-compare": "^3.1.1",
+ "react-side-effect": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.3.0"
+ }
+ },
"node_modules/react-i18next": {
"version": "12.3.1",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz",
@@ -4231,6 +4256,14 @@
"react-dom": ">=16.8"
}
},
+ "node_modules/react-side-effect": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
+ "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==",
+ "peerDependencies": {
+ "react": "^16.3.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/react-slick": {
"version": "0.30.2",
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.30.2.tgz",
@@ -5967,6 +6000,15 @@
"@types/react": "*"
}
},
+ "@types/react-helmet": {
+ "version": "6.1.11",
+ "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.11.tgz",
+ "integrity": "sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
"@types/react-router": {
"version": "5.1.20",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz",
@@ -7769,6 +7811,17 @@
"resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-2.1.0.tgz",
"integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ=="
},
+ "react-helmet": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
+ "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
+ "requires": {
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.7.2",
+ "react-fast-compare": "^3.1.1",
+ "react-side-effect": "^2.1.0"
+ }
+ },
"react-i18next": {
"version": "12.3.1",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz",
@@ -7851,6 +7904,12 @@
"react-router": "6.11.2"
}
},
+ "react-side-effect": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
+ "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==",
+ "requires": {}
+ },
"react-slick": {
"version": "0.30.2",
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.30.2.tgz",
diff --git a/package.json b/package.json
index ff002c6..8e98bcf 100755
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
"react-circular-progressbar": "^2.1.0",
"react-dom": "^18.2.0",
"react-ga4": "^2.1.0",
+ "react-helmet": "^6.1.0",
"react-i18next": "^12.3.1",
"react-pdf": "8.0.2",
"react-player": "^2.16.0",
@@ -50,6 +51,7 @@
"@types/node": "^20.5.1",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
+ "@types/react-helmet": "^6.1.11",
"@types/react-router-dom": "^5.3.3",
"@types/react-slick": "^0.23.13",
"@typescript-eslint/eslint-plugin": "^5.59.6",
diff --git a/src/api/resources/User.ts b/src/api/resources/User.ts
index b3252b8..7010679 100644
--- a/src/api/resources/User.ts
+++ b/src/api/resources/User.ts
@@ -181,6 +181,7 @@ export interface ICreateAuthorizeResponse {
userId?: string;
generatingVideo?: boolean;
videoId?: string;
+ authCode?: string;
}
export const createAuthorizeRequest = (data: ICreateAuthorizePayload): Request => {
diff --git a/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx b/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx
index e2f2a0d..e5d93c2 100644
--- a/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx
+++ b/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx
@@ -25,10 +25,14 @@ function OnboardingPage() {
const { createdDate, generatingVideo } = useSelector(
selectors.selectPersonalVideo
);
+ const authCode = useSelector(selectors.selectAuthCode);
const handleNext = useCallback(() => {
- navigate(routes.client.trialChoiceV1());
- }, [navigate]);
+ if (authCode?.length) {
+ return navigate(routes.client.tryAppV1());
+ }
+ return navigate(routes.client.trialChoiceV1());
+ }, [authCode, navigate]);
useEffect(() => {
if (isVideoReady && progress >= 100) {
diff --git a/src/components/pages/ABDesign/v1/pages/TryApp/components/AccessCodeApp/index.tsx b/src/components/pages/ABDesign/v1/pages/TryApp/components/AccessCodeApp/index.tsx
new file mode 100644
index 0000000..2bb8ad6
--- /dev/null
+++ b/src/components/pages/ABDesign/v1/pages/TryApp/components/AccessCodeApp/index.tsx
@@ -0,0 +1,23 @@
+import Title from "@/components/Title";
+import styles from "./styles.module.css";
+
+interface IAccessCodeAppProps {
+ code: string;
+}
+
+function AccessCodeApp({ code }: IAccessCodeAppProps) {
+ return (
+
+
+
+ Your access code
+
+
+
+ {code}
+
+
+ );
+}
+
+export default AccessCodeApp;
diff --git a/src/components/pages/ABDesign/v1/pages/TryApp/components/AccessCodeApp/styles.module.css b/src/components/pages/ABDesign/v1/pages/TryApp/components/AccessCodeApp/styles.module.css
new file mode 100644
index 0000000..0718c9a
--- /dev/null
+++ b/src/components/pages/ABDesign/v1/pages/TryApp/components/AccessCodeApp/styles.module.css
@@ -0,0 +1,42 @@
+.container {
+ position: relative;
+ margin-top: 32px;
+ border-radius: 24px;
+ min-height: 140px;
+ background-color: #fff;
+ justify-content: start;
+ width: 100%;
+}
+
+.header-container {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ background-color: rgb(153, 116, 246);
+ border-top-left-radius: 24px;
+ border-top-right-radius: 24px;
+}
+
+.title {
+ text-transform: capitalize;
+ margin: 0;
+ font-size: 20px;
+ line-height: 145%;
+ color: #fff;
+ font-weight: 500;
+}
+
+.code-container {
+ position: absolute;
+ top: calc(50% + 19px);
+ transform: translateY(-50%);
+ width: 100%;
+ text-align: center;
+}
+
+.code {
+ font-size: 36px;
+ font-weight: 800;
+}
diff --git a/src/components/pages/ABDesign/v1/pages/TryApp/index.tsx b/src/components/pages/ABDesign/v1/pages/TryApp/index.tsx
new file mode 100644
index 0000000..12a6a16
--- /dev/null
+++ b/src/components/pages/ABDesign/v1/pages/TryApp/index.tsx
@@ -0,0 +1,140 @@
+import { useEffect, useState } from "react";
+import TrialPaymentHeader from "../TrialPayment/components/Header";
+import Header from "../../components/Header";
+import PersonalInformation from "../TrialPayment/components/PersonalInformation";
+import WithPartnerInformation from "../TrialPayment/components/WithPartnerInformation";
+import styles from "./styles.module.css";
+import { useSelector } from "react-redux";
+import { selectors } from "@/store";
+import { getZodiacSignByDate } from "@/services/zodiac-sign";
+import Title from "@/components/Title";
+import Goal from "../TrialPayment/components/Goal";
+import Reviews from "../TrialPayment/components/Reviews";
+import { trialPaymentReviews } from "@/data/reviews";
+import AccessCodeApp from "./components/AccessCodeApp";
+import YourReading from "../TrialPayment/components/YourReading";
+import PointsList from "../TrialPayment/components/PointsList";
+import OftenAsk from "../TrialPayment/components/OftenAsk";
+import { trialPaymentPointsList } from "@/data/pointsLists";
+import BackgroundTopBlob from "../../ui/BackgroundTopBlob";
+import { useDynamicSize } from "@/hooks/useDynamicSize";
+
+function TryAppPage() {
+ const { width: pageWidth, elementRef: pageRef } = useDynamicSize({});
+ const birthdate = useSelector(selectors.selectBirthdate);
+ const zodiacSign = getZodiacSignByDate(birthdate);
+ const {
+ gender,
+ birthPlace,
+ partnerBirthPlace,
+ partnerBirthdate,
+ partnerGender,
+ goal,
+ flowChoice,
+ } = useSelector(selectors.selectQuestionnaire);
+ const partnerZodiacSign = getZodiacSignByDate(partnerBirthdate);
+ const [singleOrWithPartner, setSingleOrWithPartner] = useState<
+ "single" | "partner"
+ >("single");
+ const authCode = useSelector(selectors.selectAuthCode);
+
+ useEffect(() => {
+ if (["relationship", "married"].includes(flowChoice)) {
+ setSingleOrWithPartner("partner");
+ return;
+ }
+ setSingleOrWithPartner("single");
+ }, [flowChoice]);
+
+ const downloadApp = () => {
+ // TODO
+ window.location.href =
+ "https://apps.apple.com/us/app/aura-astrology-horoscope/id1601978549";
+ };
+
+ return (
+
+
+
+
+
+
+ {singleOrWithPartner === "partner" && (
+
+ )}
+ {singleOrWithPartner === "single" && (
+
+ )}
+
+ Your Personalized Clarity & Love Reading is ready and available in the
+ app for your iPhone!
+
+
+
+ 1. Download App
+
+
+ 2. Enter Your Access Code
+
+ {authCode}
+
+ Enter your access code in the app to access Your Personalized Reading.
+ Do not share your code with anyone
+
+
+
+
+ Users love us
+
+
+
+
+
+ );
+}
+
+export default TryAppPage;
diff --git a/src/components/pages/ABDesign/v1/pages/TryApp/styles.module.css b/src/components/pages/ABDesign/v1/pages/TryApp/styles.module.css
new file mode 100644
index 0000000..549a6f1
--- /dev/null
+++ b/src/components/pages/ABDesign/v1/pages/TryApp/styles.module.css
@@ -0,0 +1,93 @@
+.page {
+ background-color: #fff0f0;
+ height: fit-content;
+ min-height: 100dvh;
+ padding-top: 114px;
+ padding-bottom: 62px;
+ width: 100%;
+ max-width: 460px;
+ overflow: inherit;
+ overflow-x: clip;
+}
+
+.header {
+ position: absolute;
+ z-index: 3;
+ top: 32px;
+ padding: 0 14px;
+ width: 100%;
+}
+
+.background-top-blob-container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: fit-content;
+ overflow: hidden;
+}
+
+.background-top-blob {
+ scale: 1.4;
+}
+
+.download-app-title {
+ font-size: 24px;
+ line-height: 145%;
+ color: #333333;
+ font-weight: 700;
+ text-align: center;
+ margin-top: 32px;
+ margin-bottom: 16px;
+}
+
+.download-app-image {
+ width: 80%;
+ max-width: 270px;
+ height: 80px;
+ object-fit: cover;
+ animation: 1.5s ease 0s infinite normal none running pulse;
+}
+
+.code-container {
+ font-size: 28px;
+ font-weight: 600;
+ padding: 12px;
+ width: 100%;
+ max-width: 200px;
+ background-color: rgba(175, 149, 241, 0.48);
+ border-radius: 48px;
+ text-align: center;
+}
+
+.code-description {
+ text-align: center;
+ line-height: 1.3;
+ font-weight: 500;
+ font-size: 18px;
+ margin-top: 12px;
+}
+
+.title {
+ margin-top: 24px;
+ font-size: 20px;
+ line-height: 145%;
+ color: #333333;
+ font-weight: 600;
+}
+
+.header-button {
+ height: 100%;
+}
+
+@keyframes pulse {
+ 0% {
+ transform: scale(0.9);
+ }
+ 70% {
+ transform: scale(1);
+ }
+ 100% {
+ transform: scale(0.9);
+ }
+}
diff --git a/src/hooks/authentication/use-authentication.ts b/src/hooks/authentication/use-authentication.ts
index d0e92dc..d6fdf35 100644
--- a/src/hooks/authentication/use-authentication.ts
+++ b/src/hooks/authentication/use-authentication.ts
@@ -123,7 +123,7 @@ export const useAuthentication = () => {
setIsLoading(true);
setError(null)
const payload = getAuthorizationPayload(email, source);
- const { token, userId, generatingVideo, videoId } = await api.authorization(payload);
+ const { token, userId, generatingVideo, videoId, authCode } = await api.authorization(payload);
const { user } = await api.getUser({ token });
if (userId?.length) {
metricService.userParams({
@@ -135,7 +135,9 @@ export const useAuthentication = () => {
}
signUp(token, user);
setToken(token);
-
+ if (authCode?.length) {
+ dispatch(actions.userConfig.setAuthCode(authCode));
+ }
dispatch(actions.personalVideo.updateStatus({ generatingVideo: generatingVideo || false, videoId: videoId || "" }));
if (generatingVideo) {
metricService.reachGoal(EGoals.ROSE_VIDEO_CREATION_START)
diff --git a/src/init.tsx b/src/init.tsx
index dc1cf5f..587b079 100755
--- a/src/init.tsx
+++ b/src/init.tsx
@@ -13,6 +13,7 @@ import App from "./components/App";
import metricService from "./services/metric/metricService";
import "core-js/actual";
import { pdfjs } from "react-pdf";
+import MetaPixel from "./utils/FBMetaPixel";
pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.js`;
@@ -68,6 +69,7 @@ const init = async () => {
return (
+
diff --git a/src/routerComponents/ABDesign/v1/index.tsx b/src/routerComponents/ABDesign/v1/index.tsx
index b940f70..0db1f57 100644
--- a/src/routerComponents/ABDesign/v1/index.tsx
+++ b/src/routerComponents/ABDesign/v1/index.tsx
@@ -33,6 +33,7 @@ import TrialPaymentPage from "@/components/pages/ABDesign/v1/pages/TrialPayment"
import TrialPaymentWithDiscount from "@/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount";
import AdditionalDiscount from "@/components/pages/ABDesign/v1/pages/AdditionalDiscount";
import MentionedInPage from "@/components/pages/ABDesign/v1/pages/MentionedIn";
+import TryAppPage from "@/components/pages/ABDesign/v1/pages/TryApp";
function ABDesignV1Routes() {
return (
@@ -137,6 +138,10 @@ function ABDesignV1Routes() {
>
} />
+ }
+ />
}
diff --git a/src/routes.ts b/src/routes.ts
index 797a1c4..a3963ae 100755
--- a/src/routes.ts
+++ b/src/routes.ts
@@ -195,6 +195,7 @@ const routes = {
onboardingV1: () => [host, "v1", "onboarding"].join("/"),
trialChoiceV1: () => [host, "v1", "trial-choice"].join("/"),
trialPaymentV1: () => [host, "v1", "trial-payment"].join("/"),
+ tryAppV1: () => [host, "v1", "try-app"].join("/"),
trialPaymentWithDiscountV1: () =>
[host, "v1", "trial-payment-with-discount"].join("/"),
additionalDiscountV1: () => [host, "v1", "additional-discount"].join("/"),
diff --git a/src/store/index.ts b/src/store/index.ts
index f1a088d..578074d 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -50,6 +50,7 @@ import userConfig, {
selectUserDeviceType,
selectIsShowTryApp,
selectFeature,
+ selectAuthCode,
selectIsForceShortPath,
selectDateOfPaymentChatMike,
} from "./userConfig";
@@ -125,6 +126,7 @@ export const selectors = {
selectUserDeviceType,
selectIsShowTryApp,
selectFeature,
+ selectAuthCode,
selectIsForceShortPath,
selectDateOfPaymentChatMike,
selectOpenAiToken,
diff --git a/src/store/userConfig.ts b/src/store/userConfig.ts
index 5d68a98..9e9f2c4 100644
--- a/src/store/userConfig.ts
+++ b/src/store/userConfig.ts
@@ -11,6 +11,7 @@ interface IUserConfig {
isShowTryApp: boolean;
isForceShortPath: boolean;
feature: string;
+ authCode: string;
dateOfPaymentChatMike: string;
}
@@ -19,6 +20,7 @@ const initialState: IUserConfig = {
isShowTryApp: false,
isForceShortPath: false,
feature: "",
+ authCode: "",
dateOfPaymentChatMike: "",
};
@@ -45,6 +47,10 @@ const userConfigSlice = createSlice({
state.feature = action.payload;
return state;
},
+ setAuthCode(state, action: PayloadAction) {
+ state.authCode = action.payload;
+ return state;
+ },
setDateOfPaymentChatMike(state, action: PayloadAction) {
state.dateOfPaymentChatMike = action.payload.toISOString();
return state;
@@ -70,6 +76,10 @@ export const selectFeature = createSelector(
(state: { userConfig: IUserConfig }) => state.userConfig.feature,
(userConfig) => userConfig
);
+export const selectAuthCode = createSelector(
+ (state: { userConfig: IUserConfig }) => state.userConfig.authCode,
+ (userConfig) => userConfig
+);
export const selectDateOfPaymentChatMike = createSelector(
(state: { userConfig: IUserConfig }) => state.userConfig.dateOfPaymentChatMike,
(userConfig) => userConfig
diff --git a/src/utils/FBMetaPixel/index.tsx b/src/utils/FBMetaPixel/index.tsx
new file mode 100644
index 0000000..b91ead0
--- /dev/null
+++ b/src/utils/FBMetaPixel/index.tsx
@@ -0,0 +1,22 @@
+import { Helmet } from "react-helmet";
+
+const MetaPixel = () => {
+ const FBScript = `!function(f,b,e,v,n,t,s)
+{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
+n.callMethod.apply(n,arguments):n.queue.push(arguments)};
+if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
+n.queue=[];t=b.createElement(e);t.async=!0;
+t.src=v;s=b.getElementsByTagName(e)[0];
+s.parentNode.insertBefore(t,s)}(window, document,'script',
+'https://connect.facebook.net/en_US/fbevents.js');
+fbq('init', '410962885334010');
+fbq('track', 'PageView');`;
+
+ return (
+
+
+
+ );
+};
+
+export default MetaPixel;