import { useEffect, useRef, useState } from 'react'
import { Alert, Box, Button, Chip, CircularProgress, Dialog, DialogContent, DialogTitle, LinearProgress, Typography } from '@mui/material'
import { BarChart2, Building2, CheckCircle, Download, FileText, Lightbulb, TrendingUp } from 'lucide-react'
import { marketReportService } from '../../services/marketReportService'
import type { MarketReport, PropertyMarketSignal, SignalCategory } from '../../domain/marketReport'
interface Props {
propertyId: string
}
const SECTION_CONFIG: { category: SignalCategory; label: string; icon: React.ReactNode; color: string }[] = [
{ category: 'development', label: 'Entwicklungsnews', icon: , color: '#1e3a5f' },
{ category: 'demand', label: 'Nachfrage 5 km', icon: , color: '#1a7a4a' },
{ category: 'supply', label: 'Angebot 5 km', icon: , color: '#b45309' },
{ category: 'negotiation', label: 'Verhandlungshinweise', icon: , color: '#7c3aed' },
]
function SignalCard({ signal }: { signal: PropertyMarketSignal }) {
return (
{signal.title}
{signal.confidence != null && (
)}
{signal.body}
{signal.confidence != null && (
KI-Konfidenz
{Math.round(signal.confidence * 100)}%
= 0.8 ? '#1a7a4a' : signal.confidence >= 0.6 ? '#d97706' : '#64748b' },
}}
/>
)}
{signal.date && (
{new Date(signal.date).toLocaleDateString('de-CH')}
)}
{signal.source && (
{signal.source}
)}
)
}
// ── PDF generation dialog ─────────────────────────────────────────────────────
type PdfState = 'idle' | 'generating' | 'ready'
interface BerichtDialogProps {
open: boolean
onClose: () => void
report: MarketReport | null
propertyId: string
}
function BerichtDialog({ open, onClose, report, propertyId }: BerichtDialogProps) {
const [state, setState] = useState('idle')
const [progress, setProgress] = useState(0)
const timerRef = useRef | null>(null)
useEffect(() => {
if (!open) { setState('idle'); setProgress(0); return }
setState('generating')
setProgress(0)
let p = 0
timerRef.current = setInterval(() => {
p += Math.random() * 18 + 8
if (p >= 100) {
p = 100
clearInterval(timerRef.current!)
setTimeout(() => setState('ready'), 300)
}
setProgress(Math.min(100, p))
}, 200)
return () => { if (timerRef.current) clearInterval(timerRef.current) }
}, [open])
function handleDownload() {
const signals = report?.signals ?? []
const lines: string[] = [
'MARKTSIGNAL-BERICHT',
'====================',
`Objekt-ID: ${propertyId}`,
`Erstellt: ${new Date().toLocaleString('de-CH')}`,
'',
]
for (const s of signals) {
lines.push(`[${s.category.toUpperCase()}] ${s.title}`)
lines.push(s.body)
if (s.source) lines.push(`Quelle: ${s.source}`)
lines.push('')
}
const blob = new Blob([lines.join('\n')], { type: 'application/pdf' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `Marktsignal-Bericht_${propertyId}.pdf`
a.click()
URL.revokeObjectURL(url)
onClose()
}
return (
)
}
// ── Main tab component ────────────────────────────────────────────────────────
export function PropertyMarketSignalsTab({ propertyId }: Props) {
const [report, setReport] = useState(null)
const [loading, setLoading] = useState(true)
const [dialogOpen, setDialogOpen] = useState(false)
useEffect(() => {
let cancelled = false
setLoading(true)
marketReportService.getByProperty(propertyId).then(r => {
if (!cancelled) { setReport(r); setLoading(false) }
})
return () => { cancelled = true }
}, [propertyId])
if (loading) {
return (
)
}
return (
Marktsignale & Standortintelligenz
{report?.generatedAt && (
Generiert {new Date(report.generatedAt).toLocaleDateString('de-CH')}
)}
}
onClick={() => showToast('PDF-Bericht wird generiert…', 'info')}
sx={{ textTransform: 'none', fontSize: '0.8125rem' }}
>
Bericht erstellen
{!report ? (
Für dieses Objekt liegen noch keine KI-generierten Marktsignale vor.
) : (
SECTION_CONFIG.map(({ category, label, icon, color }) => {
const signals = report.signals.filter(s => s.category === category)
if (signals.length === 0) return null
return (
{icon}
{label}
{signals.map(s => )}
)
})
)}
)
}