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

Review Result ?

solutionbowl/crm-dashbaord · 61e5ceee
The commit adds a permission sync indicator component that shows a visual indicator when permissions are being refreshed. It also includes configuration adjustments for permission refresh intervals and auto-refresh settings, as well as periodic permission refresh logic in the auth hook. The implementation is clear with descriptive comments and well-structured, enhancing user experience by giving real-time feedback on permission sync status. However, the simulated API call with setTimeout in the indicator component can be improved to reflect real API responses, and more explicit error handling could be added for better robustness. There is also a minor typo in the commit message. Overall, the changes moderately increase business value by improving UX and maintaining up-to-date permissions automatically, with relatively low bug risk and decent security considerations.
Quality ?
80%
Security ?
85%
Business Value ?
70%
Maintainability ?
83%
Issues & Suggested Fixes ?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Typo In Commit Message 'Insurace' Should B...
Where commit message
Issue / Evidence typo in commit message 'insurace' should be 'insurance' and 'withdrwal' should be 'withdrawal'
Suggested Fix fix spelling for professionalism and clarity
Simulated Api Call Uses Settimeout Which M...
Where src/components/PermissionSyncIndicator.tsx:29
Issue / Evidence simulated API call uses setTimeout which might not reflect actual permission refresh status
Suggested Fix replace with real API call and update state based on actual response to improve quality and reduce bug risk
No Error Handling Around Permission Refres...
Where src/components/PermissionSyncIndicator.tsx:24-33
Issue / Evidence no error handling around permission refresh simulation
Suggested Fix add try/catch or similar error handling to improve reliability and UX
Periodic Permission Refresh Interval Sets...
Where src/hooks/useAuth.ts:47-53
Issue / Evidence periodic permission refresh interval sets an asynchronous function but the full code is missing; ensure proper error handling and cancellation logic is used to avoid memory leaks or unhandled exceptions
Suggested Fix Review and simplify this section.
Dynamic Injection Of Style Sheet In Compon...
Where src/components/PermissionSyncIndicator.tsx:113-120
Issue / Evidence dynamic injection of style sheet in component
Suggested Fix consider moving CSS animation to a dedicated stylesheet or CSS-in-JS solution for maintainability and clarity
Code Change Preview · src/components/PermissionSyncIndicator.tsx ?
Removed / Before Commit
- diff --git a/src/components/PermissionSyncIndicator.tsx b/src/components/PermissionSyncIndicator.tsx
- new file mode 100644
- index 0000000..b43c309
Added / After Commit
+ diff --git a/src/components/PermissionSyncIndicator.tsx b/src/components/PermissionSyncIndicator.tsx
+ new file mode 100644
+ index 0000000..b43c309
+ import React, { useState, useEffect } from 'react';
+ import { useAuth } from '../hooks/useAuth';
+ import authConfig from '../config/auth.config';
+ 
+ /**
+  * Permission Sync Indicator Component
+  * 
+  * Shows a visual indicator when permissions are being refreshed.
+  * Optional component - can be added to header or anywhere in the app.
+  * 
+  * Usage:
+  * <PermissionSyncIndicator />
+  */
+ const PermissionSyncIndicator: React.FC = () => {
+   const { isAuthenticated } = useAuth();
Removed / Before Commit
- diff --git a/src/config/auth.config.ts b/src/config/auth.config.ts
- new file mode 100644
- index 0000000..4046094
Added / After Commit
+ diff --git a/src/config/auth.config.ts b/src/config/auth.config.ts
+ new file mode 100644
+ index 0000000..4046094
+ /**
+  * Authentication Configuration
+  * 
+  * Configure authentication-related settings here
+  */
+ 
+ export const authConfig = {
+   /**
+    * Permission Refresh Interval (in milliseconds)
+    * 
+    * How often to automatically check for permission updates for logged-in users.
+    * This ensures that if an admin changes a user's permissions, the user will
+    * see the updated permissions without having to log out and log back in.
+    * 
+    * Default: 30000 (30 seconds)
Removed / Before Commit
- diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts
- index 6c2849d..ba11fcf 100644
- import { useState, useEffect, useMemo } from 'react';
- import authService from '../services/api/authService';
- import { UserRole } from '../services/api/types';
- 
- interface AuthUser {
- id: string;
- export const useAuth = () => {
- const [user, setUser] = useState<AuthUser | null>(null);
- const [loading, setLoading] = useState(true);
- 
- useEffect(() => {
- const currentUser = authService.getCurrentUser();
- setLoading(false);
- }, []);
- 
- Permissions auto-refreshed successfully");
Added / After Commit
+ diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts
+ index 6c2849d..ba11fcf 100644
+ import { useState, useEffect, useMemo, useRef } from 'react';
+ import authService from '../services/api/authService';
+ import { UserRole } from '../services/api/types';
+ import authConfig from '../config/auth.config';
+ 
+ interface AuthUser {
+ id: string;
+ export const useAuth = () => {
+ const [user, setUser] = useState<AuthUser | null>(null);
+ const [loading, setLoading] = useState(true);
+   const refreshIntervalRef = useRef<NodeJS.Timeout | null>(null);
+ 
+ useEffect(() => {
+ const currentUser = authService.getCurrentUser();
+ setLoading(false);
+ }, []);
Removed / Before Commit
- diff --git a/src/modules/horse/pages/Race/AdminRacepage.tsx b/src/modules/horse/pages/Race/AdminRacepage.tsx
- index 964d6a2..3b854e1 100644
- const [withdrawConfirm, setWithdrawConfirm] = useState<{
- marketId: string; runnerKey: string; runnerName: string;
- } | null>(null);
- 
- const updateRunnerToggle = useCallback(async (
- marketId: string,
- }
- 
- try {
- await withdrawRunnerFromRace({
- race_id: selectedRaceId,
- runner_id: runnerId,
- } catch (err: any) {
- toast.error(err?.response?.data?.message || "Failed to withdraw runner");
- return;
- }
Added / After Commit
+ diff --git a/src/modules/horse/pages/Race/AdminRacepage.tsx b/src/modules/horse/pages/Race/AdminRacepage.tsx
+ index 964d6a2..3b854e1 100644
+ const [withdrawConfirm, setWithdrawConfirm] = useState<{
+ marketId: string; runnerKey: string; runnerName: string;
+ } | null>(null);
+   const [withdrawLoading, setWithdrawLoading] = useState(false);
+ 
+ const updateRunnerToggle = useCallback(async (
+ marketId: string,
+ }
+ 
+ try {
+         setWithdrawLoading(true);
+ await withdrawRunnerFromRace({
+ race_id: selectedRaceId,
+ runner_id: runnerId,
+ } catch (err: any) {
+ toast.error(err?.response?.data?.message || "Failed to withdraw runner");
Removed / Before Commit
- diff --git a/src/modules/horse/pages/Race/AllRaces.tsx b/src/modules/horse/pages/Race/AllRaces.tsx
- index 6abbe88..24b8ea1 100644
- const fetchRaces = async () => {
- try {
- setLoading(true);
-       
- const response = await raceService.getAllRaces(
- currentPage,
- perPage,
- searchTerm
- );
- 
- if (response.success) {
- setRaces(response.data);
- setTotalRows(response.pagination?.total || response.data.length);
Added / After Commit
+ diff --git a/src/modules/horse/pages/Race/AllRaces.tsx b/src/modules/horse/pages/Race/AllRaces.tsx
+ index 6abbe88..24b8ea1 100644
+ const fetchRaces = async () => {
+ try {
+ setLoading(true);
+ const response = await raceService.getAllRaces(
+ currentPage,
+ perPage,
+ searchTerm
+ );
+ if (response.success) {
+ setRaces(response.data);
+ setTotalRows(response.pagination?.total || response.data.length);
Removed / Before Commit
- diff --git a/src/modules/horse/pages/Race/RaceDetail.tsx b/src/modules/horse/pages/Race/RaceDetail.tsx
- index b20c604..09b75d6 100644
- distance: string;
- start_time: string;
- status: boolean;
- event_id: {
- _id: string;
- event_name: string;
- const [punchersLoading, setPunchersLoading]     = useState(false);
- const [selectedPuncherId, setSelectedPuncherId] = useState("");
- const [assigning, setAssigning]                 = useState(false);
- 
- 
- 
- const getPuncherDisplayName = (race: RaceDetailData["race"]) => {
- }
- };
- 
Added / After Commit
+ diff --git a/src/modules/horse/pages/Race/RaceDetail.tsx b/src/modules/horse/pages/Race/RaceDetail.tsx
+ index b20c604..09b75d6 100644
+ distance: string;
+ start_time: string;
+ status: boolean;
+     insurance_bet?: boolean
+ event_id: {
+ _id: string;
+ event_name: string;
+ const [punchersLoading, setPunchersLoading]     = useState(false);
+ const [selectedPuncherId, setSelectedPuncherId] = useState("");
+ const [assigning, setAssigning]                 = useState(false);
+   const [insuranceBet, setInsuranceBet] = useState<boolean>(false);
+   const [updatingInsurance, setUpdatingInsurance] = useState(false);
+ 
+ 
+ const getPuncherDisplayName = (race: RaceDetailData["race"]) => {
+ }
Removed / Before Commit
- diff --git a/src/pages/Platforms/AdminMarketPage.tsx b/src/pages/Platforms/AdminMarketPage.tsx
- index c561a43..9fae0c5 100644
- const [withdrawConfirm, setWithdrawConfirm] = useState<{
- marketId: string; runnerKey: string; runnerName: string;
- } | null>(null);
- 
- const updateRunnerToggle = useCallback(async (
- marketId: string,
- }
- 
- try {
- await withdrawRunnerFromRace({
- race_id: selectedRaceId,
- runner_id: runnerId,
- } catch (err: any) {
- toast.error(err?.response?.data?.message || "Failed to withdraw runner");
- return;
- }
Added / After Commit
+ diff --git a/src/pages/Platforms/AdminMarketPage.tsx b/src/pages/Platforms/AdminMarketPage.tsx
+ index c561a43..9fae0c5 100644
+ const [withdrawConfirm, setWithdrawConfirm] = useState<{
+ marketId: string; runnerKey: string; runnerName: string;
+ } | null>(null);
+   const [withdrawLoading, setWithdrawLoading] = useState(false);
+ 
+ const updateRunnerToggle = useCallback(async (
+ marketId: string,
+ }
+ 
+ try {
+         setWithdrawLoading(true);
+ await withdrawRunnerFromRace({
+ race_id: selectedRaceId,
+ runner_id: runnerId,
+ } catch (err: any) {
+ toast.error(err?.response?.data?.message || "Failed to withdraw runner");
Removed / Before Commit
- diff --git a/src/pages/Platformuser/PlatformUseredit.tsx b/src/pages/Platformuser/PlatformUseredit.tsx
- index fc6468c..5fdfd16 100644
- if (hasPunchingAll || !hasPunchingChild) {
- return permissionsWithoutPunchingParent;
- }
- 
- const firstPunchingChildIndex = permissionsWithoutPunchingParent.findIndex(isPunchingChildPermission);
- 
- return [
- const navigate = useNavigate();
- const location = useLocation();
- const { id } = useParams<{ id: string }>();
-   const { userRole } = useAuth();
- const [loading, setLoading] = useState(false);
- const [saving, setSaving] = useState(false);
- const [editForm, setEditForm] = useState<EditFormState>(emptyForm);
- });
- 
Added / After Commit
+ diff --git a/src/pages/Platformuser/PlatformUseredit.tsx b/src/pages/Platformuser/PlatformUseredit.tsx
+ index fc6468c..5fdfd16 100644
+ if (hasPunchingAll || !hasPunchingChild) {
+ return permissionsWithoutPunchingParent;
+ }
+   
+ const firstPunchingChildIndex = permissionsWithoutPunchingParent.findIndex(isPunchingChildPermission);
+ 
+ return [
+ const navigate = useNavigate();
+ const location = useLocation();
+ const { id } = useParams<{ id: string }>();
+   const { userRole, refreshPermissions } = useAuth();
+ const [loading, setLoading] = useState(false);
+ const [saving, setSaving] = useState(false);
+ const [editForm, setEditForm] = useState<EditFormState>(emptyForm);
+ });
+ 
Removed / Before Commit
- diff --git a/src/services/api/authService.ts b/src/services/api/authService.ts
- index 9dffb96..a455d22 100644
- "Authorization"
- ] = `Bearer ${token}`;
- 
- Permissions refreshed after login");
- return { token, user };
- } catch (error: any) {
- console.error(
- }
- }
- 
- Admin Profile Response:", response.data);
- Updated userData with fresh permissions:", updatedUser);
- /**
- * Initialize auth (Call this once in App.tsx)
- * Automatically attach token if exists
Added / After Commit
+ diff --git a/src/services/api/authService.ts b/src/services/api/authService.ts
+ index 9dffb96..a455d22 100644
+ "Authorization"
+ ] = `Bearer ${token}`;
+ 
+       // 🔥 Fetch fresh permissions from get-admin-profile API after login
+       try {
+         await this.getAdminProfile();
+         console.log("âœ
+ Permissions refreshed after login");
+       } catch (error) {
+         console.warn("⚠️ Failed to fetch admin profile after login:", error);
+         // Don't fail login if profile fetch fails
+       }
+ 
+ return { token, user };
+ } catch (error: any) {
+ console.error(
Removed / Before Commit
- diff --git a/src/services/api/raceService.ts b/src/services/api/raceService.ts
- index 17d8fe2..5db9200 100644
- betfairEventId?: string;
- raceType?: string;
- status: boolean;
- liveUrl?: string;
- createdAt: string;
- updatedAt?: string;
Added / After Commit
+ diff --git a/src/services/api/raceService.ts b/src/services/api/raceService.ts
+ index 17d8fe2..5db9200 100644
+ betfairEventId?: string;
+ raceType?: string;
+ status: boolean;
+   insurance_bet?: boolean;
+ liveUrl?: string;
+ createdAt: string;
+ updatedAt?: string;