Update prediction-card.tsx
Deploy Iddaai Frontend / build-and-deploy (push) Successful in 2m30s

This commit is contained in:
2026-06-02 17:54:47 +03:00
parent 2695cfffb4
commit e59f4b4e72
+113 -1
View File
@@ -1172,6 +1172,39 @@ export default function PredictionCard({ prediction }: PredictionCardProps) {
const mainBandPalette = getConfidenceBandPalette(
prediction.bet_advice.confidence_band,
);
// ── Maç Sonucu Tahmini (model'in EN OLASI sonucu) ──────────────────
// The value-bet hero below optimizes ROI (often a high-odds draw/underdog,
// ~27% hit) which users misread as a "bad prediction". This block instead
// shows what the model thinks will actually happen: the highest-probability
// 1X2 outcome (~55% hit, on par with the market). Sourced from market_board.MS.
const msBoard = prediction.market_board?.MS;
const matchResultPrediction = (() => {
const probs = msBoard?.probs;
if (!probs) return null;
const labelMap: Record<string, string> = {
"1": prediction.match_info?.home_team || uiText("home", "Ev Sahibi"),
X: uiText("draw", "Beraberlik"),
"2": prediction.match_info?.away_team || uiText("away", "Deplasman"),
};
let bestKey = "";
let bestProb = -1;
for (const [k, v] of Object.entries(probs)) {
const p = typeof v === "number" ? v : 0;
if (p > bestProb) {
bestProb = p;
bestKey = k;
}
}
if (!bestKey) return null;
return {
pick: bestKey,
label: labelMap[bestKey] ?? bestKey,
prob: bestProb,
all: probs as Record<string, number>,
};
})();
const sport = getPredictionSport(prediction);
const isBasketball = sport === "basketball";
@@ -1373,6 +1406,85 @@ export default function PredictionCard({ prediction }: PredictionCardProps) {
</HStack>
</Box>
{matchResultPrediction ? (
<Box
p={4}
bg={statCardBg}
borderWidth="1px"
borderColor={borderColor}
borderRadius="2xl"
>
<HStack justify="space-between" align="start" mb={3}>
<VStack align="start" gap={1}>
<Badge colorPalette="blue" variant="subtle" borderRadius="full">
{uiText("match-result-prediction", "Maç Sonucu Tahmini")}
</Badge>
<Text fontSize="2xl" fontWeight="bold">
{matchResultPrediction.label}
</Text>
<Text fontSize="sm" color="fg.muted">
{uiText(
"match-result-copy",
"Modelin en olası gördüğü sonuç (kim kazanır).",
)}
</Text>
</VStack>
<VStack align="end" gap={0}>
<Text fontSize="2xl" fontWeight="bold" color="blue.500">
{formatPercent(matchResultPrediction.prob * 100, 0)}
</Text>
<Text fontSize="xs" color="fg.muted">
{uiText("probability-short", "olasılık")}
</Text>
</VStack>
</HStack>
{/* 1X2 dağılımı */}
<VStack align="stretch" gap={2}>
{["1", "X", "2"].map((k) => {
const p = matchResultPrediction.all[k] ?? 0;
const lbl: Record<string, string> = {
"1":
prediction.match_info?.home_team ||
uiText("home", "Ev Sahibi"),
X: uiText("draw", "Beraberlik"),
"2":
prediction.match_info?.away_team ||
uiText("away", "Deplasman"),
};
const isTop = k === matchResultPrediction.pick;
return (
<Box key={k}>
<Flex justify="space-between" mb={1}>
<Text
fontSize="sm"
fontWeight={isTop ? "semibold" : "normal"}
color={isTop ? "blue.500" : "fg.muted"}
>
{lbl[k]}
</Text>
<Text fontSize="sm" fontWeight={isTop ? "semibold" : "normal"}>
{formatPercent(p * 100, 0)}
</Text>
</Flex>
<Bar
value={p * 100}
color={isTop ? "blue.400" : "gray.400"}
trackBg={trackBgColor}
height="6px"
/>
</Box>
);
})}
</VStack>
<Text fontSize="xs" color="fg.muted" mt={3}>
{uiText(
"match-result-vs-value",
"Bu en olası sonuçtur. Aşağıdaki “Değerli Bahis” ise orana göre en kârlı görülen seçimdir — ikisi farklı olabilir.",
)}
</Text>
</Box>
) : null}
{recommendedPick ? (
<Grid templateColumns={{ base: "1fr", xl: "1.4fr 1fr" }} gap={4}>
<Box
@@ -1389,7 +1501,7 @@ export default function PredictionCard({ prediction }: PredictionCardProps) {
variant="solid"
borderRadius="full"
>
{uiText("main-recommendation", "Öne Çıkan Sinyal")}
{uiText("main-recommendation", "Değerli Bahis")}
</Badge>
<Text fontSize="2xl" fontWeight="bold">
{recommendedPick.pick}