diff --git a/src/components/CompatibilityV2/pages/FindHappiness/index.tsx b/src/components/CompatibilityV2/pages/FindHappiness/index.tsx index 5a517b1..388e358 100644 --- a/src/components/CompatibilityV2/pages/FindHappiness/index.tsx +++ b/src/components/CompatibilityV2/pages/FindHappiness/index.tsx @@ -2,7 +2,7 @@ import routes, { compatibilityV2Prefix } from "@/routes"; import styles from "./styles.module.scss"; import Title from "@/components/Title"; import Button from "../../components/Button"; -import { useLocation, useNavigate } from "react-router-dom"; +import { Navigate, useLocation, useNavigate } from "react-router-dom"; import { useTranslations } from "@/hooks/translations"; import { ELocalesPlacement } from "@/locales"; import { useDispatch } from "react-redux"; @@ -33,6 +33,8 @@ function FindHappiness() { } }, [dispatch, location.pathname]); + return + if (!ready) return null; return ( diff --git a/src/components/CompatibilityV2/pages/TrialPayment/styles.module.scss b/src/components/CompatibilityV2/pages/TrialPayment/styles.module.scss index 994c145..32e52f3 100644 --- a/src/components/CompatibilityV2/pages/TrialPayment/styles.module.scss +++ b/src/components/CompatibilityV2/pages/TrialPayment/styles.module.scss @@ -9,7 +9,7 @@ } .begin-trial { - margin-top: -20px; + margin-top: 20px; } .why-love { @@ -23,10 +23,10 @@ } .success-story { - font-size: 20px; + // font-size: 20px; font-weight: 500; margin-top: 22px; - line-height: 1 !important; + line-height: 120% !important; } .as-seen-in { diff --git a/src/components/PalmistryV1/components/EmailsList/index.tsx b/src/components/PalmistryV1/components/EmailsList/index.tsx index 5e87cc2..a520910 100644 --- a/src/components/PalmistryV1/components/EmailsList/index.tsx +++ b/src/components/PalmistryV1/components/EmailsList/index.tsx @@ -1,7 +1,6 @@ import Title from "@/components/Title" import styles from "./styles.module.scss" import { IPaywallProduct } from "@/api/resources/Paywall" -import { useState, useEffect } from "react" import { useTranslations } from "@/hooks/translations" import { ELocalesPlacement } from "@/locales" import { useEmailsGeneration } from "@/hooks/emailsGeneration/useEmailsGeneration" @@ -12,34 +11,12 @@ interface IEmailsListProps { function EmailsList({ products }: IEmailsListProps) { const { translate } = useTranslations(ELocalesPlacement.PalmistryV1); - const [countBuyingEmails, setCountBuyingEmails] = useState(3); const { displayEmails, countBoughtEmails } = useEmailsGeneration(products); - useEffect(() => { - const updateCount = () => { - const change = Math.floor(Math.random() * 3) + 1; // 1, 2 или 3 - const increase = Math.random() < 0.5; - - setCountBuyingEmails(prev => { - const newCount = increase ? prev + change : prev - change; - if (newCount < 1) return 1; - if (newCount > 5) return 5; - return newCount; - }); - - setTimeout(updateCount, 1000 + Math.random() * 3000); - }; - - updateCount(); - return () => { - setCountBuyingEmails(17); - }; - }, []); - return (
@@ -51,23 +28,22 @@ function EmailsList({ products }: IEmailsListProps) {

{translate("/trial-choice.v1.emails_list.description", { - count: countBuyingEmails + count: displayEmails?.length })}

{displayEmails.map((item) => ( -
+
{item.willBeRemoved && ( - + - - - - - - )}
diff --git a/src/components/PalmistryV1/components/EmailsList/styles.module.scss b/src/components/PalmistryV1/components/EmailsList/styles.module.scss index 110e3e5..8e38672 100644 --- a/src/components/PalmistryV1/components/EmailsList/styles.module.scss +++ b/src/components/PalmistryV1/components/EmailsList/styles.module.scss @@ -52,6 +52,13 @@ padding-inline: 16px; gap: 4px; width: 100%; + opacity: 1; + transition: opacity 1.5s ease-in-out; + will-change: opacity; + + &.removed { + opacity: 0; + } &>.priceContainer { display: flex; diff --git a/src/components/PalmistryV1/pages/TrialChoice/v1/index.tsx b/src/components/PalmistryV1/pages/TrialChoice/v1/index.tsx index 9148e27..de6beea 100644 --- a/src/components/PalmistryV1/pages/TrialChoice/v1/index.tsx +++ b/src/components/PalmistryV1/pages/TrialChoice/v1/index.tsx @@ -4,7 +4,7 @@ import { addCurrency, ELocalesPlacement } from "@/locales"; import { useNavigate } from "react-router-dom"; import { useDispatch, useSelector } from "react-redux"; import { usePaywall } from "@/hooks/paywall/usePaywall"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { actions, selectors } from "@/store"; import metricService, { EGoals, EMetrics } from "@/services/metric/metricService"; import routes from "@/routes"; @@ -30,6 +30,7 @@ function TrialChoiceV1() { placementKey: EPlacementKeys["aura.placement.palmistry.redesign"], localesPlacement: ELocalesPlacement.PalmistryV1, }); + const popularProduct = products[products.length - 1]; // const { flags } = useMetricABFlags(); // const isLongText = flags?.text?.[0] === "on"; @@ -63,6 +64,15 @@ function TrialChoiceV1() { // metricService.reachGoal(EGoals.AURA_TRIAL_CHOICE_PAGE_VISIT, [EMetrics.KLAVIYO]); // }, []); + useEffect(() => { + if (popularProduct) { + dispatch(actions.payment.update({ + activeProduct: popularProduct + })) + setIsDisabled(false); + } + }, [popularProduct]) + return (
{!isLoading && ( @@ -106,6 +116,7 @@ function TrialChoiceV1() { classNamePricesContainer={styles["prices-container"]} currency={currency} click={handlePriceItem} + preActiveItems={[popularProduct?._id]} />
diff --git a/src/components/PalmistryV1/pages/TrialChoice/v1/styles.module.scss b/src/components/PalmistryV1/pages/TrialChoice/v1/styles.module.scss index 3ab9a8d..72fd18c 100644 --- a/src/components/PalmistryV1/pages/TrialChoice/v1/styles.module.scss +++ b/src/components/PalmistryV1/pages/TrialChoice/v1/styles.module.scss @@ -114,8 +114,8 @@ .button { margin-top: 20px; transition: background 0.2s ease, color 0.2s ease; - position: sticky; - bottom: calc(0dvh + 16px); + // position: sticky; + // bottom: calc(0dvh + 16px); &:disabled { border: solid #224e90 1px; @@ -150,7 +150,7 @@ font-weight: 500; line-height: 125%; color: #2C2C2C; - // list-style-type: disc; + list-style-type: disc; margin-left: 24px; &::marker { diff --git a/src/components/PalmistryV1/pages/TrialPayment/styles.module.scss b/src/components/PalmistryV1/pages/TrialPayment/styles.module.scss index 3bb9d66..68164e9 100644 --- a/src/components/PalmistryV1/pages/TrialPayment/styles.module.scss +++ b/src/components/PalmistryV1/pages/TrialPayment/styles.module.scss @@ -26,7 +26,7 @@ font-size: 20px; font-weight: 500; margin-top: 22px; - line-height: 1 !important; + line-height: 120% !important; } .as-seen-in { diff --git a/src/hooks/emailsGeneration/useEmailsGeneration.ts b/src/hooks/emailsGeneration/useEmailsGeneration.ts index 572c461..67c171f 100644 --- a/src/hooks/emailsGeneration/useEmailsGeneration.ts +++ b/src/hooks/emailsGeneration/useEmailsGeneration.ts @@ -11,12 +11,21 @@ interface DisplayEmail { willBeRemoved: boolean; } +interface EmailsToDelete { + emails: DisplayEmail[]; + deleteAt: number; + markAt: number; + marked: boolean; +} + export const useEmailsGeneration = (products: Array) => { const { translate } = useTranslations(ELocalesPlacement.EmailGenerator); const [displayEmails, setDisplayEmails] = useState([]); const [countBoughtEmails, setCountBoughtEmails] = useState(758); - const maxEmails = 4; - const minEmails = 3; + const [emailsToDeleteQueue, setEmailsToDeleteQueue] = useState([]); + + const minEmails = 1; + const maxEmails = 5; const getRandomProduct = () => { const totalWeight = products.reduce((sum, product) => sum + (product.weight || 1), 0); @@ -27,7 +36,7 @@ export const useEmailsGeneration = (products: Array { const product = getRandomProduct(); @@ -41,53 +50,97 @@ export const useEmailsGeneration = (products: Array { - const addEmails = () => { - const count = Math.random() < 0.7 ? 1 : 2; - const newEmails = Array(count).fill(null).map(createEmail); - - setDisplayEmails(prev => { - const updatedEmails = [...prev, ...newEmails].slice(-maxEmails); - - if (updatedEmails.length < minEmails) { - const additionalCount = minEmails - updatedEmails.length; - const additionalEmails = Array(additionalCount).fill(null).map(createEmail); - return [...updatedEmails, ...additionalEmails]; - } - - return updatedEmails; - }); - - const deleteTime = 3000 + Math.random() * 6000; - - setTimeout(() => { - setDisplayEmails(prev => - prev.map(email => - newEmails.includes(email) - ? { ...email, willBeRemoved: true } - : email - ) - ); - }, deleteTime - 1000); - - setTimeout(() => { - setDisplayEmails(prev => { - const filteredEmails = prev.filter(email => !newEmails.includes(email)); - setCountBoughtEmails(prev => prev + +(filteredEmails.length >= minEmails)); - return filteredEmails.length >= minEmails ? (filteredEmails) : prev; - }); - }, deleteTime); - - setTimeout(addEmails, 1000 + Math.random() * 3000); - }; - - setDisplayEmails(Array(minEmails).fill(null).map(createEmail)); - addEmails(); - + if (!products?.length) return; + addEmails(3); return () => setDisplayEmails([]); }, [products]); + const addEmails = (countEmails?: number) => { + const addEmailsTimeout = 3000 + Math.random() * 2000; + + const count = !!countEmails ? countEmails : Math.random() < 0.6 ? 1 : 2; + const _newEmails = Array(count).fill(null).map(createEmail); + + setDisplayEmails(prev => { + const updatedEmails = [...prev, ..._newEmails].slice(-maxEmails); + + if (updatedEmails.length < minEmails) { + const additionalCount = minEmails - updatedEmails.length; + const additionalEmails = Array(additionalCount).fill(null).map(createEmail); + return [...updatedEmails, ...additionalEmails]; + } + + return updatedEmails; + }); + + const now = Date.now(); + setEmailsToDeleteQueue(prev => [...prev, ..._newEmails.map((value) => { + const deleteTime = 3000 + Math.random() * 10000; + return { + emails: [value], + deleteAt: now + deleteTime, + markAt: now + deleteTime - 1500, + marked: false + } + })]); + + const timeoutAddEmails = setTimeout(() => { + addEmails(); + clearTimeout(timeoutAddEmails); + }, addEmailsTimeout); + } + + useEffect(() => { + if (emailsToDeleteQueue.length === 0) return; + + const checkQueue = () => { + const now = Date.now(); + + setEmailsToDeleteQueue(prev => { + const updatedQueue = [...prev]; + let hasChanges = false; + + updatedQueue.forEach(item => { + if (displayEmails.length <= minEmails) return; + if (!item.marked && now >= item.markAt) { + markEmails(item.emails); + item.marked = true; + hasChanges = true; + } + if (now >= item.deleteAt) { + deleteEmails(item.emails); + hasChanges = true; + } + }); + + return hasChanges ? updatedQueue.filter(item => now < item.deleteAt) : updatedQueue; + }); + }; + + const interval = setInterval(checkQueue, 100); + return () => clearInterval(interval); + }, [emailsToDeleteQueue]); + + const deleteEmails = (emailsToDelete: DisplayEmail[]) => { + setDisplayEmails(prev => + prev.filter(email => !emailsToDelete.some(e => e.id === email.id)) + ); + setCountBoughtEmails(prev => prev + emailsToDelete.length); + } + + const markEmails = (emailsToMark: DisplayEmail[]) => { + setDisplayEmails(prev => + prev.map(email => + emailsToMark.some(e => e.id === email.id) + ? { ...email, willBeRemoved: true } + : email + ) + ); + } + return { displayEmails, countBoughtEmails }; }; \ No newline at end of file