import { Play } from "lucide-react" import { useCallback, useMemo, useState } from "react" import { useTranslation } from "react-i18next" import { ApplyButton } from "@/features" import { AddMediaButton } from "@/features/browser/components/layout/add-media-button" import { FavoriteButton } from "@/features/browser/components/layout/favorite-button" import { useResources } from "@/features/resources" import { StyleTemplateResource } from "@/features/resources/types" import { StyleTemplate } from "../types" interface StyleTemplatePreviewProps { template: StyleTemplate size: number onSelect: (templateId: string) => void previewWidth: number previewHeight: number } /** * Компонент превью стилистического шаблона * Отображает миниатюру, название, длительность и индикаторы функций */ export function StyleTemplatePreview({ template, size, onSelect, previewWidth, previewHeight, }: StyleTemplatePreviewProps): React.ReactElement { const { t, i18n } = useTranslation() const [isHovered, setIsHovered] = useState(false) const { isStyleTemplateAdded } = useResources() // Получаем текущий язык const currentLanguage = (i18n.language || "ru") as "ru" | "en" // Проверяем, добавлен ли шаблон в ресурсы const isAdded = useMemo(() => isStyleTemplateAdded(template), [isStyleTemplateAdded, template]) // Делаем превью квадратными, как в Effects const width = previewWidth ?? size const height = previewHeight ?? (size * 9) / 16 // Получаем локализованное название категории const getCategoryName = useCallback( (category: string) => { const categoryMap: Record = { intro: t("styleTemplates.categories.intro", "Интро"), outro: t("styleTemplates.categories.outro", "Концовка"), "lower-third": t("styleTemplates.categories.lowerThird", "Нижняя треть"), title: t("styleTemplates.categories.title", "Заголовок"), transition: t("styleTemplates.categories.transition", "Переход"), overlay: t("styleTemplates.categories.overlay", "Наложение"), } return categoryMap[category] || category }, [t], ) // Получаем локализованное название стиля const getStyleName = useCallback( (style: string) => { const styleMap: Record = { modern: t("styleTemplates.styles.modern", "Современный"), vintage: t("styleTemplates.styles.vintage", "Винтаж"), minimal: t("styleTemplates.styles.minimal", "Минимализм"), corporate: t("styleTemplates.styles.corporate", "Корпоративный"), creative: t("styleTemplates.styles.creative", "Креативный"), cinematic: t("styleTemplates.styles.cinematic", "Кинематографический"), } return styleMap[style] || style }, [t], ) const handlePreview = useCallback( (e: React.MouseEvent) => { e.stopPropagation() onSelect(template.id) }, [onSelect, template.id], ) const handleClick = useCallback(() => { // Only trigger preview, don't automatically add to resources onSelect(template.id) }, [onSelect, template.id]) return (
{/* Контейнер превью шаблона */}
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} onClick={handleClick} > {template.thumbnail ? ( {template.name[currentLanguage]} ) : ( // Заглушка если нет превью
{getCategoryName(template.category)}
)} {/* Кнопка воспроизведения при наведении */} {isHovered && template.previewVideo && (
)} {/* Индикаторы стиля и категории */}
{getStyleName(template.style).slice(0, 3).toUpperCase()}
{getCategoryName(template.category).slice(0, 3).toUpperCase()}
{/* Индикатор длительности */}
{template.duration.toFixed(1)}s
{/* Кнопка избранного */} {/* Кнопка применения шаблона */} {template && ( )} {/* Кнопка добавления в ресурсы */}
{/* Название шаблона */}
{template.name[currentLanguage]}
) }