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 · b21e2ed4
The commit introduces comprehensive permission handling related to 'punching' permissions for platform users, including refined normalization and filtering mechanisms. The changes add meaningful business features controlling market access based on permissions and reflect careful permission normalization and filtering logic. The code is more secure by normalizing permissions and avoiding broad access by careful filtering. However, minor risks remain due to some complex permission logic that could harbor hidden bugs. The commit message is vague, reducing clarity somewhat.
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
Vague And Not Descriptive
Where
commit message
Issue / Evidence
vague and not descriptive
Suggested Fix
provide a detailed commit message explaining the intent, scope, and main changes for better maintainability and review clarity
Commented Out Code 'Normalizedpermissions....
Where
src/pages/Platforms/AdminMarketPage.tsx:172
Issue / Evidence
commented out code 'normalizedPermissions.includes("punching")'
Suggested Fix
remove or justify commented code to avoid confusion
Normalization Does Not Handle All Edge Cas...
Where
src/pages/Platformuser/CreatePlatformUser.tsx:72
Issue / Evidence
normalization does not handle all edge cases
Suggested Fix
consider more robust normalization such as Unicode normalization or stricter validation
Permission Checking Could Be Made More Exp...
Where
src/components/PermissionRoute.tsx:29-33
Issue / Evidence
permission checking could be made more explicit
Suggested Fix
include unit tests in codebase to cover these complex permission logics
Explicit Null Returns May Be Handled Bette...
Where
src/pages/Platforms/AdminMarketPage.tsx:160-165
Issue / Evidence
explicit null returns may be handled better with TypeScript's stricter typing
Suggested Fix
improve type safety for permission processing functions
.Filter Callback Returns False When No Mar...
Where
src/pages/Platforms/AdminMarketPage.tsx:214
Issue / Evidence
.filter callback returns false when no market type, potentially excluding markets unintentionally
Suggested Fix
review business logic to confirm this is intended
Code Change Preview · src/components/PermissionRoute.tsx
?
Removed / Before Commit
- diff --git a/src/components/PermissionRoute.tsx b/src/components/PermissionRoute.tsx - index d2bd659..8c1d968 100644 - redirectTo?: string; - } - - /** - * Guards a route by permission key. - * - Non-PLATFORM_ADMIN roles always pass through. - * - PLATFORM_ADMIN must have the permission (or "all") to access. - */ - const PermissionRoute: React.FC<PermissionRouteProps> = ({ - children, - permission, - - if (userRole !== 'PLATFORM_ADMIN') return <>{children}</>; - - // Original PLATFORM_ADMIN (no permissions set) → full access - if (permissions.length === 0) return <>{children}</>;
Added / After Commit
+ diff --git a/src/components/PermissionRoute.tsx b/src/components/PermissionRoute.tsx + index d2bd659..8c1d968 100644 + redirectTo?: string; + } + + + const PermissionRoute: React.FC<PermissionRouteProps> = ({ + children, + permission, + + if (userRole !== 'PLATFORM_ADMIN') return <>{children}</>; + + // Original PLATFORM_ADMIN (no permissions set) gets full access. + if (permissions.length === 0) return <>{children}</>; + + const requiredPermission = permission.toLowerCase(); + const normalizedPermissions = permissions.map(p => p.toLowerCase()); +
Removed / Before Commit
- diff --git a/src/components/sidebar/nav.tsx b/src/components/sidebar/nav.tsx - index fd0df7a..356f590 100644 - - const punchingItem = linkIcon("punching", "Punching", Punchingicon); - - export const getMenuItemsByRole = (userRole: string | null, permissions: string[] = []): any[] => { - - if (userRole === 'OWNER') { - // Sub PLATFORM_ADMIN — show only permitted sections - const perms = permissions.map(p => p.toLowerCase()); - const hasAll = perms.includes('all'); - const hasDashboard = hasAll || perms.includes('dashboard'); - const hasUsers = hasAll || perms.includes('users'); - const hasPlatform = hasAll || perms.includes('platform'); - const hasPunching = hasAll || perms.includes('punching'); - - const items: any[] = [];
Added / After Commit
+ diff --git a/src/components/sidebar/nav.tsx b/src/components/sidebar/nav.tsx + index fd0df7a..356f590 100644 + + const punchingItem = linkIcon("punching", "Punching", Punchingicon); + + const hasPermissionPrefix = (permissions: string[], section: string) => { + const sectionKey = section.toLowerCase(); + + return permissions.some((permission) => ( + permission === sectionKey || + permission === `${sectionKey}.all` || + permission.startsWith(`${sectionKey}.`) + )); + }; + + export const getMenuItemsByRole = (userRole: string | null, permissions: string[] = []): any[] => { + + if (userRole === 'OWNER') {
Removed / Before Commit
- diff --git a/src/pages/Dashboard/Dashboard.tsx b/src/pages/Dashboard/Dashboard.tsx - index dbc7056..e79bf44 100644 - userRole !== "PLATFORM_ADMIN" || - permissions.length === 0 || - perms.includes("all") || - perms.includes("dashboard"); - - // date range - const [startDate, setStartDate] = useState(new Date()); - const today = new Date();
Added / After Commit
+ diff --git a/src/pages/Dashboard/Dashboard.tsx b/src/pages/Dashboard/Dashboard.tsx + index dbc7056..e79bf44 100644 + userRole !== "PLATFORM_ADMIN" || + permissions.length === 0 || + perms.includes("all") || + + perms.includes("dashboard"); + // date range + const [startDate, setStartDate] = useState(new Date()); + const today = new Date();
Removed / Before Commit
- diff --git a/src/pages/Platforms/AdminMarketPage.tsx b/src/pages/Platforms/AdminMarketPage.tsx - index 125169e..86256c7 100644 - import { tenantServiceInstance as axiosInstance } from "../../services/api/axiosConfig"; - import { withdrawRunnerFromRace } from "../../services/api/runnerWithdrawalService"; - import useRaceOddsSocket from "../../modules/horse/hooks/useRaceOddsSocket"; - - /* ── Types ───────────────────────────────────────────────────── */ - type AssignedRace = { _id: string; race_name: string; assigned_puncher_name?: string }; - }>; - }; - - const getRaceMarketsOddsEndpoint = (raceId: string) => `horse-racing/races/${raceId}/markets/odds`; - const getAssignedRaceLabel = (race: AssignedRace) => - race.assigned_puncher_name - String(oddsRow?.runnerId ?? oddsRow?.runner?.runnerId ?? "").trim(); - - const normalizeMarketType = (marketType?: string) => String(marketType ?? "").trim().toUpperCase(); - const isWinnerMarketType = (marketType?: string, marketName?: string) => {
Added / After Commit
+ diff --git a/src/pages/Platforms/AdminMarketPage.tsx b/src/pages/Platforms/AdminMarketPage.tsx + index 125169e..86256c7 100644 + import { tenantServiceInstance as axiosInstance } from "../../services/api/axiosConfig"; + import { withdrawRunnerFromRace } from "../../services/api/runnerWithdrawalService"; + import useRaceOddsSocket from "../../modules/horse/hooks/useRaceOddsSocket"; + import { useAuth } from "../../hooks/useAuth"; + + /* ── Types ───────────────────────────────────────────────────── */ + type AssignedRace = { _id: string; race_name: string; assigned_puncher_name?: string }; + }>; + }; + + type PermissionMarketType = "WIN" | "2PLACES" | "3PLACES" | "4PLACES" | "FANCY"; + + const getRaceMarketsOddsEndpoint = (raceId: string) => `horse-racing/races/${raceId}/markets/odds`; + const getAssignedRaceLabel = (race: AssignedRace) => + race.assigned_puncher_name + String(oddsRow?.runnerId ?? oddsRow?.runner?.runnerId ?? "").trim();
Removed / Before Commit
- diff --git a/src/pages/Platformuser/CreatePlatformUser.tsx b/src/pages/Platformuser/CreatePlatformUser.tsx - index 5bfed71..ae9df71 100644 - import React, { Fragment, useEffect, useRef, useState } from "react"; - import { Alert, Button, Card, Col, Form, Modal, Row, Spinner } from "react-bootstrap"; - import Pageheader from "../../components/pageheader/pageheader"; - import { useNavigate } from "react-router-dom"; - import { useAuth } from "../../hooks/useAuth"; - import { platformUserService } from "../../services/api/platformUserService"; - - const PERMISSIONS = [ - { key: "all", label: "All" }, - { key: "dashboard", label: "Dashboard" }, - { key: "users", label: "Users" }, - { key: "platform", label: "Platform" }, - { key: "access_horses", label: "Access Horses" }, - { key: "punching", label: "Punching" }, - ]; -
Added / After Commit
+ diff --git a/src/pages/Platformuser/CreatePlatformUser.tsx b/src/pages/Platformuser/CreatePlatformUser.tsx + index 5bfed71..ae9df71 100644 + import React, { Fragment, useEffect, useState } from "react"; + import { Alert, Button, Card, Col, Form, Modal, Row, Spinner } from "react-bootstrap"; + import Pageheader from "../../components/pageheader/pageheader"; + import { useNavigate } from "react-router-dom"; + import { useAuth } from "../../hooks/useAuth"; + import { platformUserService } from "../../services/api/platformUserService"; + + const STATIC_PERMISSION_ACCESS = [ + { + + key: "dashboard", + label: "Dashboard", + icon: "ri-dashboard-line", + items: [ + { key: "dashboard.view", label: "View Dashboard" }, + ],