expo-duooomi-app/app/searchResults.tsx

183 lines
5.5 KiB
TypeScript

import { useState, useEffect } from 'react'
import {
View,
Text,
StyleSheet,
TextInput,
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, CloseIcon } from '@/components/icon'
import SearchResultsGrid from '@/components/SearchResultsGrid'
import { useTemplates } from '@/hooks/data/use-templates'
export default function SearchResultsScreen() {
const router = useRouter()
const params = useLocalSearchParams()
const [searchText, setSearchText] = useState((params.q as string) || '')
const { execute, data, loading } = useTemplates()
useEffect(() => {
if (searchText) {
execute({ search: searchText })
}
}, [searchText])
const searchResults = data?.templates.map((template) => ({
id: parseInt(template.id),
title: template.title,
image: { uri: template.coverImageUrl },
height: template.aspectRatio === '9:16' ? 236 : 131,
videoUrl: template.previewUrl,
thumbnailUrl: template.coverImageUrl,
})) || []
return (
<SafeAreaView style={styles.container} edges={['top']}>
<StatusBar style="light" />
<RNStatusBar barStyle="light-content" />
{/* Top Bar with Search */}
<View style={styles.topBar}>
<Pressable
onPress={() => router.back()}
>
<LeftArrowIcon />
</Pressable>
<Pressable
style={styles.searchInputContainer}
onPress={() => {
router.push({
pathname: '/searchTemplate',
params: { q: searchText, focus: 'true' },
})
}}
>
<TextInput
style={styles.searchInput}
value={searchText}
onChangeText={setSearchText}
placeholder="搜索"
placeholderTextColor="#ABABAB"
underlineColorAndroid="transparent"
editable={false}
pointerEvents="none"
/>
{searchText.length > 0 && (
<Pressable
onPress={(e) => {
e.stopPropagation()
router.push({
pathname: '/searchTemplate',
params: { q: '', focus: 'true' },
})
}}
style={styles.clearButton}
>
<CloseIcon />
</Pressable>
)}
</Pressable>
<Pressable style={styles.searchButton}>
<Text style={styles.searchButtonText}></Text>
</Pressable>
</View>
{/* 搜索结果网格 */}
{loading ? (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#FFFFFF" />
</View>
) : searchResults.length === 0 ? (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}></Text>
<Text style={styles.emptySubText}>使</Text>
</View>
) : (
<SearchResultsGrid results={searchResults} />
)}
</SafeAreaView>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#090A0B',
},
topBar: {
height: 44,
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 12,
marginTop: 8,
marginBottom: 12,
},
searchInputContainer: {
flex: 1,
marginLeft: 4,
marginRight: 12,
position: 'relative',
height: 40,
},
searchInput: {
flex: 1,
color: '#F5F5F5',
fontSize: 14,
height: 40,
paddingVertical: 8,
paddingLeft: 12,
paddingRight: 36,
borderWidth: 0,
borderColor: 'transparent',
borderRadius: 100,
backgroundColor: '#16181B',
},
clearButton: {
position: 'absolute',
right: 8,
top: 0,
bottom: 0,
justifyContent: 'center',
alignItems: 'center',
padding: 4,
},
searchButton: {
paddingHorizontal: 0,
paddingVertical: 8,
},
searchButtonText: {
color: '#F5F5F5',
fontSize: 14,
fontWeight: '500',
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
emptyContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 24,
},
emptyText: {
color: '#F5F5F5',
fontSize: 16,
fontWeight: '500',
marginBottom: 8,
},
emptySubText: {
color: '#ABABAB',
fontSize: 14,
fontWeight: '400',
},
})