'use client'; import dynamic from 'next/dynamic'; import Link from 'next/link'; import * as React from 'react'; import { AddToCompareButton } from '@/components/comparison/add-to-compare-button'; import { ImageGallery } from '@/components/listings/image-gallery'; import { InquiryModal } from '@/components/listings/inquiry-modal'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { AiEstimateButton } from '@/components/valuation/ai-estimate-button'; import { formatPrice, formatPricePerM2 } from '@/lib/currency'; import type { ListingDetail } from '@/lib/listings-api'; import { PROPERTY_TYPES, DIRECTIONS, TRANSACTION_TYPES } from '@/lib/validations/listings'; const ListingMap = dynamic( () => import('@/components/map/listing-map').then((mod) => mod.ListingMap), { ssr: false, loading: () => (

{'\u0110ang t\u1ea3i b\u1ea3n \u0111\u1ed3...'}

), }, ); function getLabel(list: readonly { value: string; label: string }[], value: string | null) { if (!value) return null; return list.find((item) => item.value === value)?.label ?? value; } interface ListingDetailClientProps { listing: ListingDetail; } export function ListingDetailClient({ listing }: ListingDetailClientProps) { const { property, seller, agent } = listing; const transactionLabel = getLabel(TRANSACTION_TYPES, listing.transactionType); const propertyTypeLabel = getLabel(PROPERTY_TYPES, property.propertyType); const [inquiryOpen, setInquiryOpen] = React.useState(false); return (
{/* Breadcrumb */} {/* Header */}
{transactionLabel && ( {transactionLabel} )} {propertyTypeLabel && {propertyTypeLabel}}

{property.title}

{property.address}, {property.ward}, {property.district}, {property.city}

{formatPrice(listing.priceVND)} VND

{listing.pricePerM2 != null && (

~{formatPricePerM2(listing.pricePerM2)}

)} {listing.rentPriceMonthly && (

Thu\u00ea: {formatPrice(listing.rentPriceMonthly)}/th\u00e1ng

)}
{/* Image gallery */} {/* Quick specs bar */}
{property.bedrooms != null && ( )} {property.bathrooms != null && ( )} {property.floors != null && ( )} {property.direction && ( )}
{/* Main content */}
{/* Description */} Mô tả

{property.description}

{/* Details */} Thông tin chi tiết
{/* Amenities */} {property.amenities && property.amenities.length > 0 && ( Tiện ích
{property.amenities.map((a) => ( {a} ))}
)} {/* Map */} Vị trí trên bản đồ
{/* Sidebar */}
{/* Contact card */} Liên hệ

{seller.fullName}

{seller.phone}

{agent && (

Môi giới

{agent.agency &&

{agent.agency}

} {listing.commissionPct != null && (

Hoa hồng: {listing.commissionPct}%

)}
)}
{/* AI Estimate */} {/* Stats */}

{listing.viewCount}

Lượt xem

{listing.saveCount}

Lượt lưu

{listing.inquiryCount}

Liên hệ

{listing.publishedAt && (

Đăng ngày {new Date(listing.publishedAt).toLocaleDateString('vi-VN')}

)}
); } function QuickStat({ icon, label, value }: { icon: string; label: string; value: string }) { const icons: Record = { area: ( ), bed: ( ), bath: ( ), floors: ( ), compass: ( ), }; return (
{icons[icon]}

{label}

{value}

); } function InfoItem({ label, value }: { label: string; value: string }) { return (

{label}

{value}

); }