"use client"; import { Box, Flex, Heading, Text, SimpleGrid, Card, VStack, HStack, Badge, Button, } from "@chakra-ui/react"; import { useTranslations } from "next-intl"; import { useColorModeValue } from "@/components/ui/color-mode"; import { SlideUp, StaggerContainer, StaggerItem, ScrollSlideUp } from "@/components/motion"; import { Skeleton } from "@/components/ui/feedback/skeleton"; import { MatchCard } from "@/components/matches"; import { useQueryMatches } from "@/lib/api/matches/use-hooks"; import { useUpcomingPredictions, useValueBets, } from "@/lib/api/predictions/use-hooks"; import { useUserBettingStats } from "@/lib/api/coupons/use-hooks"; import { useSession } from "next-auth/react"; import { LuTrendingUp, LuTarget, LuTicket, LuChartBar } from "react-icons/lu"; import { useRouter } from "next/navigation"; import type { LeagueWithMatchesDto, MatchResponseDto } from "@/lib/api/matches/types"; import type { MatchPredictionDto, ValueBetDto } from "@/lib/api/predictions/types"; // ======================== // Stats Card // ======================== interface StatCardProps { label: string; value: string | number; icon: React.ReactNode; colorPalette?: string; } function StatCard({ label, value, icon, colorPalette = "primary", }: StatCardProps) { const cardBg = useColorModeValue( "rgba(255, 255, 255, 0.75)", "rgba(26, 32, 44, 0.65)", ); const borderColor = useColorModeValue( "rgba(255, 255, 255, 0.8)", "rgba(255, 255, 255, 0.06)", ); return ( {icon} {value} {label} ); } // ======================== // Value Bet Mini Card // ======================== interface ValueBetMiniCardProps { matchName: string; prediction: string; odd: number; expectedValue: number; confidence: number; } function ValueBetMiniCard({ matchName, prediction, odd, expectedValue, confidence, }: ValueBetMiniCardProps) { const cardBg = useColorModeValue("white", "gray.800"); const borderColor = useColorModeValue("gray.100", "gray.700"); return ( {matchName} {prediction} EV+ {(expectedValue * 100).toFixed(0)}% {odd.toFixed(2)} ); } // ======================== // Dashboard Content // ======================== export default function DashboardContent() { const t = useTranslations("dashboard"); const tCoupons = useTranslations("coupons"); const router = useRouter(); const { data: session } = useSession(); const cardBg = useColorModeValue("white", "gray.800"); const borderColor = useColorModeValue("gray.100", "gray.700"); // Data fetching const queryMatches = useQueryMatches(); const { data: upcomingData, isLoading: upcomingLoading } = useUpcomingPredictions(); const { data: valueBetsData, isLoading: valueBetsLoading } = useValueBets(); const { data: statsData, isLoading: statsLoading } = useUserBettingStats(); // Trigger match fetch for today if (!queryMatches.data && !queryMatches.isPending) { queryMatches.mutate({ sport: "football", limit: 20 }); } const todayMatches: MatchResponseDto[] = queryMatches.data?.data?.flatMap((l: LeagueWithMatchesDto) => l.matches) ?? []; const upcomingPredictions: MatchPredictionDto[] = upcomingData?.data?.matches ?? []; const valueBets: ValueBetDto[] = valueBetsData?.data ?? []; const userStats = statsData?.data; const userName = session?.user?.name || ""; return ( {/* Welcome Header */} {t("title")} {userName && ( {t("welcome")},{" "} {userName} {" "} 👋 )} {/* Stats Grid */} } colorPalette="primary" /> } colorPalette="green" /> } colorPalette="teal" /> } colorPalette="yellow" /> {/* Two Column Layout */} {/* Left Column — Today's Matches */} {t("todays-matches")} {queryMatches.isPending ? ( {Array.from({ length: 4 }).map((_, i) => ( ))} ) : todayMatches.length > 0 ? ( {todayMatches.slice(0, 6).map((match: MatchResponseDto) => ( ))} ) : ( {t("no-matches")} )} {/* Right Column — Predictions & Value Bets */} {/* Upcoming Predictions */} {t("upcoming-predictions")} {upcomingLoading ? ( {Array.from({ length: 3 }).map((_, i) => ( ))} ) : upcomingPredictions.length > 0 ? ( {upcomingPredictions.slice(0, 4).map((pred: MatchPredictionDto, idx: number) => ( router.push(`/matches/${pred.match_info.match_id}`) } > {pred.match_info.home_team} vs{" "} {pred.match_info.away_team} {pred.main_pick && ( {pred.main_pick.pick} {Math.round( pred.main_pick.calibrated_confidence ?? pred.main_pick.confidence, )} % )} ))} ) : ( {t("no-predictions")} )} {/* Value Bets */} {t("value-bets")} {valueBetsLoading ? ( {Array.from({ length: 3 }).map((_, i) => ( ))} ) : valueBets.length > 0 ? ( {valueBets.slice(0, 5).map((vb: ValueBetDto, idx: number) => ( ))} ) : ( {t("no-predictions")} )} ); }