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
?
71%
Quality Avg
?
72%
Security Avg
?
74%
Reviews
?
123
Review Result ?
solutionbowl/website · 3c0b7501
The changes introduce multi-race functionality by adding conditionals and UI elements related to multi-race country selection and race event listings. It extends existing components and uses standard React hooks and utilities. While the new features increase business value by enabling multi-bet handling, some areas could improve security (e.g., input validation) and reduce risk of bugs (e.g., more robust error handling and checking for undefined values). The code lacks comments for complex logic, which slightly reduces maintainability and quality. The fake work risk is low as the changes appear focused and relevant to the described feature.
Quality
?
80%
Security
?
60%
Business Value
?
80%
Maintainability
?
80%
Issues & Suggested Fixes
?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Duplicate Logic
Where
src/components/layout/RacingNavMenu.tsx:11-30
Issue / Evidence
function withOpacity is duplicated across files
Suggested Fix
refactor to a shared utility to improve maintainability and avoid bugs
Missing Validation
Where
src/components/layout/RacingNavMenu.tsx:54-56
Issue / Evidence
potential lack of validation on URL parameters
Suggested Fix
add validation/sanitization for 'country_id' to improve security and reduce bug risk
Long Function
Where
src/components/layout/RacingNavMenu.tsx:78-97
Issue / Evidence
complex logic to set initialCountryId is not documented
Suggested Fix
add comments to improve code quality and maintainability
Verify That Setactivecountryid And Setrace...
Where
src/components/layout/RacingNavMenu.tsx:129-139
Issue / Evidence
verify that setActiveCountryId and setRaceEvents handle edge cases where countries are empty or data fetching fails
Suggested Fix
add error handling to reduce bug risk
Duplicate Logic
Where
src/components/layout/SelectedMultiRaceSidebarMenu.tsx:11-25
Issue / Evidence
duplicate withOpacity code from RacingNavMenu.tsx
Suggested Fix
extract to shared util for quality and maintainability
Vague Description
Where
commit message
Issue / Evidence
vague description
Suggested Fix
improve commit message to clearly describe changes made and their purpose to improve business value and maintainability
Code Change Preview · src/components/layout/Header.tsx
?
Removed / Before Commit
- diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx - index f354ac9..51e7303 100644 - return location.pathname === "/"; - } - - return location.pathname === path || location.pathname.startsWith(`${path}/`); - };
Added / After Commit
+ diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx + index f354ac9..51e7303 100644 + return location.pathname === "/"; + } + + if (path === "/horse-racing" && location.pathname === "/multi-race") { + return true; + } + + return location.pathname === path || location.pathname.startsWith(`${path}/`); + };
Removed / Before Commit
- diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx - index 3650f5e..1960418 100644 - setIsProfileDrawerOpen(false); - }; - - const hiddenRoutes = ["/horse-racing", "/transactions"]; - - const hideDesktopSidebar = hiddenRoutes.includes(location.pathname);
Added / After Commit
+ diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx + index 3650f5e..1960418 100644 + setIsProfileDrawerOpen(false); + }; + + const hiddenRoutes = ["/horse-racing", "/transactions", "/multi-race"]; + + const hideDesktopSidebar = hiddenRoutes.includes(location.pathname);
Removed / Before Commit
- diff --git a/src/components/layout/RacingNavMenu.tsx b/src/components/layout/RacingNavMenu.tsx - index b5da9a1..94691c1 100644 - const COUNTRY_FLAG_BASE_URL = - "https://whitelable-dev-bucket.s3.ap-south-1.amazonaws.com/countries/"; - - type RacingNavMenuVariant = "sidebar" | "header"; - - interface RacingNavMenuProps { - open: boolean; - variant: RacingNavMenuVariant; - }: RacingNavMenuProps) { - const colors = useThemeColors(); - const location = useLocation(); - const [countries, setCountries] = useState<Country[]>([]); - const [activeCountryId, setActiveCountryId] = useState(""); - const [raceEvents, setRaceEvents] = useState<RaceEvent[]>([]); - if (isCurrent) { - const safeCountries = Array.isArray(data) ? data : [];
Added / After Commit
+ diff --git a/src/components/layout/RacingNavMenu.tsx b/src/components/layout/RacingNavMenu.tsx + index b5da9a1..94691c1 100644 + const COUNTRY_FLAG_BASE_URL = + "https://whitelable-dev-bucket.s3.ap-south-1.amazonaws.com/countries/"; + + const withOpacity = (color: string, opacity: number) => { + if (!color.startsWith("#")) return color; + + const hex = color.slice(1); + const normalizedHex = + hex.length === 3 + ? hex + .split("") + .map((char) => `${char}${char}`) + .join("") + : hex; + + if (normalizedHex.length !== 6) return color;
Removed / Before Commit
- diff --git a/src/components/layout/SelectedMultiRaceSidebarMenu.tsx b/src/components/layout/SelectedMultiRaceSidebarMenu.tsx - new file mode 100644 - index 0000000..644e8af
Added / After Commit
+ diff --git a/src/components/layout/SelectedMultiRaceSidebarMenu.tsx b/src/components/layout/SelectedMultiRaceSidebarMenu.tsx + new file mode 100644 + index 0000000..644e8af + import { useEffect, useMemo, useState } from "react"; + import { Link, useLocation, useSearchParams } from "react-router-dom"; + import { getCountries, getRaceEvents } from "../../services/racing"; + import type { Country, RaceEvent } from "../../types/racing"; + import { formatRaceDateTime } from "../../utils/dateFormat"; + import { useThemeColors } from "../../hooks/useThemeColors"; + + const COUNTRY_FLAG_BASE_URL = + "https://whitelable-dev-bucket.s3.ap-south-1.amazonaws.com/countries/"; + + const withOpacity = (color: string, opacity: number) => { + if (!color.startsWith("#")) return color; + + const hex = color.slice(1); + const normalizedHex =
Removed / Before Commit
- diff --git a/src/components/layout/SelectedRaceSidebarMenu.tsx b/src/components/layout/SelectedRaceSidebarMenu.tsx - index 4ecf775..69367c8 100644 - const COUNTRY_FLAG_BASE_URL = - "https://whitelable-dev-bucket.s3.ap-south-1.amazonaws.com/countries/"; - - interface SelectedRaceSidebarMenuProps { - raceId: string; - onRaceClick?: () => void; - } - - return ( - <div className="space-y-[12px] pt-[8px]"> - {/* Country Header */} - <div - className="flex items-center gap-[12px] px-[12px] py-[8px] rounded-[6px]" - style={{ - backgroundColor: 'rgba(255, 255, 255, 0.05)', - borderLeft: `3px solid ${colors.primary}`
Added / After Commit
+ diff --git a/src/components/layout/SelectedRaceSidebarMenu.tsx b/src/components/layout/SelectedRaceSidebarMenu.tsx + index 4ecf775..69367c8 100644 + const COUNTRY_FLAG_BASE_URL = + "https://whitelable-dev-bucket.s3.ap-south-1.amazonaws.com/countries/"; + + const withOpacity = (color: string, opacity: number) => { + if (!color.startsWith("#")) return color; + + const hex = color.slice(1); + const normalizedHex = + hex.length === 3 + ? hex + .split("") + .map((char) => `${char}${char}`) + .join("") + : hex; + + if (normalizedHex.length !== 6) return color;
Removed / Before Commit
- diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx - index 71943ea..f74d745 100644 - import { useEffect, useMemo, useState } from "react"; - import RacingNavMenu from "./RacingNavMenu"; - import SelectedRaceSidebarMenu from "./SelectedRaceSidebarMenu"; - - const racingMenuItems = [ - { - name: "MultiRace", - icon: "/images/horses.png", - path: "/multi-race", - sportId: 3, - }, - { - name: "Horse Racing", - icon: "/images/horses.png", - location.pathname === "/multi-race" || - location.pathname.startsWith("/horse-racing");
Added / After Commit
+ diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx + index 71943ea..f74d745 100644 + import { useEffect, useMemo, useState } from "react"; + import RacingNavMenu from "./RacingNavMenu"; + import SelectedRaceSidebarMenu from "./SelectedRaceSidebarMenu"; + import SelectedMultiRaceSidebarMenu from "./SelectedMultiRaceSidebarMenu"; + + const racingMenuItems = [ + { + name: "Horse Racing", + icon: "/images/horses.png", + location.pathname === "/multi-race" || + location.pathname.startsWith("/horse-racing"); + const selectedRaceId = location.pathname.match(/^\/horse-racing\/([^/]+)/)?.[1] ?? null; + const isMultiRacePage = location.pathname === "/multi-race"; + const [isRacingMenuOpen, setIsRacingMenuOpen] = useState(isRacingRoute); + + useEffect(() => {
Removed / Before Commit
- diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx - index b3f5b36..552293d 100644 - </div> - <p style={{ color: colors.textPrimary }}>({matches.length})</p> - </div> - - <div className="flex gap-2 overflow-x-auto no-scrollbar mb-4"> - {allMatchesTabs.map((tab) => (
Added / After Commit
+ diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx + index b3f5b36..552293d 100644 + </div> + <p style={{ color: colors.textPrimary }}>({matches.length})</p> + </div> + + + <div className="flex gap-2 overflow-x-auto no-scrollbar mb-4"> + {allMatchesTabs.map((tab) => (
Removed / Before Commit
- diff --git a/src/pages/HorseRacing.tsx b/src/pages/HorseRacing.tsx - index 78d5aad..73ed066 100644 - </> - ) : ( - /* Multibet View */ - <MultiRaceDetail /> - )} - </div> - </div>
Added / After Commit
+ diff --git a/src/pages/HorseRacing.tsx b/src/pages/HorseRacing.tsx + index 78d5aad..73ed066 100644 + </> + ) : ( + /* Multibet View */ + <MultiRaceDetail countryId={activeCountry} /> + )} + </div> + </div>
Removed / Before Commit
- diff --git a/src/pages/HorseRacingDetails.tsx b/src/pages/HorseRacingDetails.tsx - index a38491f..2502968 100644 - ? minutes - : DEFAULT_BET_START_BEFORE_IN_MIN - } - - const filterMarketsBySettleFlags = (marketsData: Market[], raceData: Race | null) => { - if (!raceData) return marketsData
Added / After Commit
+ diff --git a/src/pages/HorseRacingDetails.tsx b/src/pages/HorseRacingDetails.tsx + index a38491f..2502968 100644 + ? minutes + : DEFAULT_BET_START_BEFORE_IN_MIN + } + const filterMarketsBySettleFlags = (marketsData: Market[], raceData: Race | null) => { + if (!raceData) return marketsData
Removed / Before Commit
- diff --git a/src/pages/MultiRaceDetail.tsx b/src/pages/MultiRaceDetail.tsx - index f4491b1..78b9ac4 100644 - import { useCallback, useEffect, useMemo, useState } from "react" - import { - getMultiBetRaces, - placeMultiBet, - return first.race.id.localeCompare(second.race.id) - } - - const formatPosition = (position: number) => { - const teenRemainder = position % 100 - - if (teenRemainder >= 11 && teenRemainder <= 13) { - return `${position}th` - } - - const suffix = position % 10 === 1 - ? "st"
Added / After Commit
+ diff --git a/src/pages/MultiRaceDetail.tsx b/src/pages/MultiRaceDetail.tsx + index f4491b1..78b9ac4 100644 + import { useCallback, useEffect, useMemo, useState } from "react" + import { useSearchParams, useLocation } from "react-router-dom" + import { + getMultiBetRaces, + placeMultiBet, + return first.race.id.localeCompare(second.race.id) + } + + // const formatPosition = (position: number) => { + // const teenRemainder = position % 100 + // + // if (teenRemainder >= 11 && teenRemainder <= 13) { + // return `${position}th` + // } + // + // const suffix = position % 10 === 1
Removed / Before Commit
- diff --git a/src/services/racing.ts b/src/services/racing.ts - index b52e12f..2e0e311 100644 - data?: unknown - } - - export const getMultiBetRaces = async (): Promise<MultiBetRacesResponse> => { - const response = await fetch(API_ENDPOINTS.racing.getMultiBetRaces, { - method: "GET", - headers: getApiHeaders(), - })
Added / After Commit
+ diff --git a/src/services/racing.ts b/src/services/racing.ts + index b52e12f..2e0e311 100644 + data?: unknown + } + + export const getMultiBetRaces = async (countryId?: string): Promise<MultiBetRacesResponse> => { + const countryQuery = countryId + ? `?country_id=${encodeURIComponent(countryId)}` + : "" + + const response = await fetch(`${API_ENDPOINTS.racing.getMultiBetRaces}${countryQuery}`, { + method: "GET", + headers: getApiHeaders(), + })