Files
property-match/src/pages/supply/Properties.tsx
T
Benjamin Sutter e13fe470fb refactor: replace split-panel with overlay Drawer on Properties and FutureAvailability
650px right Drawer overlays the list instead of compressing it — full list always visible, detail panel has adequate space.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 21:25:08 +02:00

87 lines
2.9 KiB
TypeScript

import { useState } from 'react'
import { Box, Drawer } from '@mui/material'
import { PageHeader } from '../../components/layout'
import { useProperties } from '../../hooks/useProperties'
import { PropertyFilterBar, PropertyTable, PropertyDetailView } from '../../components/supply'
import type { PropertyTableFilters } from '../../components/supply'
import type { Property } from '../../domain/property'
function applyFilters(properties: Property[], filters: PropertyTableFilters): Property[] {
let result = [...properties]
if (filters.search) {
const q = filters.search.toLowerCase()
result = result.filter(
p =>
p.title.toLowerCase().includes(q) ||
p.location.city.toLowerCase().includes(q) ||
p.address.street.toLowerCase().includes(q),
)
}
if (filters.assetTypes && filters.assetTypes.length > 0) {
result = result.filter(p => filters.assetTypes!.includes(p.assetType))
}
if (filters.availabilityStatus) {
result = result.filter(p => p.availabilityStatus === filters.availabilityStatus)
}
if (filters.sortBy) {
const dir = filters.sortDir === 'asc' ? 1 : -1
result.sort((a, b) => {
switch (filters.sortBy) {
case 'dataQuality': return dir * (a.dataQuality.score - b.dataQuality.score)
case 'area': return dir * (a.areaSqm - b.areaSqm)
case 'rent': return dir * (a.rentPricePerSqm - b.rentPricePerSqm)
case 'confidence': return dir * (a.confidenceScore - b.confidenceScore)
case 'availability': return dir * a.availabilityStatus.localeCompare(b.availabilityStatus)
default: return 0
}
})
}
return result
}
export default function Properties() {
const [selectedId, setSelectedId] = useState<string | null>(null)
const [filters, setFilters] = useState<PropertyTableFilters>({})
const { data: properties = [], isLoading, isError } = useProperties()
const filtered = applyFilters(properties, filters)
return (
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>
<PageHeader
title="Objektverwaltung"
subtitle={`${filtered.length} von ${properties.length} Objekten`}
/>
<PropertyFilterBar filters={filters} onFiltersChange={setFilters} />
<Box sx={{ flex: 1, overflowY: 'auto' }}>
<PropertyTable
properties={filtered}
isLoading={isLoading}
isError={isError}
selectedId={selectedId}
onSelect={setSelectedId}
filters={filters}
onFiltersChange={setFilters}
/>
</Box>
<Drawer
anchor="right"
open={!!selectedId}
onClose={() => setSelectedId(null)}
slotProps={{ paper: { sx: { width: 650, boxShadow: '-4px 0 24px rgba(0,0,0,0.10)' } } }}
>
{selectedId && (
<PropertyDetailView propertyId={selectedId} onClose={() => setSelectedId(null)} />
)}
</Drawer>
</Box>
)
}