diff --git a/src/pages/PersonalizationAI/AuditoryLink.tsx b/src/pages/PersonalizationAI/AuditoryLink.tsx index 0e17653f..8b4b9727 100644 --- a/src/pages/PersonalizationAI/AuditoryLink.tsx +++ b/src/pages/PersonalizationAI/AuditoryLink.tsx @@ -1,12 +1,11 @@ import { AuditoryItem } from "@/api/auditory"; -import CopyIcon from "@/assets/icons/CopyIcon"; import Trash from "@/assets/icons/trash"; import { useCurrentQuiz } from "@/stores/quizes/hooks"; import { InfoPopover } from "@/ui_kit/InfoPopover"; import TooltipClickInfo from "@/ui_kit/Toolbars/TooltipClickInfo"; import { useDomainDefine } from "@/utils/hooks/useDomainDefine"; -import { IconButton, ListItem, Skeleton, Typography, useTheme } from "@mui/material"; -import { useEffect, useMemo, useState } from "react"; +import { IconButton, ListItem, Typography, useTheme } from "@mui/material"; +import { CopyButton } from "./CopyButton"; interface AuditoryLinkProps { item: AuditoryItem; @@ -20,66 +19,7 @@ export const AuditoryLink = ({ utmParams, item, index, onDelete }: AuditoryLinkP const quiz = useCurrentQuiz(); const { isTestServer } = useDomainDefine(); - const getCreatedTime = (timestamp: number) => { - // Если timestamp в секундах (10 цифр) - if (timestamp.toString().length === 10) { - return new Date(timestamp * 1000).getTime(); - } - // Если timestamp в миллисекундах (13 цифр) - return new Date(timestamp).getTime(); - }; - - const [isLoading, setIsLoading] = useState(() => { - if (!item.created_at) return false; - const now = new Date().getTime(); - const created = getCreatedTime(item.created_at); - const diffInMinutes = (now - created) / (1000 * 60); - console.log('Initial state:', { - created_at: item.created_at, - format: item.created_at.toString().length === 10 ? 'seconds' : 'milliseconds', - now, - created, - diffInMinutes, - isLoading: diffInMinutes < 2 - }); - return diffInMinutes < 2; - }); - - useEffect(() => { - if (!item.created_at) return; - - const now = new Date().getTime(); - const created = getCreatedTime(item.created_at); - const diffInMinutes = (now - created) / (1000 * 60); - - console.log('Effect check:', { - created_at: item.created_at, - format: item.created_at.toString().length === 10 ? 'seconds' : 'milliseconds', - now, - created, - diffInMinutes, - timeDiff: now - created - }); - - if (now - created < 1000) { - console.log('Setting loading to true for new link'); - setIsLoading(true); - } - - if (diffInMinutes < 2) { - const timeLeft = Math.ceil((2 - diffInMinutes) * 60 * 1000); - console.log('Setting timer for:', timeLeft, 'ms'); - const timer = setTimeout(() => { - console.log('Timer finished, setting loading to false'); - setIsLoading(false); - }, timeLeft); - - return () => clearTimeout(timer); - } - }, [item.created_at]); - const handleCopy = (text: string) => { - if (isLoading) return; navigator.clipboard.writeText(text); }; @@ -127,32 +67,11 @@ export const AuditoryLink = ({ utmParams, item, index, onDelete }: AuditoryLinkP - {isLoading ? ( - - ) : ( - handleCopy(linkText)} - > - - - )} + } > diff --git a/src/pages/PersonalizationAI/CopyButton.tsx b/src/pages/PersonalizationAI/CopyButton.tsx new file mode 100644 index 00000000..9bcf0fe6 --- /dev/null +++ b/src/pages/PersonalizationAI/CopyButton.tsx @@ -0,0 +1,161 @@ +import { IconButton, Skeleton, useTheme, Tooltip, ClickAwayListener } from "@mui/material"; +import { useEffect, useState } from "react"; +import CopyIcon from "@/assets/icons/CopyIcon"; +import { useSnackbar } from "notistack"; + +interface CopyButtonProps { + created_at: number; + onCopy: (text: string) => void; + text: string; +} + +export const CopyButton = ({ created_at, onCopy, text }: CopyButtonProps) => { + const theme = useTheme(); + const { enqueueSnackbar } = useSnackbar(); + const [open, setOpen] = useState(false); + const [timeLeft, setTimeLeft] = useState(""); + + const getCreatedTime = (timestamp: number) => { + // Если timestamp в секундах (10 цифр) + if (timestamp.toString().length === 10) { + return new Date(timestamp * 1000).getTime(); + } + // Если timestamp в миллисекундах (13 цифр) + return new Date(timestamp).getTime(); + }; + + const formatTimeLeft = (milliseconds: number) => { + const minutes = Math.floor(milliseconds / (1000 * 60)); + const seconds = Math.floor((milliseconds % (1000 * 60)) / 1000); + return `${minutes}:${seconds.toString().padStart(2, '0')}`; + }; + + const [isLoading, setIsLoading] = useState(() => { + if (!created_at) return false; + const now = new Date().getTime(); + const created = getCreatedTime(created_at); + const diffInMinutes = (now - created) / (1000 * 60); + return diffInMinutes < 2; + }); + + useEffect(() => { + if (!created_at) return; + + const now = new Date().getTime(); + const created = getCreatedTime(created_at); + const diffInMinutes = (now - created) / (1000 * 60); + + if (now - created < 1000) { + setIsLoading(true); + } + + if (diffInMinutes < 2) { + const timeLeft = Math.ceil((2 - diffInMinutes) * 60 * 1000); + setTimeLeft(formatTimeLeft(timeLeft)); + + const timer = setInterval(() => { + const currentTime = new Date().getTime(); + const elapsed = currentTime - created; + const remaining = 2 * 60 * 1000 - elapsed; + + if (remaining <= 0) { + setIsLoading(false); + clearInterval(timer); + return; + } + + setTimeLeft(formatTimeLeft(remaining)); + }, 1000); + + return () => clearInterval(timer); + } + }, [created_at]); + + const handleClick = () => { + if (isLoading) return; + onCopy(text); + enqueueSnackbar("Ссылка успешно скопирована", { variant: "success" }); + }; + + const handleTooltipClose = () => { + setOpen(false); + }; + + const handleTooltipOpen = () => { + setOpen(true); + }; + + if (isLoading) { + return ( + +
+ + + +
+
+ ); + } + + return ( + + + + ); +}; \ No newline at end of file