208 lines
6.4 KiB
TypeScript
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
|
|
}
|