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

Review Result ?

solutionbowl/website · e698d220
The commit adds UI components and styling for transaction cards and tabs, improving user experience by providing detailed bet information with copy-to-clipboard functionality and responsive filters. Code is mostly well-structured with appropriate usage of hooks and components. However, there are minor redundancies and some areas could improve security and robustness, such as clipboard API usage and error handling improvements.
Quality ?
80%
Security ?
60%
Business Value ?
70%
Maintainability ?
80%
Issues & Suggested Fixes ?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Clipboard.writetext Called Without Error H...
Where src/components/transactions/TransactionCard.tsx:27
Issue / Evidence clipboard.writeText called without error handling
Suggested Fix add try-catch or fallback to improve security and user feedback
Redundant Setcountries Call On The Same Da...
Where src/pages/HorseRacing.tsx:52
Issue / Evidence redundant setCountries call on the same data
Suggested Fix remove duplicate to improve code clarity and reduce potential bugs
Detailrow Component Accepts 'Any' Type Pro...
Where src/components/transactions/TransactionCard.tsx:13
Issue / Evidence DetailRow component accepts 'any' type props
Suggested Fix add stricter typing for better type-safety and code quality
Missing Detailed Description
Where commit message
Issue / Evidence missing detailed description
Suggested Fix improve commit message by summarizing actual changes to improve traceability and business value understanding
Catch Block Only Logs Error
Where src/pages/HorseRacing.tsx:36
Issue / Evidence catch block only logs error
Suggested Fix add user-friendly error handling or retry mechanisms to reduce bug risk and improve UX
Code Change Preview · src/components/transactions/TransactionCard.tsx ?
Removed / Before Commit
- diff --git a/src/components/transactions/TransactionCard.tsx b/src/components/transactions/TransactionCard.tsx
- index e8d591b..fc690b9 100644
- import { useState } from "react";
- import { formatDate, formatStatusLabel, typeColor } from "./helpers";
- import { ChevronDown, ChevronUp, Flag, User, Target, TrendingUp, Calendar, Hash, CheckCircle, Copy } from "lucide-react";
- 
- export default function TransactionCard({ row, colors, historyType = "single", betType = "current" }: any) {
- const [isExpanded, setIsExpanded] = useState(false);
- 
- if (historyType === "multi") {
- return (
-       <div 
-         className="rounded-[12px] overflow-hidden border-l-4"
-         style={{ 
-           backgroundColor: colors.secondary,
-           borderLeftColor: row.bet_status === "WON" ? "#4ade80" : row.bet_status === "LOST" ? "#f87171" : "#fbbf24"
-         }}
- >
Added / After Commit
+ diff --git a/src/components/transactions/TransactionCard.tsx b/src/components/transactions/TransactionCard.tsx
+ index e8d591b..fc690b9 100644
+ import { useState } from "react";
+ import { formatDate, formatStatusLabel, typeColor } from "./helpers";
+ import { ChevronDown, ChevronUp, CheckCircle, Copy, Hash, Calendar } from "lucide-react";
+ 
+ const getStatusStyles = (status = "") => {
+   const s = status.toUpperCase();
+   if (s === "WON") return { color: "#16a34a", bg: "#dcfce7" };
+   if (s === "LOST") return { color: "#dc2626", bg: "#fee2e2" };
+   if (s === "VOID" || s === "CANCELLED") return { color: "#475569", bg: "#e2e8f0" };
+   return { color: "#ca8a04", bg: "#fef3c7" };
+ };
+ 
+ function DetailRow({ icon, label, value, colors, valueClassName = "", copyable = false }: any) {
+   const [copied, setCopied] = useState(false);
+   return (
+     <div className="flex items-center justify-between py-[5px] border-b last:border-0" style={{ borderColor: `${colors.secondary}60` }}>
Removed / Before Commit
- diff --git a/src/components/transactions/TransactionRow.tsx b/src/components/transactions/TransactionRow.tsx
- index f468c72..2a986ae 100644
- label: "Odds",
- value: row.odds_request || row.odds_matched || "-",
- icon: TrendingUp,
-           color: colors.primary,
- chip: true,
- },
- {
- color: oddsTypeColor,
- chip: true,
- },
- {
- label: "Odds",
- value: row.odds_request || row.odds_matched || "-",
- icon: TrendingUp,
-           color: colors.primary,
- chip: true,
Added / After Commit
+ diff --git a/src/components/transactions/TransactionRow.tsx b/src/components/transactions/TransactionRow.tsx
+ index f468c72..2a986ae 100644
+ label: "Odds",
+ value: row.odds_request || row.odds_matched || "-",
+ icon: TrendingUp,
+           color: colors.accent,
+ chip: true,
+ },
+ {
+ color: oddsTypeColor,
+ chip: true,
+ },
+ 
+ {
+ label: "Odds",
+ value: row.odds_request || row.odds_matched || "-",
+ icon: TrendingUp,
+           color: colors.accent,
Removed / Before Commit
- diff --git a/src/components/transactions/TransactionTabs.tsx b/src/components/transactions/TransactionTabs.tsx
- index b76fe24..69753a7 100644
- import { useRef, useState } from "react";
- import type { TransactionFilters } from "./helpers";
- import { Calendar, ChevronDown,  Clock3, History, RotateCcw } from "lucide-react";
- 
- // const TABS = ['Bet History', 'Deposit', 'Withdraw'];
- 
- return (
- <div className="pt-[10px]">
- <div
-           className="mb-4 rounded-[10px] border px-4 py-4 shadow-sm"
- style={{
- borderColor: `${colors.primary}35`,
- }}
- borderColor: `${colors.secondary}70`,
- }}
- >
Added / After Commit
+ diff --git a/src/components/transactions/TransactionTabs.tsx b/src/components/transactions/TransactionTabs.tsx
+ index b76fe24..69753a7 100644
+ import { useRef, useState } from "react";
+ import type { TransactionFilters } from "./helpers";
+ import { Calendar, ChevronDown, Clock3, Filter, History, RotateCcw } from "lucide-react";
+ 
+ // const TABS = ['Bet History', 'Deposit', 'Withdraw'];
+ 
+ return (
+ <div className="pt-[10px]">
+ <div
+           className="hidden md:block mb-4 rounded-[10px] border px-4 py-4 shadow-sm"
+ style={{
+ borderColor: `${colors.primary}35`,
+ }}
+ borderColor: `${colors.secondary}70`,
+ }}
+ >
Removed / Before Commit
- diff --git a/src/hooks/useThemeColors.ts b/src/hooks/useThemeColors.ts
- index eaef4af..242dc78 100644
- primary: theme?.primaryColor ?? '#0052CC',
- secondary: theme?.secondaryColor ?? '#6B7280',
- background: theme?.backgroundColor ?? '#1C1B22',
-     accent: theme?.accentColor ?? '#0052CC',
- card: theme?.cardColor ?? '#2A2A2A',
- textPrimary: theme?.textPrimary ?? '#FFFFFF',
- textSecondary: theme?.textSecondary ?? '#9CA3AF',
- success: theme?.successColor ?? '#10B981',
- warning: theme?.warningColor ?? '#F59E0B',
- error: theme?.errorColor ?? '#EF4444',
- };
- };
Added / After Commit
+ diff --git a/src/hooks/useThemeColors.ts b/src/hooks/useThemeColors.ts
+ index eaef4af..242dc78 100644
+ primary: theme?.primaryColor ?? '#0052CC',
+ secondary: theme?.secondaryColor ?? '#6B7280',
+ background: theme?.backgroundColor ?? '#1C1B22',
+     accent: theme?.accentColor ?? '#3284ff',
+ card: theme?.cardColor ?? '#2A2A2A',
+ textPrimary: theme?.textPrimary ?? '#FFFFFF',
+ textSecondary: theme?.textSecondary ?? '#9CA3AF',
+ success: theme?.successColor ?? '#10B981',
+ warning: theme?.warningColor ?? '#F59E0B',
+ error: theme?.errorColor ?? '#EF4444',
+     
+ };
+ };
Removed / Before Commit
- diff --git a/src/main.tsx b/src/main.tsx
- index cac0984..f63e7ab 100644
- import { StrictMode } from 'react'
- import { createRoot } from 'react-dom/client'
- import './index.css'
- import App from './App.tsx'
- import '@fortawesome/fontawesome-free/css/all.min.css';
- 
- createRoot(document.getElementById('root')!).render(
-   <StrictMode>
- <ConfigProvider>
- <AuthProvider>
- <GlobalAuthModalProvider>
- </GlobalAuthModalProvider>
- </AuthProvider>
- </ConfigProvider>
-   </StrictMode>,
- )
Added / After Commit
+ diff --git a/src/main.tsx b/src/main.tsx
+ index cac0984..f63e7ab 100644
+ // import { StrictMode } from 'react'
+ import { createRoot } from 'react-dom/client'
+ import './index.css'
+ import App from './App.tsx'
+ import '@fortawesome/fontawesome-free/css/all.min.css';
+ 
+ createRoot(document.getElementById('root')!).render(
+   // <StrictMode>
+ <ConfigProvider>
+ <AuthProvider>
+ <GlobalAuthModalProvider>
+ </GlobalAuthModalProvider>
+ </AuthProvider>
+ </ConfigProvider>
+   // </StrictMode>,
+ )
Removed / Before Commit
- diff --git a/src/pages/AccountStatement.tsx b/src/pages/AccountStatement.tsx
- index 1385a66..40b0b21 100644
- <h3 style={{ color: colors.textPrimary }}>Account Statement</h3>
- </div>
- 
-           <div
- className="hidden h-[35px] min-w-[260px] items-center justify-center rounded-[10px] px-4 text-[12px] font-semibold md:flex"
- style={{ backgroundColor: colors.primary, color: "#000" }}
- >
- Available Credit: {formatAmount(Number(availableCredit || 0))}
-           </div>
- </div>
- 
- <div className="mb-3 flex justify-end md:hidden">
Added / After Commit
+ diff --git a/src/pages/AccountStatement.tsx b/src/pages/AccountStatement.tsx
+ index 1385a66..40b0b21 100644
+ <h3 style={{ color: colors.textPrimary }}>Account Statement</h3>
+ </div>
+ 
+           {/* <div
+ className="hidden h-[35px] min-w-[260px] items-center justify-center rounded-[10px] px-4 text-[12px] font-semibold md:flex"
+ style={{ backgroundColor: colors.primary, color: "#000" }}
+ >
+ Available Credit: {formatAmount(Number(availableCredit || 0))}
+           </div> */}
+ </div>
+ 
+ <div className="mb-3 flex justify-end md:hidden">
Removed / Before Commit
- diff --git a/src/pages/HorseRacing.tsx b/src/pages/HorseRacing.tsx
- index 011f353..6d6887b 100644
- loadCountries()
- }, [])
- 
-   useEffect(() => {
-     if (activeCountry) {
-       loadRaceEvents(activeCountry)
-     }
-   }, [activeCountry])
- 
-   const loadCountries = async () => {
- try {
-       const data = await getCountries()
-       setCountries(data)
-       if (data.length > 0) {
-         setActiveCountry(data[0]._id)
-       }
Added / After Commit
+ diff --git a/src/pages/HorseRacing.tsx b/src/pages/HorseRacing.tsx
+ index 011f353..6d6887b 100644
+ loadCountries()
+ }, [])
+ 
+ useEffect(() => {
+   if (!activeCountry) return
+ 
+   const fetchEvents = async () => {
+     setLoading(true)
+ try {
+       const data = await getRaceEvents(activeCountry)
+       setRaceEvents(data)
+ } catch (error) {
+       console.error("Error loading race events:", error)
+ } finally {
+ setLoading(false)
+ }
Removed / Before Commit
- diff --git a/src/pages/HorseRacingDetails.tsx b/src/pages/HorseRacingDetails.tsx
- index 15b120b..2c52ae7 100644
- 
- 
- 
- const DEFAULT_FANCY_TYPE = "DEFAULT"
- const STANDALONE_FANCY_TYPES = new Set(["OBJECTION", "ODDS & EVENS", "PHOTO"])
- const MARKET_TYPE_DISPLAY_ORDER = [
- const filteredMarkets = filterMarketsBySettleFlags(marketsData.data || [], race)
- const transformedMarkets = transformRaceMarkets(filteredMarkets)
- 
-     // Fetch exposure data and merge
- try {
- const exposureResponse = await getRaceExposure(raceId)
- if (exposureResponse.success && exposureResponse.data) {
Added / After Commit
+ diff --git a/src/pages/HorseRacingDetails.tsx b/src/pages/HorseRacingDetails.tsx
+ index 15b120b..2c52ae7 100644
+ 
+ 
+ 
+ 
+ const DEFAULT_FANCY_TYPE = "DEFAULT"
+ const STANDALONE_FANCY_TYPES = new Set(["OBJECTION", "ODDS & EVENS", "PHOTO"])
+ const MARKET_TYPE_DISPLAY_ORDER = [
+ const filteredMarkets = filterMarketsBySettleFlags(marketsData.data || [], race)
+ const transformedMarkets = transformRaceMarkets(filteredMarkets)
+ 
+     
+ try {
+ const exposureResponse = await getRaceExposure(raceId)
+ if (exposureResponse.success && exposureResponse.data) {
Removed / Before Commit
- diff --git a/src/pages/RaceDetail.tsx b/src/pages/RaceDetail.tsx
- index dd43085..d09573d 100644
- 
- const [raceData, marketsData] = await Promise.all([
- getRaceDetails(raceId),
- getRaceMarkets(raceId)
- ])
- 
- setRace(raceData)
- setMarkets(marketsData.data || [])
- } catch (err) {
- if (loading) {
- return (
- <div className="flex justify-center items-center min-h-[400px]">
-         <div style={{ color: colors.textPrimary }}>Loading race details...</div>
- </div>
- )
- }
Added / After Commit
+ diff --git a/src/pages/RaceDetail.tsx b/src/pages/RaceDetail.tsx
+ index dd43085..d09573d 100644
+ 
+ const [raceData, marketsData] = await Promise.all([
+ getRaceDetails(raceId),
+           
+ getRaceMarkets(raceId)
+ ])
+         
+ setRace(raceData)
+ setMarkets(marketsData.data || [])
+ } catch (err) {
+ if (loading) {
+ return (
+ <div className="flex justify-center items-center min-h-[400px]">
+         <div style={{ color: colors.textPrimary }}>Loading race details</div>
+ </div>
+ )
Removed / Before Commit
- diff --git a/src/services/racing.ts b/src/services/racing.ts
- index ff77c9d..e929594 100644
- import type { RaceMarketsResponse } from "../types/raceMarkets"
- import { API_ENDPOINTS, getApiHeaders, getPublicApiHeaders } from "../config/api.config"
- 
- export const getCountries = async (): Promise<Country[]> => {
- const response = await fetch(`${API_ENDPOINTS.RACING}/getCountries`, {
- method: "GET",
- headers: getApiHeaders(),
- })
- 
- const data = await response.json()
- return data.data
- }
- 
- export const getRaceEvents = async (countryId: string): Promise<RaceEvent[]> => {
-   const response = await fetch(
-     `${API_ENDPOINTS.RACING}/getRaceEvents?country_id=${countryId}`,
Added / After Commit
+ diff --git a/src/services/racing.ts b/src/services/racing.ts
+ index ff77c9d..e929594 100644
+ import type { RaceMarketsResponse } from "../types/raceMarkets"
+ import { API_ENDPOINTS, getApiHeaders, getPublicApiHeaders } from "../config/api.config"
+ 
+ let countriesCache: Country[] | null = null
+ 
+ 
+ export const getCountries = async (): Promise<Country[]> => {
+   console.log(">>> getCountries API")
+ 
+   if (countriesCache) {
+     console.log("⚡ Returning cached countries")
+     return countriesCache
+   }
+ 
+ const response = await fetch(`${API_ENDPOINTS.RACING}/getCountries`, {
+ method: "GET",