Files
hfb_sys/frontend/src/features/listings/api/listings.ts
T

208 lines
6.4 KiB
TypeScript

import { apiClient } from '@/shared/api/client'
import type { ApiResponse } from '@/shared/types/types'
import type { ListingReviewStatus, ListingStatus } from '@/shared/types/status'
export interface Listing {
id: number
account_id: number
owner_id: number
owner_phone?: string
owner_nickname?: string
title: string
description: string
game_name: string
server_region: string
login_platform: string
rank_level: string
haf_coin_amount: number
asset_summary?: Record<string, unknown>
screenshot_urls: string[]
cover_url: string
price: number
deposit_amount: number
is_accelerated_sale?: boolean
in_transaction: boolean
status: ListingStatus
review_status: ListingReviewStatus
review_reason: string
published_at?: string
created_at: string
updated_at: string
}
export interface ListingPayload {
title: string
description: string
server_region: string
login_platform: string
rank_level: string
haf_coin_amount: number
asset_summary?: Record<string, unknown>
screenshot_urls: string[]
price: number
deposit_amount: number
agreed_virtual_asset_sale: boolean
agreed_seller_agreement: boolean
}
export interface PublicListingQuery {
page?: number
page_size?: number
keyword?: string
sort?: string
zone?: string
server?: string
region?: string
login_method?: string
rank?: string
insurance?: string
stamina?: string
load?: string
skin_group?: string
skin_name?: string
min_coin?: number
max_coin?: number
min_price?: number
max_price?: number
min_deposit?: number
max_deposit?: number
min_total?: number
max_total?: number
min_fire_level?: number
max_fire_level?: number
min_secret_kd?: number
max_secret_kd?: number
[key: `resource_${string}_min`]: number | undefined
[key: `resource_${string}_max`]: number | undefined
}
export interface PublicListingPage {
items: Listing[]
total: number
page: number
page_size: number
zone_counts: Record<string, number>
}
export async function fetchListings(query: PublicListingQuery = {}) {
const page = await fetchListingsPage(query)
return page.items
}
export async function fetchListingsPage(query: PublicListingQuery = {}) {
const params = Object.fromEntries(
Object.entries(query).filter(([, value]) => value !== '' && value !== undefined && value !== null)
)
const { data } = await apiClient.get<ApiResponse<Partial<PublicListingPage>>>('/listings', { params })
return normalizePublicListingPage(data.data, query)
}
function normalizePublicListingPage(data: Partial<PublicListingPage>, query: PublicListingQuery): PublicListingPage {
const items = Array.isArray(data.items) ? data.items : []
return {
items,
total: Number.isFinite(Number(data.total)) ? Number(data.total) : items.length,
page: Number.isFinite(Number(data.page)) ? Number(data.page) : Number(query.page || 1),
page_size: Number.isFinite(Number(data.page_size)) ? Number(data.page_size) : Number(query.page_size || items.length || 20),
zone_counts: data.zone_counts && typeof data.zone_counts === 'object' ? data.zone_counts : {},
}
}
export async function fetchListing(id: string | number) {
const { data } = await apiClient.get<ApiResponse<Listing>>(`/listings/${id}`)
return data.data
}
export async function fetchSellerListings() {
const { data } = await apiClient.get<ApiResponse<{ items: Listing[] }>>('/seller/listings')
return data.data.items
}
export async function createListing(payload: ListingPayload) {
const { data } = await apiClient.post<ApiResponse<Listing>>('/listings', payload)
return data.data
}
export async function submitListingReview(id: number) {
const { data } = await apiClient.post<ApiResponse<Listing>>(`/listings/${id}/submit-review`)
return data.data
}
export async function offlineListing(id: number) {
const { data } = await apiClient.delete<ApiResponse<{ offline: boolean }>>(`/listings/${id}`)
return data.data
}
export async function fetchPendingReviewListings() {
const { data } = await apiClient.get<ApiResponse<{ items: Listing[] }>>('/admin/listings/pending')
return data.data.items
}
export interface AdminListingQuery {
owner_id?: string
status?: ListingStatus | ''
review_status?: ListingReviewStatus | ''
limit?: number
page?: number
page_size?: number
}
export interface AdminListingPage {
items: Listing[]
total: number
page: number
page_size: number
}
export async function fetchAdminListings(query: AdminListingQuery = {}) {
const params = Object.fromEntries(Object.entries(query).filter(([, value]) => value !== '' && value !== undefined))
const { data } = await apiClient.get<ApiResponse<AdminListingPage>>('/admin/listings', { params })
return normalizeAdminListingPage(data.data, query)
}
function normalizeAdminListingPage(data: Partial<AdminListingPage>, query: AdminListingQuery): AdminListingPage {
const items = Array.isArray(data.items) ? data.items : []
return {
items,
total: Number.isFinite(Number(data.total)) ? Number(data.total) : items.length,
page: Number.isFinite(Number(data.page)) ? Number(data.page) : Number(query.page || 1),
page_size: Number.isFinite(Number(data.page_size)) ? Number(data.page_size) : Number(query.page_size || items.length || 10),
}
}
export async function fetchAdminListing(id: string | number) {
const { data } = await apiClient.get<ApiResponse<Listing>>(`/admin/listings/${id}`)
return data.data
}
export async function adminOfflineListing(id: number, reason: string) {
const { data } = await apiClient.post<ApiResponse<Listing>>(`/admin/listings/${id}/offline`, { reason })
return data.data
}
export async function adminMarkListingAbnormal(id: number, reason: string) {
const { data } = await apiClient.post<ApiResponse<Listing>>(`/admin/listings/${id}/mark-abnormal`, { reason })
return data.data
}
export async function approveListing(id: number) {
const { data } = await apiClient.post<ApiResponse<Listing>>(`/admin/listings/${id}/approve`)
return data.data
}
export interface AdminListingPriceAdjustPayload {
buyer_ratio?: number
buyer_total_price?: number
reason?: string
}
export async function adjustListingReviewPrice(id: number, payload: AdminListingPriceAdjustPayload) {
const { data } = await apiClient.post<ApiResponse<Listing>>(`/admin/listings/${id}/adjust-price`, payload)
return data.data
}
export async function rejectListing(id: number, reason: string) {
const { data } = await apiClient.post<ApiResponse<Listing>>(`/admin/listings/${id}/reject`, { reason })
return data.data
}