import React from "react" import { useFavorites } from "@/features/app-state" import { useStyleTemplatesAdapter as useUnifiedStyleTemplatesAdapter } from "@/features/browser/hooks/use-resources" import { useDraggable } from "@/features/drag-drop" import { StyleTemplatePreview } from "@/features/style-templates/components/style-template-preview" import { StyleTemplate } from "@/features/style-templates/types" import type { ListAdapter, ListItem, PreviewComponentProps } from "../types/list" // Адаптер типа для StyleTemplate чтобы соответствовать ListItem type StyleTemplateListItem = StyleTemplate & ListItem /** * Компонент превью для стилистических шаблонов */ const StyleTemplatePreviewWrapper: React.FC> = ({ item: template, size, viewMode, onClick, onAddToTimeline, }) => { const handleClick = () => { onClick?.(template) } // Используем DragDropManager для перетаскивания const dragProps = useDraggable( "template", () => template, () => ({ url: template.thumbnail || `/style-templates/${template.id}.png`, width: 120, height: 80, }), ) const handleSelect = (_templateId: string) => { // Template selected onAddToTimeline?.(template) } // Для стилистических шаблонов StyleTemplatePreview ожидает другие пропсы const previewSize = typeof size === "number" ? size : size.width const previewWidth = typeof size === "number" ? size : size.width const previewHeight = typeof size === "number" ? size : size.height if (viewMode === "list") { return (
{/* Template preview thumbnail */}
{template.thumbnail ? ( {typeof ) : (
{(typeof template.name === "string" ? template.name : template.name.ru).substring(0, 2).toUpperCase()}
)} {/* Animation indicator */} {template.hasAnimation &&
}
{/* Template Info */}
{typeof template.name === "string" ? template.name : template.name.ru}
{(typeof template.description === "string" ? template.description : template.description?.ru) || `${template.category} • ${template.style}`}
{/* Category */}
{template.category}
{/* Style */}
{template.style}
{/* Duration */}
{template.duration}s
{/* Features */}
{template.hasText &&
} {template.hasAnimation &&
}
) } // Thumbnails mode - use the original StyleTemplatePreview component return (
) } /** * Хук для создания адаптера стилистических шаблонов * Мигрирован на унифицированную систему browser-хуков */ export function useStyleTemplatesAdapter(): ListAdapter { const { isItemFavorite } = useFavorites() // Используем унифицированный адаптер с конфигурацией для стилистических шаблонов const { items, loading, error, stats, ...restAdapter } = useUnifiedStyleTemplatesAdapter({ PreviewComponent: StyleTemplatePreviewWrapper, customHandlers: { getSortValue: (template: StyleTemplate, sortBy: string) => { switch (sortBy) { case "name": return (typeof template.name === "string" ? template.name : template.name.ru).toLowerCase() case "category": return template.category.toLowerCase() case "style": return template.style.toLowerCase() case "duration": return template.duration case "aspectRatio": return template.aspectRatio default: return (typeof template.name === "string" ? template.name : template.name.ru).toLowerCase() } }, getSearchableText: (template: StyleTemplate) => { const texts: string[] = [ typeof template.name === "string" ? template.name : template.name.ru, typeof template.name === "string" ? "" : template.name.en, typeof template.description === "string" ? template.description : template.description?.ru || "", typeof template.description === "string" ? "" : template.description?.en || "", template.category, template.style, template.aspectRatio, ...(Array.isArray(template.tags) ? template.tags : template.tags?.ru || []), ...(Array.isArray(template.tags) ? [] : template.tags?.en || []), ] return texts.filter(Boolean) }, getGroupValue: (template: StyleTemplate, groupBy: string) => { switch (groupBy) { case "category": return template.category || "other" case "style": return template.style || "other" case "aspectRatio": return template.aspectRatio || "16:9" case "duration": if (template.duration <= 3) return "Короткие (≤3с)" if (template.duration <= 10) return "Средние (3-10с)" return "Длинные (>10с)" case "features": if (template.hasText && template.hasAnimation) return "Текст + анимация" if (template.hasText) return "С текстом" if (template.hasAnimation) return "С анимацией" return "Базовые" default: return "" } }, matchesFilter: (template: StyleTemplate, filterType: string) => { if (filterType === "all") return true // Фильтрация по категории if (["intro", "outro", "lower-third", "title", "transition", "overlay"].includes(filterType)) { return template.category === filterType } // Фильтрация по стилю if (["modern", "vintage", "minimal", "corporate", "creative", "cinematic"].includes(filterType)) { return template.style === filterType } // Фильтрация по соотношению сторон if (["16:9", "9:16", "1:1"].includes(filterType)) { return template.aspectRatio === filterType } // Фильтрация по наличию текста if (filterType === "hasText") { return template.hasText } // Фильтрация по наличию анимации if (filterType === "hasAnimation") { return template.hasAnimation } return true }, }, }) // Извлекаем только поля, соответствующие ListAdapter const listAdapter: ListAdapter = { useData: () => ({ items: items as StyleTemplateListItem[], loading, error: error ? new Error(error) : null, }), PreviewComponent: StyleTemplatePreviewWrapper as unknown as React.ComponentType< PreviewComponentProps >, getSortValue: restAdapter.getSortValue, getSearchableText: restAdapter.getSearchableText, getGroupValue: restAdapter.getGroupValue, matchesFilter: restAdapter.matchesFilter, importHandlers: restAdapter.importHandlers, favoriteType: restAdapter.favoriteType, // Проверка избранного (переопределяем) isFavorite: (template: StyleTemplateListItem) => isItemFavorite( { id: template.id, path: "", name: typeof template.name === "string" ? template.name : (template.name as any).ru, }, "template", ), } return listAdapter }