162 lines
4.9 KiB
TypeScript
162 lines
4.9 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import {
|
|
View,
|
|
Text,
|
|
StyleSheet,
|
|
Pressable,
|
|
StatusBar as RNStatusBar,
|
|
ActivityIndicator,
|
|
} from 'react-native'
|
|
import { StatusBar } from 'expo-status-bar'
|
|
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
import { useRouter, useLocalSearchParams } from 'expo-router'
|
|
|
|
import { LeftArrowIcon } from '@/components/icon'
|
|
import SearchResultsGrid from '@/components/SearchResultsGrid'
|
|
import { useTemplateDetail, useTemplates } from '@/hooks/data'
|
|
|
|
export default function TemplateDetailScreen() {
|
|
const router = useRouter()
|
|
const params = useLocalSearchParams()
|
|
const templateId = params.templateId as string
|
|
|
|
const { data: templateDetail, loading: detailLoading, error: detailError, execute: fetchDetail } = useTemplateDetail()
|
|
const { data: relatedTemplates, loading: relatedLoading, execute: fetchRelated } = useTemplates()
|
|
|
|
const [gridData, setGridData] = useState<any[]>([])
|
|
|
|
useEffect(() => {
|
|
if (templateId) {
|
|
fetchDetail({ id: templateId })
|
|
fetchRelated({ limit: 10 })
|
|
}
|
|
}, [templateId])
|
|
|
|
useEffect(() => {
|
|
if (relatedTemplates?.templates) {
|
|
const formattedData = relatedTemplates.templates
|
|
.filter((template) => template.id !== templateId)
|
|
.map((template, index) => ({
|
|
id: Number(template.id) || index,
|
|
title: template.title,
|
|
image: { uri: template.coverImageUrl },
|
|
height: 200,
|
|
videoUrl: template.previewUrl,
|
|
thumbnailUrl: template.coverImageUrl,
|
|
}))
|
|
setGridData(formattedData)
|
|
}
|
|
}, [relatedTemplates, templateId])
|
|
|
|
if (detailError) {
|
|
return (
|
|
<SafeAreaView style={styles.container} edges={['top']}>
|
|
<StatusBar style="light" />
|
|
<RNStatusBar barStyle="light-content" />
|
|
<View style={styles.header}>
|
|
<Pressable onPress={() => router.back()} style={styles.backButton}>
|
|
<LeftArrowIcon />
|
|
</Pressable>
|
|
</View>
|
|
<View style={styles.errorContainer}>
|
|
<Text style={styles.errorText}>加载失败</Text>
|
|
</View>
|
|
</SafeAreaView>
|
|
)
|
|
}
|
|
|
|
if (detailLoading) {
|
|
return (
|
|
<SafeAreaView style={styles.container} edges={['top']}>
|
|
<StatusBar style="light" />
|
|
<RNStatusBar barStyle="light-content" />
|
|
<View style={styles.header}>
|
|
<Pressable onPress={() => router.back()} style={styles.backButton}>
|
|
<LeftArrowIcon />
|
|
</Pressable>
|
|
</View>
|
|
<View style={styles.loadingContainer}>
|
|
<ActivityIndicator size="large" color="#FFFFFF" />
|
|
</View>
|
|
</SafeAreaView>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<SafeAreaView style={styles.container} edges={['top']}>
|
|
<StatusBar style="light" />
|
|
<RNStatusBar barStyle="light-content" />
|
|
|
|
<View style={styles.header}>
|
|
<Pressable onPress={() => router.back()} style={styles.backButton}>
|
|
<LeftArrowIcon />
|
|
</Pressable>
|
|
</View>
|
|
|
|
<View style={styles.titleSection}>
|
|
<Text style={styles.mainTitle}>
|
|
{templateDetail?.title || ''}
|
|
</Text>
|
|
<Text style={styles.subTitle}>
|
|
{templateDetail?.description || ''}
|
|
</Text>
|
|
</View>
|
|
|
|
{relatedLoading ? (
|
|
<View style={styles.loadingContainer}>
|
|
<ActivityIndicator size="small" color="#FFFFFF" />
|
|
</View>
|
|
) : (
|
|
<SearchResultsGrid results={gridData} />
|
|
)}
|
|
</SafeAreaView>
|
|
)
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: '#090A0B',
|
|
},
|
|
header: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
paddingTop: 12,
|
|
paddingHorizontal: 12,
|
|
paddingBottom: 24,
|
|
},
|
|
backButton: {
|
|
padding: 4,
|
|
},
|
|
titleSection: {
|
|
paddingHorizontal: 12,
|
|
paddingBottom: 24,
|
|
},
|
|
mainTitle: {
|
|
color: '#F5F5F5',
|
|
fontSize: 20,
|
|
fontWeight: '500',
|
|
marginBottom: 4,
|
|
},
|
|
subTitle: {
|
|
color: '#ABABAB',
|
|
fontSize: 14,
|
|
fontWeight: '400',
|
|
},
|
|
loadingContainer: {
|
|
flex: 1,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
errorContainer: {
|
|
flex: 1,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
errorText: {
|
|
color: '#ABABAB',
|
|
fontSize: 16,
|
|
},
|
|
})
|
|
|