Showing AI reviews for super-admin
Project AI Score ?
72%
Quality Avg ?
77%
Security Avg ?
64%
Reviews ?
91

Review Result ?

solutionbowl/super-admin · c9f40bb3
This commit introduces a refresh toggle component and integrates it into various parts of the app, improving user control over refresh behavior. The code uses hooks and localStorage to preserve toggle state across sessions. The implementation is clean and uses proper React patterns. However, the commit message is too brief and vague. Also, the refresh toggle is stored in localStorage with a simple true/false string, which may have limitations on security or data integrity. The impact on security is limited but could be improved with better validation or isolation of the stored value. Despite extensive usage, there is minor potential risk for race conditions or inconsistent UI state if the window event handling is not robust. Overall, the change adds real business value by enhancing UX for auto-refresh functionality and seems well implemented.
Quality ?
90%
Security ?
70%
Business Value ?
85%
Maintainability ?
90%
Issues & Suggested Fixes ?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Insufficient Description
Where commit message
Issue / Evidence insufficient description
Suggested Fix expand to clearly describe feature and its scope for better history and code review.
Missing Validation
Where src/hooks/useRefreshToggle.ts:8
Issue / Evidence localStorage value is stored as plain string with no validation
Suggested Fix consider adding validation and error handling to prevent corrupted or maliciously altered values affecting app state.
Synchronization Relies On Window Events Wh...
Where src/hooks/useRefreshToggle.ts:24-42
Issue / Evidence synchronization relies on window events which may lead to race conditions under heavy concurrent usage
Suggested Fix consider adding debounce or state consistency checks to improve robustness.
Conditional Classname Uses A Logical And W...
Where src/components/common/RefreshToggle.tsx:16
Issue / Evidence conditional className uses a logical AND which may add an invalid class if isRefreshEnabled is false
Suggested Fix change to a clearer conditional expression to avoid unexpected class names.
Code Change Preview · src/components/common/RefreshToggle.tsx ?
Removed / Before Commit
- diff --git a/src/components/common/RefreshToggle.tsx b/src/components/common/RefreshToggle.tsx
- new file mode 100644
- index 0000000..1ab716b
Added / After Commit
+ diff --git a/src/components/common/RefreshToggle.tsx b/src/components/common/RefreshToggle.tsx
+ new file mode 100644
+ index 0000000..1ab716b
+ import { RefreshCw } from "lucide-react";
+ import { Switch } from "@/components/ui/switch";
+ import { cn } from "@/lib/utils";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export function RefreshToggle() {
+   const { isRefreshEnabled, setRefreshEnabled } = useRefreshToggle();
+ 
+   return (
+     <div
+       className={cn(
+         "hidden items-center gap-2 rounded-lg bg-background px-2.5 py-1.5 ring-1 ring-border md:flex",
+         isRefreshEnabled ? "text-primary" : "text-muted-foreground",
+       )}
+     >
Removed / Before Commit
- diff --git a/src/components/top-navbar.tsx b/src/components/top-navbar.tsx
- index e8e1453..a24f6b8 100644
- } from "@/components/ui/dropdown-menu";
- import { Avatar, AvatarFallback } from "@/components/ui/avatar";
- import { useAuth } from "@/hooks/useAuth";
- 
- function useClock() {
- const [now, setNow] = useState<Date | null>(null);
- (+00:00) UTC
- <ChevronDown className="h-3 w-3 opacity-70" />
- </button>
- 
- <div className="ml-auto flex items-center gap-1.5">
- <div className="hidden md:flex flex-col items-end mr-3 leading-tight">
- <span className="text-[12px]">
- Logged in as <span className="font-bold text-gold">{displayName}</span>
Added / After Commit
+ diff --git a/src/components/top-navbar.tsx b/src/components/top-navbar.tsx
+ index e8e1453..a24f6b8 100644
+ } from "@/components/ui/dropdown-menu";
+ import { Avatar, AvatarFallback } from "@/components/ui/avatar";
+ import { useAuth } from "@/hooks/useAuth";
+ import { RefreshToggle } from "@/components/common/RefreshToggle";
+ 
+ function useClock() {
+ const [now, setNow] = useState<Date | null>(null);
+ (+00:00) UTC
+ <ChevronDown className="h-3 w-3 opacity-70" />
+ </button>
+       <RefreshToggle />
+ 
+ <div className="ml-auto flex items-center gap-1.5">
+         
+ 
+ <div className="hidden md:flex flex-col items-end mr-3 leading-tight">
Removed / Before Commit
- diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx
- index 2b24460..52a64f8 100644
- import { getEffectivePermissions, hasPanelPermission } from "@/config/panel-policy";
- import { authService } from "@/services/api/authService";
- import type { AuthUser, LoginRequest } from "@/services/api/types";
- 
- interface AuthContextValue {
- user: AuthUser | null;
- async (credentials: LoginRequest) => {
- queryClient.clear();
- const result = await authService.login(credentials);
- queryClient.clear();
- setUser(result.user);
- setIsAuthenticated(true);
- 
- const logout = useCallback(() => {
- authService.logout();
- queryClient.clear();
Added / After Commit
+ diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx
+ index 2b24460..52a64f8 100644
+ import { getEffectivePermissions, hasPanelPermission } from "@/config/panel-policy";
+ import { authService } from "@/services/api/authService";
+ import type { AuthUser, LoginRequest } from "@/services/api/types";
+ import { resetStoredRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ interface AuthContextValue {
+ user: AuthUser | null;
+ async (credentials: LoginRequest) => {
+ queryClient.clear();
+ const result = await authService.login(credentials);
+       resetStoredRefreshToggle();
+ queryClient.clear();
+ setUser(result.user);
+ setIsAuthenticated(true);
+ 
+ const logout = useCallback(() => {
Removed / Before Commit
- diff --git a/src/hooks/useAutoRefresh.ts b/src/hooks/useAutoRefresh.ts
- index 3194256..4487ba9 100644
- import { useEffect, useRef, useState } from "react";
- 
- 
- 
- export function useAutoRefresh(onRefresh: () => void, seconds = 30) {
- const [countdown, setCountdown] = useState(seconds);
- const onRefreshRef = useRef(onRefresh);
- onRefreshRef.current = onRefresh;
- 
- useEffect(() => {
- setCountdown(seconds);
- const interval = setInterval(() => {
- setCountdown((prev) => {
- if (prev <= 1) {
- });
- }, 1000);
Added / After Commit
+ diff --git a/src/hooks/useAutoRefresh.ts b/src/hooks/useAutoRefresh.ts
+ index 3194256..4487ba9 100644
+ import { useEffect, useRef, useState } from "react";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ 
+ export function useAutoRefresh(onRefresh: () => void, seconds = 30) {
+ const [countdown, setCountdown] = useState(seconds);
+ const onRefreshRef = useRef(onRefresh);
+   const { isRefreshEnabled } = useRefreshToggle();
+ onRefreshRef.current = onRefresh;
+ 
+ useEffect(() => {
+ setCountdown(seconds);
+     if (!isRefreshEnabled) return;
+ 
+ const interval = setInterval(() => {
+ setCountdown((prev) => {
Removed / Before Commit
- diff --git a/src/hooks/useRefreshToggle.ts b/src/hooks/useRefreshToggle.ts
- new file mode 100644
- index 0000000..4a6e4d7
Added / After Commit
+ diff --git a/src/hooks/useRefreshToggle.ts b/src/hooks/useRefreshToggle.ts
+ new file mode 100644
+ index 0000000..4a6e4d7
+ import { useCallback, useEffect, useState } from "react";
+ 
+ export const REFRESH_TOGGLE_STORAGE_KEY = "superAdminRefreshEnabled";
+ const REFRESH_TOGGLE_EVENT = "refresh-toggle:changed";
+ 
+ function readRefreshEnabled() {
+   if (typeof window === "undefined") return false;
+   return window.localStorage.getItem(REFRESH_TOGGLE_STORAGE_KEY) === "true";
+ }
+ 
+ export function setStoredRefreshEnabled(enabled: boolean) {
+   if (typeof window === "undefined") return;
+   window.localStorage.setItem(REFRESH_TOGGLE_STORAGE_KEY, String(enabled));
+   window.dispatchEvent(new Event(REFRESH_TOGGLE_EVENT));
+ }
Removed / Before Commit
- diff --git a/src/routes/agency-management.user-details.$userId.tsx b/src/routes/agency-management.user-details.$userId.tsx
- index d948c69..105ec20 100644
- DownlineUser,
- } from "@/services/api/internalTypes";
- import CsvExportButton from "@/components/common/CsvExportButton";
- 
- export const Route = createFileRoute("/agency-management/user-details/$userId")({
- component: UserDetailsPage,
- function UserDetailsPage() {
- const { userId } = Route.useParams();
- const [search, setSearch] = useState("");
- 
- const usersQuery = useQuery({
- queryKey: ["credit-downline-users"],
- <Button
- variant="outline"
- onClick={() => {
- usersQuery.refetch();
Added / After Commit
+ diff --git a/src/routes/agency-management.user-details.$userId.tsx b/src/routes/agency-management.user-details.$userId.tsx
+ index d948c69..105ec20 100644
+ DownlineUser,
+ } from "@/services/api/internalTypes";
+ import CsvExportButton from "@/components/common/CsvExportButton";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/agency-management/user-details/$userId")({
+ component: UserDetailsPage,
+ function UserDetailsPage() {
+ const { userId } = Route.useParams();
+ const [search, setSearch] = useState("");
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const usersQuery = useQuery({
+ queryKey: ["credit-downline-users"],
+ <Button
+ variant="outline"
Removed / Before Commit
- diff --git a/src/routes/balance.tsx b/src/routes/balance.tsx
- index 3dfed93..d260023 100644
- import { Badge } from "@/components/ui/badge";
- import { internalServices } from "@/services/api/internalServices";
- import type { CreditBalanceSummary } from "@/services/api/internalTypes";
- 
- export const Route = createFileRoute("/balance")({
- component: BalancePage,
- function BalancePage() {
- const [lookupUserId, setLookupUserId] = useState("");
- const [selectedUserId, setSelectedUserId] = useState("");
- 
- const balanceQuery = useQuery({
- queryKey: ["credit-balance-summary", selectedUserId || "current-user"],
- </Button> */}
- <Button
- variant="outline"
-                 onClick={() => balanceQuery.refetch()}
Added / After Commit
+ diff --git a/src/routes/balance.tsx b/src/routes/balance.tsx
+ index 3dfed93..d260023 100644
+ import { Badge } from "@/components/ui/badge";
+ import { internalServices } from "@/services/api/internalServices";
+ import type { CreditBalanceSummary } from "@/services/api/internalTypes";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/balance")({
+ component: BalancePage,
+ function BalancePage() {
+ const [lookupUserId, setLookupUserId] = useState("");
+ const [selectedUserId, setSelectedUserId] = useState("");
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const balanceQuery = useQuery({
+ queryKey: ["credit-balance-summary", selectedUserId || "current-user"],
+ </Button> */}
+ <Button
Removed / Before Commit
- diff --git a/src/routes/bet-list.tsx b/src/routes/bet-list.tsx
- index 9f3be0b..49b9845 100644
- import { internalServices } from "@/services/api/internalServices";
- import type { Bet, MultiBetLeg } from "@/services/api/betTypes";
- import { cn } from "@/lib/utils";
- 
- export const Route = createFileRoute("/bet-list")({
- component: BetListPage,
- });
- const [expandedMultiBetId, setExpandedMultiBetId] = useState<string | null>(null);
- const [refreshCountdown, setRefreshCountdown] = useState(refreshIntervalSeconds);
- 
- const { fromDate, toDate } = useMemo(
- () => parseDateRange(appliedFilters.dateRange),
- const activeError = isAgentMode ? agentBetsQuery.error : error;
- 
- useEffect(() => {
- const timer = window.setInterval(() => {
Added / After Commit
+ diff --git a/src/routes/bet-list.tsx b/src/routes/bet-list.tsx
+ index 9f3be0b..49b9845 100644
+ import { internalServices } from "@/services/api/internalServices";
+ import type { Bet, MultiBetLeg } from "@/services/api/betTypes";
+ import { cn } from "@/lib/utils";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/bet-list")({
+ component: BetListPage,
+ });
+ const [expandedMultiBetId, setExpandedMultiBetId] = useState<string | null>(null);
+ const [refreshCountdown, setRefreshCountdown] = useState(refreshIntervalSeconds);
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const { fromDate, toDate } = useMemo(
+ () => parseDateRange(appliedFilters.dateRange),
+ const activeError = isAgentMode ? agentBetsQuery.error : error;
+ 
Removed / Before Commit
- diff --git a/src/routes/bet-ticket.tsx b/src/routes/bet-ticket.tsx
- index e7fefbe..9a935d5 100644
- import { format } from "date-fns";
- import { useAutoRefresh } from "@/hooks/useAutoRefresh";
- import BetsExcelExportButton from "@/components/common/BetsExcelExportButton";
- 
- export const Route = createFileRoute("/bet-ticket")({
- component: BetTicketPage,
- const [maxStake, setMaxStake] = useState(1000);
- const [userName, setUserName] = useState("");
- const navigate = useNavigate();
- 
- const [applied, setApplied] = useState<BetTickerParams>(DEFAULT_PARAMS);
- const [expandedBetId, setExpandedBetId] = useState<string | null>(null);
- <div className="flex items-center gap-2">
- <Button
- className="h-9 rounded-lg gradient-plum text-white hover:opacity-90 px-6 shadow-plum"
-               onClick={() => refetch()}
Added / After Commit
+ diff --git a/src/routes/bet-ticket.tsx b/src/routes/bet-ticket.tsx
+ index e7fefbe..9a935d5 100644
+ import { format } from "date-fns";
+ import { useAutoRefresh } from "@/hooks/useAutoRefresh";
+ import BetsExcelExportButton from "@/components/common/BetsExcelExportButton";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/bet-ticket")({
+ component: BetTicketPage,
+ const [maxStake, setMaxStake] = useState(1000);
+ const [userName, setUserName] = useState("");
+ const navigate = useNavigate();
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const [applied, setApplied] = useState<BetTickerParams>(DEFAULT_PARAMS);
+ const [expandedBetId, setExpandedBetId] = useState<string | null>(null);
+ <div className="flex items-center gap-2">
+ <Button
Removed / Before Commit
- diff --git a/src/routes/blocked-ips.tsx b/src/routes/blocked-ips.tsx
- index 35e4a5a..264abe0 100644
- import { RefreshCw } from "lucide-react";
- import CsvExportButton from "@/components/common/CsvExportButton";
- import type { CsvColumn } from "@/utils/csv/types";
- 
- export const Route = createFileRoute("/blocked-ips")({
- component: BlockedIPsPage,
- const [blockForm, setBlockForm] = useState({ ipAddress: "", reason: "" });
- const pageSize = 10;
- const queryClient = useQueryClient();
- 
- // Fetch blocked IPs
- const {
- </Button>
- <Button
- variant="outline"
-               onClick={() => refetch()}
Added / After Commit
+ diff --git a/src/routes/blocked-ips.tsx b/src/routes/blocked-ips.tsx
+ index 35e4a5a..264abe0 100644
+ import { RefreshCw } from "lucide-react";
+ import CsvExportButton from "@/components/common/CsvExportButton";
+ import type { CsvColumn } from "@/utils/csv/types";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/blocked-ips")({
+ component: BlockedIPsPage,
+ const [blockForm, setBlockForm] = useState({ ipAddress: "", reason: "" });
+ const pageSize = 10;
+ const queryClient = useQueryClient();
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ // Fetch blocked IPs
+ const {
+ </Button>
+ <Button
Removed / Before Commit
- diff --git a/src/routes/credit-transactions.tsx b/src/routes/credit-transactions.tsx
- index 201bc3b..8993ff8 100644
- import { internalServices } from "@/services/api/internalServices";
- import type { CreditTransaction, CreditTransactionUser } from "@/services/api/internalTypes";
- import type { CsvColumn } from "@/utils/csv/types";
- 
- export const Route = createFileRoute("/credit-transactions")({
- component: CreditTransactionsPage,
- 
- function CreditTransactionsPage() {
- const [search, setSearch] = useState("");
- 
- const [currentPage, setCurrentPage] = useState(1);
- const pageSize = 10;
- </div>
- <Button
- variant="outline"
-                 onClick={() => transactionsQuery.refetch()}
Added / After Commit
+ diff --git a/src/routes/credit-transactions.tsx b/src/routes/credit-transactions.tsx
+ index 201bc3b..8993ff8 100644
+ import { internalServices } from "@/services/api/internalServices";
+ import type { CreditTransaction, CreditTransactionUser } from "@/services/api/internalTypes";
+ import type { CsvColumn } from "@/utils/csv/types";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/credit-transactions")({
+ component: CreditTransactionsPage,
+ 
+ function CreditTransactionsPage() {
+ const [search, setSearch] = useState("");
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const [currentPage, setCurrentPage] = useState(1);
+ const pageSize = 10;
+ </div>
+ <Button
Removed / Before Commit
- diff --git a/src/routes/marketing.tsx b/src/routes/marketing.tsx
- index 2de88f8..786e687 100644
- import { internalServices } from "@/services/api/internalServices";
- import type { Banner, BannerFormValues } from "@/services/api/internalTypes";
- import TablePagination from "@/components/common/TablePagination";
- export const Route = createFileRoute("/marketing")({
- component: MarketingPage,
- head: () => ({ meta: [{ title: "Banners - B2B-B2C Panel" }] }),
- 
- function MarketingPage() {
- const { user, hasPermission } = useAuth();
- const isOwner = getNavigationMode(getPanelRole(user)) === "full";
- const canView = isOwner || hasPermission("banner.view");
- const canCreate = isOwner || hasPermission("banner.create");
- />
- <Button
- variant="outline"
-               onClick={() => bannersQuery.refetch()}
Added / After Commit
+ diff --git a/src/routes/marketing.tsx b/src/routes/marketing.tsx
+ index 2de88f8..786e687 100644
+ import { internalServices } from "@/services/api/internalServices";
+ import type { Banner, BannerFormValues } from "@/services/api/internalTypes";
+ import TablePagination from "@/components/common/TablePagination";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ export const Route = createFileRoute("/marketing")({
+ component: MarketingPage,
+ head: () => ({ meta: [{ title: "Banners - B2B-B2C Panel" }] }),
+ 
+ function MarketingPage() {
+ const { user, hasPermission } = useAuth();
+   const { isRefreshEnabled } = useRefreshToggle();
+ const isOwner = getNavigationMode(getPanelRole(user)) === "full";
+ const canView = isOwner || hasPermission("banner.view");
+ const canCreate = isOwner || hasPermission("banner.create");
+ />
+ <Button
Removed / Before Commit
- diff --git a/src/routes/MultiBet.tsx b/src/routes/MultiBet.tsx
- index 796fdbb..c5d1083 100644
- import type { MultiBetProfitLossReport } from "@/services/api/internalServices";
- import { cn } from "@/lib/utils";
- import CsvExportButton from "@/components/common/CsvExportButton";
- 
- export const Route = createFileRoute("/MultiBet")({
- component: MultiBetReport,
- const [openDates, setOpenDates] = useState<Set<string>>(new Set());
- const [openBets, setOpenBets] = useState<Set<string>>(new Set());
- const [refreshCountdown, setRefreshCountdown] = useState(30);
- 
- const { data, isLoading, isFetching, error, refetch } = useQuery({
- queryKey: ["multi-bet-pl", applied],
- }, [data]);
- 
- useEffect(() => {
- const timer = window.setInterval(() => {
Added / After Commit
+ diff --git a/src/routes/MultiBet.tsx b/src/routes/MultiBet.tsx
+ index 796fdbb..c5d1083 100644
+ import type { MultiBetProfitLossReport } from "@/services/api/internalServices";
+ import { cn } from "@/lib/utils";
+ import CsvExportButton from "@/components/common/CsvExportButton";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/MultiBet")({
+ component: MultiBetReport,
+ const [openDates, setOpenDates] = useState<Set<string>>(new Set());
+ const [openBets, setOpenBets] = useState<Set<string>>(new Set());
+ const [refreshCountdown, setRefreshCountdown] = useState(30);
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const { data, isLoading, isFetching, error, refetch } = useQuery({
+ queryKey: ["multi-bet-pl", applied],
+ }, [data]);
+ 
Removed / Before Commit
- diff --git a/src/routes/net-exposure-bet.tsx b/src/routes/net-exposure-bet.tsx
- index b130a69..c4bf679 100644
- import { tenantApiClient } from "@/services/api/apiClient";
- import { format } from "date-fns";
- import { getExposureParams } from "@/lib/nav-params";
- 
- export const Route = createFileRoute("/net-exposure-bet")({
- component: NetExposureBetPage,
- const navigate = useNavigate();
- const [refreshCountdown, setRefreshCountdown] = useState(15);
- const [expandedBetId, setExpandedBetId] = useState<string | null>(null);
- 
- const { data, isLoading, error, refetch, isFetching } = useQuery({
- queryKey: ["net-exposure-bets", raceId, marketId, userId],
- const total = data?.total ?? 0;
- 
- useEffect(() => {
- const timer = window.setInterval(() => {
Added / After Commit
+ diff --git a/src/routes/net-exposure-bet.tsx b/src/routes/net-exposure-bet.tsx
+ index b130a69..c4bf679 100644
+ import { tenantApiClient } from "@/services/api/apiClient";
+ import { format } from "date-fns";
+ import { getExposureParams } from "@/lib/nav-params";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/net-exposure-bet")({
+ component: NetExposureBetPage,
+ const navigate = useNavigate();
+ const [refreshCountdown, setRefreshCountdown] = useState(15);
+ const [expandedBetId, setExpandedBetId] = useState<string | null>(null);
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const { data, isLoading, error, refetch, isFetching } = useQuery({
+ queryKey: ["net-exposure-bets", raceId, marketId, userId],
+ const total = data?.total ?? 0;
+ 
Removed / Before Commit
- diff --git a/src/routes/net-exposure-detail.tsx b/src/routes/net-exposure-detail.tsx
- index e139544..db2815c 100644
- };
- 
- // useEffect(() => {
- //   const timer = window.setInterval(() => {
- //     setRefreshCountdown((current) => Math.max(0, current - 1));
- //   }, 1000);
- }, [raceId, marketId]);
- 
- // useEffect(() => {
-   //   if (refreshCountdown !== 0) return;
- //   refetchAll();
- //   setRefreshCountdown(10);
-   // }, [refreshCountdown]);
- 
- // const handleManualRefresh = () => {
- //   refetchAll();
Added / After Commit
+ diff --git a/src/routes/net-exposure-detail.tsx b/src/routes/net-exposure-detail.tsx
+ index e139544..db2815c 100644
+ };
+ 
+ // useEffect(() => {
+   //   if (!isRefreshEnabled) {
+   //     setRefreshCountdown(10);
+   //     return;
+   //   }
+ //   const timer = window.setInterval(() => {
+ //     setRefreshCountdown((current) => Math.max(0, current - 1));
+ //   }, 1000);
+ }, [raceId, marketId]);
+ 
+ // useEffect(() => {
+   //   if (!isRefreshEnabled || refreshCountdown !== 0) return;
+ //   refetchAll();
+ //   setRefreshCountdown(10);
Removed / Before Commit
- diff --git a/src/routes/net-exposure-herarchy.tsx b/src/routes/net-exposure-herarchy.tsx
- index c074f5e..18f44ed 100644
- import { Button } from "@/components/ui/button";
- import { cn } from "@/lib/utils";
- import { getExposureParams } from "@/lib/nav-params";
- 
- export const Route = createFileRoute("/net-exposure-herarchy")({
- component: NetExposureHierarchyPage,
- function NetExposureHierarchyPage() {
- const { raceId, marketId, userId: initialUserId } = getExposureParams();
- const navigate = useNavigate();
- 
- const [activeUserId, setActiveUserId] = useState(initialUserId ?? "");
- const [drillStack, setDrillStack] = useState<string[]>([]);
- const downlineUsers = hierarchy.slice(1);
- 
- const handleRefresh = () => {
- hierarchyQuery.refetch();
Added / After Commit
+ diff --git a/src/routes/net-exposure-herarchy.tsx b/src/routes/net-exposure-herarchy.tsx
+ index c074f5e..18f44ed 100644
+ import { Button } from "@/components/ui/button";
+ import { cn } from "@/lib/utils";
+ import { getExposureParams } from "@/lib/nav-params";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/net-exposure-herarchy")({
+ component: NetExposureHierarchyPage,
+ function NetExposureHierarchyPage() {
+ const { raceId, marketId, userId: initialUserId } = getExposureParams();
+ const navigate = useNavigate();
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const [activeUserId, setActiveUserId] = useState(initialUserId ?? "");
+ const [drillStack, setDrillStack] = useState<string[]>([]);
+ const downlineUsers = hierarchy.slice(1);
+ 
Removed / Before Commit
- diff --git a/src/routes/net-exposure.tsx b/src/routes/net-exposure.tsx
- index 21b2b6c..d907588 100644
- import { useAutoRefresh } from "@/hooks/useAutoRefresh";
- import { internalServices } from "@/services/api/internalServices";
- import { setExposureParams } from "@/lib/nav-params";
- 
- export const Route = createFileRoute("/net-exposure")({
- component: NetExposurePage,
- function NetExposurePage() {
- const [selectedSport, setSelectedSport] = useState<SportType>("My P/L");
- const navigate = useNavigate();
- 
- const sportOptions: SportType[] = [
- "My P/L",
- <h2 className="text-xl font-bold tracking-tight">Net Exposure</h2>
- <Button
- className="h-9 rounded-lg gradient-plum text-white hover:opacity-90 px-6 shadow-plum"
-             onClick={() => refetch()}
Added / After Commit
+ diff --git a/src/routes/net-exposure.tsx b/src/routes/net-exposure.tsx
+ index 21b2b6c..d907588 100644
+ import { useAutoRefresh } from "@/hooks/useAutoRefresh";
+ import { internalServices } from "@/services/api/internalServices";
+ import { setExposureParams } from "@/lib/nav-params";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/net-exposure")({
+ component: NetExposurePage,
+ function NetExposurePage() {
+ const [selectedSport, setSelectedSport] = useState<SportType>("My P/L");
+ const navigate = useNavigate();
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const sportOptions: SportType[] = [
+ "My P/L",
+ <h2 className="text-xl font-bold tracking-tight">Net Exposure</h2>
+ <Button
Removed / Before Commit
- diff --git a/src/routes/pl-by-agent.tsx b/src/routes/pl-by-agent.tsx
- index c464e9f..a081a22 100644
- } from "@/components/ui/table";
- import { internalServices } from "@/services/api/internalServices";
- import { useReportSocket } from "@/hooks/useReportSocket";
- import type {
- ProfitLossAgentRow,
- ProfitLossDateGroup,
- );
- const [appliedFilters, setAppliedFilters] = useState(defaultFilters);
- const [refreshCountdown, setRefreshCountdown] = useState(refreshIntervalSeconds);
- 
- const reportQuery = useQuery({
- queryKey: ["horse-racing-profit-loss-by-agent", appliedFilters],
- const refetchReport = reportQuery.refetch;
- 
- const refreshAppliedReport = () => {
- refetchReport();
Added / After Commit
+ diff --git a/src/routes/pl-by-agent.tsx b/src/routes/pl-by-agent.tsx
+ index c464e9f..a081a22 100644
+ } from "@/components/ui/table";
+ import { internalServices } from "@/services/api/internalServices";
+ import { useReportSocket } from "@/hooks/useReportSocket";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ import type {
+ ProfitLossAgentRow,
+ ProfitLossDateGroup,
+ );
+ const [appliedFilters, setAppliedFilters] = useState(defaultFilters);
+ const [refreshCountdown, setRefreshCountdown] = useState(refreshIntervalSeconds);
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const reportQuery = useQuery({
+ queryKey: ["horse-racing-profit-loss-by-agent", appliedFilters],
+ const refetchReport = reportQuery.refetch;
+ 
Removed / Before Commit
- diff --git a/src/routes/pl-by-market.tsx b/src/routes/pl-by-market.tsx
- index 5fc49b6..491d0ab 100644
- } from "@/components/ui/table";
- import { internalServices } from "@/services/api/internalServices";
- import { useReportSocket } from "@/hooks/useReportSocket";
- import type {
- ProfitLossDateGroup,
- ProfitLossMarketRow,
- );
- const [appliedFilters, setAppliedFilters] = useState(defaultFilters);
- const [refreshCountdown, setRefreshCountdown] = useState(refreshIntervalSeconds);
- 
- const reportQuery = useQuery({
- queryKey: ["horse-racing-global-profit-loss", appliedFilters],
- 
- useReportSocket({
- onProfitLoss: () => {
- refetchReport();
Added / After Commit
+ diff --git a/src/routes/pl-by-market.tsx b/src/routes/pl-by-market.tsx
+ index 5fc49b6..491d0ab 100644
+ } from "@/components/ui/table";
+ import { internalServices } from "@/services/api/internalServices";
+ import { useReportSocket } from "@/hooks/useReportSocket";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ import type {
+ ProfitLossDateGroup,
+ ProfitLossMarketRow,
+ );
+ const [appliedFilters, setAppliedFilters] = useState(defaultFilters);
+ const [refreshCountdown, setRefreshCountdown] = useState(refreshIntervalSeconds);
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ const reportQuery = useQuery({
+ queryKey: ["horse-racing-global-profit-loss", appliedFilters],
+ 
+ useReportSocket({
Removed / Before Commit
- diff --git a/src/routes/statement.tsx b/src/routes/statement.tsx
- index e26a717..1ad3958 100644
- import { cn } from "@/lib/utils";
- import CsvExportButton from "@/components/common/CsvExportButton";
- import type { CsvColumn } from "@/utils/csv/types";
- 
- export const Route = createFileRoute("/statement")({
- component: StatementPage,
- function StatementPage() {
- const [searchQuery, setSearchQuery] = useState("");
- const [currentPage, setCurrentPage] = useState(1);
- const pageSize = 10;
- const transactionsQuery = useQuery({
- queryKey: ["credit-transactions"],
- </div>
- <Button
- variant="outline"
-               onClick={() => transactionsQuery.refetch()}
Added / After Commit
+ diff --git a/src/routes/statement.tsx b/src/routes/statement.tsx
+ index e26a717..1ad3958 100644
+ import { cn } from "@/lib/utils";
+ import CsvExportButton from "@/components/common/CsvExportButton";
+ import type { CsvColumn } from "@/utils/csv/types";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/statement")({
+ component: StatementPage,
+ function StatementPage() {
+ const [searchQuery, setSearchQuery] = useState("");
+ const [currentPage, setCurrentPage] = useState(1);
+   const { isRefreshEnabled } = useRefreshToggle();
+ const pageSize = 10;
+ const transactionsQuery = useQuery({
+ queryKey: ["credit-transactions"],
+ </div>
+ <Button
Removed / Before Commit
- diff --git a/src/routes/transfer-statement.tsx b/src/routes/transfer-statement.tsx
- index c5fca50..1274784 100644
- import { Input } from "@/components/ui/input";
- import CsvExportButton from "@/components/common/CsvExportButton";
- import type { CsvColumn } from "@/utils/csv/types";
- import {
- Table,
- TableBody,
- const [appliedFilters, setAppliedFilters] = useState(defaultFilters);
- const [currentPage, setCurrentPage] = useState(1);
- const [pageInput, setPageInput] = useState("1");
- 
- useEffect(() => {
- setPageInput(String(currentPage));
- 
- <Button
- type="button"
-               onClick={() => refetch()}
Added / After Commit
+ diff --git a/src/routes/transfer-statement.tsx b/src/routes/transfer-statement.tsx
+ index c5fca50..1274784 100644
+ import { Input } from "@/components/ui/input";
+ import CsvExportButton from "@/components/common/CsvExportButton";
+ import type { CsvColumn } from "@/utils/csv/types";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ import {
+ Table,
+ TableBody,
+ const [appliedFilters, setAppliedFilters] = useState(defaultFilters);
+ const [currentPage, setCurrentPage] = useState(1);
+ const [pageInput, setPageInput] = useState("1");
+   const { isRefreshEnabled } = useRefreshToggle();
+ 
+ useEffect(() => {
+ setPageInput(String(currentPage));
+ 
+ <Button
Removed / Before Commit
- diff --git a/src/routes/transfer.tsx b/src/routes/transfer.tsx
- index d1e0c96..900b345 100644
- import { createFileRoute } from "@tanstack/react-router";
- import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
- import { useMutation, useQuery } from "@tanstack/react-query";
- import { motion } from "motion/react";
- import { toast } from "sonner";
- import { Card } from "@/components/ui/card";
- TransferListUser,
- } from "@/services/api/internalTypes";
- import type { CsvColumn } from "@/utils/csv/types";
- 
- export const Route = createFileRoute("/transfer")({
- component: TransferPage,
- 
- function TransferPage() {
- const { user } = useAuth();
- const panelRole = getPanelRole(user);
Added / After Commit
+ diff --git a/src/routes/transfer.tsx b/src/routes/transfer.tsx
+ index d1e0c96..900b345 100644
+ import { createFileRoute } from "@tanstack/react-router";
+ import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+ import { motion } from "motion/react";
+ import { toast } from "sonner";
+ import { Card } from "@/components/ui/card";
+ TransferListUser,
+ } from "@/services/api/internalTypes";
+ import type { CsvColumn } from "@/utils/csv/types";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ export const Route = createFileRoute("/transfer")({
+ component: TransferPage,
+ 
+ function TransferPage() {
+ const { user } = useAuth();
Removed / Before Commit
- diff --git a/src/routes/user-details.$userId.tsx b/src/routes/user-details.$userId.tsx
- index f659b5c..b5c02fc 100644
- import { createFileRoute, useNavigate } from "@tanstack/react-router";
- import { useQuery } from "@tanstack/react-query";
- import { motion } from "motion/react";
- import { Card } from "@/components/ui/card";
- import { Button } from "@/components/ui/button";
- });
- 
- // const handleRefresh = () => {
- //   if (activeTab === "activity") refetchActivity();
- //   else if (activeTab === "balance") refetchBalance();
- //   else if (activeTab === "betlist") refetchBetList();
- {/* {activeTab !== "net-exposure" && (
- <Button
- onClick={handleRefresh}
-             disabled={isCurrentTabFetching}
- className="ml-auto h-9 rounded-lg gradient-plum text-white px-4 shadow-plum hover:opacity-90"
Added / After Commit
+ diff --git a/src/routes/user-details.$userId.tsx b/src/routes/user-details.$userId.tsx
+ index f659b5c..b5c02fc 100644
+ import { createFileRoute, useNavigate } from "@tanstack/react-router";
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
+ import { motion } from "motion/react";
+ import { Card } from "@/components/ui/card";
+ import { Button } from "@/components/ui/button";
+ });
+ 
+ // const handleRefresh = () => {
+   //   if (!isRefreshEnabled) return;
+ //   if (activeTab === "activity") refetchActivity();
+ //   else if (activeTab === "balance") refetchBalance();
+ //   else if (activeTab === "betlist") refetchBetList();
+ {/* {activeTab !== "net-exposure" && (
+ <Button
+ onClick={handleRefresh}
+             disabled={!isRefreshEnabled || isCurrentTabFetching}
Removed / Before Commit
- diff --git a/src/routes/user-exposure-detail.tsx b/src/routes/user-exposure-detail.tsx
- index e82bfb3..c9e489c 100644
- queryKey: ["net-exposure-detail", raceId, marketId, parentUserId],
- queryFn: () => fetchDetail(raceId, marketId, parentUserId),
- enabled: Boolean(raceId && marketId),
-     staleTime: 30_000,
- });
- 
- const oddsQuery = useQuery({
- queryKey: ["race-odds", raceId],
- queryFn: () => fetchOdds(raceId),
- enabled: Boolean(raceId),
-     staleTime: 30_000,
- });
- 
- const hierarchyUserId = activeUserId || parentUserId || "";
- queryKey: ["net-exposure-hierarchy", raceId, marketId, hierarchyUserId],
- queryFn: () => fetchHierarchy(raceId, marketId, hierarchyUserId),
Added / After Commit
+ diff --git a/src/routes/user-exposure-detail.tsx b/src/routes/user-exposure-detail.tsx
+ index e82bfb3..c9e489c 100644
+ queryKey: ["net-exposure-detail", raceId, marketId, parentUserId],
+ queryFn: () => fetchDetail(raceId, marketId, parentUserId),
+ enabled: Boolean(raceId && marketId),
+     refetchOnMount: "always",
+     staleTime: 0,
+ });
+ 
+ const oddsQuery = useQuery({
+ queryKey: ["race-odds", raceId],
+ queryFn: () => fetchOdds(raceId),
+ enabled: Boolean(raceId),
+     refetchOnMount: "always",
+     staleTime: 0,
+ });
+ 
+ const hierarchyUserId = activeUserId || parentUserId || "";
Removed / Before Commit
- diff --git a/src/routes/user-listing.tsx b/src/routes/user-listing.tsx
- index 0609262..4bfc704 100644
- import CsvExportButton from "@/components/common/CsvExportButton";
- import type { CsvColumn } from "@/utils/csv/types";
- import { cn } from "@/lib/utils";
- 
- const statusFilterValues = ["ACTIVE", "INACTIVE", "CLOSED"] as const;
- type StatusFilter = (typeof statusFilterValues)[number];
- const navigate = useNavigate({ from: "/user-listing" });
- const { status: statusParam } = Route.useSearch();
- const { permissions, refreshPermissions, user } = useAuth();
- const panelRole = getPanelRole(user);
- const hasFullAccess = panelRole === "owner";
- const creatableRoles = getCreatableRoles(panelRole);
- await Promise.allSettled([
- refreshPermissions(),
- queryClient.invalidateQueries({ queryKey: ["credit-transactions"] }),
- ]);
Added / After Commit
+ diff --git a/src/routes/user-listing.tsx b/src/routes/user-listing.tsx
+ index 0609262..4bfc704 100644
+ import CsvExportButton from "@/components/common/CsvExportButton";
+ import type { CsvColumn } from "@/utils/csv/types";
+ import { cn } from "@/lib/utils";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ 
+ const statusFilterValues = ["ACTIVE", "INACTIVE", "CLOSED"] as const;
+ type StatusFilter = (typeof statusFilterValues)[number];
+ const navigate = useNavigate({ from: "/user-listing" });
+ const { status: statusParam } = Route.useSearch();
+ const { permissions, refreshPermissions, user } = useAuth();
+   const { isRefreshEnabled } = useRefreshToggle();
+ const panelRole = getPanelRole(user);
+ const hasFullAccess = panelRole === "owner";
+ const creatableRoles = getCreatableRoles(panelRole);
+ await Promise.allSettled([
+ refreshPermissions(),