import { ChefHat, Home, Monitor, Refrigerator, Sofa, Store, type LucideIcon, } from 'lucide-react'; import { apiClient } from './api-client'; // ─── Types ────────────────────────────────────────────── export type TransferCategory = 'FURNITURE' | 'APPLIANCE' | 'OFFICE_EQUIPMENT' | 'KITCHEN' | 'PREMISES' | 'FULL_UNIT'; export type TransferCondition = 'NEW' | 'LIKE_NEW' | 'GOOD' | 'FAIR' | 'WORN'; export type TransferListingStatus = 'DRAFT' | 'PENDING_REVIEW' | 'ACTIVE' | 'RESERVED' | 'SOLD' | 'EXPIRED' | 'REJECTED'; export type TransferPricingSource = 'MANUAL' | 'AI_ESTIMATED' | 'NEGOTIABLE'; export interface TransferListingListItem { id: string; sellerId: string; category: TransferCategory; status: TransferListingStatus; title: string; address: string; district: string; city: string; latitude: number; longitude: number; askingPriceVND: string; // BigInt serialized as string aiEstimatePriceVND: string | null; pricingSource: TransferPricingSource; isNegotiable: boolean; areaM2: number | null; media: { url: string; type: string; order: number; caption?: string }[] | null; viewCount: number; inquiryCount: number; publishedAt: string | null; itemCount: number; } export interface TransferItemData { id: string; name: string; brand: string | null; modelName: string | null; category: TransferCategory; condition: TransferCondition; purchaseYear: number | null; originalPriceVND: string | null; askingPriceVND: string; aiEstimatePriceVND: string | null; aiConfidence: number | null; quantity: number; dimensions: { widthCm?: number; heightCm?: number; depthCm?: number; weightKg?: number } | null; media: { url: string; type: string; order: number }[] | null; notes: string | null; } export interface TransferListingDetail { id: string; sellerId: string; category: TransferCategory; status: TransferListingStatus; title: string; description: string | null; address: string; ward: string | null; district: string; city: string; latitude: number; longitude: number; askingPriceVND: string; aiEstimatePriceVND: string | null; aiConfidence: number | null; pricingSource: TransferPricingSource; isNegotiable: boolean; areaM2: number | null; monthlyRentVND: string | null; depositMonths: number | null; remainingLeaseMo: number | null; businessType: string | null; footTraffic: string | null; media: { url: string; type: string; order: number; caption?: string }[] | null; viewCount: number; saveCount: number; inquiryCount: number; contactPhone: string | null; contactName: string | null; items: TransferItemData[]; createdAt: string; updatedAt: string; } export interface TransferStats { totalListings: number; totalValue: string; byCategory: { category: string; count: number; avgPrice: number }[]; byDistrict: { district: string; count: number; avgPrice: number }[]; byStatus: { status: string; count: number }[]; } export interface PaginatedResult { data: T[]; total: number; page: number; limit: number; totalPages: number; } export interface SearchTransferListingsParams { q?: string; category?: TransferCategory; status?: TransferListingStatus; district?: string; city?: string; minPrice?: number; maxPrice?: number; page?: number; limit?: number; } // ─── Labels ───────────────────────────────────────────── export const CATEGORY_LABELS: Record = { FURNITURE: 'Nội thất', APPLIANCE: 'Thiết bị gia dụng', OFFICE_EQUIPMENT: 'Thiết bị văn phòng', KITCHEN: 'Bếp & thiết bị', PREMISES: 'Mặt bằng', FULL_UNIT: 'Trọn bộ', }; export const CATEGORY_ICONS: Record = { FURNITURE: Sofa, APPLIANCE: Refrigerator, OFFICE_EQUIPMENT: Monitor, KITCHEN: ChefHat, PREMISES: Store, FULL_UNIT: Home, }; export const CONDITION_LABELS: Record = { NEW: 'Mới', LIKE_NEW: 'Như mới', GOOD: 'Tốt', FAIR: 'Khá', WORN: 'Cũ', }; export const CONDITION_COLORS: Record = { NEW: 'bg-green-100 text-green-800', LIKE_NEW: 'bg-emerald-100 text-emerald-800', GOOD: 'bg-blue-100 text-blue-800', FAIR: 'bg-amber-100 text-amber-800', WORN: 'bg-red-100 text-red-800', }; export const STATUS_LABELS: Record = { DRAFT: 'Nháp', PENDING_REVIEW: 'Chờ duyệt', ACTIVE: 'Đang đăng', RESERVED: 'Đã giữ', SOLD: 'Đã bán', EXPIRED: 'Hết hạn', REJECTED: 'Từ chối', }; // ─── API Functions ────────────────────────────────────── export const transferApi = { search: (params: SearchTransferListingsParams = {}) => { const query = new URLSearchParams(); Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== '') query.append(key, String(value)); }); const qs = query.toString(); return apiClient.get>( `/transfer/listings${qs ? `?${qs}` : ''}`, ); }, getById: (id: string) => apiClient.get(`/transfer/listings/${id}`), getStats: () => apiClient.get('/transfer/stats'), };