'use client'; import * as React from 'react'; import Link from 'next/link'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Select } from '@/components/ui/select'; import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'; import { ListingStatusBadge } from '@/components/listings/listing-status-badge'; import { listingsApi, type ListingDetail, type ListingStatus, type PaginatedResult, } from '@/lib/listings-api'; import { PROPERTY_TYPES, TRANSACTION_TYPES, LISTING_STATUSES } from '@/lib/validations/listings'; import { useAuthStore } from '@/lib/auth-store'; function formatPrice(priceVND: string): string { const num = Number(priceVND); if (num >= 1_000_000_000) return `${(num / 1_000_000_000).toFixed(1)} ty`; if (num >= 1_000_000) return `${(num / 1_000_000).toFixed(0)} trieu`; return num.toLocaleString('vi-VN'); } function formatDate(dateStr: string | null): string { if (!dateStr) return 'N/A'; return new Date(dateStr).toLocaleDateString('vi-VN', { day: '2-digit', month: '2-digit', year: 'numeric', }); } type ViewMode = 'grid' | 'table'; export default function ListingsPage() { const { tokens } = useAuthStore(); const [result, setResult] = React.useState | null>(null); const [loading, setLoading] = React.useState(true); const [viewMode, setViewMode] = React.useState('grid'); const [filters, setFilters] = React.useState({ transactionType: '', propertyType: '', status: '' as string, page: 1, }); const fetchListings = React.useCallback(() => { setLoading(true); const params: Record = { page: filters.page, limit: 12 }; if (filters.transactionType) params['transactionType'] = filters.transactionType; if (filters.propertyType) params['propertyType'] = filters.propertyType; if (filters.status) params['status'] = filters.status; listingsApi .search(params) .then(setResult) .catch(() => setResult(null)) .finally(() => setLoading(false)); }, [filters]); React.useEffect(() => { fetchListings(); }, [fetchListings]); // Stats from current page data const stats = React.useMemo(() => { if (!result) return { total: 0, active: 0, pending: 0, views: 0 }; return { total: result.total, active: result.data.filter((l) => l.status === 'ACTIVE').length, pending: result.data.filter((l) => l.status === 'PENDING_REVIEW').length, views: result.data.reduce((s, l) => s + l.viewCount, 0), }; }, [result]); return (
{/* Header */}

Quan ly tin dang

Quan ly, theo doi va cap nhat cac tin dang cua ban

{/* Stats */}
Tong tin dang {loading ? '...' : stats.total} Dang hoat dong {loading ? '...' : stats.active} Cho duyet {loading ? '...' : stats.pending} Tong luot xem {loading ? '...' : stats.views}
{/* Filters + View Toggle */}
{/* Content */} {loading ? (
) : !result || result.data.length === 0 ? (

Chua co tin dang nao

) : viewMode === 'grid' ? ( /* Grid View */
{result.data.map((listing) => (
{listing.property.media.length > 0 ? ( {listing.property.title} ) : (
Chua co anh
)}

{formatPrice(listing.priceVND)} VND

{listing.property.title}

{listing.property.district}, {listing.property.city}

{listing.property.areaM2} m2 {listing.property.bedrooms != null && ( {listing.property.bedrooms} PN )} {listing.property.bathrooms != null && listing.property.bathrooms > 0 && ( {listing.property.bathrooms} PT )}
{listing.viewCount} luot xem {listing.inquiryCount} lien he {listing.saveCount} da luu
))}
) : ( /* Table View */
{result.data.map((listing) => ( ))}
Tin dang Loai Gia Dien tich Trang thai Luot xem Lien he Ngay dang
{listing.property.media.length > 0 ? ( ) : (
N/A
)}

{listing.property.title}

{listing.property.district}, {listing.property.city}

{listing.property.propertyType} {formatPrice(listing.priceVND)} {listing.property.areaM2} m2 {listing.viewCount} {listing.inquiryCount} {formatDate(listing.publishedAt ?? listing.createdAt)}
)} {/* Pagination */} {result && result.totalPages > 1 && (
Trang {result.page} / {result.totalPages}
)}
); }