b2530f9e20
Reale Jahresbelastung (Change 6): - FitOutCostPanel zeigt Jahresmiete + amortisierte Ausbaukosten für alle fitOut-Werte - FULL/PREMIUM: Ausbau CHF 0 (bezugsfertig), SHELL/BASIC: CRB/BKP-Richtwerte amortisiert über 5 J. - Match-Card-Chip zeigt geschätzte Investition (orange wenn >100k) - FitOutInvestment-Typ + calcFitOutInvestment() in fitOutUtils.ts - BackendAIService + MockAIService mit generateFitOutAdvice (IAIService-Interface) Must-have Kriterien (Nicht prüfbar Fix): - ÖV-Anbindung: Minutengrenze aus Freitext extrahiert, gegen publicTransportMinutes geprüft - Mindestfläche: m²-Wert aus Freitext extrahiert, gegen areaSqm geprüft - Ausbaugrad: neues Keyword-Rule für FULL/PREMIUM fitOut-Datenpflege: - fitOut-Werte zu 32 fehlenden Properties ergänzt (Logistik=SHELL, Standard=BASIC, Modern=FULL) - MAB-Werte (200/150/250 CHF/m²) zu 3 BASIC-Objekten hinzugefügt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
103 lines
3.6 KiB
TypeScript
103 lines
3.6 KiB
TypeScript
import { Box, Card, FormControlLabel, MenuItem, Switch, TextField, Typography } from '@mui/material'
|
|
import { FIT_OUT_OPTIONS } from '../../pages/supply/newListingConstants'
|
|
|
|
interface Props {
|
|
floor: string
|
|
onFloorChange: (v: string) => void
|
|
fitOut: string
|
|
onFitOutChange: (v: string) => void
|
|
parking: string
|
|
onParkingChange: (v: string) => void
|
|
ceilingHeight: string
|
|
onCeilingHeightChange: (v: string) => void
|
|
mieterausbaubeitrag: string
|
|
onMieterausbaubeitragChange: (v: string) => void
|
|
isFlexible: boolean
|
|
onIsFlexibleChange: (v: boolean) => void
|
|
minLettableSqm: string
|
|
onMinLettableSqmChange: (v: string) => void
|
|
}
|
|
|
|
export function TechnicalDetailsSection({
|
|
floor, onFloorChange,
|
|
fitOut, onFitOutChange,
|
|
parking, onParkingChange,
|
|
ceilingHeight, onCeilingHeightChange,
|
|
mieterausbaubeitrag, onMieterausbaubeitragChange,
|
|
isFlexible, onIsFlexibleChange,
|
|
minLettableSqm, onMinLettableSqmChange,
|
|
}: Props) {
|
|
return (
|
|
<Card sx={{ p: 3, mb: 3 }}>
|
|
<Typography variant="subtitle2" sx={{ fontWeight: 700, mb: 2 }}>Technische Details (optional)</Typography>
|
|
<Box sx={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 2 }}>
|
|
<TextField
|
|
label="Stockwerk" value={floor}
|
|
onChange={e => onFloorChange(e.target.value)}
|
|
size="small" type="number" fullWidth placeholder="0 = EG"
|
|
/>
|
|
<TextField
|
|
select label="Ausbaustandard" value={fitOut}
|
|
onChange={e => onFitOutChange(e.target.value)} size="small" fullWidth
|
|
>
|
|
{FIT_OUT_OPTIONS.map(o => (
|
|
<MenuItem key={o.value} value={o.value}>{o.label}</MenuItem>
|
|
))}
|
|
</TextField>
|
|
<TextField
|
|
label="Mieterausbaubeitrag (CHF/m²)"
|
|
value={mieterausbaubeitrag}
|
|
onChange={e => onMieterausbaubeitragChange(e.target.value)}
|
|
size="small" type="number" fullWidth
|
|
slotProps={{ htmlInput: { min: 0, max: 1000, step: 25 } }}
|
|
helperText="Beitrag des Vermieters"
|
|
/>
|
|
<TextField
|
|
label="Parkplätze" value={parking}
|
|
onChange={e => onParkingChange(e.target.value)}
|
|
size="small" type="number" slotProps={{ htmlInput: { min: 0 } }} fullWidth
|
|
/>
|
|
<TextField
|
|
label="Deckenhöhe (m)" value={ceilingHeight}
|
|
onChange={e => onCeilingHeightChange(e.target.value)}
|
|
size="small" type="number" slotProps={{ htmlInput: { step: 0.1, min: 2 } }} fullWidth
|
|
/>
|
|
</Box>
|
|
|
|
{/* Divisibility */}
|
|
<Box sx={{ mt: 2.5, pt: 2, borderTop: '1px solid #f1f5f9', display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
<FormControlLabel
|
|
control={
|
|
<Switch
|
|
checked={isFlexible}
|
|
onChange={e => onIsFlexibleChange(e.target.checked)}
|
|
size="small"
|
|
/>
|
|
}
|
|
label={
|
|
<Box>
|
|
<Typography variant="body2" sx={{ fontWeight: 600 }}>Fläche ist teilbar</Typography>
|
|
<Typography variant="caption" color="text.secondary">
|
|
Mieter können auch nur einen Teil der Fläche mieten
|
|
</Typography>
|
|
</Box>
|
|
}
|
|
sx={{ m: 0, flex: 1 }}
|
|
/>
|
|
{isFlexible && (
|
|
<TextField
|
|
label="Mindesteinheit (m²)"
|
|
value={minLettableSqm}
|
|
onChange={e => onMinLettableSqmChange(e.target.value)}
|
|
size="small"
|
|
type="number"
|
|
sx={{ width: 180 }}
|
|
slotProps={{ htmlInput: { min: 10, step: 10 } }}
|
|
helperText="Kleinste vermietbare Einheit"
|
|
/>
|
|
)}
|
|
</Box>
|
|
</Card>
|
|
)
|
|
}
|