diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 0c7cf9d..b6d010b 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -388,8 +388,8 @@ export default function HomeScreen() { away: item.event_away_team, homeTeamName: item.event_home_team, awayTeamName: item.event_away_team, - homeTeamLogo: item.home_team_logo, - awayTeamLogo: item.away_team_logo, + homeTeamLogo: item.home_team_logo || "", + awayTeamLogo: item.away_team_logo || "", scoreText: item.event_halftime_result || "0 - 0", fav: false, sportId: sportId, diff --git a/app/live-detail/[id].tsx b/app/live-detail/[id].tsx index e661e01..e5d9ed9 100644 --- a/app/live-detail/[id].tsx +++ b/app/live-detail/[id].tsx @@ -5,14 +5,17 @@ import { LiveScoreHeader } from "@/components/live-detail/live-score-header"; import { OddsCard } from "@/components/live-detail/odds-card"; import { OtherInfoCard } from "@/components/live-detail/other-info-card"; import { StatsCard } from "@/components/live-detail/stats-card"; +import { BasketballOverallStats } from "@/components/match-detail/basketball/basketball-overall-stats"; +import { BasketballScoreTable } from "@/components/match-detail/basketball/basketball-score-table"; +import { BasketballStats } from "@/components/match-detail/basketball/basketball-stats"; import { ThemedText } from "@/components/themed-text"; import { ThemedView } from "@/components/themed-view"; import { Colors } from "@/constants/theme"; import { useTheme } from "@/context/ThemeContext"; import { fetchLiveScore } from "@/lib/api"; -import { LiveScoreMatch } from "@/types/api"; +import { LiveScoreMatch, MatchDetailData } from "@/types/api"; import { useLocalSearchParams } from "expo-router"; -import React, { useEffect, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { ActivityIndicator, @@ -36,11 +39,72 @@ export default function LiveDetailScreen() { const [loading, setLoading] = useState(true); const [match, setMatch] = useState(null); - const [activeTab, setActiveTab] = useState("detail"); // Default to detail to show all data + const [activeTab, setActiveTab] = useState("detail"); + + const convertToMatchDetailData = useMemo((): MatchDetailData | null => { + if (!match) return null; + + return { + events: [], + match: { + ID: 0, + CreatedAt: "", + UpdatedAt: "", + DeletedAt: null, + eventKey: match.event_key.toString(), + eventDate: match.event_date, + eventTime: match.event_time, + eventHomeTeam: match.event_home_team, + homeTeamKey: match.home_team_key.toString(), + homeTeamLogo: match.home_team_logo || "", + eventAwayTeam: match.event_away_team, + awayTeamKey: match.away_team_key.toString(), + awayTeamLogo: match.away_team_logo || "", + eventHalftimeResult: match.event_halftime_result || "", + eventFinalResult: match.event_final_result, + eventFtResult: "", + eventPenaltyResult: "", + eventStatus: match.event_status, + countryName: match.country_name, + leagueName: match.league_name, + leagueKey: match.league_key.toString(), + leagueRound: match.league_round, + leagueSeason: match.league_season, + eventLive: match.event_live, + eventStadium: "", + eventReferee: "", + eventCountryKey: match.event_country_key?.toString() || "", + leagueLogo: match.league_logo || "", + countryLogo: match.country_logo || "", + eventHomeFormation: "", + eventAwayFormation: "", + fkStageKey: "", + stageName: "", + leagueGroup: "", + sportId: parseInt(sport_id || "1"), + eventQuarter: match.event_quarter || "", + eventSet: "", + eventType: "", + eventToss: "", + eventManOfMatch: "", + scores: match.scores, + stats: match.statistics, + players: match.player_statistics ? { + home_team: (match.player_statistics.home_team || []).map(p => ({ + ...p, + player_oncourt: p.player_oncourt || undefined, + })), + away_team: (match.player_statistics.away_team || []).map(p => ({ + ...p, + player_oncourt: p.player_oncourt || undefined, + })), + } : undefined, + }, + }; + }, [match, sport_id]); useEffect(() => { loadLiveDetail(); - // 设置每 15 秒更新一次直播比分 const timer = setInterval(() => { refreshLiveDetail(); }, 15000); @@ -60,14 +124,12 @@ export default function LiveDetailScreen() { const refreshLiveDetail = async () => { try { - // Fetch live scores for the league const sportId = parseInt(sport_id || "1"); const leagueId = parseInt(league_id || "0"); const liveData = await fetchLiveScore(sportId, leagueId); if (liveData && Array.isArray(liveData)) { - // Find the specific match const found = liveData.find((m) => m.event_key.toString() === id); console.log("found", JSON.stringify(found, null, 2)); if (found) { @@ -99,7 +161,37 @@ export default function LiveDetailScreen() { } const renderTabContent = () => { + if (!match) return null; + const numericSportId = parseInt(sport_id || "1"); + + if (numericSportId === 2 && convertToMatchDetailData) { + switch (activeTab) { + case "stats": + return ; + case "overall": + return ; + case "odds": + return ( + + ); + case "detail": + return ( + <> + + + ); + default: + return ( + + + {t("detail.empty_stats")} + + + ); + } + } + switch (activeTab) { case "stats": return ; @@ -140,6 +232,7 @@ export default function LiveDetailScreen() { activeTab={activeTab} onTabChange={setActiveTab} isDark={isDark} + sportId={parseInt(sport_id || "1")} /> {renderTabContent()} diff --git a/components/live-detail/live-match-tabs.tsx b/components/live-detail/live-match-tabs.tsx index e3eccf5..c4e9359 100644 --- a/components/live-detail/live-match-tabs.tsx +++ b/components/live-detail/live-match-tabs.tsx @@ -8,31 +8,53 @@ interface LiveMatchTabsProps { activeTab: string; onTabChange: (tab: string) => void; isDark: boolean; + sportId?: number; } export function LiveMatchTabs({ activeTab, onTabChange, isDark, + sportId = 1, }: LiveMatchTabsProps) { const { t } = useTranslation(); const containerBg = isDark ? "#121212" : "#F5F5F5"; - const tabs = [ - { - id: "detail", - label: t("detail.tabs.info"), - icon: "document-text-outline", - }, - { id: "stats", label: t("detail.tabs.stats"), icon: "stats-chart-outline" }, - { id: "odds", label: t("detail.tabs.odds"), icon: "cash-outline" }, - { id: "lineup", label: t("detail.tabs.lineup"), icon: "shirt-outline" }, - { - id: "analysis", - label: t("detail.tabs.analysis"), - icon: "pie-chart-outline", - }, - ]; + const getTabs = () => { + if (sportId === 2) { + return [ + { + id: "detail", + label: t("detail.tabs.info"), + icon: "document-text-outline", + }, + { id: "stats", label: t("detail.tabs.stats"), icon: "stats-chart-outline" }, + { + id: "overall", + label: t("detail.tabs.overall"), + icon: "bar-chart-outline", + }, + { id: "odds", label: t("detail.tabs.odds"), icon: "cash-outline" }, + ]; + } + return [ + { + id: "detail", + label: t("detail.tabs.info"), + icon: "document-text-outline", + }, + { id: "stats", label: t("detail.tabs.stats"), icon: "stats-chart-outline" }, + { id: "odds", label: t("detail.tabs.odds"), icon: "cash-outline" }, + { id: "lineup", label: t("detail.tabs.lineup"), icon: "shirt-outline" }, + { + id: "analysis", + label: t("detail.tabs.analysis"), + icon: "pie-chart-outline", + }, + ]; + }; + + const tabs = getTabs(); return ( diff --git a/types/api.ts b/types/api.ts index c31bfe2..f8a84d3 100644 --- a/types/api.ts +++ b/types/api.ts @@ -52,10 +52,10 @@ export interface LiveScoreMatch { event_time: string; event_home_team: string; home_team_key: number; - home_team_logo: string; + home_team_logo: string | null; event_away_team: string; away_team_key: number; - away_team_logo: string; + away_team_logo: string | null; event_final_result: string; event_halftime_result: string; event_status: string; @@ -68,6 +68,7 @@ export interface LiveScoreMatch { country_name: string; country_logo: string; event_country_key: number; + event_quarter?: string; // Tennis specific event_first_player?: string; event_first_player_logo?: string; @@ -75,7 +76,12 @@ export interface LiveScoreMatch { event_second_player_logo?: string; event_serve?: string; pointbypoint?: any[]; - scores?: any[]; // LiveScoreMatch uses array for scores, Match uses string + scores?: any[] | { + "1stQuarter"?: Array<{ score_home: string; score_away: string }>; + "2ndQuarter"?: Array<{ score_home: string; score_away: string }>; + "3rdQuarter"?: Array<{ score_home: string; score_away: string }>; + "4thQuarter"?: Array<{ score_home: string; score_away: string }>; + }; goalscorers?: { time: string; home_scorer: string; @@ -112,7 +118,64 @@ export interface LiveScoreMatch { info_time: string; score: string; }[]; - lineups?: unknown; + lineups?: { + home_team?: { + starting_lineups?: Array<{ player: string; player_id: number }>; + substitutes?: Array<{ player: string; player_id: number }>; + }; + away_team?: { + starting_lineups?: Array<{ player: string; player_id: number }>; + substitutes?: Array<{ player: string; player_id: number }>; + }; + }; + player_statistics?: { + home_team?: Array<{ + player: string; + player_id: number; + player_position?: string; + player_minutes?: string; + player_points?: string; + player_total_rebounds?: string; + player_offence_rebounds?: string; + player_defense_rebounds?: string; + player_assists?: string; + player_steals?: string; + player_blocks?: string; + player_turnovers?: string; + player_personal_fouls?: string; + player_plus_minus?: string; + player_field_goals_made?: string; + player_field_goals_attempts?: string; + player_threepoint_goals_made?: string; + player_threepoint_goals_attempts?: string; + player_freethrows_goals_made?: string; + player_freethrows_goals_attempts?: string; + player_oncourt?: string | null; + }>; + away_team?: Array<{ + player: string; + player_id: number; + player_position?: string; + player_minutes?: string; + player_points?: string; + player_total_rebounds?: string; + player_offence_rebounds?: string; + player_defense_rebounds?: string; + player_assists?: string; + player_steals?: string; + player_blocks?: string; + player_turnovers?: string; + player_personal_fouls?: string; + player_plus_minus?: string; + player_field_goals_made?: string; + player_field_goals_attempts?: string; + player_threepoint_goals_made?: string; + player_threepoint_goals_attempts?: string; + player_freethrows_goals_made?: string; + player_freethrows_goals_attempts?: string; + player_oncourt?: string | null; + }>; + }; statistics?: { type: string; home: string;