'use client'; import dynamic from 'next/dynamic'; import { useState } from 'react'; import { Badge } from '@/components/ui/badge'; import { ComparablesMap } from '@/components/valuation/comparables-map'; import { ComparablesTable } from '@/components/valuation/comparables-table'; import { ExportPdfButton } from '@/components/valuation/export-pdf-button'; import { MarketContextCard } from '@/components/valuation/market-context-card'; import { ValuationCompare } from '@/components/valuation/valuation-compare'; import { ValuationForm } from '@/components/valuation/valuation-form'; import { ValuationHistory } from '@/components/valuation/valuation-history'; import { ValuationResults } from '@/components/valuation/valuation-results'; import { ValueDriversChart } from '@/components/valuation/value-drivers-chart'; import { ApiError } from '@/lib/api-client'; import { useAvmV2Flag } from '@/lib/hooks/use-avm-v2-flag'; import { useValuationPredict, useValuationHistory, useValuationDetail, } from '@/lib/hooks/use-valuation'; import type { ValuationRequest, ValuationResult } from '@/lib/valuation-api'; function getValuationErrorMessage(error: unknown): { title: string; detail: string } { if (error instanceof ApiError) { if (error.status === 429) { return { title: 'Quá nhiều yêu cầu', detail: 'Bạn đã gửi quá nhiều yêu cầu định giá. Vui lòng đợi một lát rồi thử lại.', }; } if (error.status === 402 || /quota|subscription/i.test(error.message)) { return { title: 'Đã hết hạn mức', detail: 'Gói đăng ký hiện tại đã hết lượt định giá AI. Hãy nâng cấp hoặc thử lại vào chu kỳ sau.', }; } if (error.status === 503 || /model|unavailable/i.test(error.message)) { return { title: 'Dịch vụ AI tạm thời không khả dụng', detail: 'Mô hình định giá đang bận hoặc bảo trì. Vui lòng thử lại sau vài phút.', }; } return { title: 'Không thể định giá', detail: error.message || 'Đã xảy ra lỗi không xác định. Vui lòng thử lại sau.', }; } return { title: 'Không thể định giá', detail: 'Vui lòng kiểm tra kết nối mạng và thử lại.', }; } const ValuationHistoryChart = dynamic( () => import('@/components/valuation/valuation-history-chart').then( (m) => m.ValuationHistoryChart, ), { ssr: false, loading: () => (
Đang tải...
), }, ); type ViewMode = 'single' | 'compare'; export default function ValuationPage() { const avmV2 = useAvmV2Flag(); const [historyPage, setHistoryPage] = useState(1); const [selectedId, setSelectedId] = useState(null); const [viewMode, setViewMode] = useState('single'); const predictMutation = useValuationPredict(); const { data: historyData, isLoading: historyLoading } = useValuationHistory(historyPage); const { data: selectedResult } = useValuationDetail(selectedId ?? ''); const currentResult: ValuationResult | undefined = predictMutation.data ?? selectedResult; const handleSubmit = (data: ValuationRequest) => { setSelectedId(null); predictMutation.mutate(data); }; const handleSelectHistory = (id: string) => { setSelectedId(id); }; return (

Định giá AI

{avmV2 && ( AVM v2 )}

Sử dụng AI để ước tính giá trị bất động sản dựa trên dữ liệu thị trường

{currentResult && viewMode === 'single' && ( )}
{avmV2 && (
)} {viewMode === 'compare' && avmV2 ? ( ) : (
{predictMutation.isError && (() => { const { title, detail } = getValuationErrorMessage(predictMutation.error); return (

{title}

{detail}

); })()} {currentResult && ( <> {avmV2 && currentResult.priceDrivers.length > 0 && ( )} {currentResult.comparables.length > 0 && ( )} {avmV2 && currentResult.comparables.length > 0 && ( )} {currentResult.marketContext && ( )} {currentResult.valuationHistory && currentResult.valuationHistory.length >= 2 && ( )} )}
)}
); }