为比赛和球队添加收藏功能,更新状态检查和切换逻辑
This commit is contained in:
@@ -38,6 +38,11 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) {
|
||||
const [isFav, setIsFav] = useState(false);
|
||||
const [favLoading, setFavLoading] = useState(false);
|
||||
|
||||
const [isHomeFav, setIsHomeFav] = useState(false);
|
||||
const [isAwayFav, setIsAwayFav] = useState(false);
|
||||
const [homeFavLoading, setHomeFavLoading] = useState(false);
|
||||
const [awayFavLoading, setAwayFavLoading] = useState(false);
|
||||
|
||||
// 检查收藏状态
|
||||
React.useEffect(() => {
|
||||
const loadFavStatus = async () => {
|
||||
@@ -51,6 +56,36 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) {
|
||||
loadFavStatus();
|
||||
}, [match.event_key]);
|
||||
|
||||
// 检查主队收藏状态
|
||||
React.useEffect(() => {
|
||||
const loadHomeFav = async () => {
|
||||
try {
|
||||
const res = await checkFavorite("team", match.home_team_key.toString());
|
||||
setIsHomeFav(res.isFavorite);
|
||||
} catch (error) {
|
||||
console.error("Check home team favorite status error:", error);
|
||||
}
|
||||
};
|
||||
if (match.home_team_key) {
|
||||
loadHomeFav();
|
||||
}
|
||||
}, [match.home_team_key]);
|
||||
|
||||
// 检查客队收藏状态
|
||||
React.useEffect(() => {
|
||||
const loadAwayFav = async () => {
|
||||
try {
|
||||
const res = await checkFavorite("team", match.away_team_key.toString());
|
||||
setIsAwayFav(res.isFavorite);
|
||||
} catch (error) {
|
||||
console.error("Check away team favorite status error:", error);
|
||||
}
|
||||
};
|
||||
if (match.away_team_key) {
|
||||
loadAwayFav();
|
||||
}
|
||||
}, [match.away_team_key]);
|
||||
|
||||
const toggleFavorite = async () => {
|
||||
if (favLoading) return;
|
||||
setFavLoading(true);
|
||||
@@ -76,6 +111,38 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) {
|
||||
setFavLoading(false);
|
||||
}
|
||||
};
|
||||
const toggleTeamFavorite = async (teamKey: number, isHome: boolean) => {
|
||||
const isTeamFav = isHome ? isHomeFav : isAwayFav;
|
||||
const setLoading = isHome ? setHomeFavLoading : setAwayFavLoading;
|
||||
const setFav = isHome ? setIsHomeFav : setIsAwayFav;
|
||||
const loading = isHome ? homeFavLoading : awayFavLoading;
|
||||
|
||||
if (loading) return;
|
||||
setLoading(true);
|
||||
|
||||
const newFavState = !isTeamFav;
|
||||
try {
|
||||
if (newFavState) {
|
||||
await addFavorite({
|
||||
teamId: teamKey,
|
||||
type: "team",
|
||||
typeId: teamKey.toString(),
|
||||
notify: true,
|
||||
});
|
||||
} else {
|
||||
await removeFavorite({
|
||||
type: "team",
|
||||
typeId: teamKey.toString(),
|
||||
});
|
||||
}
|
||||
setFav(newFavState);
|
||||
} catch (error) {
|
||||
console.error("Toggle team favorite error:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const lastServerMatchRef = React.useRef(
|
||||
`${match.event_status}-${match.event_time}`
|
||||
);
|
||||
@@ -163,11 +230,24 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) {
|
||||
{/* Score Section */}
|
||||
<View style={styles.scoreRow}>
|
||||
<View style={styles.teamInfo}>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
source={{ uri: match.home_team_logo }}
|
||||
style={styles.teamLogo}
|
||||
/>
|
||||
<View style={styles.teamLogoRow}>
|
||||
<TouchableOpacity
|
||||
onPress={() => toggleTeamFavorite(match.home_team_key, true)}
|
||||
disabled={homeFavLoading}
|
||||
style={styles.starBtnLeft}
|
||||
>
|
||||
<IconSymbol
|
||||
name={isHomeFav ? "star" : "star-outline"}
|
||||
size={20}
|
||||
color={isHomeFav ? "#FFD700" : "rgba(255,255,255,0.5)"}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
source={{ uri: match.home_team_logo }}
|
||||
style={styles.teamLogo}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<ThemedText style={styles.teamName} numberOfLines={2}>
|
||||
{match.event_home_team}
|
||||
@@ -202,11 +282,24 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) {
|
||||
</View>
|
||||
|
||||
<View style={styles.teamInfo}>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
source={{ uri: match.away_team_logo }}
|
||||
style={styles.teamLogo}
|
||||
/>
|
||||
<View style={styles.teamLogoRow}>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
source={{ uri: match.away_team_logo }}
|
||||
style={styles.teamLogo}
|
||||
/>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
onPress={() => toggleTeamFavorite(match.away_team_key, false)}
|
||||
disabled={awayFavLoading}
|
||||
style={styles.starBtnRight}
|
||||
>
|
||||
<IconSymbol
|
||||
name={isAwayFav ? "star" : "star-outline"}
|
||||
size={20}
|
||||
color={isAwayFav ? "#FFD700" : "rgba(255,255,255,0.5)"}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<ThemedText style={styles.teamName} numberOfLines={2}>
|
||||
{match.event_away_team}
|
||||
@@ -261,13 +354,26 @@ const styles = StyleSheet.create({
|
||||
alignItems: "center",
|
||||
width: "30%",
|
||||
},
|
||||
teamLogoRow: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
marginBottom: 10,
|
||||
},
|
||||
logoContainer: {
|
||||
width: 70,
|
||||
height: 70,
|
||||
marginBottom: 10,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
},
|
||||
starBtnLeft: {
|
||||
padding: 8,
|
||||
marginRight: -4,
|
||||
},
|
||||
starBtnRight: {
|
||||
padding: 8,
|
||||
marginLeft: -4,
|
||||
},
|
||||
teamLogo: {
|
||||
width: 60,
|
||||
height: 60,
|
||||
|
||||
@@ -22,14 +22,19 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
|
||||
const [isFav, setIsFav] = useState(false);
|
||||
const [favLoading, setFavLoading] = useState(false);
|
||||
|
||||
// 检查收藏状态
|
||||
const [isHomeFav, setIsHomeFav] = useState(false);
|
||||
const [isAwayFav, setIsAwayFav] = useState(false);
|
||||
const [homeFavLoading, setHomeFavLoading] = useState(false);
|
||||
const [awayFavLoading, setAwayFavLoading] = useState(false);
|
||||
|
||||
// 检查比赛收藏状态
|
||||
React.useEffect(() => {
|
||||
const loadFavStatus = async () => {
|
||||
try {
|
||||
const res = await checkFavorite("match", match.eventKey.toString());
|
||||
setIsFav(res.isFavorite);
|
||||
} catch (error) {
|
||||
console.error("Check favorite status error:", error);
|
||||
console.error("Check match favorite status error:", error);
|
||||
}
|
||||
};
|
||||
if (match.eventKey) {
|
||||
@@ -37,6 +42,36 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
|
||||
}
|
||||
}, [match.eventKey]);
|
||||
|
||||
// 检查主队收藏状态
|
||||
React.useEffect(() => {
|
||||
const loadHomeFav = async () => {
|
||||
try {
|
||||
const res = await checkFavorite("team", match.homeTeamKey.toString());
|
||||
setIsHomeFav(res.isFavorite);
|
||||
} catch (error) {
|
||||
console.error("Check home team favorite status error:", error);
|
||||
}
|
||||
};
|
||||
if (match.homeTeamKey) {
|
||||
loadHomeFav();
|
||||
}
|
||||
}, [match.homeTeamKey]);
|
||||
|
||||
// 检查客队收藏状态
|
||||
React.useEffect(() => {
|
||||
const loadAwayFav = async () => {
|
||||
try {
|
||||
const res = await checkFavorite("team", match.awayTeamKey.toString());
|
||||
setIsAwayFav(res.isFavorite);
|
||||
} catch (error) {
|
||||
console.error("Check away team favorite status error:", error);
|
||||
}
|
||||
};
|
||||
if (match.awayTeamKey) {
|
||||
loadAwayFav();
|
||||
}
|
||||
}, [match.awayTeamKey]);
|
||||
|
||||
const toggleFavorite = async () => {
|
||||
if (favLoading) return;
|
||||
setFavLoading(true);
|
||||
@@ -63,6 +98,38 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
|
||||
}
|
||||
};
|
||||
|
||||
const toggleTeamFavorite = async (teamKey: string, isHome: boolean) => {
|
||||
const isTeamFav = isHome ? isHomeFav : isAwayFav;
|
||||
const setLoading = isHome ? setHomeFavLoading : setAwayFavLoading;
|
||||
const setFav = isHome ? setIsHomeFav : setIsAwayFav;
|
||||
const loading = isHome ? homeFavLoading : awayFavLoading;
|
||||
|
||||
if (loading) return;
|
||||
setLoading(true);
|
||||
|
||||
const newFavState = !isTeamFav;
|
||||
try {
|
||||
if (newFavState) {
|
||||
await addFavorite({
|
||||
teamId: Number(teamKey),
|
||||
type: "team",
|
||||
typeId: teamKey.toString(),
|
||||
notify: true,
|
||||
});
|
||||
} else {
|
||||
await removeFavorite({
|
||||
type: "team",
|
||||
typeId: teamKey.toString(),
|
||||
});
|
||||
}
|
||||
setFav(newFavState);
|
||||
} catch (error) {
|
||||
console.error("Toggle team favorite error:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<LinearGradient
|
||||
colors={["#521e10", "#0e0e10"]}
|
||||
@@ -108,11 +175,24 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
|
||||
{/* Score Section */}
|
||||
<View style={styles.scoreRow}>
|
||||
<View style={styles.teamInfo}>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
source={{ uri: match.homeTeamLogo }}
|
||||
style={styles.teamLogo}
|
||||
/>
|
||||
<View style={styles.teamLogoRow}>
|
||||
<TouchableOpacity
|
||||
onPress={() => toggleTeamFavorite(match.homeTeamKey, true)}
|
||||
disabled={homeFavLoading}
|
||||
style={styles.starBtnLeft}
|
||||
>
|
||||
<IconSymbol
|
||||
name={isHomeFav ? "star" : "star-outline"}
|
||||
size={20}
|
||||
color={isHomeFav ? "#FFD700" : "rgba(255,255,255,0.5)"}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
source={{ uri: match.homeTeamLogo }}
|
||||
style={styles.teamLogo}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<ThemedText style={styles.teamName} numberOfLines={2}>
|
||||
{match.eventHomeTeam}
|
||||
@@ -133,11 +213,24 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
|
||||
</View>
|
||||
|
||||
<View style={styles.teamInfo}>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
source={{ uri: match.awayTeamLogo }}
|
||||
style={styles.teamLogo}
|
||||
/>
|
||||
<View style={styles.teamLogoRow}>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
source={{ uri: match.awayTeamLogo }}
|
||||
style={styles.teamLogo}
|
||||
/>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
onPress={() => toggleTeamFavorite(match.awayTeamKey, false)}
|
||||
disabled={awayFavLoading}
|
||||
style={styles.starBtnRight}
|
||||
>
|
||||
<IconSymbol
|
||||
name={isAwayFav ? "star" : "star-outline"}
|
||||
size={20}
|
||||
color={isAwayFav ? "#FFD700" : "rgba(255,255,255,0.5)"}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<ThemedText style={styles.teamName} numberOfLines={2}>
|
||||
{match.eventAwayTeam}
|
||||
@@ -202,13 +295,26 @@ const styles = StyleSheet.create({
|
||||
flex: 1,
|
||||
alignItems: "center",
|
||||
},
|
||||
teamLogoRow: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
marginBottom: 10,
|
||||
},
|
||||
logoContainer: {
|
||||
width: 70,
|
||||
height: 70,
|
||||
marginBottom: 10,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
},
|
||||
starBtnLeft: {
|
||||
padding: 8,
|
||||
marginRight: -4,
|
||||
},
|
||||
starBtnRight: {
|
||||
padding: 8,
|
||||
marginLeft: -4,
|
||||
},
|
||||
teamLogo: {
|
||||
width: 60,
|
||||
height: 60,
|
||||
|
||||
@@ -431,6 +431,7 @@ export const fetchUserProfile = async (): Promise<UserProfile> => {
|
||||
|
||||
export const addFavorite = async (request: FavoriteRequest): Promise<any> => {
|
||||
try {
|
||||
// console.log("Adding favorite with request:", request);
|
||||
const response = await apiClient.post<ApiResponse<any>>(
|
||||
API_ENDPOINTS.FAVORITES,
|
||||
request
|
||||
@@ -450,6 +451,7 @@ export const removeFavorite = async (request: {
|
||||
typeId: string;
|
||||
}): Promise<any> => {
|
||||
try {
|
||||
console.log("Removing favorite with request:", request);
|
||||
const response = await apiClient.delete<ApiResponse<any>>(
|
||||
API_ENDPOINTS.FAVORITES,
|
||||
{ data: request }
|
||||
@@ -498,6 +500,7 @@ export const fetchFavorites = async (
|
||||
}
|
||||
);
|
||||
if (response.data.code === 0) {
|
||||
console.log("Fetched favorites:", JSON.stringify(response.data.data));
|
||||
return response.data.data;
|
||||
}
|
||||
throw new Error(response.data.message);
|
||||
|
||||
Reference in New Issue
Block a user