import { MatchCard } from "@/components/match-card"; import { ThemedText } from "@/components/themed-text"; import { ThemedView } from "@/components/themed-view"; import { IconSymbol, IconSymbolName } from "@/components/ui/icon-symbol"; import { Colors } from "@/constants/theme"; import { useTheme } from "@/context/ThemeContext"; import { fetchFavorites, removeFavorite } from "@/lib/api"; import { storage } from "@/lib/storage"; import { FavoriteItem, Match } from "@/types/api"; import { Image } from "expo-image"; import { useRouter } from "expo-router"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { ActivityIndicator, FlatList, RefreshControl, ScrollView, StyleSheet, TouchableOpacity, View, } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; type FilterType = "match" | "team" | "player"; interface FilterTab { key: FilterType; label: string; icon: IconSymbolName; } export default function FavoriteScreen() { const { theme } = useTheme(); const { t } = useTranslation(); const insets = useSafeAreaInsets(); const router = useRouter(); const isDark = theme === "dark"; const iconColor = isDark ? Colors.dark.icon : Colors.light.icon; const textColor = isDark ? Colors.dark.text : Colors.light.text; const [activeTab, setActiveTab] = useState("match"); const [favorites, setFavorites] = useState([]); const [loading, setLoading] = useState(false); const [refreshing, setRefreshing] = useState(false); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); const tabs: FilterTab[] = [ { key: "match", label: t("favorites.filter_match"), icon: "football-outline", }, { key: "team", label: t("favorites.filter_team"), icon: "shield-outline", }, { key: "player", label: t("favorites.filter_player"), icon: "person-outline", }, ]; const loadFavorites = async (isRefresh = false) => { if (loading) return; setLoading(true); try { const token = await storage.getAccessToken(); if (!token) { setFavorites([]); setHasMore(false); return; } const currentPage = isRefresh ? 1 : page; const res = await fetchFavorites(activeTab, currentPage); if (isRefresh) { setFavorites(res.list); setHasMore(res.list.length >= 20); // Assuming pageSize 20 } else { setFavorites((prev) => [...prev, ...res.list]); setHasMore(res.list.length >= 20); } if (res.list.length > 0) { setPage(currentPage + 1); } } catch (error) { console.error(error); } finally { setLoading(false); setRefreshing(false); } }; useEffect(() => { setPage(1); setFavorites([]); setHasMore(true); loadFavorites(true); }, [activeTab]); const onRefresh = () => { setRefreshing(true); setPage(1); setHasMore(true); loadFavorites(true); }; const loadMore = () => { if (!loading && hasMore) { loadFavorites(false); } }; const handleUnfavorite = async (type: string, typeId: string) => { try { await removeFavorite({ type, typeId }); setFavorites((prev) => prev.filter((item) => item.typeId !== typeId)); } catch (error) { console.error("Remove favorite failed", error); } }; const renderMatchItem = (item: FavoriteItem) => { const m = item.match; if (!m) return null; // Use current date as placeholder if not provided, or parse eventTime // Assuming m contains necessary fields or we map carefully const mappedMatch: Match = { id: m.id ? m.id.toString() : item.matchId ? item.matchId.toString() : item.typeId, league: m.leagueName || "", time: m.eventTime || "", home: m.eventHomeTeam || "", away: m.eventAwayTeam || "", scoreText: m.eventFinalResult || "0 - 0", fav: true, leagueId: m.leagueKey, sportId: 1, // Default isLive: false, // Provide default }; return ( handleUnfavorite("match", item.typeId)} /> ); }; const renderGenericItem = (item: FavoriteItem) => { let name = ""; let logo = ""; let desc = ""; if (activeTab === "team" && item.team) { name = item.team.name; logo = item.team.logo; } else if (activeTab === "player" && item.player) { name = item.player.name; logo = item.player.photo || item.player.avatar; desc = item.player.teamName; } else { name = t("favorites.unknown"); } return ( {name} {desc ? ( {desc} ) : null} handleUnfavorite(activeTab, item.typeId)} > ); }; return ( {/* Header */} {t("tabs.fav")} {/* Tabs */} {tabs.map((tab) => { const isActive = activeTab === tab.key; return ( setActiveTab(tab.key)} > {tab.label} ); })} {/* Content */} item.id.toString()} renderItem={({ item }) => { if (activeTab === "match") return renderMatchItem(item); return renderGenericItem(item); }} contentContainerStyle={styles.list} refreshControl={ } onEndReached={loadMore} onEndReachedThreshold={0.5} ListFooterComponent={ loading && favorites.length > 0 ? ( ) : null } ListEmptyComponent={ !loading ? ( {t("favorites.no_data")} ) : null } /> ); } const styles = StyleSheet.create({ container: { flex: 1, }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", paddingHorizontal: 20, paddingBottom: 15, }, tabContainer: { flexDirection: "row", paddingHorizontal: 16, paddingBottom: 10, gap: 10, }, tabButton: { flexDirection: "row", alignItems: "center", paddingVertical: 6, paddingHorizontal: 12, borderRadius: 20, borderWidth: 1, gap: 6, }, tabText: { fontSize: 14, fontWeight: "600", }, list: { padding: 16, paddingBottom: 100, }, genericItem: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", padding: 12, marginBottom: 12, borderRadius: 12, borderWidth: 1, }, itemContent: { flexDirection: "row", alignItems: "center", }, empty: { padding: 40, alignItems: "center", }, });