import { useState } from 'react'
import { useNavigate, useParams, useSearchParams } from 'react-router'
import {
Alert,
Box,
Button,
Chip,
CircularProgress,
Divider,
Paper,
TextField,
Typography,
} from '@mui/material'
import {
ArrowLeft,
Building2,
Calendar,
CheckCircle2,
Mail,
MapPin,
ShieldCheck,
Layers,
} from 'lucide-react'
import { usePropertyById } from '../../hooks/useProperties'
import type { PropertyUnit } from '../../domain/property'
const FLOOR_LABEL = (level: number) =>
level === 0 ? 'EG' : level < 0 ? `UG ${Math.abs(level)}` : `${level}.OG`
function UnitStatusChip({ unit }: { unit: PropertyUnit }) {
if (unit.schattenmarktRelease?.enabled) {
return (
}
label="PRE-MARKET"
sx={{ bgcolor: '#f0fdf4', color: '#1a7a4a', border: '1px solid #86efac', fontWeight: 700, fontSize: '0.68rem', height: 20 }}
/>
)
}
if (unit.available) {
return
}
return
}
function UnitRow({ unit, highlighted }: { unit: PropertyUnit; highlighted: boolean }) {
const availableFrom = unit.schattenmarktRelease?.availableFrom ?? unit.leaseEndDate
const monthlyRent = unit.rentPricePerSqm ? Math.round(unit.rentPricePerSqm / 12) : undefined
return (
{FLOOR_LABEL(unit.floorLevel)}{unit.unitLabel ? ` · ${unit.unitLabel}` : ''}
{unit.currentTenant && (
{unit.currentTenant}
)}
{unit.areaSqm.toLocaleString('de-CH')} m²
{monthlyRent ? `CHF ${monthlyRent}/m²/Mt.` : '–'}
{availableFrom
? new Date(availableFrom).toLocaleDateString('de-CH', { month: 'long', year: 'numeric' })
: '–'}
)
}
export default function PropertyDetail() {
const { propertyId } = useParams<{ propertyId: string }>()
const [searchParams] = useSearchParams()
const highlightUnitId = searchParams.get('unit')
const navigate = useNavigate()
const { data: property, isLoading } = usePropertyById(propertyId ?? '')
const [inquiryName, setInquiryName] = useState('')
const [inquiryText, setInquiryText] = useState('')
const [sent, setSent] = useState(false)
if (isLoading) {
return (
)
}
if (!property) {
return (
Objekt nicht gefunden.
)
}
const preMarketUnits = (property.units ?? []).filter(u => u.schattenmarktRelease?.enabled)
const otherUnits = (property.units ?? []).filter(u => !u.schattenmarktRelease?.enabled)
const monthlyRentDisplay = Math.round(property.rentPricePerSqm / 12)
function handleSendInquiry() {
if (!inquiryName.trim() || !inquiryText.trim()) return
setSent(true)
}
return (
{/* Back */}
}
onClick={() => navigate(-1)}
size="small"
sx={{ mb: 2, textTransform: 'none', color: 'text.secondary' }}
>
Zurück zu den Ergebnissen
{/* Header */}
{property.images?.[0] && (
)}
{property.assetType}
{property.title}
{property.address.street} {property.address.houseNumber}, {property.address.postalCode} {property.address.city}
CHF {monthlyRentDisplay}/m²/Mt.
{property.areaSqm.toLocaleString('de-CH')} m² total
{preMarketUnits.length > 0 && (
{preMarketUnits.length} Einheit{preMarketUnits.length !== 1 ? 'en' : ''} für Pre-Market freigegeben — noch vor offizieller Insertion
)}
{/* Units */}
{(property.units ?? []).length > 0 && (
Einheiten
{/* Column headers */}
{['Einheit', 'Fläche', 'Miete', 'Verfügbar ab', 'Status'].map(h => (
{h}
))}
{preMarketUnits.map(u => (
))}
{otherUnits.map(u => (
))}
)}
{/* Inquiry */}
Verwaltung kontaktieren
{sent ? (
}
severity="success"
sx={{ borderRadius: 1 }}
>
Ihre Anfrage wurde übermittelt. Die Verwaltung meldet sich in Kürze.
) : (
Ihr Name
setInquiryName(e.target.value)}
/>
Bezug
u.id === highlightUnitId)?.unitLabel ?? 'Einheit')
: property.title
}
InputProps={{ readOnly: true }}
sx={{ '& .MuiInputBase-input': { color: 'text.secondary', fontSize: '0.85rem' } }}
/>
Ihre Nachricht
setInquiryText(e.target.value)}
/>
Antwortzeit: typisch 1–2 Werktage
}
sx={{ bgcolor: '#7c3aed', '&:hover': { bgcolor: '#6d28d9' }, textTransform: 'none' }}
>
Anfrage senden
)}
Diese Fläche ist noch nicht offiziell auf dem Markt. Die Verwaltung hat sie explizit für qualifizierte Suchanfragen freigegeben. Ihre Anfrage wird vertraulich behandelt.
)
}