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 · d33d230f
The commit adds jersey image support across various components with consistent conditional rendering and styling. It improves the visual appeal and user experience by displaying runner jerseys. The changes impact multiple UI components including HorseRow, MarketCard, and MultiRaceDetail, as well as related types and services, ensuring full integration. However, there is no validation or fallback handling for invalid or malicious jersey URLs, which may pose a minor security risk. Bug risk is low but exists where jersey data may be missing or malformed. The commit message could be more descriptive.
Quality
?
85%
Security
?
80%
Business Value
?
90%
Maintainability
?
83%
Issues & Suggested Fixes
?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Issue
Where
commit message
Issue / Evidence
issue
Suggested Fix
provide a clearer, more detailed commit message describing key changes
Missing Validation
Where
src/components/racing/HorseRow.tsx:501
Issue / Evidence
missing validation
Suggested Fix
add validation or sanitization of jerseyImageUrl to mitigate potential security risks
No Fallback Image
Where
src/components/racing/MarketCard.tsx:189
Issue / Evidence
no fallback image
Suggested Fix
add fallback UI for cases where jersey image fails to load
Image Alt Attribute
Where
src/pages/MultiRaceDetail.tsx:543
Issue / Evidence
image alt attribute
Suggested Fix
improve alt text to be more descriptive for accessibility
Duplicate Logic
Where
src/pages/MultiRaceDetail.tsx:535-557
Issue / Evidence
code duplication
Suggested Fix
consider refactoring similar JSX code blocks for rendering jerseys or numbers into a reusable component
Code Change Preview · src/components/racing/HorseRow.tsx
?
Removed / Before Commit
- diff --git a/src/components/racing/HorseRow.tsx b/src/components/racing/HorseRow.tsx - index 762aba2..ae113ba 100644 - onBlockBetStakeChange?.(event.target.value) - }, [isAuthenticated, authModal, onBlockBetStakeChange]) - - if (showBlockBetting && isMobile) { - return ( - <div - <div - className="grid px-[10px] py-[10px] items-center gap-[6px]" - style={{ - gridTemplateColumns: mobileOddsGridColumns - }} - > - <div className="min-w-0"> - <p className="text-white text-[13px] font-semibold leading-[17px] truncate"> - {horseData.horse_number}. {horseData.gateNo ? `${horseData.gateNo} ` : ''}{horseData.name} - blockBetChecked ? "border-l-[3px] border-l-[#0a54ff] bg-[#101722]" : ""
Added / After Commit
+ diff --git a/src/components/racing/HorseRow.tsx b/src/components/racing/HorseRow.tsx + index 762aba2..ae113ba 100644 + onBlockBetStakeChange?.(event.target.value) + }, [isAuthenticated, authModal, onBlockBetStakeChange]) + + // Get jersey image URL from runner data (API sends 'jersey' field) + const jerseyImageUrl = runner.jersey || runner.runner?.jersey + + if (showBlockBetting && isMobile) { + return ( + <div + <div + className="grid px-[10px] py-[10px] items-center gap-[6px]" + style={{ + gridTemplateColumns: jerseyImageUrl ? `auto ${mobileOddsGridColumns}` : mobileOddsGridColumns + }} + > + {/* Jersey Image - only show if URL exists */}
Removed / Before Commit
- diff --git a/src/components/racing/MarketCard.tsx b/src/components/racing/MarketCard.tsx - index 3779fb9..9de3cf9 100644 - const isToteMarket = raceType === "ToteMarket" - const showBlockBetting = isWinnerBlockMarket(market) - const isMobile = typeof window !== "undefined" && window.innerWidth < 768 - const mobileBlockBetGridColumns = isToteMarket - ? "minmax(0, 1fr) 60px" - : "minmax(0, 1fr) 60px 60px" - className="grid px-[14px] py-[8px]" - style={{ - gridTemplateColumns: showBlockBetting - ? blockBetGridColumns - : window.innerWidth >= 768 - ? isToteMarket ? "1fr 130px" : "1fr 130px 130px" - : isToteMarket ? "1fr 60px" : "1fr 60px 60px" - }} - > - {useDesktopBlockBetLayout ? (
Added / After Commit
+ diff --git a/src/components/racing/MarketCard.tsx b/src/components/racing/MarketCard.tsx + index 3779fb9..9de3cf9 100644 + const isToteMarket = raceType === "ToteMarket" + const showBlockBetting = isWinnerBlockMarket(market) + const isMobile = typeof window !== "undefined" && window.innerWidth < 768 + + // Check if any runner has jersey image URL (API sends 'jersey' field) + const hasAnyJerseyImage = market.odds.some(runner => + runner.jersey || runner.runner?.jersey + ) + + const mobileBlockBetGridColumns = isToteMarket + ? "minmax(0, 1fr) 60px" + : "minmax(0, 1fr) 60px 60px" + className="grid px-[14px] py-[8px]" + style={{ + gridTemplateColumns: showBlockBetting + ? hasAnyJerseyImage ? `auto ${blockBetGridColumns}` : blockBetGridColumns
Removed / Before Commit
- diff --git a/src/pages/MultiRaceDetail.tsx b/src/pages/MultiRaceDetail.tsx - index 22679c3..6fcbee9 100644 - backOdd: number | null - back_static_volume: number | null - silkColor: string - } - - type Race = { - backOdd: toNullableNumber(runner.back_odd), - back_static_volume: toNullableNumber(runner.back_static_volume), - silkColor: getSilkColor(runnerIndex), - } - }), - } - selected ? "bg-white/[0.06]" : "hover:bg-white/[0.035]" - } ${locked || !hasBackOdd ? "cursor-not-allowed opacity-45" : "cursor-pointer"}`} - > - <span
Added / After Commit
+ diff --git a/src/pages/MultiRaceDetail.tsx b/src/pages/MultiRaceDetail.tsx + index 22679c3..6fcbee9 100644 + backOdd: number | null + back_static_volume: number | null + silkColor: string + jersey?: string + } + + type Race = { + backOdd: toNullableNumber(runner.back_odd), + back_static_volume: toNullableNumber(runner.back_static_volume), + silkColor: getSilkColor(runnerIndex), + jersey: runner.jersey || runner.runner?.jersey, + } + }), + } + selected ? "bg-white/[0.06]" : "hover:bg-white/[0.035]" + } ${locked || !hasBackOdd ? "cursor-not-allowed opacity-45" : "cursor-pointer"}`}
Removed / Before Commit
- diff --git a/src/services/racing.ts b/src/services/racing.ts - index 2c50875..4360923 100644 - back_static_volume: number | null - back_volume: number | null - lay_volume: number | null - } - - export interface MultiBetRace {
Added / After Commit
+ diff --git a/src/services/racing.ts b/src/services/racing.ts + index 2c50875..4360923 100644 + back_static_volume: number | null + back_volume: number | null + lay_volume: number | null + jersey?: string + runner?: { + runnerId: string + name: string + jersey?: string + horse_number: number + gateNo: number + jockey: string + trainer: string + } + } + + export interface MultiBetRace {
Removed / Before Commit
- diff --git a/src/types/raceMarkets.ts b/src/types/raceMarkets.ts - index e0f0bce..15c5b2d 100644 - horse_number: number - jockey: string - trainer: string - } - - export interface RunnerOdds { - runner?: Runner - runnerId?: string - name?: string - back_static_volume: number | null - back_volume: number | null - lay_static_volume: number | null
Added / After Commit
+ diff --git a/src/types/raceMarkets.ts b/src/types/raceMarkets.ts + index e0f0bce..15c5b2d 100644 + horse_number: number + jockey: string + trainer: string + jersey?: string + } + + export interface RunnerOdds { + runner?: Runner + runnerId?: string + name?: string + jersey?: string + back_static_volume: number | null + back_volume: number | null + lay_static_volume: number | null