Showing AI reviews for crm-dashbaord
Project AI Score ?
73%
Quality Avg ?
74%
Security Avg ?
74%
Reviews ?
130

Review Result ?

solutionbowl/crm-dashbaord · 14138afb
This commit implements the API integration to withdraw a runner from a race across three UI components and adds the relevant service call. It uses async handling with error feedback via toasts, improving UX on failure cases. However, the code lacks strong validation beyond presence checks, does not include unit or integration tests, and uses a hardcoded API endpoint which may lead to environment inflexibility. No explicit security or error handling improvements related to API responses or potential attacker inputs are seen. Overall the commit adds valuable business logic but could be improved in robustness and security.
Quality ?
85%
Security ?
50%
Business Value ?
75%
Maintainability ?
78%
Issues & Suggested Fixes ?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Hardcoded Api Endpoint
Where src/services/api/runnerWithdrawalService.ts:3
Issue / Evidence hardcoded API endpoint
Suggested Fix change to use environment configurations to support multiple deployment environments
Missing Validation
Where src/modules/horse/pages/Race/AdminRacepage.tsx:676
Issue / Evidence no input validation on runnerId and marketId beyond presence checks
Suggested Fix add stricter validation or type guards to reduce unexpected runtime errors
Missing Validation
Where src/modules/horse/pages/Race/ToteRacepage.tsx:674
Issue / Evidence no input validation on runnerId and marketId beyond presence checks
Suggested Fix add stricter validation or type guards to reduce unexpected runtime errors
Missing Validation
Where src/pages/Platforms/AdminMarketPage.tsx:713
Issue / Evidence no input validation on runnerId and marketId beyond presence checks
Suggested Fix add stricter validation or type guards to reduce unexpected runtime errors
Poor Description
Where commit message
Issue / Evidence poor description
Suggested Fix enhance commit message to include what has been implemented and how errors are handled to improve maintainability and clarity
Code Change Preview · src/modules/horse/pages/Race/AdminRacepage.tsx ?
Removed / Before Commit
- diff --git a/src/modules/horse/pages/Race/AdminRacepage.tsx b/src/modules/horse/pages/Race/AdminRacepage.tsx
- index 3978f6a..9cb6a44 100644
- import Pageheader from "../../components/pageheader/pageheader";
- 
- import { tenantServiceInstance as axiosInstance } from "../../../../services/api/axiosConfig";
- import useRaceOddsSocket from "../../hooks/useRaceOddsSocket";
- 
- /* ── Types ───────────────────────────────────────────────────── */
- };
- 
- const getRaceMarketsOddsEndpoint = (raceId: string) => `horse-racing/races/${raceId}/markets/odds`;
- const hasOwn = <T extends object>(obj: T, key: PropertyKey): key is keyof T => Object.prototype.hasOwnProperty.call(obj, key);
- 
- const buildGlobalStateMap = (marketList: Market[]) => {
- runner?.gateNo ??
- null;
- 
- const normalizeMarketType = (marketType?: string) => String(marketType ?? "").trim().toUpperCase();
Added / After Commit
+ diff --git a/src/modules/horse/pages/Race/AdminRacepage.tsx b/src/modules/horse/pages/Race/AdminRacepage.tsx
+ index 3978f6a..9cb6a44 100644
+ import Pageheader from "../../components/pageheader/pageheader";
+ 
+ import { tenantServiceInstance as axiosInstance } from "../../../../services/api/axiosConfig";
+ import { withdrawRunnerFromRace } from "../../../../services/api/runnerWithdrawalService";
+ import useRaceOddsSocket from "../../hooks/useRaceOddsSocket";
+ 
+ /* ── Types ───────────────────────────────────────────────────── */
+ };
+ 
+ const getRaceMarketsOddsEndpoint = (raceId: string) => `horse-racing/races/${raceId}/markets/odds`;
+ 
+ const hasOwn = <T extends object>(obj: T, key: PropertyKey): key is keyof T => Object.prototype.hasOwnProperty.call(obj, key);
+ 
+ const buildGlobalStateMap = (marketList: Market[]) => {
+ runner?.gateNo ??
+ null;
Removed / Before Commit
- diff --git a/src/modules/horse/pages/Race/ToteRacepage.tsx b/src/modules/horse/pages/Race/ToteRacepage.tsx
- index 86f44bc..5dc7143 100644
- import Pageheader from "../../components/pageheader/pageheader";
- 
- import { tenantServiceInstance as axiosInstance } from "../../../../services/api/axiosConfig";
- import useRaceOddsSocket from "../../hooks/useRaceOddsSocket";
- 
- 
- runner?.gateNo ??
- null;
- 
- const normalizeMarketType = (marketType?: string) => String(marketType ?? "").trim().toUpperCase();
- const isWinnerMarketType = (marketType?: string, marketName?: string) => {
- const normalizedType = normalizeMarketType(marketType);
- marketId: string; runnerKey: string; runnerName: string;
- } | null>(null);
- 
-   const updateRunnerToggle = useCallback(async (    marketId: string,
Added / After Commit
+ diff --git a/src/modules/horse/pages/Race/ToteRacepage.tsx b/src/modules/horse/pages/Race/ToteRacepage.tsx
+ index 86f44bc..5dc7143 100644
+ import Pageheader from "../../components/pageheader/pageheader";
+ 
+ import { tenantServiceInstance as axiosInstance } from "../../../../services/api/axiosConfig";
+ import { withdrawRunnerFromRace } from "../../../../services/api/runnerWithdrawalService";
+ import useRaceOddsSocket from "../../hooks/useRaceOddsSocket";
+ 
+ 
+ runner?.gateNo ??
+ null;
+ 
+ const getOddsRowRunnerId = (oddsRow?: OddsRow) =>
+   String(oddsRow?.runnerId ?? oddsRow?.runner?.runnerId ?? "").trim();
+ 
+ const normalizeMarketType = (marketType?: string) => String(marketType ?? "").trim().toUpperCase();
+ const isWinnerMarketType = (marketType?: string, marketName?: string) => {
+ const normalizedType = normalizeMarketType(marketType);
Removed / Before Commit
- diff --git a/src/pages/Platforms/AdminMarketPage.tsx b/src/pages/Platforms/AdminMarketPage.tsx
- index ab0b2d2..1e4097f 100644
- import { useParams } from "react-router-dom";
- import Pageheader from "../../modules/horse/components/pageheader/pageheader";
- import { tenantServiceInstance as axiosInstance } from "../../services/api/axiosConfig";
- import useRaceOddsSocket from "../../modules/horse/hooks/useRaceOddsSocket";
- 
- /* ── Types ───────────────────────────────────────────────────── */
- runner?.gateNo ??
- null;
- 
- const normalizeMarketType = (marketType?: string) => String(marketType ?? "").trim().toUpperCase();
- const isWinnerMarketType = (marketType?: string, marketName?: string) => {
- const normalizedType = normalizeMarketType(marketType);
- marketId: string; runnerKey: string; runnerName: string;
- } | null>(null);
- 
-   const updateRunnerToggle = useCallback(async (    marketId: string,
Added / After Commit
+ diff --git a/src/pages/Platforms/AdminMarketPage.tsx b/src/pages/Platforms/AdminMarketPage.tsx
+ index ab0b2d2..1e4097f 100644
+ import { useParams } from "react-router-dom";
+ import Pageheader from "../../modules/horse/components/pageheader/pageheader";
+ import { tenantServiceInstance as axiosInstance } from "../../services/api/axiosConfig";
+ import { withdrawRunnerFromRace } from "../../services/api/runnerWithdrawalService";
+ import useRaceOddsSocket from "../../modules/horse/hooks/useRaceOddsSocket";
+ 
+ /* ── Types ───────────────────────────────────────────────────── */
+ runner?.gateNo ??
+ null;
+ 
+ const getOddsRowRunnerId = (oddsRow?: OddsRow) =>
+   String(oddsRow?.runnerId ?? oddsRow?.runner?.runnerId ?? "").trim();
+ 
+ const normalizeMarketType = (marketType?: string) => String(marketType ?? "").trim().toUpperCase();
+ const isWinnerMarketType = (marketType?: string, marketName?: string) => {
+ const normalizedType = normalizeMarketType(marketType);
Removed / Before Commit
- diff --git a/src/services/api/runnerWithdrawalService.ts b/src/services/api/runnerWithdrawalService.ts
- new file mode 100644
- index 0000000..8540043
Added / After Commit
+ diff --git a/src/services/api/runnerWithdrawalService.ts b/src/services/api/runnerWithdrawalService.ts
+ new file mode 100644
+ index 0000000..8540043
+ import { tenantServiceInstance as axiosInstance } from "./axiosConfig";
+ 
+ const RUNNER_WITHDRAWAL_ENDPOINT = "https://api.digitalbowls.com/tenant/api/test/runnerWithdrawal";
+ 
+ export type RunnerWithdrawalPayload = {
+   race_id: string;
+   runner_id: string;
+ };
+ 
+ export const withdrawRunnerFromRace = (payload: RunnerWithdrawalPayload) =>
+   axiosInstance.post(RUNNER_WITHDRAWAL_ENDPOINT, payload);