diff --git a/src/components/supply/PropertyMarketSignalsTab.tsx b/src/components/supply/PropertyMarketSignalsTab.tsx index 15d49cc..6ad31d2 100644 --- a/src/components/supply/PropertyMarketSignalsTab.tsx +++ b/src/components/supply/PropertyMarketSignalsTab.tsx @@ -1,8 +1,7 @@ -import { useEffect, useState } from 'react' -import { Alert, Box, Button, Chip, CircularProgress, LinearProgress, Typography } from '@mui/material' -import { BarChart2, Building2, FileText, Lightbulb, TrendingUp } from 'lucide-react' +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 { useToastStore } from '../../stores/toastStore' import type { MarketReport, PropertyMarketSignal, SignalCategory } from '../../domain/marketReport' interface Props { @@ -94,10 +93,133 @@ function SignalCard({ signal }: { signal: PropertyMarketSignal }) { ) } +// ── 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 ( + + + Bericht erstellen + + + {state === 'generating' && ( + + + + + PDF-Bericht wird generiert… + + + + + {Math.round(progress)}% — Marktsignale werden aufbereitet + + + )} + + {state === 'ready' && ( + + + + + Bericht ist bereit + + + + Dateiname + + Marktsignal-Bericht_{propertyId}.pdf + + + {report?.signals.length ?? 0} Signale · {new Date().toLocaleDateString('de-CH')} + + + + + + + + )} + + + ) +} + +// ── Main tab component ──────────────────────────────────────────────────────── + export function PropertyMarketSignalsTab({ propertyId }: Props) { const [report, setReport] = useState(null) const [loading, setLoading] = useState(true) - const showToast = useToastStore(s => s.showToast) + const [dialogOpen, setDialogOpen] = useState(false) useEffect(() => { let cancelled = false