AI Review Center
Commit Review Workspace ?
Select a commit on the left to inspect quality, security, business value, findings, and suggested code changes.
Project AI Score
?
72%
Quality Avg
?
77%
Security Avg
?
64%
Reviews
?
91
Review Result ?
solutionbowl/super-admin · 846680ae
This commit adds UI improvements including date/time display, timezone switcher in the navbar, and refresh toggle features. The clock uses hooks and memoization appropriately. Important controls implement proper state and logout functionality. Some redundant or copy-pasted code is present that could be simplified. Refresh toggling and staleTime/refetchOnMount settings improve API freshness but could impact performance if not calibrated. Security is reasonably handled with user info display and logout, but no explicit security enhancements or risks are introduced.
Quality
?
85%
Security
?
80%
Business Value
?
80%
Maintainability
?
85%
Issues & Suggested Fixes
?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Useeffect Cleanup Without Dependencies
Where
src/components/top-navbar.tsx:26
Issue / Evidence
useEffect cleanup without dependencies
Suggested Fix
add dependency array to useEffect for timer to limit unnecessary rerenders
Compute Initials
Where
src/components/top-navbar.tsx:100
Issue / Evidence
compute initials
Suggested Fix
cache or memoize initials calculation to avoid recomputation on every render
Duplicate Logic
Where
src/routes/bet-list.tsx:102
Issue / Evidence
repeated query options
Suggested Fix
consolidate staleTime and refetchOnMount options to a shared config to reduce duplication
Duplicate Logic
Where
src/routes/MultiBet.tsx:51
Issue / Evidence
repeated query options
Suggested Fix
consolidate staleTime and refetchOnMount options to a shared config to reduce duplication
Duplicate Logic
Where
src/router.tsx:8
Issue / Evidence
repeated query options
Suggested Fix
consolidate staleTime and refetchOnMount options to a shared config to reduce duplication
Code Change Preview · src/components/common/RefreshToggle.tsx
?
Removed / Before Commit
- diff --git a/src/components/common/RefreshToggle.tsx b/src/components/common/RefreshToggle.tsx - index 1ab716b..7b9cb5d 100644 - isRefreshEnabled ? "text-primary" : "text-muted-foreground", - )} - > - <RefreshCw className={cn("h-3.5 w-3.5", isRefreshEnabled && "text-emerald-500")} /> - <span className="text-xs font-medium">Refresh</span> - <Switch - checked={isRefreshEnabled} - onCheckedChange={setRefreshEnabled}
Added / After Commit
+ diff --git a/src/components/common/RefreshToggle.tsx b/src/components/common/RefreshToggle.tsx + index 1ab716b..7b9cb5d 100644 + isRefreshEnabled ? "text-primary" : "text-muted-foreground", + )} + > + <RefreshCw className={cn("h-3.5 w-3.5", isRefreshEnabled && "text-primary")} /> + <span className="text-xs font-medium">Auto Refresh</span> + <Switch + checked={isRefreshEnabled} + onCheckedChange={setRefreshEnabled}
Removed / Before Commit
- diff --git a/src/components/top-navbar.tsx b/src/components/top-navbar.tsx - index a24f6b8..b56a073 100644 - import { useEffect, useState } from "react"; - import { ChevronDown, LogOut, User, Settings as SettingsIcon, Clock, Globe } from "lucide-react"; - import { Button } from "@/components/ui/button"; - import { SidebarTrigger } from "@/components/ui/sidebar"; - import { - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuTrigger, - } from "@/components/ui/dropdown-menu"; - import { Avatar, AvatarFallback } from "@/components/ui/avatar"; - import { useAuth } from "@/hooks/useAuth"; - import { RefreshToggle } from "@/components/common/RefreshToggle"; - - function useClock() {
Added / After Commit
+ diff --git a/src/components/top-navbar.tsx b/src/components/top-navbar.tsx + index a24f6b8..b56a073 100644 + import { useEffect, useMemo, useState } from "react"; + import { + ChevronDown, + LogOut, + Clock, + Globe, + } from "lucide-react"; + + import { Button } from "@/components/ui/button"; + import { SidebarTrigger } from "@/components/ui/sidebar"; + import { + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuTrigger, + } from "@/components/ui/dropdown-menu";
Removed / Before Commit
- diff --git a/src/router.tsx b/src/router.tsx - index 7a1bbc2..397c62d 100644 - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - staleTime: 1000 * 60 * 5, - refetchOnWindowFocus: false, - }, - },
Added / After Commit
+ diff --git a/src/router.tsx b/src/router.tsx + index 7a1bbc2..397c62d 100644 + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 0, + refetchOnMount: "always", + refetchOnWindowFocus: false, + }, + },
Removed / Before Commit
- diff --git a/src/routes/bet-list.tsx b/src/routes/bet-list.tsx - index b39c5d0..48696cb 100644 - fromDate, - toDate, - ...(market_id ? { market_id } : {}), - }), - enabled: !isAgentMode, - retry: 1, - staleTime: 30000, - }); - - const agentBetsQuery = useQuery({ - queryFn: () => internalServices.horseRacingReports.raceAgentBets(race_id!, agent_id!), - enabled: isAgentMode, - retry: 1, - staleTime: 30000, - }); -
Added / After Commit
+ diff --git a/src/routes/bet-list.tsx b/src/routes/bet-list.tsx + index b39c5d0..48696cb 100644 + fromDate, + toDate, + ...(market_id ? { market_id } : {}), + }), + enabled: !isAgentMode, + retry: 1, + refetchOnMount: "always", + staleTime: 0, + }); + + const agentBetsQuery = useQuery({ + queryFn: () => internalServices.horseRacingReports.raceAgentBets(race_id!, agent_id!), + enabled: isAgentMode, + retry: 1, + refetchOnMount: "always", + staleTime: 0,
Removed / Before Commit
- diff --git a/src/routes/bet-ticket.tsx b/src/routes/bet-ticket.tsx - index e7fefbe..9c39012 100644 - import { format } from "date-fns"; - import { useAutoRefresh } from "@/hooks/useAutoRefresh"; - import BetsExcelExportButton from "@/components/common/BetsExcelExportButton"; - - export const Route = createFileRoute("/bet-ticket")({ - component: BetTicketPage, - const [maxStake, setMaxStake] = useState(1000); - const [userName, setUserName] = useState(""); - const navigate = useNavigate(); - - const [applied, setApplied] = useState<BetTickerParams>(DEFAULT_PARAMS); - const [expandedBetId, setExpandedBetId] = useState<string | null>(null); - const { data, isLoading, isFetching, refetch } = useQuery({ - queryKey: ["bet-ticker", applied], - queryFn: () => fetchBetTicker(applied), - staleTime: 30_000,
Added / After Commit
+ diff --git a/src/routes/bet-ticket.tsx b/src/routes/bet-ticket.tsx + index e7fefbe..9c39012 100644 + import { format } from "date-fns"; + import { useAutoRefresh } from "@/hooks/useAutoRefresh"; + import BetsExcelExportButton from "@/components/common/BetsExcelExportButton"; + import { useRefreshToggle } from "@/hooks/useRefreshToggle"; + + export const Route = createFileRoute("/bet-ticket")({ + component: BetTicketPage, + const [maxStake, setMaxStake] = useState(1000); + const [userName, setUserName] = useState(""); + const navigate = useNavigate(); + const { isRefreshEnabled } = useRefreshToggle(); + + const [applied, setApplied] = useState<BetTickerParams>(DEFAULT_PARAMS); + const [expandedBetId, setExpandedBetId] = useState<string | null>(null); + const { data, isLoading, isFetching, refetch } = useQuery({ + queryKey: ["bet-ticker", applied],
Removed / Before Commit
- diff --git a/src/routes/blocked-ips.tsx b/src/routes/blocked-ips.tsx - index 35e4a5a..5469c58 100644 - page: currentPage, - limit: pageSize, - }), - staleTime: 30000, // 30 seconds - }); - - // Mutation for blocking IP (POST)
Added / After Commit
+ diff --git a/src/routes/blocked-ips.tsx b/src/routes/blocked-ips.tsx + index 35e4a5a..5469c58 100644 + page: currentPage, + limit: pageSize, + }), + refetchOnMount: "always", + staleTime: 0, + }); + + // Mutation for blocking IP (POST)
Removed / Before Commit
- diff --git a/src/routes/MultiBet.tsx b/src/routes/MultiBet.tsx - index f82443d..381f935 100644 - queryKey: ["multi-bet-pl", applied], - queryFn: () => - internalServices.horseRacingReports.multiBetProfitLoss(applied.fromDate, applied.toDate), - staleTime: 5 * 60 * 1000, - refetchOnWindowFocus: false, - }); - const csvExportRows = useMemo(() => { - onClick={refreshReport} - disabled={isFetching} - > - Refresh - </Button> - <CsvExportButton - filename={`multi-bet-pl-${applied.fromDate}-to-${applied.toDate}.csv`}
Added / After Commit
+ diff --git a/src/routes/MultiBet.tsx b/src/routes/MultiBet.tsx + index f82443d..381f935 100644 + queryKey: ["multi-bet-pl", applied], + queryFn: () => + internalServices.horseRacingReports.multiBetProfitLoss(applied.fromDate, applied.toDate), + refetchOnMount: "always", + staleTime: 0, + refetchOnWindowFocus: false, + }); + const csvExportRows = useMemo(() => { + onClick={refreshReport} + disabled={isFetching} + > + {isRefreshEnabled ? `Refresh (${refreshCountdown}s)` : "Refresh"} + </Button> + <CsvExportButton + filename={`multi-bet-pl-${applied.fromDate}-to-${applied.toDate}.csv`}
Removed / Before Commit
- diff --git a/src/routes/net-exposure-bet.tsx b/src/routes/net-exposure-bet.tsx - index 70ff53a..c3d0d67 100644 - queryKey: ["net-exposure-bets", raceId, marketId, userId], - queryFn: () => fetchBets(raceId, marketId, 1, userId), - enabled: Boolean(raceId && marketId), - staleTime: 30_000, - retry: 1, - }); - - disabled={isFetching} - > - <RefreshCw className={cn("mr-2 h-3.5 w-3.5", isFetching && "animate-spin")} /> - Refresh ({refreshCountdown}s) - </Button> - </div>
Added / After Commit
+ diff --git a/src/routes/net-exposure-bet.tsx b/src/routes/net-exposure-bet.tsx + index 70ff53a..c3d0d67 100644 + queryKey: ["net-exposure-bets", raceId, marketId, userId], + queryFn: () => fetchBets(raceId, marketId, 1, userId), + enabled: Boolean(raceId && marketId), + refetchOnMount: "always", + staleTime: 0, + retry: 1, + }); + + disabled={isFetching} + > + <RefreshCw className={cn("mr-2 h-3.5 w-3.5", isFetching && "animate-spin")} /> + {isRefreshEnabled ? `Refresh (${refreshCountdown}s)` : "Refresh"} + </Button> + </div>
Removed / Before Commit
- diff --git a/src/routes/net-exposure-detail.tsx b/src/routes/net-exposure-detail.tsx - index dc32c77..da1c9d1 100644 - queryKey: ["net-exposure-detail", raceId, marketId, parentUserId], - queryFn: () => fetchDetail(raceId, marketId, parentUserId), - enabled: Boolean(raceId && marketId), - staleTime: 30_000, - }); - - const oddsQuery = useQuery({ - queryKey: ["race-odds", raceId], - queryFn: () => fetchOdds(raceId), - enabled: Boolean(raceId), - staleTime: 30_000, - }); - - const hierarchyQuery = useQuery({ - queryKey: ["net-exposure-hierarchy", raceId, marketId, activeUserId], - queryFn: () => fetchHierarchy(raceId, marketId, activeUserId),
Added / After Commit
+ diff --git a/src/routes/net-exposure-detail.tsx b/src/routes/net-exposure-detail.tsx + index dc32c77..da1c9d1 100644 + queryKey: ["net-exposure-detail", raceId, marketId, parentUserId], + queryFn: () => fetchDetail(raceId, marketId, parentUserId), + enabled: Boolean(raceId && marketId), + refetchOnMount: "always", + staleTime: 0, + }); + + const oddsQuery = useQuery({ + queryKey: ["race-odds", raceId], + queryFn: () => fetchOdds(raceId), + enabled: Boolean(raceId), + refetchOnMount: "always", + staleTime: 0, + }); + + const hierarchyQuery = useQuery({
Removed / Before Commit
- diff --git a/src/routes/net-exposure-herarchy.tsx b/src/routes/net-exposure-herarchy.tsx - index c074f5e..f71c8d5 100644 - queryKey: ["net-exposure-hierarchy", raceId, marketId, activeUserId], - queryFn: () => fetchHierarchy(raceId, marketId, activeUserId), - enabled: Boolean(raceId && marketId), - staleTime: 30_000, - }); - - const runnerCols = ["1", "X", "2"];
Added / After Commit
+ diff --git a/src/routes/net-exposure-herarchy.tsx b/src/routes/net-exposure-herarchy.tsx + index c074f5e..f71c8d5 100644 + queryKey: ["net-exposure-hierarchy", raceId, marketId, activeUserId], + queryFn: () => fetchHierarchy(raceId, marketId, activeUserId), + enabled: Boolean(raceId && marketId), + refetchOnMount: "always", + staleTime: 0, + }); + + const runnerCols = ["1", "X", "2"];
Removed / Before Commit
- diff --git a/src/routes/net-exposure.tsx b/src/routes/net-exposure.tsx - index 21b2b6c..63d4d39 100644 - import { useAutoRefresh } from "@/hooks/useAutoRefresh"; - import { internalServices } from "@/services/api/internalServices"; - import { setExposureParams } from "@/lib/nav-params"; - - export const Route = createFileRoute("/net-exposure")({ - component: NetExposurePage, - function NetExposurePage() { - const [selectedSport, setSelectedSport] = useState<SportType>("My P/L"); - const navigate = useNavigate(); - - const sportOptions: SportType[] = [ - "My P/L", - const { data: rawData, isLoading, error, refetch, isFetching } = useQuery({ - queryKey: ["net-exposure"], - queryFn: fetchNetExposure, - staleTime: 30_000,
Added / After Commit
+ diff --git a/src/routes/net-exposure.tsx b/src/routes/net-exposure.tsx + index 21b2b6c..63d4d39 100644 + import { useAutoRefresh } from "@/hooks/useAutoRefresh"; + import { internalServices } from "@/services/api/internalServices"; + import { setExposureParams } from "@/lib/nav-params"; + import { useRefreshToggle } from "@/hooks/useRefreshToggle"; + + export const Route = createFileRoute("/net-exposure")({ + component: NetExposurePage, + function NetExposurePage() { + const [selectedSport, setSelectedSport] = useState<SportType>("My P/L"); + const navigate = useNavigate(); + const { isRefreshEnabled } = useRefreshToggle(); + + const sportOptions: SportType[] = [ + "My P/L", + const { data: rawData, isLoading, error, refetch, isFetching } = useQuery({ + queryKey: ["net-exposure"],
Removed / Before Commit
- diff --git a/src/routes/pl-by-agent.tsx b/src/routes/pl-by-agent.tsx - index b22dc1e..3df2694 100644 - disabled={reportQuery.isFetching} - className="h-9 rounded-lg gradient-plum px-6 text-white shadow-plum hover:opacity-90" - > - Refresh ({refreshCountdown}s) - </Button> - <CsvExportButton - filename={`pl-by-agent-${appliedFilters.fromDate}-to-${appliedFilters.toDate}.csv`}
Added / After Commit
+ diff --git a/src/routes/pl-by-agent.tsx b/src/routes/pl-by-agent.tsx + index b22dc1e..3df2694 100644 + disabled={reportQuery.isFetching} + className="h-9 rounded-lg gradient-plum px-6 text-white shadow-plum hover:opacity-90" + > + {isRefreshEnabled ? `Refresh (${refreshCountdown}s)` : "Refresh"} + </Button> + <CsvExportButton + filename={`pl-by-agent-${appliedFilters.fromDate}-to-${appliedFilters.toDate}.csv`}
Removed / Before Commit
- diff --git a/src/routes/pl-by-market.tsx b/src/routes/pl-by-market.tsx - index 99787c9..e50b929 100644 - disabled={reportQuery.isFetching} - className="h-9 rounded-lg gradient-plum px-6 text-white shadow-plum hover:opacity-90" - > - Refresh ({refreshCountdown}s) - </Button> - <CsvExportButton - filename={`pl-by-market-${appliedFilters.fromDate}-to-${appliedFilters.toDate}.csv`}
Added / After Commit
+ diff --git a/src/routes/pl-by-market.tsx b/src/routes/pl-by-market.tsx + index 99787c9..e50b929 100644 + disabled={reportQuery.isFetching} + className="h-9 rounded-lg gradient-plum px-6 text-white shadow-plum hover:opacity-90" + > + {isRefreshEnabled ? `Refresh (${refreshCountdown}s)` : "Refresh"} + </Button> + <CsvExportButton + filename={`pl-by-market-${appliedFilters.fromDate}-to-${appliedFilters.toDate}.csv`}
Removed / Before Commit
- diff --git a/src/routes/user-exposure-detail.tsx b/src/routes/user-exposure-detail.tsx - index 39024d6..2450e90 100644 - // setRefreshCountdown(10); - // }, [isRefreshEnabled, refreshCountdown]); - - // const handleManualRefresh = () => { - // refetchAll(); - // setRefreshCountdown(10); - // }; - - const toggleBetLegs = (betId: string) => { - setExpandedBetId((current) => (current === betId ? null : betId)); - <h2 className="text-lg font-bold tracking-tight"> - {race ? `${race.raceName} — ${market?.marketName ?? ""}` : "Net Exposure Detail"} - </h2> - {/* <Button - size="sm" - className="ml-auto h-8 rounded-md bg-emerald-600 px-4 text-white hover:bg-emerald-700"
Added / After Commit
+ diff --git a/src/routes/user-exposure-detail.tsx b/src/routes/user-exposure-detail.tsx + index 39024d6..2450e90 100644 + // setRefreshCountdown(10); + // }, [isRefreshEnabled, refreshCountdown]); + + const handleManualRefresh = () => { + refetchAll(); + setRefreshCountdown(10); + }; + + const toggleBetLegs = (betId: string) => { + setExpandedBetId((current) => (current === betId ? null : betId)); + <h2 className="text-lg font-bold tracking-tight"> + {race ? `${race.raceName} — ${market?.marketName ?? ""}` : "Net Exposure Detail"} + </h2> + <Button + size="sm" + className="ml-auto h-8 rounded-md bg-emerald-600 px-4 text-white hover:bg-emerald-700"