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
?
73%
Quality Avg
?
74%
Security Avg
?
74%
Reviews
?
130
Review Result ?
solutionbowl/crm-dashbaord · 6301f3af
The commit adds a custom hook useBets for fetching bet data and many utility functions and state management for a horse race admin page. It improves feature completeness with data handling and UI toggles but could be improved with better type usage, error handling, and documentation. The security posture is decent due to controlled API usage and error toast notifications. Low bug risk overall, though mutable states and dependency handling could be better. Fake work risk is low given meaningful feature additions.
Quality
?
85%
Security
?
80%
Business Value
?
80%
Maintainability
?
80%
Issues & Suggested Fixes
?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Generic Error Typed As 'Any', Use A More S...
Where
src/modules/horse/hooks/useBets.ts:27
Issue / Evidence
generic error typed as 'any', use a more specific error type or error handling utility to improve bug risk and quality
Suggested Fix
Review and simplify this section.
Long Function
Where
src/modules/horse/hooks/useBets.ts:10
Issue / Evidence
early return condition using 'isOwner' alongside api params could cause premature skips; clarify or decouple conditions for better correctness
Suggested Fix
Review and simplify this section.
Long Function
Where
src/modules/horse/pages/Race/AdminRacepage.tsx:114
Issue / Evidence
complex isSameRunner function could be simplified or documented for maintainability and reduced bug risk
Suggested Fix
Review and simplify this section.
Logic Assumes Missing Gateno Means Runners...
Where
src/modules/horse/pages/Race/AdminRacepage.tsx:131
Issue / Evidence
logic assumes missing gateNo means runners match; verify to avoid false positives (bug risk)
Suggested Fix
Review and simplify this section.
Multiple Nullable Fields On Odds And Runne...
Where
src/modules/horse/pages/Race/AdminRacepage.tsx:61-66
Issue / Evidence
multiple nullable fields on odds and runner data should have clearer typing instead of multiple optional nullables for better code quality
Suggested Fix
Review and simplify this section.
Long Function
Where
src/modules/horse/pages/Race/AdminRacepage.tsx:629-632
Issue / Evidence
setRunnerPercentDrafts and markets updates dependent on complex keys; add comments/documentation to improve maintainability
Suggested Fix
Review and simplify this section.
Long Function
Where
src/modules/horse/pages/Race/AdminRacepage.tsx:635-665
Issue / Evidence
applyRunnerPercent has nested, complex logic with toast notifications for error; consider extracting smaller functions for clarity and testing
Suggested Fix
Review and simplify this section.
Too Generic And Low Detail
Where
commit message
Issue / Evidence
too generic and low detail
Suggested Fix
improve commit message to include a concise summary of main changes and rationale for better traceability and business value
Code Change Preview · src/modules/horse/hooks/useBets.ts
?
Removed / Before Commit
- diff --git a/src/modules/horse/hooks/useBets.ts b/src/modules/horse/hooks/useBets.ts - new file mode 100644 - index 0000000..2d2e3bc - \ No newline at end of file
Added / After Commit
+ diff --git a/src/modules/horse/hooks/useBets.ts b/src/modules/horse/hooks/useBets.ts + new file mode 100644 + index 0000000..2d2e3bc + import { useEffect, useState } from "react"; + import { toast } from "react-toastify"; + import { tenantServiceInstance as axiosInstance } from "../../../services/api/axiosConfig"; + + export const useBets = (raceId: string | undefined, marketType: string | undefined, isOwner: boolean) => { + const [betRows, setBetRows] = useState<any[]>([]); + const [loading, setLoading] = useState(false); + + const fetchBets = async () => { + if (!raceId || !marketType || !isOwner) { + setBetRows([]); + return; + } + + try {
Removed / Before Commit
- diff --git a/src/modules/horse/pages/Race/AdminRacepage.tsx b/src/modules/horse/pages/Race/AdminRacepage.tsx - index e0b62c8..3ec68f0 100644 - runnerId?: string; - name?: string; - exposure?: number | null; - runner: { - runnerId?: string; - name?: string; - horse_number: number; - - type GlobalState = { active: boolean; suspended: boolean; inactive: boolean }; - type StatusField = keyof GlobalState; - - type UpdateOddsPayload = { - marketsData: Array<{ - lay_static_volume: number | null; - back_volume: number | null; - lay_volume: number | null;
Added / After Commit
+ diff --git a/src/modules/horse/pages/Race/AdminRacepage.tsx b/src/modules/horse/pages/Race/AdminRacepage.tsx + index e0b62c8..3ec68f0 100644 + runnerId?: string; + name?: string; + exposure?: number | null; + exposureProfit?: number | null; + back_percent?: number | null; + lay_percent?: number | null; + runner:{ + runnerId?: string; + name?: string; + horse_number: number; + + type GlobalState = { active: boolean; suspended: boolean; inactive: boolean }; + type StatusField = keyof GlobalState; + type OddsField = keyof Pick<OddsRow, "back_odd" | "lay_odd">; + + type UpdateOddsPayload = {
Removed / Before Commit
- diff --git a/src/modules/horse/pages/Race/stats.module.css b/src/modules/horse/pages/Race/stats.module.css - new file mode 100644 - index 0000000..982b42d
Added / After Commit
+ diff --git a/src/modules/horse/pages/Race/stats.module.css b/src/modules/horse/pages/Race/stats.module.css + new file mode 100644 + index 0000000..982b42d + /* Stats Page Styles */ + + .page { + background: #ffffff; + border: 1px solid #e5e7eb; + border-radius: 18px; + box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08); + overflow: hidden; + } + + .panel { + background: #ffffff; + border: 1px solid #e5e7eb; + border-radius: 14px; + color: #111827;
Removed / Before Commit
- diff --git a/src/modules/horse/pages/Race/stats.tsx b/src/modules/horse/pages/Race/stats.tsx - index 6ccf770..f56e556 100644 - import Pageheader from "../../components/pageheader/pageheader"; - import { tenantServiceInstance as axiosInstance } from "../../../../services/api/axiosConfig"; - import useRaceOddsSocket from "../../hooks/useRaceOddsSocket"; - - type Runner = { - runnerId?: string; - runnerId?: string; - runner: Runner; - exposure: number; - back_static_volume: number | null; - lay_static_volume: number | null; - back_volume: number | null; - oddsRow?.stack ?? - oddsRow?.pnl - ) ?? 0, - back_static_volume: toNullableNumber(oddsRow?.back_static_volume),
Added / After Commit
+ diff --git a/src/modules/horse/pages/Race/stats.tsx b/src/modules/horse/pages/Race/stats.tsx + index 6ccf770..f56e556 100644 + import Pageheader from "../../components/pageheader/pageheader"; + import { tenantServiceInstance as axiosInstance } from "../../../../services/api/axiosConfig"; + import useRaceOddsSocket from "../../hooks/useRaceOddsSocket"; + import { adjustOdd } from "../../utils/odds"; + import { useBets } from "../../hooks/useBets"; + import styles from "./stats.module.css"; + + type Runner = { + runnerId?: string; + runnerId?: string; + runner: Runner; + exposure: number; + exposureProfit: number; + back_static_volume: number | null; + lay_static_volume: number | null; + back_volume: number | null;
Removed / Before Commit
- diff --git a/src/modules/horse/utils/odds.tsx b/src/modules/horse/utils/odds.tsx - new file mode 100644 - index 0000000..c2a155c - \ No newline at end of file
Added / After Commit
+ diff --git a/src/modules/horse/utils/odds.tsx b/src/modules/horse/utils/odds.tsx + new file mode 100644 + index 0000000..c2a155c + export const adjustOdd = (value: number | null | undefined) => { + if (value === null || value === undefined) return value; + return value + 1; + }; + \ No newline at end of file
Removed / Before Commit
- diff --git a/src/pages/Auth/Login.tsx b/src/pages/Auth/Login.tsx - index 110034a..efdc949 100644 - // Show success message - toast.success("Login successful!"); - - // Redirect to dashboard - navigate("/dashboard"); - } catch (error: any) { - console.error("Login error:", error); - - }; - - // Quick login with predefined credentials - const handleQuickLogin = async (username: string, password: string, role: string) => { - setFormData({ username, password }); - - try { - setLoading(true);
Added / After Commit
+ diff --git a/src/pages/Auth/Login.tsx b/src/pages/Auth/Login.tsx + index 110034a..efdc949 100644 + // Show success message + toast.success("Login successful!"); + + // Get user data to check permissions + const user = authService.getCurrentUser(); + + + const permissions: string[] = Array.isArray(user?.permissions) + ? user.permissions + : []; + + const lowerPermissions = permissions.map((p: string) => p.toLowerCase()); + + const hasOnlyHorseAccess = + lowerPermissions.length === 1 && + lowerPermissions.includes("access_horses");
Removed / Before Commit
- diff --git a/src/pages/Platforms/AdminMarketPage.tsx b/src/pages/Platforms/AdminMarketPage.tsx - index 25cd5f9..0d37d7a 100644 - runnerId?: string; - name?: string; - exposure?: number | null; - runner: { - runnerId?: string; - name?: string; - horse_number: number; - - type GlobalState = { active: boolean; suspended: boolean; inactive: boolean }; - type StatusField = keyof GlobalState; - - type UpdateOddsPayload = { - marketsData: Array<{ - lay_static_volume: number | null; - back_volume: number | null; - lay_volume: number | null;
Added / After Commit
+ diff --git a/src/pages/Platforms/AdminMarketPage.tsx b/src/pages/Platforms/AdminMarketPage.tsx + index 25cd5f9..0d37d7a 100644 + runnerId?: string; + name?: string; + exposure?: number | null; + exposureProfit?: number | null; + back_percent?: number | null; + lay_percent?: number | null; + runner:{ + runnerId?: string; + name?: string; + horse_number: number; + + type GlobalState = { active: boolean; suspended: boolean; inactive: boolean }; + type StatusField = keyof GlobalState; + type OddsField = keyof Pick<OddsRow, "back_odd" | "lay_odd">; + + type UpdateOddsPayload = {
Removed / Before Commit
- diff --git a/src/pages/Races/stats.css b/src/pages/Races/stats.css - new file mode 100644 - index 0000000..d5d4cf6
Added / After Commit
+ diff --git a/src/pages/Races/stats.css b/src/pages/Races/stats.css + new file mode 100644 + index 0000000..d5d4cf6 + .stats-page { + background: #ffffff; + border: 1px solid #e5e7eb; + border-radius: 18px; + box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08); + overflow: hidden; + } + + .stats-header { + border-bottom: 1px solid #e5e7eb; + } + + .stats-heading { + color: #111827; + }
Removed / Before Commit
- diff --git a/src/pages/Races/stats.tsx b/src/pages/Races/stats.tsx - index a3cc8b0..f715624 100644 - import { authService } from "../../services/api/authService"; - import { tenantServiceInstance as axiosInstance } from "../../services/api/axiosConfig"; - import useRaceOddsSocket from "../../modules/horse/hooks/useRaceOddsSocket"; - - type Runner = { - runnerId?: string; - runnerId?: string; - runner: Runner; - exposure: number; - back_static_volume: number | null; - lay_static_volume: number | null; - back_volume: number | null; - username?: string; - phone?: string | number; - market_name?: string; - odds_type?: string;
Added / After Commit
+ diff --git a/src/pages/Races/stats.tsx b/src/pages/Races/stats.tsx + index a3cc8b0..f715624 100644 + import { authService } from "../../services/api/authService"; + import { tenantServiceInstance as axiosInstance } from "../../services/api/axiosConfig"; + import useRaceOddsSocket from "../../modules/horse/hooks/useRaceOddsSocket"; + import "./stats.css"; + + type Runner = { + runnerId?: string; + runnerId?: string; + runner: Runner; + exposure: number; + exposureProfit: number; + back_static_volume: number | null; + lay_static_volume: number | null; + back_volume: number | null; + username?: string; + phone?: string | number;