import { GenerateBtn } from '@/components/sker/generate-btn'; import { Header } from '@/components/sker/header'; import { ImgTab } from '@/components/sker/img-tab'; import { Page } from '@/components/sker/page'; import VideoPlayer from '@/components/sker/video-player/video-player'; import { getTagByName } from '@/lib/api/tags'; import Feather from '@expo/vector-icons/Feather'; import { router, useLocalSearchParams } from 'expo-router'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Image, ScrollView, StyleSheet, Text, TouchableOpacity, View, } from 'react-native'; type TemplateFrame = { id: string; uri: string; avatar?: string; title?: string; titleEn?: string; }; export default function TemplateDetailScreen() { const { id } = useLocalSearchParams<{ id: string }>(); const [looks, setLooks] = useState([]); const [selectedId, setSelectedId] = useState(null); const abortControllerRef = useRef(null); useEffect(() => { if (!id || typeof id !== 'string') { return; } abortControllerRef.current?.abort(); abortControllerRef.current = new AbortController(); const signal = abortControllerRef.current.signal; const hydrateLooks = async () => { try { const templateResponse = await getTagByName(id); if (signal.aborted) return; if (templateResponse?.success && templateResponse.data) { const template = templateResponse.data; const frames: TemplateFrame[] = template.templates.map(it => ({ id: it.id, uri: it.previewUrl, title: it.title, titleEn: it.titleEn, avatar: it.coverImageUrl })); if (signal.aborted) return; setLooks(frames); setSelectedId(frames.find(f => f.id === id)?.id ?? frames[0]?.id ?? template.id); } else { if (signal.aborted) return; } } catch (templateError) { if (signal.aborted) return; console.warn('Failed to fetch template detail:', templateError); } finally { } }; hydrateLooks(); return () => abortControllerRef.current?.abort(); }, [id]); const current = useMemo(() => { if (looks.length === 0) { return null; } if (!selectedId) { return looks[0]; } return looks.find(look => look.id === selectedId) ?? looks[0]; }, [looks, selectedId]); const infoTitle = useMemo(() => { return current?.titleEn ?? current?.title ?? 'Loading template' }, [current]); const handleGenerate = useCallback(() => { if (current?.id) { router.push(`/templates/${current.id}/form`); } }, [current]); return (
{ setSelectedId(id) }} /> {infoTitle} ); } const styles = StyleSheet.create({ canvas: { flex: 1, backgroundColor: '#040404', }, safeArea: { flex: 1, }, body: { flex: 1, }, scrollContent: { paddingHorizontal: 40, paddingBottom: 40, }, loadingState: { flexDirection: 'row', alignItems: 'center', gap: 12, paddingHorizontal: 24, paddingVertical: 8, }, loadingLabel: { fontSize: 13, color: 'rgba(255, 255, 255, 0.7)', }, errorBanner: { marginHorizontal: 24, marginTop: 8, paddingHorizontal: 16, paddingVertical: 10, borderRadius: 16, backgroundColor: 'rgba(255, 94, 94, 0.12)', }, errorText: { color: '#FF8A8A', fontSize: 13, fontWeight: '600', marginBottom: 8, }, retryButton: { backgroundColor: 'rgba(255, 94, 94, 0.2)', paddingHorizontal: 16, paddingVertical: 8, borderRadius: 12, alignSelf: 'flex-start', }, retryLabel: { color: '#FF8A8A', fontSize: 13, fontWeight: '700', }, headerBar: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 24, paddingTop: 8, paddingBottom: 8, gap: 12, }, headerTitle: { flex: 1, textAlign: 'center', fontSize: 18, fontWeight: '600', color: '#FFFFFF', letterSpacing: 0.4, }, headerPlaceholder: { width: 48, height: 48, }, topCarousel: { marginTop: 12, paddingVertical: 8, borderRadius: 22, backgroundColor: 'rgba(255, 255, 255, 0.04)', }, emptyCarousel: { alignItems: 'center', justifyContent: 'center', height: 80, }, emptyCarouselText: { color: 'rgba(255, 255, 255, 0.6)', fontSize: 13, }, carouselContent: { paddingHorizontal: 12, alignItems: 'center', gap: 12, }, previewFrame: { width: 56, height: 56, borderRadius: 18, overflow: 'hidden', backgroundColor: 'rgba(255, 255, 255, 0.08)', }, previewFrameActive: { transform: [{ scale: 1.05 }], }, previewImage: { width: '100%', height: '100%', }, heroStage: { marginTop: 32, borderRadius: 36, backgroundColor: '#111111', overflow: 'hidden', shadowColor: '#000000', shadowOpacity: 0.45, shadowRadius: 32, shadowOffset: { width: 0, height: 18 }, elevation: 24, }, heroImage: { width: '100%', height: 456, borderRadius: 36, }, bottomInfoRow: { flexDirection: 'row', alignItems: 'center', gap: 16, marginTop: 32, }, infoCard: { flex: 1, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 12, borderRadius: 24, gap: 12, }, infoThumbnail: { width: 48, height: 48, borderRadius: 10, marginRight: 0, rotation: 6 }, infoTitle: { fontSize: 14, fontWeight: '600', color: '#FFFFFF', flex: 1, flexShrink: 1, }, generateButton: { width: '100%', height: 56, borderRadius: 28, backgroundColor: '#D1FF00', alignItems: 'center', justifyContent: 'center', flexDirection: 'row', gap: 10, marginTop: 18, }, generateButtonDisabled: { opacity: 0.6, }, generateLabel: { fontSize: 16, fontWeight: '700', color: '#050505', letterSpacing: 0.3, }, });