import React, { useState, useEffect } from "react"; import { View, ScrollView, Pressable, ActivityIndicator, RefreshControl, } from "react-native"; import { Text } from "@/components/ui/text"; import { useSirouRouter } from "@sirou/react-native"; import { AppRoutes } from "@/lib/routes"; import { api, newsApi } from "@/lib/api"; import { EmptyState } from "@/components/EmptyState"; import { ScreenWrapper } from "@/components/ScreenWrapper"; import { StandardHeader } from "@/components/StandardHeader"; interface NewsItem { id: string; title: string; content: string; category: "ANNOUNCEMENT" | "UPDATE" | "MAINTENANCE" | "NEWS"; priority: "LOW" | "MEDIUM" | "HIGH"; publishedAt: string; viewCount: number; } function getCategoryColor(category: string) { switch (category) { case "ANNOUNCEMENT": return "bg-amber-500"; case "UPDATE": return "bg-blue-500"; case "MAINTENANCE": return "bg-red-500"; default: return "bg-emerald-500"; } } function getCategoryLabel(category: string) { switch (category) { case "ANNOUNCEMENT": return "ANNOUNCEMENT"; case "UPDATE": return "UPDATE"; case "MAINTENANCE": return "MAINTENANCE"; default: return "NEWS"; } } export default function NewsListScreen() { const nav = useSirouRouter(); const getNewsApi = () => { if (newsApi) return newsApi; return api.news; }; const [allNews, setAllNews] = useState([]); const [loading, setLoading] = useState(true); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); const [loadingMore, setLoadingMore] = useState(false); const [refreshing, setRefreshing] = useState(false); const fetchNews = async (pageNum: number, isRefresh = false) => { try { if (!isRefresh) { pageNum === 1 ? setLoading(true) : setLoadingMore(true); } const service = getNewsApi(); if (!service) throw new Error("News service unavailable"); const response = await service.getAll({ query: { page: pageNum, limit: 10, isPublished: true }, }); const newData = response.data || []; if (isRefresh) { setAllNews(newData); } else { setAllNews((prev) => (pageNum === 1 ? newData : [...prev, ...newData])); } setHasMore(response?.meta?.hasNextPage ?? false); setPage(pageNum); } catch (err) { console.error("[News] Fetch error:", err); } finally { setLoading(false); setLoadingMore(false); setRefreshing(false); } }; useEffect(() => { fetchNews(1); }, []); const onRefresh = () => { setRefreshing(true); fetchNews(1, true); }; const loadMore = () => { if (hasMore && !loadingMore && !loading) { fetchNews(page + 1); } }; if (loading && allNews.length === 0) { return ( ); } return ( } contentContainerStyle={{ paddingBottom: 60 }} onScroll={({ nativeEvent }) => { const isCloseToBottom = nativeEvent.layoutMeasurement.height + nativeEvent.contentOffset.y >= nativeEvent.contentSize.height - 20; if (isCloseToBottom) loadMore(); }} scrollEventThrottle={400} > Latest News {allNews.length > 0 ? ( {allNews.map((item) => ( nav.go("news/[id]", { id: item.id })} > {getCategoryLabel(item.category)} {new Date(item.publishedAt).toLocaleDateString()} {item.title} {item.content} ))} {hasMore && ( {loadingMore ? ( ) : ( Load More )} )} ) : ( )} ); }