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 · b9fdef9f
This commit adds jersey image support to horse racing components by fetching jersey URLs from runner data and rendering the images conditionally in multiple components. The code includes defensive access to nested properties and enhances UI with jersey visuals, which may improve user experience. However, the commit lacks added tests or error handling for image loading issues.
Quality
?
85%
Security
?
80%
Business Value
?
80%
Maintainability
?
83%
Issues & Suggested Fixes
?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Potential Missing Alt Text Fallback If Hor...
Where
src/components/racing/HorseRow.tsx:518
Issue / Evidence
potential missing alt text fallback if horse_number is undefined
Suggested Fix
add fallback text for alt attribute to improve accessibility and quality score
No Error Handling For Broken/Missing Image...
Where
src/components/racing/HorseRow.tsx:519
Issue / Evidence
no error handling for broken/missing images
Suggested Fix
add onError handler to <img> elements for fallback image or hide to reduce bug risk and improve user experience
Empty <Div> Used For Spacing If Jerseys Ex...
Where
src/components/racing/MarketCard.tsx:251
Issue / Evidence
empty <div> used for spacing if jerseys exist
Suggested Fix
consider replacing with semantic element or ARIA roles for accessibility and quality
No Loading Or Error Handling For Jersey Im...
Where
src/pages/MultiRaceDetail.tsx:543
Issue / Evidence
no loading or error handling for jersey images
Suggested Fix
implement lazy loading or error fallback to improve performance and resilience
Vague And Lacks Details
Where
commit message
Issue / Evidence
vague and lacks details
Suggested Fix
improve message to describe purpose, scope, and impact of jersey image addition for better business value and review clarity
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