fitst commit
This commit is contained in:
125
screens/announcements/ui/AnnouncementDetail.tsx
Normal file
125
screens/announcements/ui/AnnouncementDetail.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import BottomSheet, { BottomSheetScrollView } from '@gorhom/bottom-sheet';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { ResizeMode, Video } from 'expo-av';
|
||||
import React, { useMemo, useRef } from 'react';
|
||||
import { Dimensions, Image, ScrollView, StyleSheet, Text, View } from 'react-native';
|
||||
import { announcement_api } from '../lib/api';
|
||||
|
||||
const { width, height } = Dimensions.get('window');
|
||||
|
||||
export default function AnnouncementDetailSheet({ id }: { id: number }) {
|
||||
const bottomSheetRef = useRef<BottomSheet>(null);
|
||||
|
||||
// Sheet sizes
|
||||
const snapPoints = useMemo(() => [height * 0.3, height * 0.7], []);
|
||||
|
||||
const { data, isLoading, isError } = useQuery({
|
||||
queryKey: ['announcement_detail', id],
|
||||
queryFn: () => announcement_api.detail(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
const announcement = data?.data?.data;
|
||||
const files = announcement?.files || [];
|
||||
|
||||
return (
|
||||
<BottomSheet
|
||||
ref={bottomSheetRef}
|
||||
index={0}
|
||||
snapPoints={snapPoints}
|
||||
handleIndicatorStyle={{ backgroundColor: '#94a3b8' }}
|
||||
backgroundStyle={{ backgroundColor: '#0f172a', borderRadius: 24 }}
|
||||
>
|
||||
<BottomSheetScrollView contentContainerStyle={styles.contentContainer}>
|
||||
{isLoading && <Text style={styles.loading}>Yuklanmoqda...</Text>}
|
||||
{isError && <Text style={styles.error}>Xatolik yuz berdi</Text>}
|
||||
|
||||
{announcement && (
|
||||
<>
|
||||
{/* Carousel */}
|
||||
{files.length > 0 && (
|
||||
<ScrollView
|
||||
horizontal
|
||||
pagingEnabled
|
||||
showsHorizontalScrollIndicator={false}
|
||||
style={styles.carousel}
|
||||
>
|
||||
{files.map((file) => {
|
||||
const isVideo = file.file?.endsWith('.mp4');
|
||||
return (
|
||||
<View key={file.id} style={styles.mediaContainer}>
|
||||
{isVideo ? (
|
||||
<Video
|
||||
source={{ uri: file.file }}
|
||||
style={styles.media}
|
||||
useNativeControls
|
||||
resizeMode={ResizeMode.CONTAIN}
|
||||
/>
|
||||
) : (
|
||||
<Image source={{ uri: file.file }} style={styles.media} />
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</ScrollView>
|
||||
)}
|
||||
|
||||
{/* Title */}
|
||||
<Text style={styles.title}>{announcement.title}</Text>
|
||||
|
||||
{/* Meta */}
|
||||
<View style={styles.metaRow}>
|
||||
<View style={styles.metaItem}>
|
||||
<Ionicons name="calendar-outline" size={16} color="#94a3b8" />
|
||||
<Text style={styles.metaText}>
|
||||
{new Date(announcement.created_at).toLocaleDateString()}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.metaItem}>
|
||||
<Ionicons name="eye-outline" size={16} color="#94a3b8" />
|
||||
<Text style={styles.metaText}>{announcement.total_view_count} ko'rildi</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Status */}
|
||||
{/* <View style={styles.statusBadge}>
|
||||
<Text style={styles.statusText}>
|
||||
{announcement.status === 'pending' && 'Kutilmoqda'}
|
||||
{announcement.status === 'paid' && "To'langan"}
|
||||
{announcement.status === 'verified' && 'Tasdiqlangan'}
|
||||
{announcement.status === 'canceled' && 'Bekor qilingan'}
|
||||
</Text>
|
||||
</View> */}
|
||||
|
||||
{/* Description */}
|
||||
<Text style={styles.desc}>{announcement.description}</Text>
|
||||
</>
|
||||
)}
|
||||
</BottomSheetScrollView>
|
||||
</BottomSheet>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
contentContainer: { padding: 20, gap: 12 },
|
||||
carousel: { marginBottom: 12 },
|
||||
mediaContainer: { width: width - 40, height: 200, marginRight: 12 },
|
||||
media: { width: '100%', height: '100%', borderRadius: 16 },
|
||||
title: { fontSize: 18, fontWeight: '700', color: '#f1f5f9' },
|
||||
metaRow: { flexDirection: 'row', gap: 16, marginVertical: 8 },
|
||||
metaItem: { flexDirection: 'row', alignItems: 'center', gap: 6 },
|
||||
metaText: { color: '#94a3b8', fontSize: 14 },
|
||||
statusBadge: {
|
||||
alignSelf: 'flex-start',
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 6,
|
||||
borderRadius: 12,
|
||||
backgroundColor: '#2563eb',
|
||||
marginBottom: 12,
|
||||
},
|
||||
statusText: { color: '#f1f5f9', fontWeight: '600' },
|
||||
desc: { color: '#cbd5f5', fontSize: 14, lineHeight: 20 },
|
||||
loading: { color: '#cbd5f5', fontSize: 16 },
|
||||
error: { color: '#ef4444', fontSize: 16 },
|
||||
});
|
||||
Reference in New Issue
Block a user