"use client"; import { Badge, Box, Button, Card, Flex, Grid, Heading, HStack, Icon, IconButton, Separator, Text, VStack, } from "@chakra-ui/react"; import { useTranslations } from "next-intl"; import React from "react"; import { LuBadgeAlert, LuChartBar, LuCircleHelp, LuDatabase, LuTrendingUp, LuZap, } from "react-icons/lu"; import { useColorModeValue } from "@/components/ui/color-mode"; import { Tooltip } from "@/components/ui/overlays/tooltip"; import { useGenerateFrequencyCoupon } from "@/lib/api/coupons/use-hooks"; import type { FrequencyCouponResultDto, FrequencyCouponBetDto, } from "@/lib/api/coupons/types"; import { ApiError } from "@/lib/api/create-api-client"; import { useCouponStore } from "@/lib/stores/coupon-store"; const AVAILABLE_MARKETS = ["OU1.5", "OU2.5", "OU3.5", "BTTS", "MS"]; function InfoIcon({ content, label }: { content: string; label: string }) { return ( ); } const profileColor = (p: string) => ({ GOLCU: "red", DEFANSIF: "blue", NORMAL: "gray" })[p] || "gray"; const profileLabel = (p: string, t: ReturnType) => ({ GOLCU: t("freq-league-golcu"), DEFANSIF: t("freq-league-defansif"), NORMAL: t("freq-league-normal"), })[p] || p; export default function FrequencyPanel() { const t = useTranslations("coupons"); const { addItem, clearCoupon } = useCouponStore(); const cardBg = useColorModeValue("white", "gray.800"); const mutedBg = useColorModeValue("gray.50", "whiteAlpha.50"); const borderColor = useColorModeValue("gray.200", "gray.700"); const freqMutation = useGenerateFrequencyCoupon(); const [minSignal, setMinSignal] = React.useState(0.65); const [maxMatches, setMaxMatches] = React.useState(3); const [selectedMarkets, setSelectedMarkets] = React.useState([]); const [result, setResult] = React.useState< FrequencyCouponResultDto | undefined >(undefined); const toggleMarket = (m: string) => setSelectedMarkets((prev) => prev.includes(m) ? prev.filter((x) => x !== m) : [...prev, m], ); const handleGenerate = () => { freqMutation.mutate( { maxMatches, minSignal, markets: selectedMarkets.length > 0 ? selectedMarkets : undefined, }, { onSuccess: (response) => { const data = (response as any)?.data ?? response; setResult(data as FrequencyCouponResultDto); // Sync to coupon store if (data && Array.isArray((data as any).bets)) { clearCoupon(); (data as FrequencyCouponResultDto).bets.forEach( (bet: FrequencyCouponBetDto) => addItem({ matchId: bet.match_id, matchName: bet.match_name, market: bet.market, pick: bet.pick, odd: bet.odds, }), ); } }, onError: () => setResult(undefined), }, ); }; const errorMessage = freqMutation.error instanceof ApiError ? freqMutation.error.message : freqMutation.error instanceof Error ? freqMutation.error.message : undefined; return ( {/* Controls Card */} {t("freq-engine-title")} {t("freq-engine-subtitle")} {/* Min Signal Slider */} {t("freq-min-signal")} {(minSignal * 100).toFixed(0)}% setMinSignal(Number(e.target.value) / 100)} style={{ width: "100%", accentColor: "#0891b2", cursor: "pointer", }} /> 50% 95% {/* Max Matches */} {t("match-count-label")} {maxMatches} setMaxMatches(Number(e.target.value))} style={{ width: "100%", accentColor: "#9333ea", cursor: "pointer", }} /> 2 5 {/* Market Filter */} {t("freq-markets")} {AVAILABLE_MARKETS.map((m) => { const active = selectedMarkets.includes(m); return ( toggleMarket(m)} _hover={{ opacity: 0.8 }} > {m} ); })} {selectedMarkets.length === 0 && ( Tüm marketler taranacak )} {/* Results Card */} {result && result.bets.length > 0 && ( {t("freq-engine-title")} {result.ev_positive ? t("freq-ev-positive") : t("freq-ev-negative")} {/* EV Stats */} {t("freq-ev-label")} {result.expected_value.toFixed(3)} {t("freq-hit-rate")} {(result.expected_hit_rate * 100).toFixed(1)}% {t("total-odds")} {result.total_odds.toFixed(2)} {/* Bets */} {result.bets.map((bet: FrequencyCouponBetDto) => ( {bet.match_name} {bet.league} • {bet.market}: {bet.pick} {bet.odds.toFixed(2)} {t("freq-home-signal")} {(bet.home_signal * 100).toFixed(0)}% {bet.home_odds_band} {t("freq-away-signal")} {(bet.away_signal * 100).toFixed(0)}% {bet.away_odds_band} {t("freq-combined-signal")} {(bet.combined_signal * 100).toFixed(0)}% {t("freq-league-profile")}:{" "} {profileLabel(bet.league_profile, t)} {t("freq-match-count")}: {bet.home_match_count}/ {bet.away_match_count} ))} {/* Reasoning */} {result.reasoning.length > 0 && ( {t("freq-reasoning-title")} {result.reasoning.map((r, i) => ( • {r} ))} )} {/* Rejected */} {result.rejected_matches.length > 0 && ( {t("rejected-matches-title")} {result.rejected_matches.map((entry, i) => ( {entry.match_name}: {entry.reason} ))} )} )} {/* No result message */} {result && result.bets.length === 0 && ( {t("freq-no-result")} )} {/* Error */} {errorMessage && ( {errorMessage} )} ); }