From 3ee9e0fe90843acf95638bc6405bfe54ab78d09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B5=D0=BD=D0=B8=D1=81=20=D0=9A=D0=B0=D1=82=D0=B0?= =?UTF-8?q?=D0=B5=D0=B2?= Date: Mon, 27 May 2024 20:43:33 +0000 Subject: [PATCH] AW-84-AW-85-defaultContent-loadContent --- src/components/App/index.tsx | 4 + .../ABDesign/v1/pages/Onboarding/index.tsx | 3 + src/components/pages/Onboarding/index.tsx | 3 + src/hooks/paywall/defaultPaywalls.ts | 246 ++++++++++++++++++ src/hooks/paywall/usePaywall.tsx | 31 ++- src/store/index.ts | 6 + src/store/paywalls.ts | 54 ++++ 7 files changed, 342 insertions(+), 5 deletions(-) create mode 100644 src/hooks/paywall/defaultPaywalls.ts create mode 100644 src/store/paywalls.ts diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 29eeeae..62371bd 100755 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -162,6 +162,10 @@ function App(): JSX.Element { const birthdate = user?.profile?.birthday || birthdateFromStore; const birthPlace = user?.profile?.birthplace || birthPlaceFromStore; + useLayoutEffect(() => { + dispatch(actions.paywalls.resetIsMustUpdate()); + }, [dispatch]); + useEffect(() => { // api.getAppConfig({ bundleId: "auraweb" }), dispatch( diff --git a/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx b/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx index cf78572..c7c57dc 100644 --- a/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx +++ b/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx @@ -5,6 +5,8 @@ import routes from "@/routes"; import { useNavigate } from "react-router-dom"; import { onboardingTitles } from "../../data/onboarding"; import ProgressBarLine from "@/components/ui/ProgressBarLine"; +import { usePaywall } from "@/hooks/paywall/usePaywall"; +import { EPlacementKeys } from "@/api/resources/Paywall"; function OnboardingPage() { const navigate = useNavigate(); @@ -14,6 +16,7 @@ function OnboardingPage() { const classNameTimeOut = useRef(); const [progress, setProgress] = useState(0); const progressInterval = useRef(); + usePaywall({ placementKey: EPlacementKeys["aura.placement.redesign.main"] }); const handleNext = useCallback(() => { navigate(routes.client.trialChoiceV1()); diff --git a/src/components/pages/Onboarding/index.tsx b/src/components/pages/Onboarding/index.tsx index 6d0fbb0..8549e8a 100755 --- a/src/components/pages/Onboarding/index.tsx +++ b/src/components/pages/Onboarding/index.tsx @@ -4,6 +4,8 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { onboardingTitles } from "@/data/onboarding"; import routes from "@/routes"; import { useNavigate } from "react-router-dom"; +import { usePaywall } from "@/hooks/paywall/usePaywall"; +import { EPlacementKeys } from "@/api/resources/Paywall"; function OnboardingPage() { const navigate = useNavigate(); @@ -11,6 +13,7 @@ function OnboardingPage() { const [periodClassName, setPeriodClassName] = useState(""); const titleInterval = useRef(); const classNameTimeOut = useRef(); + usePaywall({ placementKey: EPlacementKeys["aura.placement.main"] }); const handleNext = useCallback(() => { navigate(routes.client.trialChoice()); diff --git a/src/hooks/paywall/defaultPaywalls.ts b/src/hooks/paywall/defaultPaywalls.ts new file mode 100644 index 0000000..0276219 --- /dev/null +++ b/src/hooks/paywall/defaultPaywalls.ts @@ -0,0 +1,246 @@ +import { EPlacementKeys, IPaywall } from "@/api/resources/Paywall"; + +export const defaultPaywalls: { [key in EPlacementKeys]: IPaywall } = { + "aura.placement.redesign.main": { + "_id": "664215e2859ff1199d3a6e9a", + "key": "aura.paywall.redesign.main", + "name": "Main redesign paywall without free trial", + "products": [ + { + "_id": "65ff043dfc0fcfc4be550035", + "key": "compatibility.pdf.trial.0", + "productId": "prod_PnStTEBzrPLgvL", + "name": "Сompatibility AURA | Trial $0.99", + "priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4", + "type": "subscription", + "description": "Description", + "discountPrice": null, + "discountPriceId": null, + "isDiscount": false, + "isFreeTrial": false, + "isTrial": true, + "price": 1900, + "trialDuration": 3, + "trialPrice": 99, + "trialPriceId": "price_1PFiSkIlX4lgwUxrVel0l445" + }, + { + "_id": "66420b6e859ff1199d3a6e88", + "key": "compatibility.pdf.trial.1", + "productId": "prod_PnStTEBzrPLgvL", + "name": "Сompatibility AURA | Trial $5.00", + "priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4", + "type": "subscription", + "description": "Description", + "discountPrice": null, + "discountPriceId": null, + "isDiscount": false, + "isFreeTrial": false, + "isTrial": true, + "price": 1900, + "trialDuration": 3, + "trialPrice": 500, + "trialPriceId": "price_1PFyASIlX4lgwUxriLtzsk05" + }, + { + "_id": "66420be1859ff1199d3a6e89", + "key": "compatibility.pdf.trial.2", + "productId": "prod_PnStTEBzrPLgvL", + "name": "Сompatibility AURA | Trial $9.00", + "priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4", + "type": "subscription", + "description": "Description", + "discountPrice": null, + "discountPriceId": null, + "isDiscount": false, + "isFreeTrial": false, + "isTrial": true, + "price": 1900, + "trialDuration": 3, + "trialPrice": 900, + "trialPriceId": "price_1PFyAuIlX4lgwUxr4fFoauCV" + }, + { + "_id": "66420c1c859ff1199d3a6e8a", + "key": "compatibility.pdf.trial.3", + "productId": "prod_PnStTEBzrPLgvL", + "name": "Сompatibility AURA | Trial $13.76", + "priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4", + "type": "subscription", + "description": "Description", + "discountPrice": null, + "discountPriceId": null, + "isDiscount": false, + "isFreeTrial": false, + "isTrial": true, + "price": 1900, + "trialDuration": 3, + "trialPrice": 1376, + "trialPriceId": "price_1PFyBQIlX4lgwUxrMnEUkV73" + } + ], + "properties": [ + { + "key": "text.0", + "value": "We've helped millions of people to have happier lives and better relationships, and we want to help you too.", + "_id": "664542bbfe0a8eb4ee0b4f27" + }, + { + "key": "text.0.color", + "value": "millions", + "_id": "664542bbfe0a8eb4ee0b4f28" + }, + { + "key": "text.1", + "value": "Money shouldn’t stand in the way of finding astrology guidance that finally works. So, choose an amount that you think is reasonable to try us out for one week.", + "_id": "664542bbfe0a8eb4ee0b4f29" + }, + { + "key": "text.2", + "value": "It costs us $13.67 to offer a 3-day trial, but please choose the amount you are comfortable with.", + "_id": "664542bbfe0a8eb4ee0b4f2a" + }, + { + "key": "text.3", + "value": "This option will help us support those who need to select the lowest trial prices!", + "_id": "664542bbfe0a8eb4ee0b4f2b" + }, + { + "key": "text.4", + "value": "*Cost of trial as of February 2024", + "_id": "664542bbfe0a8eb4ee0b4f2c" + }, + { + "key": "text.5", + "value": "${quantity} people joined today", + "_id": "664542bbfe0a8eb4ee0b4f2d" + }, + { + "key": "text.button.1", + "value": "See my plan", + "_id": "664542bbfe0a8eb4ee0b4f2e" + } + ] + }, + "aura.placement.main": { + "_id": "664215e2859ff1199d3a6e9a", + "key": "aura.paywall.redesign.main", + "name": "Main redesign paywall without free trial", + "products": [ + { + "_id": "65ff043dfc0fcfc4be550035", + "key": "compatibility.pdf.trial.0", + "productId": "prod_PnStTEBzrPLgvL", + "name": "Сompatibility AURA | Trial $0.99", + "priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4", + "type": "subscription", + "description": "Description", + "discountPrice": null, + "discountPriceId": null, + "isDiscount": false, + "isFreeTrial": false, + "isTrial": true, + "price": 1900, + "trialDuration": 3, + "trialPrice": 99, + "trialPriceId": "price_1PFiSkIlX4lgwUxrVel0l445" + }, + { + "_id": "66420b6e859ff1199d3a6e88", + "key": "compatibility.pdf.trial.1", + "productId": "prod_PnStTEBzrPLgvL", + "name": "Сompatibility AURA | Trial $5.00", + "priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4", + "type": "subscription", + "description": "Description", + "discountPrice": null, + "discountPriceId": null, + "isDiscount": false, + "isFreeTrial": false, + "isTrial": true, + "price": 1900, + "trialDuration": 3, + "trialPrice": 500, + "trialPriceId": "price_1PFyASIlX4lgwUxriLtzsk05" + }, + { + "_id": "66420be1859ff1199d3a6e89", + "key": "compatibility.pdf.trial.2", + "productId": "prod_PnStTEBzrPLgvL", + "name": "Сompatibility AURA | Trial $9.00", + "priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4", + "type": "subscription", + "description": "Description", + "discountPrice": null, + "discountPriceId": null, + "isDiscount": false, + "isFreeTrial": false, + "isTrial": true, + "price": 1900, + "trialDuration": 3, + "trialPrice": 900, + "trialPriceId": "price_1PFyAuIlX4lgwUxr4fFoauCV" + }, + { + "_id": "66420c1c859ff1199d3a6e8a", + "key": "compatibility.pdf.trial.3", + "productId": "prod_PnStTEBzrPLgvL", + "name": "Сompatibility AURA | Trial $13.76", + "priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4", + "type": "subscription", + "description": "Description", + "discountPrice": null, + "discountPriceId": null, + "isDiscount": false, + "isFreeTrial": false, + "isTrial": true, + "price": 1900, + "trialDuration": 3, + "trialPrice": 1376, + "trialPriceId": "price_1PFyBQIlX4lgwUxrMnEUkV73" + } + ], + "properties": [ + { + "key": "text.0", + "value": "We've helped millions of people to have happier lives and better relationships, and we want to help you too.", + "_id": "664542bbfe0a8eb4ee0b4f27" + }, + { + "key": "text.0.color", + "value": "millions", + "_id": "664542bbfe0a8eb4ee0b4f28" + }, + { + "key": "text.1", + "value": "Money shouldn’t stand in the way of finding astrology guidance that finally works. So, choose an amount that you think is reasonable to try us out for one week.", + "_id": "664542bbfe0a8eb4ee0b4f29" + }, + { + "key": "text.2", + "value": "It costs us $13.67 to offer a 3-day trial, but please choose the amount you are comfortable with.", + "_id": "664542bbfe0a8eb4ee0b4f2a" + }, + { + "key": "text.3", + "value": "This option will help us support those who need to select the lowest trial prices!", + "_id": "664542bbfe0a8eb4ee0b4f2b" + }, + { + "key": "text.4", + "value": "*Cost of trial as of February 2024", + "_id": "664542bbfe0a8eb4ee0b4f2c" + }, + { + "key": "text.5", + "value": "${quantity} people joined today", + "_id": "664542bbfe0a8eb4ee0b4f2d" + }, + { + "key": "text.button.1", + "value": "See my plan", + "_id": "664542bbfe0a8eb4ee0b4f2e" + } + ] + } +} \ No newline at end of file diff --git a/src/hooks/paywall/usePaywall.tsx b/src/hooks/paywall/usePaywall.tsx index 8970747..1bdc2fc 100644 --- a/src/hooks/paywall/usePaywall.tsx +++ b/src/hooks/paywall/usePaywall.tsx @@ -1,9 +1,10 @@ import { useApi } from "@/api"; import { EPlacementKeys, IPaywall } from "@/api/resources/Paywall"; -import { selectors } from "@/store"; +import { actions, selectors } from "@/store"; import { useCallback, useEffect, useMemo, useState } from "react"; -import { useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import parse from "html-react-parser"; +import { defaultPaywalls } from "./defaultPaywalls"; interface IUsePaywallProps { placementKey: EPlacementKeys; @@ -20,6 +21,7 @@ interface IGetTextProps { export function usePaywall({ placementKey }: IUsePaywallProps) { const api = useApi(); + const dispatch = useDispatch(); const token = useSelector(selectors.selectToken); const [paywall, setPaywall] = useState(); const [isLoading, setIsLoading] = useState(false); @@ -29,6 +31,8 @@ export function usePaywall({ placementKey }: IUsePaywallProps) { () => paywall?.properties || [], [paywall?.properties] ); + const isMustUpdate = useSelector(selectors.selectPaywallsIsMustUpdate); + const paywalls = useSelector(selectors.selectPaywalls); const getPaywallByPlacementKey = useCallback( async (placementKey: EPlacementKeys) => { @@ -41,20 +45,37 @@ export function usePaywall({ placementKey }: IUsePaywallProps) { }); if ("paywall" in paywall && paywall.paywall) { setPaywall(paywall.paywall); + dispatch( + actions.paywalls.updatePaywall({ + [placementKey]: paywall.paywall, + }) + ); + dispatch( + actions.paywalls.updateIsMustUpdate({ + [placementKey]: false, + }) + ); } } catch (error) { console.error(error); setError(true); + setPaywall(defaultPaywalls[placementKey]); } finally { setIsLoading(false); } }, - [api, token] + [api, dispatch, token] ); useEffect(() => { - getPaywallByPlacementKey(placementKey); - }, [getPaywallByPlacementKey, placementKey]); + if (isMustUpdate[placementKey] || !paywalls[placementKey]) { + getPaywallByPlacementKey(placementKey); + } else { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + setPaywall(paywalls[placementKey]!); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [getPaywallByPlacementKey, placementKey, isMustUpdate]); const getText = useCallback( ( diff --git a/src/store/index.ts b/src/store/index.ts index 6d23e08..868cc4d 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -14,6 +14,7 @@ import form, { selectors as formSelectors, } from "./form"; import aura, { actions as auraActions } from "./aura"; +import paywalls, { actions as paywallsActions } from "./paywalls"; import siteConfig, { selectHome, selectOpenAiToken, @@ -67,6 +68,7 @@ import palmistry, { actions as palmistryActions, selectPalmistryLines, } from "./palmistry"; +import { selectPaywallsIsMustUpdate, selectPaywalls } from "./paywalls"; const preloadedState = loadStore(); export const actions = { @@ -76,6 +78,7 @@ export const actions = { status: userStatusActions, subscriptionPlan: subscriptionPlasActions, aura: auraActions, + paywalls: paywallsActions, siteConfig: siteConfigActions, compatibility: compatibilityActions, compatibilities: compatibilitiesActions, @@ -115,6 +118,8 @@ export const selectors = { selectIsForceShortPath, selectOpenAiToken, selectPalmistryLines, + selectPaywalls, + selectPaywallsIsMustUpdate, ...formSelectors, }; @@ -134,6 +139,7 @@ export const reducer = combineReducers({ questionnaire, userConfig, palmistry, + paywalls, }); export type RootState = ReturnType; diff --git a/src/store/paywalls.ts b/src/store/paywalls.ts new file mode 100644 index 0000000..4190ded --- /dev/null +++ b/src/store/paywalls.ts @@ -0,0 +1,54 @@ +import { EPlacementKeys, IPaywall } from '@/api/resources/Paywall' +import { createSlice, createSelector } from '@reduxjs/toolkit' +import type { PayloadAction } from '@reduxjs/toolkit' + +type TAdditionalParameters = { + isMustUpdate: { + [key in EPlacementKeys]: boolean + }; +} + +type TPaywalls = { + [key in EPlacementKeys]: IPaywall | null; +} & TAdditionalParameters + +type IPayloadUpdatePaywall = { + [key in EPlacementKeys]: IPaywall +} + +const initialState: TPaywalls = { + "aura.placement.main": null, + "aura.placement.redesign.main": null, + isMustUpdate: { + "aura.placement.main": true, + "aura.placement.redesign.main": true, + }, +} + +const paywallsSlice = createSlice({ + name: 'paywalls', + initialState, + reducers: { + updatePaywall(state, action: PayloadAction>) { + return { ...state, ...action.payload } + }, + updateIsMustUpdate(state, action: PayloadAction>) { + return { ...state, isMustUpdate: { ...state.isMustUpdate, ...action.payload } } + }, + resetIsMustUpdate(state) { + return { ...state, isMustUpdate: initialState.isMustUpdate } + } + }, + extraReducers: (builder) => builder.addCase('reset', () => initialState), +}) + +export const { actions } = paywallsSlice +export const selectPaywalls = createSelector( + (state: { paywalls: TPaywalls }) => state.paywalls, + (paywalls) => paywalls +) +export const selectPaywallsIsMustUpdate = createSelector( + (state: { paywalls: TPaywalls }) => state.paywalls.isMustUpdate, + (paywalls) => paywalls +) +export default paywallsSlice.reducer