Showing AI reviews for website
Project AI Score ?
71%
Quality Avg ?
72%
Security Avg ?
74%
Reviews ?
123

Review Result ?

solutionbowl/website · f8b88153
This commit adds UI enhancements and navigation logic for multi-race and country selection in a racing app, including color opacity utilities and state management. The code generally follows good conventions but lacks some comments and error handling which could affect robustness and maintainability.
Quality ?
85%
Security ?
60%
Business Value ?
70%
Maintainability ?
80%
Issues & Suggested Fixes ?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Missing Validation
Where src/components/layout/RacingNavMenu.tsx:12
Issue / Evidence Lack of validation for color string format
Suggested Fix add validation or sanitize inputs to avoid runtime errors
Possible Null Or Empty String Handling Wit...
Where src/components/layout/RacingNavMenu.tsx:53-56
Issue / Evidence Possible null or empty string handling with locationState and URL search params
Suggested Fix add fallback handling and input validation to prevent errors
Long Function
Where src/components/layout/RacingNavMenu.tsx:78-97
Issue / Evidence Complex logic for setting initialCountryId lacks comments
Suggested Fix add comments to improve readability and maintainability
Missing Checks If Countries Array Is Empty...
Where src/components/layout/RacingNavMenu.tsx:118-125
Issue / Evidence Missing checks if countries array is empty before accessing it
Suggested Fix add guards to prevent potential runtime errors
Missing Validation
Where src/components/layout/SelectedMultiRaceSidebarMenu.tsx:12
Issue / Evidence Similar color function lacks input validation
Suggested Fix add validation to maintain consistency and prevent potential bugs
Non Descriptive Commit Message
Where commit message
Issue / Evidence Non-descriptive commit message
Suggested Fix improve commit message to clearly describe the changes and their purpose for better project history clarity
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/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..ddb5978 100644
- import { useCallback, useEffect, useMemo, useState } from "react"
- import {
- getMultiBetRaces,
- placeMultiBet,
- type MultiBetRace,
- type PlaceMultiBetRequest,
- } from "../services/racing"
- // import { betService } from "../services/betService"
- import { useThemeColors } from "../hooks/useThemeColors"
- back_static_volume: number | null
- silkColor: string
- jersey?: string
- }
- 
- type Race = {
- return first.race.id.localeCompare(second.race.id)
Added / After Commit
+ diff --git a/src/pages/MultiRaceDetail.tsx b/src/pages/MultiRaceDetail.tsx
+ index f4491b1..ddb5978 100644
+ import { useCallback, useEffect, useMemo, useState } from "react"
+ import { useSearchParams, useLocation } from "react-router-dom"
+ import {
+ getMultiBetRaces,
+   getRaceExposure,
+ placeMultiBet,
+ type MultiBetRace,
+ type PlaceMultiBetRequest,
+   type ExposureData,
+ } from "../services/racing"
+ // import { betService } from "../services/betService"
+ import { useThemeColors } from "../hooks/useThemeColors"
+ back_static_volume: number | null
+ silkColor: string
+ jersey?: string
+   exposure?: number
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(),
+ })