206 lines
6.1 KiB
TypeScript
206 lines
6.1 KiB
TypeScript
import { ThemedText } from "@/components/themed-text";
|
|
import { MatchDetailData } from "@/types/api";
|
|
import { Image } from "expo-image";
|
|
import React from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { StyleSheet, View } from "react-native";
|
|
import { LinearGradient } from "expo-linear-gradient";
|
|
import { getInitials, getLogoGradient } from "@/lib/avatar-utils";
|
|
|
|
interface TennisScoreTableProps {
|
|
data: MatchDetailData;
|
|
isDark: boolean;
|
|
}
|
|
|
|
export function TennisScoreTable({ data, isDark }: TennisScoreTableProps) {
|
|
const { t } = useTranslation();
|
|
const { match } = data;
|
|
const bgColor = isDark ? "#1C1C1E" : "#FFF";
|
|
const borderColor = isDark ? "#2C2C2E" : "rgba(0,0,0,0.06)";
|
|
const headerTextColor = isDark ? "#666" : "#999";
|
|
const textColor = isDark ? "#FFF" : "#000";
|
|
|
|
const isTennis = match.sportId === 3;
|
|
const scores = (match.scores as any) || [];
|
|
const firstPlayer = match.eventFirstPlayer || "";
|
|
const secondPlayer = match.eventSecondPlayer || "";
|
|
const firstPlayerLogo = match.eventFirstPlayerLogo || "";
|
|
const secondPlayerLogo = match.eventSecondPlayerLogo || "";
|
|
|
|
const hasFirstLogo = firstPlayerLogo && firstPlayerLogo.trim() !== "" && !firstPlayerLogo.includes("placehold");
|
|
const hasSecondLogo = secondPlayerLogo && secondPlayerLogo.trim() !== "" && !secondPlayerLogo.includes("placehold");
|
|
const firstGradient = getLogoGradient(firstPlayer);
|
|
const secondGradient = getLogoGradient(secondPlayer);
|
|
const firstInitials = getInitials(firstPlayer);
|
|
const secondInitials = getInitials(secondPlayer);
|
|
|
|
const headers = [t("detail.score_table.set") || "Set"];
|
|
scores.forEach((_, index) => {
|
|
headers.push(`${index + 1}`);
|
|
});
|
|
if (scores.length === 0) {
|
|
headers.push("1");
|
|
}
|
|
|
|
return (
|
|
<View style={[styles.container, { backgroundColor: bgColor, borderColor }]}>
|
|
<View style={[styles.header, { borderBottomColor: borderColor }]}>
|
|
<View style={styles.headerLeft}>
|
|
<ThemedText style={[styles.headerText, { color: headerTextColor }]}>
|
|
{t("detail.score_table.player") || "Player"}
|
|
</ThemedText>
|
|
</View>
|
|
{headers.slice(1).map((header, index) => (
|
|
<View key={index} style={styles.headerCell}>
|
|
<ThemedText style={[styles.headerText, { color: headerTextColor }]}>
|
|
{header}
|
|
</ThemedText>
|
|
</View>
|
|
))}
|
|
</View>
|
|
|
|
<View style={[styles.row, { borderBottomColor: borderColor }]}>
|
|
<View style={styles.playerCell}>
|
|
{hasFirstLogo ? (
|
|
<Image source={{ uri: firstPlayerLogo }} style={styles.playerLogo} />
|
|
) : (
|
|
<LinearGradient
|
|
colors={[firstGradient.color1, firstGradient.color2]}
|
|
start={{ x: 0, y: 0 }}
|
|
end={{ x: 1, y: 1 }}
|
|
style={styles.playerLogoGradient}
|
|
>
|
|
<ThemedText style={styles.playerLogoText}>{firstInitials}</ThemedText>
|
|
</LinearGradient>
|
|
)}
|
|
<ThemedText style={[styles.playerName, { color: textColor }]} numberOfLines={1}>
|
|
{firstPlayer}
|
|
</ThemedText>
|
|
</View>
|
|
{scores.length > 0 ? (
|
|
scores.map((score: any, index: number) => (
|
|
<View key={index} style={styles.scoreCell}>
|
|
<ThemedText style={[styles.scoreText, { color: textColor }]}>
|
|
{score.score_first || "0"}
|
|
</ThemedText>
|
|
</View>
|
|
))
|
|
) : (
|
|
<View style={styles.scoreCell}>
|
|
<ThemedText style={[styles.scoreText, { color: textColor }]}>0</ThemedText>
|
|
</View>
|
|
)}
|
|
</View>
|
|
|
|
<View style={styles.row}>
|
|
<View style={styles.playerCell}>
|
|
{hasSecondLogo ? (
|
|
<Image source={{ uri: secondPlayerLogo }} style={styles.playerLogo} />
|
|
) : (
|
|
<LinearGradient
|
|
colors={[secondGradient.color1, secondGradient.color2]}
|
|
start={{ x: 0, y: 0 }}
|
|
end={{ x: 1, y: 1 }}
|
|
style={styles.playerLogoGradient}
|
|
>
|
|
<ThemedText style={styles.playerLogoText}>{secondInitials}</ThemedText>
|
|
</LinearGradient>
|
|
)}
|
|
<ThemedText style={[styles.playerName, { color: textColor }]} numberOfLines={1}>
|
|
{secondPlayer}
|
|
</ThemedText>
|
|
</View>
|
|
{scores.length > 0 ? (
|
|
scores.map((score: any, index: number) => (
|
|
<View key={index} style={styles.scoreCell}>
|
|
<ThemedText style={[styles.scoreText, { color: textColor }]}>
|
|
{score.score_second || "0"}
|
|
</ThemedText>
|
|
</View>
|
|
))
|
|
) : (
|
|
<View style={styles.scoreCell}>
|
|
<ThemedText style={[styles.scoreText, { color: textColor }]}>0</ThemedText>
|
|
</View>
|
|
)}
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
marginHorizontal: 16,
|
|
marginTop: 12,
|
|
borderRadius: 16,
|
|
borderWidth: 1,
|
|
overflow: "hidden",
|
|
},
|
|
header: {
|
|
flexDirection: "row",
|
|
borderBottomWidth: 1,
|
|
paddingVertical: 12,
|
|
paddingHorizontal: 12,
|
|
},
|
|
headerLeft: {
|
|
flex: 1,
|
|
minWidth: 120,
|
|
},
|
|
headerCell: {
|
|
flex: 1,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
minWidth: 40,
|
|
},
|
|
headerText: {
|
|
fontSize: 12,
|
|
fontWeight: "600",
|
|
},
|
|
row: {
|
|
flexDirection: "row",
|
|
borderBottomWidth: 1,
|
|
paddingVertical: 12,
|
|
paddingHorizontal: 12,
|
|
alignItems: "center",
|
|
},
|
|
playerCell: {
|
|
flex: 1,
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
minWidth: 120,
|
|
gap: 8,
|
|
},
|
|
playerLogo: {
|
|
width: 32,
|
|
height: 32,
|
|
borderRadius: 16,
|
|
},
|
|
playerLogoGradient: {
|
|
width: 32,
|
|
height: 32,
|
|
borderRadius: 16,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
},
|
|
playerLogoText: {
|
|
fontSize: 10,
|
|
fontWeight: "700",
|
|
color: "rgba(255, 255, 255, 0.92)",
|
|
},
|
|
playerName: {
|
|
flex: 1,
|
|
fontSize: 13,
|
|
fontWeight: "600",
|
|
},
|
|
scoreCell: {
|
|
flex: 1,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
minWidth: 40,
|
|
},
|
|
scoreText: {
|
|
fontSize: 15,
|
|
fontWeight: "700",
|
|
},
|
|
});
|