Merge branch 'develop' into 'main'

Develop

See merge request witapp/aura-webapp!282
This commit is contained in:
Daniil Chemerkin 2024-08-05 18:46:00 +00:00
commit e1bc061027
15 changed files with 412 additions and 4 deletions

59
package-lock.json generated
View File

@ -28,6 +28,7 @@
"react-circular-progressbar": "^2.1.0", "react-circular-progressbar": "^2.1.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-ga4": "^2.1.0", "react-ga4": "^2.1.0",
"react-helmet": "^6.1.0",
"react-i18next": "^12.3.1", "react-i18next": "^12.3.1",
"react-pdf": "8.0.2", "react-pdf": "8.0.2",
"react-player": "^2.16.0", "react-player": "^2.16.0",
@ -44,6 +45,7 @@
"@types/node": "^20.5.1", "@types/node": "^20.5.1",
"@types/react": "^18.2.6", "@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4", "@types/react-dom": "^18.2.4",
"@types/react-helmet": "^6.1.11",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
"@types/react-slick": "^0.23.13", "@types/react-slick": "^0.23.13",
"@typescript-eslint/eslint-plugin": "^5.59.6", "@typescript-eslint/eslint-plugin": "^5.59.6",
@ -1563,6 +1565,15 @@
"@types/react": "*" "@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": { "node_modules/@types/react-router": {
"version": "5.1.20", "version": "5.1.20",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", "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", "resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-2.1.0.tgz",
"integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ==" "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": { "node_modules/react-i18next": {
"version": "12.3.1", "version": "12.3.1",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz", "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz",
@ -4231,6 +4256,14 @@
"react-dom": ">=16.8" "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": { "node_modules/react-slick": {
"version": "0.30.2", "version": "0.30.2",
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.30.2.tgz", "resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.30.2.tgz",
@ -5967,6 +6000,15 @@
"@types/react": "*" "@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": { "@types/react-router": {
"version": "5.1.20", "version": "5.1.20",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", "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", "resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-2.1.0.tgz",
"integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ==" "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": { "react-i18next": {
"version": "12.3.1", "version": "12.3.1",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz", "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz",
@ -7851,6 +7904,12 @@
"react-router": "6.11.2" "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": { "react-slick": {
"version": "0.30.2", "version": "0.30.2",
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.30.2.tgz", "resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.30.2.tgz",

View File

@ -34,6 +34,7 @@
"react-circular-progressbar": "^2.1.0", "react-circular-progressbar": "^2.1.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-ga4": "^2.1.0", "react-ga4": "^2.1.0",
"react-helmet": "^6.1.0",
"react-i18next": "^12.3.1", "react-i18next": "^12.3.1",
"react-pdf": "8.0.2", "react-pdf": "8.0.2",
"react-player": "^2.16.0", "react-player": "^2.16.0",
@ -50,6 +51,7 @@
"@types/node": "^20.5.1", "@types/node": "^20.5.1",
"@types/react": "^18.2.6", "@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4", "@types/react-dom": "^18.2.4",
"@types/react-helmet": "^6.1.11",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
"@types/react-slick": "^0.23.13", "@types/react-slick": "^0.23.13",
"@typescript-eslint/eslint-plugin": "^5.59.6", "@typescript-eslint/eslint-plugin": "^5.59.6",

View File

@ -181,6 +181,7 @@ export interface ICreateAuthorizeResponse {
userId?: string; userId?: string;
generatingVideo?: boolean; generatingVideo?: boolean;
videoId?: string; videoId?: string;
authCode?: string;
} }
export const createAuthorizeRequest = (data: ICreateAuthorizePayload): Request => { export const createAuthorizeRequest = (data: ICreateAuthorizePayload): Request => {

View File

@ -25,10 +25,14 @@ function OnboardingPage() {
const { createdDate, generatingVideo } = useSelector( const { createdDate, generatingVideo } = useSelector(
selectors.selectPersonalVideo selectors.selectPersonalVideo
); );
const authCode = useSelector(selectors.selectAuthCode);
const handleNext = useCallback(() => { const handleNext = useCallback(() => {
navigate(routes.client.trialChoiceV1()); if (authCode?.length) {
}, [navigate]); return navigate(routes.client.tryAppV1());
}
return navigate(routes.client.trialChoiceV1());
}, [authCode, navigate]);
useEffect(() => { useEffect(() => {
if (isVideoReady && progress >= 100) { if (isVideoReady && progress >= 100) {

View File

@ -0,0 +1,23 @@
import Title from "@/components/Title";
import styles from "./styles.module.css";
interface IAccessCodeAppProps {
code: string;
}
function AccessCodeApp({ code }: IAccessCodeAppProps) {
return (
<div className={styles.container}>
<div className={styles["header-container"]}>
<Title className={styles.title} variant="h4">
Your access code
</Title>
</div>
<div className={styles["code-container"]}>
<span className={styles.code}>{code}</span>
</div>
</div>
);
}
export default AccessCodeApp;

View File

@ -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;
}

View File

@ -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 (
<section
className={`${styles.page} page`}
ref={pageRef}
style={{
backgroundColor: gender === "male" ? "#C1E5FF" : "#F7EBFF",
}}
>
<div className={styles["background-top-blob-container"]}>
<BackgroundTopBlob
width={pageWidth}
height={200}
className={styles["background-top-blob"]}
/>
</div>
<Header className={styles.header} />
<TrialPaymentHeader
buttonClick={downloadApp}
buttonText="get my reading in the app"
buttonClassName={styles["header-button"]}
/>
{singleOrWithPartner === "partner" && (
<WithPartnerInformation
zodiacSign={zodiacSign}
gender={gender}
birthPlace={birthPlace}
birthdate={birthdate}
partnerBirthPlace={partnerBirthPlace}
partnerBirthDate={partnerBirthdate}
partnerGender={partnerGender}
partnerZodiacSign={partnerZodiacSign}
/>
)}
{singleOrWithPartner === "single" && (
<PersonalInformation
zodiacSign={zodiacSign}
gender={gender}
birthPlace={birthPlace}
birthdate={birthdate}
/>
)}
<Title variant="h2" className={styles.title}>
Your Personalized Clarity & Love Reading is ready and available in the
app for your iPhone!
</Title>
<Goal goal={goal} />
<AccessCodeApp code={authCode} />
<span className={styles["download-app-title"]}>1. Download App</span>
<img
className={styles["download-app-image"]}
src="/download-app.svg"
alt="Download on the app store"
onClick={downloadApp}
/>
<span className={styles["download-app-title"]}>
2. Enter Your Access Code
</span>
<div className={styles["code-container"]}>{authCode}</div>
<p className={styles["code-description"]}>
Enter your access code in the app to access Your Personalized Reading.
Do not share your code with anyone
</p>
<YourReading
gender={gender}
zodiacSign={zodiacSign}
buttonClick={downloadApp}
singleOrWithPartner={singleOrWithPartner}
callToActionText="To read the full reading you need get access through the app for your iPhone"
buttonText="get my reading in the app"
/>
<Title
variant="h2"
className={styles.title}
style={{ marginTop: "88px" }}
>
Users love us
</Title>
<Reviews reviews={trialPaymentReviews} />
<PointsList title="What you get" points={trialPaymentPointsList} />
<OftenAsk />
</section>
);
}
export default TryAppPage;

View File

@ -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);
}
}

View File

@ -123,7 +123,7 @@ export const useAuthentication = () => {
setIsLoading(true); setIsLoading(true);
setError(null) setError(null)
const payload = getAuthorizationPayload(email, source); 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 }); const { user } = await api.getUser({ token });
if (userId?.length) { if (userId?.length) {
metricService.userParams({ metricService.userParams({
@ -135,7 +135,9 @@ export const useAuthentication = () => {
} }
signUp(token, user); signUp(token, user);
setToken(token); setToken(token);
if (authCode?.length) {
dispatch(actions.userConfig.setAuthCode(authCode));
}
dispatch(actions.personalVideo.updateStatus({ generatingVideo: generatingVideo || false, videoId: videoId || "" })); dispatch(actions.personalVideo.updateStatus({ generatingVideo: generatingVideo || false, videoId: videoId || "" }));
if (generatingVideo) { if (generatingVideo) {
metricService.reachGoal(EGoals.ROSE_VIDEO_CREATION_START) metricService.reachGoal(EGoals.ROSE_VIDEO_CREATION_START)

View File

@ -13,6 +13,7 @@ import App from "./components/App";
import metricService from "./services/metric/metricService"; import metricService from "./services/metric/metricService";
import "core-js/actual"; import "core-js/actual";
import { pdfjs } from "react-pdf"; 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`; pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.js`;
@ -68,6 +69,7 @@ const init = async () => {
return ( return (
<React.Fragment> <React.Fragment>
<MetaPixel />
<I18nextProvider i18n={i18nextInstance}> <I18nextProvider i18n={i18nextInstance}>
<Provider store={store}> <Provider store={store}>
<BrowserRouter> <BrowserRouter>

View File

@ -33,6 +33,7 @@ import TrialPaymentPage from "@/components/pages/ABDesign/v1/pages/TrialPayment"
import TrialPaymentWithDiscount from "@/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount"; import TrialPaymentWithDiscount from "@/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount";
import AdditionalDiscount from "@/components/pages/ABDesign/v1/pages/AdditionalDiscount"; import AdditionalDiscount from "@/components/pages/ABDesign/v1/pages/AdditionalDiscount";
import MentionedInPage from "@/components/pages/ABDesign/v1/pages/MentionedIn"; import MentionedInPage from "@/components/pages/ABDesign/v1/pages/MentionedIn";
import TryAppPage from "@/components/pages/ABDesign/v1/pages/TryApp";
function ABDesignV1Routes() { function ABDesignV1Routes() {
return ( return (
@ -137,6 +138,10 @@ function ABDesignV1Routes() {
> >
<Route path=":subPlan" element={<TrialPaymentPage />} /> <Route path=":subPlan" element={<TrialPaymentPage />} />
</Route> </Route>
<Route
path={routes.client.tryAppV1()}
element={<TryAppPage />}
/>
<Route <Route
path={routes.client.trialPaymentWithDiscountV1()} path={routes.client.trialPaymentWithDiscountV1()}
element={<TrialPaymentWithDiscount />} element={<TrialPaymentWithDiscount />}

View File

@ -195,6 +195,7 @@ const routes = {
onboardingV1: () => [host, "v1", "onboarding"].join("/"), onboardingV1: () => [host, "v1", "onboarding"].join("/"),
trialChoiceV1: () => [host, "v1", "trial-choice"].join("/"), trialChoiceV1: () => [host, "v1", "trial-choice"].join("/"),
trialPaymentV1: () => [host, "v1", "trial-payment"].join("/"), trialPaymentV1: () => [host, "v1", "trial-payment"].join("/"),
tryAppV1: () => [host, "v1", "try-app"].join("/"),
trialPaymentWithDiscountV1: () => trialPaymentWithDiscountV1: () =>
[host, "v1", "trial-payment-with-discount"].join("/"), [host, "v1", "trial-payment-with-discount"].join("/"),
additionalDiscountV1: () => [host, "v1", "additional-discount"].join("/"), additionalDiscountV1: () => [host, "v1", "additional-discount"].join("/"),

View File

@ -50,6 +50,7 @@ import userConfig, {
selectUserDeviceType, selectUserDeviceType,
selectIsShowTryApp, selectIsShowTryApp,
selectFeature, selectFeature,
selectAuthCode,
selectIsForceShortPath, selectIsForceShortPath,
selectDateOfPaymentChatMike, selectDateOfPaymentChatMike,
} from "./userConfig"; } from "./userConfig";
@ -125,6 +126,7 @@ export const selectors = {
selectUserDeviceType, selectUserDeviceType,
selectIsShowTryApp, selectIsShowTryApp,
selectFeature, selectFeature,
selectAuthCode,
selectIsForceShortPath, selectIsForceShortPath,
selectDateOfPaymentChatMike, selectDateOfPaymentChatMike,
selectOpenAiToken, selectOpenAiToken,

View File

@ -11,6 +11,7 @@ interface IUserConfig {
isShowTryApp: boolean; isShowTryApp: boolean;
isForceShortPath: boolean; isForceShortPath: boolean;
feature: string; feature: string;
authCode: string;
dateOfPaymentChatMike: string; dateOfPaymentChatMike: string;
} }
@ -19,6 +20,7 @@ const initialState: IUserConfig = {
isShowTryApp: false, isShowTryApp: false,
isForceShortPath: false, isForceShortPath: false,
feature: "", feature: "",
authCode: "",
dateOfPaymentChatMike: "", dateOfPaymentChatMike: "",
}; };
@ -45,6 +47,10 @@ const userConfigSlice = createSlice({
state.feature = action.payload; state.feature = action.payload;
return state; return state;
}, },
setAuthCode(state, action: PayloadAction<string>) {
state.authCode = action.payload;
return state;
},
setDateOfPaymentChatMike(state, action: PayloadAction<Date>) { setDateOfPaymentChatMike(state, action: PayloadAction<Date>) {
state.dateOfPaymentChatMike = action.payload.toISOString(); state.dateOfPaymentChatMike = action.payload.toISOString();
return state; return state;
@ -70,6 +76,10 @@ export const selectFeature = createSelector(
(state: { userConfig: IUserConfig }) => state.userConfig.feature, (state: { userConfig: IUserConfig }) => state.userConfig.feature,
(userConfig) => userConfig (userConfig) => userConfig
); );
export const selectAuthCode = createSelector(
(state: { userConfig: IUserConfig }) => state.userConfig.authCode,
(userConfig) => userConfig
);
export const selectDateOfPaymentChatMike = createSelector( export const selectDateOfPaymentChatMike = createSelector(
(state: { userConfig: IUserConfig }) => state.userConfig.dateOfPaymentChatMike, (state: { userConfig: IUserConfig }) => state.userConfig.dateOfPaymentChatMike,
(userConfig) => userConfig (userConfig) => userConfig

View File

@ -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 (
<Helmet>
<script>{FBScript}</script>
</Helmet>
);
};
export default MetaPixel;