'use client'; import { useMutation } from '@tanstack/react-query'; import { AlertTriangle, Check, RefreshCw, Sparkles } from 'lucide-react'; import Link from 'next/link'; import * as React from 'react'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { ApiError } from '@/lib/api-client'; import { analyticsApi } from '@/lib/analytics-api'; import type { AiConfidence, ListingAiAdvice } from '@/lib/analytics-api'; import { useAuthStore } from '@/lib/auth-store'; import { formatPrice } from '@/lib/currency'; interface AiAdviceCardsProps { listingId: string; /** suitableFor labels already shown by the PersonaFitCard — used to de-dupe. */ existingPersonas?: string[]; } const CONFIDENCE_STYLE: Record = { high: { label: 'Độ tin cậy cao', variant: 'success' }, medium: { label: 'Độ tin cậy trung bình', variant: 'warning' }, low: { label: 'Độ tin cậy thấp', variant: 'destructive' }, }; export function AiAdviceCards({ listingId, existingPersonas = [] }: AiAdviceCardsProps) { const user = useAuthStore((s) => s.user); const isAdmin = user?.role === 'ADMIN'; const mutation = useMutation({ mutationFn: () => analyticsApi.getListingAiAdvice(listingId), }); const { data, error, isPending, isSuccess } = mutation; // Not loaded yet — show trigger button. if (!isSuccess && !isPending && !error) { return ( ); } // Loading — skeleton. if (isPending) { return ( AI đang phân tích…
); } // Error state. if (error) { const apiErr = error instanceof ApiError ? error : null; const status = apiErr?.status ?? 0; const notConfigured = status === 503; if (notConfigured) { return (

AI chưa được cấu hình. Liên hệ quản trị viên.

{isAdmin && ( Cấu hình Claude API → )}
); } return (

Không lấy được phân tích AI. {apiErr?.message ?? 'Vui lòng thử lại.'}

); } // Success — render the two cards. if (!data) return null; const { valuation, advice } = data; const confStyle = CONFIDENCE_STYLE[valuation.confidence] ?? CONFIDENCE_STYLE.medium; const extraPersonas = advice.suitableFor.filter( (p) => !existingPersonas.includes(p), ); return (
{/* Card 1 — AI định giá */} AI định giá

{formatPrice(valuation.estimateVND)} VND

Khoảng {formatPrice(valuation.lowVND)} – {formatPrice(valuation.highVND)} VND

{confStyle.label}
{valuation.rationale && (

{valuation.rationale}

)}
{/* Card 2 — AI nhận định */} AI nhận định {advice.summary && (

{advice.summary}

)}
{advice.pros.length > 0 && (

Điểm mạnh

    {advice.pros.map((p, i) => (
  • {p}
  • ))}
)} {advice.cons.length > 0 && (

Cần cân nhắc

    {advice.cons.map((c, i) => (
  • {c}
  • ))}
)}
{extraPersonas.length > 0 && (

Phù hợp với

{extraPersonas.map((p) => (
{p} AI gợi ý
))}
)}
); }