develop
This commit is contained in:
parent
d0c61ca094
commit
2384081811
@ -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 <Navigate to={routes.client.compatibilityV2Gender()} />
|
||||
|
||||
if (!ready) return null;
|
||||
|
||||
return (
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.header}>
|
||||
@ -51,23 +28,22 @@ function EmailsList({ products }: IEmailsListProps) {
|
||||
</div>
|
||||
<p className={styles.description}>
|
||||
{translate("/trial-choice.v1.emails_list.description", {
|
||||
count: countBuyingEmails
|
||||
count: displayEmails?.length
|
||||
})}
|
||||
</p>
|
||||
<div className={styles.emails}>
|
||||
{displayEmails.map((item) => (
|
||||
<div key={item.id} className={styles.emailContainer}>
|
||||
<div key={item.id} className={`${styles.emailContainer} ${item.willBeRemoved ? styles.removed : ""}`}>
|
||||
<div className={styles.priceContainer}>
|
||||
{item.willBeRemoved && (
|
||||
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="17" height="17" rx="8.5" fill="url(#paint0_linear_263_585)" />
|
||||
<rect
|
||||
width="17"
|
||||
height="17"
|
||||
rx="8.5"
|
||||
fill="#62DFA1"
|
||||
/>
|
||||
<path d="M7.2586 12C7.08625 12 6.9139 11.9285 6.78205 11.785L4.19724 8.96395C4.13481 8.89628 4.0852 8.8154 4.05132 8.7261C4.01745 8.63679 4 8.54086 4 8.44395C4 8.34704 4.01745 8.2511 4.05132 8.1618C4.0852 8.07249 4.13481 7.99162 4.19724 7.92394C4.32473 7.78583 4.49574 7.70853 4.67379 7.70853C4.85184 7.70853 5.02285 7.78583 5.15034 7.92394L7.2586 10.2245L11.8491 5.21541C11.9766 5.0773 12.1476 5 12.3256 5C12.5037 5 12.6747 5.0773 12.8022 5.21541C12.8648 5.28298 12.9145 5.36382 12.9485 5.45314C12.9825 5.54246 13 5.63844 13 5.73541C13 5.83239 12.9825 5.92837 12.9485 6.01769C12.9145 6.10701 12.8648 6.18785 12.8022 6.25542L7.73515 11.7845C7.60814 11.9234 7.43683 12.0009 7.2586 12Z" fill="#F4F4F4" />
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_263_585" x1="8.5" y1="17" x2="8.5" y2="0" gradientUnits="userSpaceOnUse">
|
||||
<stop stopColor="#00D26A" />
|
||||
<stop offset="1" stopColor="#62DFA1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
)}
|
||||
<div className={styles.price}>
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 (
|
||||
<div className={styles.container}>
|
||||
{!isLoading && (
|
||||
@ -106,6 +116,7 @@ function TrialChoiceV1() {
|
||||
classNamePricesContainer={styles["prices-container"]}
|
||||
currency={currency}
|
||||
click={handlePriceItem}
|
||||
preActiveItems={[popularProduct?._id]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
margin-top: 22px;
|
||||
line-height: 1 !important;
|
||||
line-height: 120% !important;
|
||||
}
|
||||
|
||||
.as-seen-in {
|
||||
|
||||
@ -11,12 +11,21 @@ interface DisplayEmail {
|
||||
willBeRemoved: boolean;
|
||||
}
|
||||
|
||||
interface EmailsToDelete {
|
||||
emails: DisplayEmail[];
|
||||
deleteAt: number;
|
||||
markAt: number;
|
||||
marked: boolean;
|
||||
}
|
||||
|
||||
export const useEmailsGeneration = (products: Array<IPaywallProduct & { weight: number }>) => {
|
||||
const { translate } = useTranslations(ELocalesPlacement.EmailGenerator);
|
||||
const [displayEmails, setDisplayEmails] = useState<DisplayEmail[]>([]);
|
||||
const [countBoughtEmails, setCountBoughtEmails] = useState(758);
|
||||
const maxEmails = 4;
|
||||
const minEmails = 3;
|
||||
const [emailsToDeleteQueue, setEmailsToDeleteQueue] = useState<EmailsToDelete[]>([]);
|
||||
|
||||
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<IPaywallProduct & { weight:
|
||||
if (random <= 0) return product;
|
||||
}
|
||||
return products[0];
|
||||
};
|
||||
}
|
||||
|
||||
const createEmail = () => {
|
||||
const product = getRandomProduct();
|
||||
@ -41,53 +50,97 @@ export const useEmailsGeneration = (products: Array<IPaywallProduct & { weight:
|
||||
id: Date.now() + Math.random(),
|
||||
willBeRemoved: false
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// creating emails
|
||||
useEffect(() => {
|
||||
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 };
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user