Add files via upload

This commit is contained in:
Egor
2026-01-17 06:01:21 +03:00
committed by GitHub
parent 73292185cc
commit ce7b69eca5

413
src/api/adminUsers.ts Normal file
View File

@@ -0,0 +1,413 @@
import apiClient from './client'
// ============ Types ============
export interface UserSubscriptionInfo {
id: number
status: string
is_trial: boolean
start_date: string | null
end_date: string | null
traffic_limit_gb: number
traffic_used_gb: number
device_limit: number
tariff_id: number | null
tariff_name: string | null
autopay_enabled: boolean
is_active: boolean
days_remaining: number
}
export interface UserPromoGroupInfo {
id: number
name: string
is_default: boolean
}
export interface UserListItem {
id: number
telegram_id: number
username: string | null
first_name: string | null
last_name: string | null
full_name: string
status: string
balance_kopeks: number
balance_rubles: number
created_at: string
last_activity: string | null
has_subscription: boolean
subscription_status: string | null
subscription_is_trial: boolean
subscription_end_date: string | null
promo_group_id: number | null
promo_group_name: string | null
total_spent_kopeks: number
purchase_count: number
has_restrictions: boolean
restriction_topup: boolean
restriction_subscription: boolean
}
export interface UsersListResponse {
users: UserListItem[]
total: number
offset: number
limit: number
}
export interface UserTransactionItem {
id: number
type: string
amount_kopeks: number
amount_rubles: number
description: string | null
payment_method: string | null
is_completed: boolean
created_at: string
}
export interface UserReferralInfo {
referral_code: string
referrals_count: number
total_earnings_kopeks: number
commission_percent: number | null
referred_by_id: number | null
referred_by_username: string | null
}
export interface UserDetailResponse {
id: number
telegram_id: number
username: string | null
first_name: string | null
last_name: string | null
full_name: string
status: string
language: string
balance_kopeks: number
balance_rubles: number
email: string | null
email_verified: boolean
created_at: string
updated_at: string | null
last_activity: string | null
cabinet_last_login: string | null
subscription: UserSubscriptionInfo | null
promo_group: UserPromoGroupInfo | null
referral: UserReferralInfo
total_spent_kopeks: number
purchase_count: number
used_promocodes: number
has_had_paid_subscription: boolean
lifetime_used_traffic_bytes: number
restriction_topup: boolean
restriction_subscription: boolean
restriction_reason: string | null
promo_offer_discount_percent: number
promo_offer_discount_source: string | null
promo_offer_discount_expires_at: string | null
recent_transactions: UserTransactionItem[]
}
export interface UsersStatsResponse {
total_users: number
active_users: number
blocked_users: number
deleted_users: number
new_today: number
new_week: number
new_month: number
users_with_subscription: number
users_with_active_subscription: number
users_with_trial: number
users_with_expired_subscription: number
total_balance_kopeks: number
total_balance_rubles: number
avg_balance_kopeks: number
active_today: number
active_week: number
active_month: number
}
// Available tariffs
export interface PeriodPriceInfo {
days: number
price_kopeks: number
price_rubles: number
}
export interface UserAvailableTariff {
id: number
name: string
description: string | null
is_active: boolean
is_trial_available: boolean
traffic_limit_gb: number
device_limit: number
tier_level: number
display_order: number
period_prices: PeriodPriceInfo[]
is_daily: boolean
daily_price_kopeks: number
custom_days_enabled: boolean
price_per_day_kopeks: number
min_days: number
max_days: number
is_available: boolean
requires_promo_group: boolean
}
export interface UserAvailableTariffsResponse {
user_id: number
promo_group_id: number | null
promo_group_name: string | null
tariffs: UserAvailableTariff[]
total: number
current_tariff_id: number | null
current_tariff_name: string | null
}
// Sync types
export interface PanelUserInfo {
uuid: string | null
short_uuid: string | null
username: string | null
status: string | null
expire_at: string | null
traffic_limit_gb: number
traffic_used_gb: number
device_limit: number
subscription_url: string | null
active_squads: string[]
}
export interface SyncFromPanelResponse {
success: boolean
message: string
panel_user: PanelUserInfo | null
changes: Record<string, unknown>
errors: string[]
}
export interface SyncToPanelResponse {
success: boolean
message: string
action: string
panel_uuid: string | null
changes: Record<string, unknown>
errors: string[]
}
export interface PanelSyncStatusResponse {
user_id: number
telegram_id: number
remnawave_uuid: string | null
last_sync: string | null
bot_subscription_status: string | null
bot_subscription_end_date: string | null
bot_traffic_limit_gb: number
bot_traffic_used_gb: number
panel_found: boolean
panel_status: string | null
panel_expire_at: string | null
panel_traffic_limit_gb: number
panel_traffic_used_gb: number
has_differences: boolean
differences: string[]
}
// Update types
export interface UpdateBalanceRequest {
amount_kopeks: number
description?: string
create_transaction?: boolean
}
export interface UpdateBalanceResponse {
success: boolean
old_balance_kopeks: number
new_balance_kopeks: number
message: string
}
export interface UpdateSubscriptionRequest {
action: 'extend' | 'set_end_date' | 'change_tariff' | 'set_traffic' | 'toggle_autopay' | 'cancel' | 'activate' | 'create'
days?: number
end_date?: string
tariff_id?: number
traffic_limit_gb?: number
traffic_used_gb?: number
autopay_enabled?: boolean
is_trial?: boolean
device_limit?: number
}
export interface UpdateSubscriptionResponse {
success: boolean
message: string
subscription: UserSubscriptionInfo | null
}
export interface UpdateUserStatusResponse {
success: boolean
old_status: string
new_status: string
message: string
}
export interface UpdateRestrictionsRequest {
restriction_topup?: boolean
restriction_subscription?: boolean
restriction_reason?: string
}
export interface UpdateRestrictionsResponse {
success: boolean
restriction_topup: boolean
restriction_subscription: boolean
restriction_reason: string | null
message: string
}
export interface SyncFromPanelRequest {
update_subscription?: boolean
update_traffic?: boolean
create_if_missing?: boolean
}
export interface SyncToPanelRequest {
create_if_missing?: boolean
update_status?: boolean
update_traffic_limit?: boolean
update_expire_date?: boolean
update_squads?: boolean
}
// ============ API ============
export const adminUsersApi = {
// List users
getUsers: async (params: {
offset?: number
limit?: number
search?: string
status?: 'active' | 'blocked' | 'deleted'
sort_by?: 'created_at' | 'balance' | 'traffic' | 'last_activity' | 'total_spent' | 'purchase_count'
} = {}): Promise<UsersListResponse> => {
const response = await apiClient.get('/cabinet/admin/users', { params })
return response.data
},
// Get users stats
getStats: async (): Promise<UsersStatsResponse> => {
const response = await apiClient.get('/cabinet/admin/users/stats')
return response.data
},
// Get user detail
getUser: async (userId: number): Promise<UserDetailResponse> => {
const response = await apiClient.get(`/cabinet/admin/users/${userId}`)
return response.data
},
// Get user by telegram ID
getUserByTelegram: async (telegramId: number): Promise<UserDetailResponse> => {
const response = await apiClient.get(`/cabinet/admin/users/by-telegram/${telegramId}`)
return response.data
},
// Get available tariffs for user
getAvailableTariffs: async (userId: number, includeInactive = false): Promise<UserAvailableTariffsResponse> => {
const response = await apiClient.get(`/cabinet/admin/users/${userId}/available-tariffs`, {
params: { include_inactive: includeInactive }
})
return response.data
},
// Update balance
updateBalance: async (userId: number, data: UpdateBalanceRequest): Promise<UpdateBalanceResponse> => {
const response = await apiClient.post(`/cabinet/admin/users/${userId}/balance`, data)
return response.data
},
// Update subscription
updateSubscription: async (userId: number, data: UpdateSubscriptionRequest): Promise<UpdateSubscriptionResponse> => {
const response = await apiClient.post(`/cabinet/admin/users/${userId}/subscription`, data)
return response.data
},
// Update status
updateStatus: async (userId: number, status: 'active' | 'blocked' | 'deleted', reason?: string): Promise<UpdateUserStatusResponse> => {
const response = await apiClient.post(`/cabinet/admin/users/${userId}/status`, { status, reason })
return response.data
},
// Block user
blockUser: async (userId: number, reason?: string): Promise<UpdateUserStatusResponse> => {
const response = await apiClient.post(`/cabinet/admin/users/${userId}/block`, null, { params: { reason } })
return response.data
},
// Unblock user
unblockUser: async (userId: number): Promise<UpdateUserStatusResponse> => {
const response = await apiClient.post(`/cabinet/admin/users/${userId}/unblock`)
return response.data
},
// Update restrictions
updateRestrictions: async (userId: number, data: UpdateRestrictionsRequest): Promise<UpdateRestrictionsResponse> => {
const response = await apiClient.post(`/cabinet/admin/users/${userId}/restrictions`, data)
return response.data
},
// Update promo group
updatePromoGroup: async (userId: number, promoGroupId: number | null): Promise<{ success: boolean; message: string }> => {
const response = await apiClient.post(`/cabinet/admin/users/${userId}/promo-group`, { promo_group_id: promoGroupId })
return response.data
},
// Delete user
deleteUser: async (userId: number, softDelete = true, reason?: string): Promise<{ success: boolean; message: string }> => {
const response = await apiClient.delete(`/cabinet/admin/users/${userId}`, {
data: { soft_delete: softDelete, reason }
})
return response.data
},
// Get referrals
getReferrals: async (userId: number, offset = 0, limit = 50): Promise<UsersListResponse> => {
const response = await apiClient.get(`/cabinet/admin/users/${userId}/referrals`, {
params: { offset, limit }
})
return response.data
},
// Get transactions
getTransactions: async (userId: number, params: {
offset?: number
limit?: number
transaction_type?: string
} = {}): Promise<{ transactions: UserTransactionItem[]; total: number; offset: number; limit: number }> => {
const response = await apiClient.get(`/cabinet/admin/users/${userId}/transactions`, { params })
return response.data
},
// Sync status
getSyncStatus: async (userId: number): Promise<PanelSyncStatusResponse> => {
const response = await apiClient.get(`/cabinet/admin/users/${userId}/sync/status`)
return response.data
},
// Sync from panel
syncFromPanel: async (userId: number, data: SyncFromPanelRequest = {}): Promise<SyncFromPanelResponse> => {
const response = await apiClient.post(`/cabinet/admin/users/${userId}/sync/from-panel`, data)
return response.data
},
// Sync to panel
syncToPanel: async (userId: number, data: SyncToPanelRequest = {}): Promise<SyncToPanelResponse> => {
const response = await apiClient.post(`/cabinet/admin/users/${userId}/sync/to-panel`, data)
return response.data
},
}