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

Review Result ?

solutionbowl/super-admin · eb780348
This commit introduces a centralized refresh toggle feature with a UI component, hook, and localStorage sync across many parts of the app. The toggle allows users to enable or disable automatic refreshes, which can improve UX by controlling data fetching behavior. The implementation includes proper syncing of state on storage and custom events. However, there is mild risk of subtle bugs if state read/write from localStorage is inconsistent or if the window object is not available (e.g., server-side rendering). No immediate security concerns are apparent since the feature deals mostly with UI state and local storage without sensitive data exposure. The commit message is minimal and could be more descriptive. The widespread integration indicates good business value by improving user control over refresh behavior across features.
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
Commit Message Is Too Terse And Unclear
Where commit message
Issue / Evidence commit message is too terse and unclear
Suggested Fix provide a descriptive summary of what the refresh toggle does and its impact to improve clarity and documentation
Client Environment Assumption
Where src/hooks/useRefreshToggle.ts:7
Issue / Evidence client environment assumption
Suggested Fix add a fallback or safeguard for server-side rendering to ensure no runtime errors when window is undefined
Localstorage Setitem Error Handling
Where src/hooks/useRefreshToggle.ts:13
Issue / Evidence localStorage setItem error handling
Suggested Fix consider wrapping localStorage calls in try-catch blocks to handle possible storage quota exceeded errors gracefully
Event Listeners Not Typed
Where src/hooks/useRefreshToggle.ts:28
Issue / Evidence event listeners not typed
Suggested Fix add typings for the event listener callback parameters for better type safety
Conditional Classname Assembly
Where src/components/common/RefreshToggle.tsx:16
Issue / Evidence conditional className assembly
Suggested Fix consider using a more robust classnames utility or approach to avoid possible class concatenation errors, e.g. using cn with object syntax
Usecallback Dependency List
Where src/hooks/useRefreshToggle.ts:39
Issue / Evidence useCallback dependency list
Suggested Fix confirm if any dependencies need to be added to useCallback hook's dependency array for correctness
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(),