From 853e1c9c8477c028a7046e1c83c3089b00847cb9 Mon Sep 17 00:00:00 2001 From: Fringg Date: Wed, 29 Apr 2026 06:22:38 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20user=20detail=20=E2=80=94=20separate=20r?= =?UTF-8?q?equest=20history=20sub=20selector,=20split=20mount=20effects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Request history subscription selector no longer mutates shared activeSubscriptionId — uses independent requestHistorySubId state - Request history reloads when subscription selector changes - Split mount effect: loadPanelInfo in separate effect to avoid redundant loadUser calls when activeSubscriptionId changes --- src/pages/AdminUserDetail.tsx | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/pages/AdminUserDetail.tsx b/src/pages/AdminUserDetail.tsx index 20bacb3..e4baf70 100644 --- a/src/pages/AdminUserDetail.tsx +++ b/src/pages/AdminUserDetail.tsx @@ -390,6 +390,7 @@ export default function AdminUserDetail() { const [requestHistoryOffset, setRequestHistoryOffset] = useState(0); const [requestHistoryTotal, setRequestHistoryTotal] = useState(0); const [requestHistoryExpanded, setRequestHistoryExpanded] = useState(false); + const [requestHistorySubId, setRequestHistorySubId] = useState(null); const userId = id ? parseInt(id, 10) : null; @@ -498,7 +499,7 @@ export default function AdminUserDetail() { setRequestHistoryLoading(true); const data = await adminUsersApi.getSubscriptionRequestHistory( userId, - activeSubscriptionId ?? undefined, + requestHistorySubId ?? undefined, offset, 20, ); @@ -511,7 +512,7 @@ export default function AdminUserDetail() { setRequestHistoryLoading(false); } }, - [userId, activeSubscriptionId], + [userId, requestHistorySubId], ); const loadNodeUsage = useCallback(async () => { @@ -606,8 +607,22 @@ export default function AdminUserDetail() { return; } loadUser(); + }, [userId, loadUser, navigate]); + + // Load panel info when subscription changes (separate from mount to avoid redundant loadUser) + useEffect(() => { + if (!userId || isNaN(userId)) return; loadPanelInfo(); - }, [userId, loadUser, loadPanelInfo, navigate]); + }, [userId, loadPanelInfo]); + + // Reload request history when the request-history subscription selector changes + useEffect(() => { + if (!requestHistoryExpanded || requestHistorySubId === null) return; + setRequestHistory([]); + setRequestHistoryOffset(0); + setRequestHistoryTotal(0); + loadRequestHistory(0); + }, [requestHistorySubId]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { if (activeTab === 'info') { @@ -860,6 +875,7 @@ export default function AdminUserDetail() { if (user && userSubscriptions.length > 0 && !hasAutoSelectedSub.current) { const activeSub = userSubscriptions.find((s) => s.is_active) ?? userSubscriptions[0]; setActiveSubscriptionId(activeSub.id); + setRequestHistorySubId(activeSub.id); hasAutoSelectedSub.current = true; } }, [user, userSubscriptions]); @@ -2511,13 +2527,9 @@ export default function AdminUserDetail() { {userSubscriptions.length > 1 && (