import { Alert, Box, Chip, IconButton, LinearProgress, Skeleton, Table, TableBody, TableCell, TableHead, TableRow, Tooltip, Typography, } from '@mui/material' import { Bookmark, Eye } from 'lucide-react' import type { Property } from '../../domain/property' import type { PropertyTableFilters } from './PropertyFilterBar' import { getAssetTypeColor, getAssetTypeLabel, qualityColor, } from './propertyHelpers' interface PropertyTableProps { properties: Property[] isLoading: boolean isError: boolean selectedId: string | null onSelect: (id: string) => void onViewDetail?: (id: string) => void filters: PropertyTableFilters onFiltersChange: (f: PropertyTableFilters) => void } const COL_HEADERS = [ 'Objekt', 'Typ', 'Standort', 'Fläche', 'Miete CHF/m²/Jahr', 'Aktueller Mieter', 'Mietlaufzeit', 'Breakoutoption', 'Breakoutoption Zeitpunkt', 'Datenqualität', 'Aktionen', ] function LoadingRows() { return ( <> {Array.from({ length: 5 }).map((_, i) => ( {COL_HEADERS.map((h) => ( ))} ))} ) } export function PropertyTable({ properties, isLoading, isError, selectedId, onSelect, onViewDetail, filters, onFiltersChange, }: PropertyTableProps) { if (isError) { return Objekte konnten nicht geladen werden. } function handleSort(field: PropertyTableFilters['sortBy']) { if (filters.sortBy === field) { onFiltersChange({ ...filters, sortDir: filters.sortDir === 'asc' ? 'desc' : 'asc' }) } else { onFiltersChange({ ...filters, sortBy: field, sortDir: 'desc' }) } } function SortableHeader({ field, label }: { field: PropertyTableFilters['sortBy']; label: string }) { const isActive = filters.sortBy === field return ( handleSort(field)} > {label}{isActive ? (filters.sortDir === 'asc' ? ' ↑' : ' ↓') : ''} ) } return ( Objekt Typ Standort Aktueller Mieter Mietlaufzeit Breakoutoption Breakoutoption Zeitpunkt Aktionen {isLoading ? ( ) : properties.length === 0 ? ( Keine Objekte gefunden. ) : ( properties.map(p => { const isSelected = p.id === selectedId const qScore = p.dataQuality.score const hasCritical = p.dataQuality.missingCriticalFields.length > 0 return ( onSelect(p.id)} sx={{ cursor: 'pointer', bgcolor: isSelected ? 'rgba(30,58,95,0.06)' : hasCritical ? 'rgba(192,57,43,0.03)' : 'inherit', borderLeft: isSelected ? '3px solid #1e3a5f' : '3px solid transparent', '&:hover': { bgcolor: isSelected ? 'rgba(30,58,95,0.08)' : 'rgba(0,0,0,0.02)' }, }} > {/* Objekt */} {p.title} {p.address.street} {p.address.houseNumber}, {p.address.city} {/* Typ */} {/* Standort */} {p.location.city} {p.location.canton && ( {p.location.canton} )} {/* Fläche */} {p.areaSqm.toLocaleString('de-CH')} {/* Miete */} {p.rentPricePerSqm > 0 ? `CHF ${p.rentPricePerSqm.toLocaleString('de-CH')}` : k.A.} {/* Aktueller Mieter */} {p.currentTenant ?? } {/* Mietlaufzeit */} {p.leaseTerm ?? } {/* Breakoutoption */} {p.breakoutOption == null ? : } {/* Breakoutoption Zeitpunkt */} {p.breakoutOptionDate ? new Date(p.breakoutOptionDate).toLocaleDateString('de-CH') : } {/* Datenqualität */} {Math.round(qScore * 100)}% {/* Aktionen */} e.stopPropagation()}> onViewDetail ? onViewDetail(p.id) : onSelect(p.id)}> ) }) )}
) }