w-aura/src/hooks/emailsGeneration/useEmailsGeneration.ts
Daniil Chemerkin 2384081811 develop
2025-02-27 19:46:50 +00:00

146 lines
4.8 KiB
TypeScript

import { useState, useEffect } from 'react';
import { IPaywallProduct } from "@/api/resources/Paywall";
import { generateRealisticEmail } from "@/services/random-value/emailGenerator";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
interface DisplayEmail {
email: string;
price: number;
id: number;
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 [emailsToDeleteQueue, setEmailsToDeleteQueue] = useState<EmailsToDelete[]>([]);
const minEmails = 1;
const maxEmails = 5;
const getRandomProduct = () => {
const totalWeight = products.reduce((sum, product) => sum + (product.weight || 1), 0);
let random = Math.random() * totalWeight;
for (const product of products) {
random -= (product.weight || 1);
if (random <= 0) return product;
}
return products[0];
}
const createEmail = () => {
const product = getRandomProduct();
return {
email: generateRealisticEmail(
translate("firstNames").split(",") || [],
translate("lastNames").split(",") || [],
translate("domains").split(",") || []
),
price: (product.trialPrice || 0) / 100,
id: Date.now() + Math.random(),
willBeRemoved: false
};
}
// creating emails
useEffect(() => {
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 };
};