'use client';
import { ShieldCheck, ShieldAlert, ShieldQuestion, TrendingUp, TrendingDown } from 'lucide-react';
import { Badge } from '@/components/ui/badge';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { formatPrice, formatPricePerM2 } from '@/lib/currency';
import type { ConfidenceExplanation, ValuationResult } from '@/lib/valuation-api';
interface ValuationResultsProps {
result: ValuationResult;
}
function getConfidenceBadge(confidence: number): {
label: string;
variant: 'success' | 'warning' | 'destructive';
icon: typeof ShieldCheck;
} {
if (confidence >= 0.8) {
return { label: 'Độ tin cậy cao', variant: 'success', icon: ShieldCheck };
}
if (confidence >= 0.5) {
return { label: 'Độ tin cậy trung bình', variant: 'warning', icon: ShieldAlert };
}
return { label: 'Độ tin cậy thấp', variant: 'destructive', icon: ShieldQuestion };
}
function ConfidenceDetail({ explanation }: { explanation: ConfidenceExplanation }) {
return (
{explanation.summary}
{explanation.factors.map((factor) => (
{factor.contribution === 'positive' ? (
) : (
)}
{factor.factor}
— {factor.detail}
))}
);
}
function PriceRangeBar({
low,
high,
estimated,
}: {
low: number;
high: number;
estimated: number;
}) {
const range = high - low;
const position = range > 0 ? ((estimated - low) / range) * 100 : 50;
return (
{formatPrice(low)}
{formatPrice(estimated)}
{formatPrice(high)}
);
}
export function ValuationResults({ result }: ValuationResultsProps) {
const confidencePct = Math.round(result.confidence * 100);
const badge = getConfidenceBadge(result.confidence);
const BadgeIcon = badge.icon;
// Sort drivers by absolute impact for chart display
const sortedDrivers = [...result.priceDrivers].sort(
(a, b) => Math.abs(b.impact) - Math.abs(a.impact),
);
const maxImpact = Math.max(...sortedDrivers.map((d) => Math.abs(d.impact)), 1);
return (
{/* Main estimate card */}
Giá ước tính bởi AI
{formatPrice(result.estimatedPriceVND)} VNĐ
{badge.label}
{/* Stats grid */}
Độ tin cậy
= 80
? 'bg-green-500'
: confidencePct >= 50
? 'bg-yellow-500'
: 'bg-red-500'
}`}
style={{ width: `${confidencePct}%` }}
/>
{confidencePct}%
Giá/m²
{formatPricePerM2(result.pricePerM2)}
{/* Price range bar */}
{/* Confidence explanation (deep analysis) */}
{result.confidenceExplanation && (
)}
{/* Value drivers — horizontal bar chart */}
{sortedDrivers.length > 0 && (
Yếu tố ảnh hưởng giá
Các yếu tố chính tác động đến giá trị bất động sản
{sortedDrivers.map((driver) => {
const barWidth = (Math.abs(driver.impact) / maxImpact) * 100;
const isPositive = driver.direction === 'positive';
return (
{driver.feature}
{isPositive ? '+' : '-'}
{Math.abs(driver.impact).toFixed(1)}%
{driver.explanation && (
{driver.explanation}
)}
);
})}
)}
);
}