diff --git a/src/locales/en.json b/src/locales/en.json index 2885ce5..ef4ea57 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -3118,6 +3118,8 @@ "noReferrals": "No referrals yet", "removeReferral": "Remove referral", "referralRemoved": "Referral removed successfully", + "addReferral": "Add Referral", + "referralAdded": "Referral added successfully", "searchPlaceholder": "Search by name, email, or Telegram ID...", "alreadyReferred": "already has referrer", "noUsersFound": "No users found" diff --git a/src/locales/fa.json b/src/locales/fa.json index 950ec6a..3cf08b8 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -2736,6 +2736,8 @@ "noReferrals": "هنوز معرفی‌ای نیست", "removeReferral": "حذف معرفی", "referralRemoved": "معرفی حذف شد", + "addReferral": "افزودن معرفی", + "referralAdded": "معرفی اضافه شد", "searchPlaceholder": "جستجو بر اساس نام، ایمیل یا شناسه تلگرام...", "alreadyReferred": "قبلاً معرفی شده", "noUsersFound": "کاربری یافت نشد" diff --git a/src/locales/ru.json b/src/locales/ru.json index ef17dc3..12fdadb 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -3629,6 +3629,8 @@ "noReferrals": "Рефералов пока нет", "removeReferral": "Удалить реферала", "referralRemoved": "Реферал удалён", + "addReferral": "Добавить реферала", + "referralAdded": "Реферал добавлен", "searchPlaceholder": "Поиск по имени, email или Telegram ID...", "alreadyReferred": "уже чей-то реферал", "noUsersFound": "Пользователи не найдены" diff --git a/src/locales/zh.json b/src/locales/zh.json index 712540c..aa9e1d8 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -2735,6 +2735,8 @@ "noReferrals": "暂无推荐", "removeReferral": "移除推荐", "referralRemoved": "推荐已移除", + "addReferral": "添加推荐", + "referralAdded": "推荐已添加", "searchPlaceholder": "按名称、邮箱或 Telegram ID 搜索...", "alreadyReferred": "已有推荐人", "noUsersFound": "未找到用户" diff --git a/src/pages/AdminUserDetail.tsx b/src/pages/AdminUserDetail.tsx index 053a023..c7840ba 100644 --- a/src/pages/AdminUserDetail.tsx +++ b/src/pages/AdminUserDetail.tsx @@ -315,6 +315,12 @@ export default function AdminUserDetail() { const [referrerSearchResults, setReferrerSearchResults] = useState([]); const [referrerSearchLoading, setReferrerSearchLoading] = useState(false); const referrerSearchRef = useRef(null); + // Add referral (bind someone as this user's referral) + const [showAddReferral, setShowAddReferral] = useState(false); + const [addReferralSearchQuery, setAddReferralSearchQuery] = useState(''); + const [addReferralSearchResults, setAddReferralSearchResults] = useState([]); + const [addReferralSearchLoading, setAddReferralSearchLoading] = useState(false); + const addReferralSearchRef = useRef(null); // Panel info & node usage const [panelInfo, setPanelInfo] = useState(null); @@ -950,6 +956,26 @@ export default function AdminUserDetail() { } }; + // Add a referral: assign current user as referrer of selected user + const handleAddReferral = async (targetUserId: number) => { + if (!userId) return; + setActionLoading(true); + try { + await adminUsersApi.assignReferrer(targetUserId, userId); + await loadReferralsList(); + await loadUser(); + setShowAddReferral(false); + setAddReferralSearchQuery(''); + setAddReferralSearchResults([]); + notify.success(t('admin.users.detail.referrals.referralAdded')); + } catch (error: unknown) { + const axiosErr = error as { response?: { data?: { detail?: string } } }; + notify.error(axiosErr?.response?.data?.detail || t('common.error')); + } finally { + setActionLoading(false); + } + }; + // Referrals tab: debounced user search for referrer assignment useEffect(() => { if (referrerSearchQuery.length < 2 || !showReferrerSearch) { @@ -994,6 +1020,53 @@ export default function AdminUserDetail() { } }, [showReferrerSearch]); + // Referrals tab: debounced search for adding referral + useEffect(() => { + if (addReferralSearchQuery.length < 2 || !showAddReferral) { + setAddReferralSearchResults([]); + setAddReferralSearchLoading(false); + return; + } + setAddReferralSearchLoading(true); + let cancelled = false; + const timer = setTimeout(async () => { + try { + const data = await adminUsersApi.getUsers({ search: addReferralSearchQuery, limit: 10 }); + if (!cancelled) { + setAddReferralSearchResults(data.users || []); + setAddReferralSearchLoading(false); + } + } catch { + if (!cancelled) { + setAddReferralSearchResults([]); + setAddReferralSearchLoading(false); + } + } + }, 300); + return () => { + cancelled = true; + clearTimeout(timer); + }; + }, [addReferralSearchQuery, showAddReferral]); + + // Referrals tab: close add-referral dropdown on click outside + useEffect(() => { + const handleClickOutside = (e: MouseEvent) => { + if ( + addReferralSearchRef.current && + !addReferralSearchRef.current.contains(e.target as Node) + ) { + setShowAddReferral(false); + setAddReferralSearchQuery(''); + setAddReferralSearchResults([]); + } + }; + if (showAddReferral) { + document.addEventListener('mousedown', handleClickOutside); + return () => document.removeEventListener('mousedown', handleClickOutside); + } + }, [showAddReferral]); + const handleResetTrial = async () => { if (!userId) return; setActionLoading(true); @@ -3146,8 +3219,80 @@ export default function AdminUserDetail() {

{t('admin.users.detail.referrals.referralsList')} ({referralsTotal})

+ {!showAddReferral && ( + + )} + {/* Add referral search */} + {showAddReferral && ( +
+
+ setAddReferralSearchQuery(e.target.value)} + placeholder={t('admin.users.detail.referrals.searchPlaceholder')} + className="flex-1 rounded-lg border border-dark-600 bg-dark-700 px-3 py-2.5 text-sm text-dark-100 placeholder-dark-500 focus:border-accent-500 focus:outline-none" + autoFocus + /> + +
+ {addReferralSearchQuery.length >= 2 && addReferralSearchResults.length > 0 && ( +
+ {addReferralSearchResults + .filter((u) => u.id !== userId) + .map((u) => ( + + ))} + {addReferralSearchResults.filter((u) => u.id !== userId).length === 0 && ( +
+ {t('admin.users.detail.referrals.noUsersFound')} +
+ )} +
+ )} + {addReferralSearchQuery.length >= 2 && + !addReferralSearchLoading && + addReferralSearchResults.length === 0 && ( +
+ {t('admin.users.detail.referrals.noUsersFound')} +
+ )} +
+ )} + {referralsListLoading ? (