diff --git a/frontend/src/admin/AdminPanel.svelte b/frontend/src/admin/AdminPanel.svelte index 1f9a246..e290043 100644 --- a/frontend/src/admin/AdminPanel.svelte +++ b/frontend/src/admin/AdminPanel.svelte @@ -422,6 +422,13 @@ usersStore.openUser(uid); } + function closeUserCard() { + usersStore.closeUser({ skipPush: true }); + if (active === "users" || active === "payments") { + onSectionChange(active); + } + } + function resolvedAvatarUrl(user) { return userAvatarUrl(user) || (user?.email ? gravatarCache.gravatarUrl(user.email) : ""); } @@ -892,4 +899,5 @@ {trafficPercentValue} {trafficLeftLabel} {trafficOfLabel} + onClose={closeUserCard} /> diff --git a/frontend/src/admin/sections/UserDetailModal.svelte b/frontend/src/admin/sections/UserDetailModal.svelte index 1bfac32..30f5fab 100644 --- a/frontend/src/admin/sections/UserDetailModal.svelte +++ b/frontend/src/admin/sections/UserDetailModal.svelte @@ -42,6 +42,7 @@ export let userTelegramProfileLink = () => ""; export let userTelegramProfileLinkKind = () => ""; export let openTelegramProfileLink = () => false; + export let onClose = () => usersStore.closeUser(); let avatarPreviewOpen = false; let avatarPreviewUrl = ""; @@ -184,7 +185,7 @@ : ""} description={openedUser?.username ? "@" + openedUser.username : ""} closeLabel={at("close", {}, "Закрыть")} - onclose={usersStore.closeUser} + onclose={onClose} class="admin-dialog admin-user-dialog" > {#if openedUser} diff --git a/frontend/src/lib/admin/stores/usersStore.js b/frontend/src/lib/admin/stores/usersStore.js index 7a0f6a7..716e1e8 100644 --- a/frontend/src/lib/admin/stores/usersStore.js +++ b/frontend/src/lib/admin/stores/usersStore.js @@ -16,68 +16,44 @@ export function createUsersStore({ api, onToast, at, routePrefix = "" }) { usersSort: "", usersLoading: false, - ..._closedUserModalState(), + openedUser: null, + openedUserDetail: null, + userDetailLoading: false, + userMessageDraft: "", + userExtendDays: 30, + userExtendHwidDevices: true, + userActionBusy: false, + userDeleteOpen: false, + userBanConfirmOpen: false, + userMessageConfirmOpen: false, + userReferralsOpen: false, + userReferralsLoading: false, + userReferrals: [], + userReferralsTotal: 0, + userReferralsPage: 0, userReferralsPageSize: USERS_PAGE_SIZE, + userReferralsInviter: null, + userDetailTab: "profile", + premiumUnlimitedDraft: false, + premiumBonusGbDraft: "", + regularUnlimitedDraft: false, + regularBonusGbDraft: "", + hwidUnlimitedDraft: false, + hwidDeviceLimitDraft: "", + grantTrafficGbDraft: "", + grantTrafficKindDraft: "regular", + + userLogs: [], + userLogsTotal: 0, + userLogsPage: 0, + userLogsLoading: false, + userLogsLoaded: false, + userLogsUserId: null, userLogsPageSize: USER_LOGS_PAGE_SIZE, }); let _activeRef = "stats"; // fallback if active isn't tracked let _pathContext = null; - let _openUserRequestId = 0; - - function _closedUserModalState() { - return { - openedUser: null, - openedUserDetail: null, - userDetailLoading: false, - userMessageDraft: "", - userExtendDays: 30, - userExtendHwidDevices: true, - userActionBusy: false, - userDeleteOpen: false, - userBanConfirmOpen: false, - userMessageConfirmOpen: false, - userReferralsOpen: false, - userReferralsLoading: false, - userReferrals: [], - userReferralsTotal: 0, - userReferralsPage: 0, - userReferralsInviter: null, - userDetailTab: "profile", - premiumUnlimitedDraft: false, - premiumBonusGbDraft: "", - regularUnlimitedDraft: false, - regularBonusGbDraft: "", - hwidUnlimitedDraft: false, - hwidDeviceLimitDraft: "", - grantTrafficGbDraft: "", - grantTrafficKindDraft: "regular", - userLogs: [], - userLogsTotal: 0, - userLogsPage: 0, - userLogsLoading: false, - userLogsLoaded: false, - userLogsUserId: null, - }; - } - - function _openingUserModalState(user, userId) { - return { - ..._closedUserModalState(), - openedUser: user, - userDetailLoading: true, - userDetailTab: "subscription", - userLogsUserId: userId, - }; - } - - function _isCurrentUserRequest(s, requestId, userId) { - return ( - requestId === _openUserRequestId && - Boolean(s.openedUser) && - s.openedUser.user_id === userId - ); - } function setActive(active) { _activeRef = active; @@ -148,15 +124,31 @@ export function createUsersStore({ api, onToast, at, routePrefix = "" }) { const userId = typeof userOrId === "object" && userOrId !== null ? userOrId.user_id : Number(userOrId); if (!userId) return; - const requestId = ++_openUserRequestId; _setPathContext(opts.pathContext); - const openedUser = - typeof userOrId === "object" && userOrId !== null ? userOrId : { user_id: userId }; state.update((s) => ({ ...s, - ..._openingUserModalState(openedUser, userId), - userActionBusy: s.userActionBusy, + openedUser: + typeof userOrId === "object" && userOrId !== null ? userOrId : { user_id: userId }, + openedUserDetail: null, + userMessageDraft: "", + userMessageConfirmOpen: false, + userExtendDays: 30, + userExtendHwidDevices: true, + userDetailLoading: true, + userDetailTab: "subscription", + userReferralsOpen: false, + userReferralsLoading: false, + userReferrals: [], + userReferralsTotal: 0, + userReferralsPage: 0, + userReferralsInviter: null, + userLogs: [], + userLogsTotal: 0, + userLogsPage: 0, + userLogsLoading: false, + userLogsLoaded: false, + userLogsUserId: userId, })); if (!opts.skipPush) _pushUserPath(userId); @@ -169,52 +161,54 @@ export function createUsersStore({ api, onToast, at, routePrefix = "" }) { const hasHwidLimit = sub?.hwid_device_limit !== null && sub?.hwid_device_limit !== undefined; const hwidLimit = hasHwidLimit ? Number(sub?.hwid_device_limit) : null; - state.update((s) => { - if (!_isCurrentUserRequest(s, requestId, userId)) return s; - return { - ...s, - openedUserDetail: res, - openedUser: res.user ? { ...res.user, ...s.openedUser, ...res.user } : s.openedUser, - premiumUnlimitedDraft: Boolean(sub?.premium_unlimited_override), - premiumBonusGbDraft: bonusBytes > 0 ? +(bonusBytes / 1024 ** 3).toFixed(2) : "", - regularUnlimitedDraft: Boolean(sub?.regular_unlimited_override), - regularBonusGbDraft: - regularBonusBytes > 0 ? +(regularBonusBytes / 1024 ** 3).toFixed(2) : "", - hwidUnlimitedDraft: hasHwidLimit && hwidLimit === 0, - hwidDeviceLimitDraft: hasHwidLimit && hwidLimit > 0 ? String(hwidLimit) : "", - grantTrafficGbDraft: "", - grantTrafficKindDraft: "regular", - }; - }); + state.update((s) => ({ + ...s, + openedUserDetail: res, + openedUser: res.user ? { ...res.user, ...s.openedUser, ...res.user } : s.openedUser, + premiumUnlimitedDraft: Boolean(sub?.premium_unlimited_override), + premiumBonusGbDraft: bonusBytes > 0 ? +(bonusBytes / 1024 ** 3).toFixed(2) : "", + regularUnlimitedDraft: Boolean(sub?.regular_unlimited_override), + regularBonusGbDraft: + regularBonusBytes > 0 ? +(regularBonusBytes / 1024 ** 3).toFixed(2) : "", + hwidUnlimitedDraft: hasHwidLimit && hwidLimit === 0, + hwidDeviceLimitDraft: hasHwidLimit && hwidLimit > 0 ? String(hwidLimit) : "", + grantTrafficGbDraft: "", + grantTrafficKindDraft: "regular", + })); } else { - let shouldClearPath = false; - let shouldShowError = false; - state.update((s) => { - if (!_isCurrentUserRequest(s, requestId, userId)) return s; - shouldShowError = true; - shouldClearPath = true; - _pathContext = null; - return { ...s, ..._closedUserModalState() }; - }); - if (shouldShowError) onToast(res?.error || "load_failed"); - if (shouldClearPath && !opts.skipPush) _pushUserPath(null); + onToast(res?.error || "load_failed"); + state.update((s) => ({ ...s, openedUser: null })); + if (!opts.skipPush) _pushUserPath(null); + _pathContext = null; } } finally { - state.update((s) => { - if (!_isCurrentUserRequest(s, requestId, userId)) return s; - return { ...s, userDetailLoading: false }; - }); + state.update((s) => ({ ...s, userDetailLoading: false })); } } function closeUser(opts = {}) { let wasOpen = false; - _openUserRequestId += 1; state.update((s) => { wasOpen = Boolean(s.openedUser); return { ...s, - ..._closedUserModalState(), + openedUser: null, + openedUserDetail: null, + userDeleteOpen: false, + userBanConfirmOpen: false, + userMessageConfirmOpen: false, + userReferralsOpen: false, + userReferralsLoading: false, + userReferrals: [], + userReferralsTotal: 0, + userReferralsPage: 0, + userReferralsInviter: null, + userLogs: [], + userLogsTotal: 0, + userLogsPage: 0, + userLogsLoading: false, + userLogsLoaded: false, + userLogsUserId: null, }; }); if (wasOpen && !opts.skipPush) _pushUserPath(null);