fix: carry all unit data into + Inserat prefill

When clicking + Inserat in UnitStructurePanel, the new listing form
now pre-populates: floor label, fit-out standard, parking, ceiling
height, Mieterausbaubeitrag, Teilbar toggle, min lettable sqm, and
availability date from the unit and its parent property.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-06-09 21:32:54 +02:00
parent 87ea4c4dfc
commit 96a2507979
3 changed files with 49 additions and 21 deletions
+23 -4
View File
@@ -143,21 +143,30 @@ export function UnitStructurePanel({ p }: { p: Property }) {
</Box> </Box>
</Tooltip> </Tooltip>
{/* Inline min-unit editor */} {/* Inline min-unit editor — show when actively editing OR when teilbar is on but min sqm not set */}
{editingFlexUnit === u.id && ( {(editingFlexUnit === u.id || (u.isFlexible && !u.minLettableSqm)) && (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}> <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
<TextField <TextField
size="small" size="small"
type="number" type="number"
placeholder="Min m²" autoFocus={!u.minLettableSqm}
placeholder="Min m² *"
value={flexDraft[u.id] ?? ''} value={flexDraft[u.id] ?? ''}
onChange={e => setFlexDraft(d => ({ ...d, [u.id]: parseInt(e.target.value) || undefined }))} onChange={e => setFlexDraft(d => ({ ...d, [u.id]: parseInt(e.target.value) || undefined }))}
sx={{ width: 72, '& .MuiInputBase-input': { fontSize: '0.68rem', py: 0.375, px: 0.75 } }} error={!flexDraft[u.id] && u.isFlexible && !u.minLettableSqm}
sx={{
width: 80,
'& .MuiInputBase-input': { fontSize: '0.68rem', py: 0.375, px: 0.75 },
'& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: (!flexDraft[u.id] && u.isFlexible && !u.minLettableSqm) ? '#ef4444' : undefined },
},
}}
slotProps={{ htmlInput: { min: 10, max: u.areaSqm, step: 10 } }} slotProps={{ htmlInput: { min: 10, max: u.areaSqm, step: 10 } }}
/> />
<Button <Button
size="small" size="small"
variant="contained" variant="contained"
disabled={!flexDraft[u.id]}
sx={{ fontSize: '0.58rem', py: 0.25, px: 0.75, minWidth: 0, bgcolor: '#1d4ed8', '&:hover': { bgcolor: '#1e40af' } }} sx={{ fontSize: '0.58rem', py: 0.25, px: 0.75, minWidth: 0, bgcolor: '#1d4ed8', '&:hover': { bgcolor: '#1e40af' } }}
onClick={() => { onClick={() => {
updateUnit.mutate({ unitId: u.id, data: { isFlexible: true, minLettableSqm: flexDraft[u.id] } }) updateUnit.mutate({ unitId: u.id, data: { isFlexible: true, minLettableSqm: flexDraft[u.id] } })
@@ -166,6 +175,7 @@ export function UnitStructurePanel({ p }: { p: Property }) {
> >
</Button> </Button>
{editingFlexUnit === u.id && u.minLettableSqm && (
<Button <Button
size="small" size="small"
variant="text" variant="text"
@@ -174,6 +184,7 @@ export function UnitStructurePanel({ p }: { p: Property }) {
> >
</Button> </Button>
)}
</Box> </Box>
)} )}
@@ -193,6 +204,14 @@ export function UnitStructurePanel({ p }: { p: Property }) {
rentPricePerSqm: u.rentPricePerSqm ?? p.rentPricePerSqm, rentPricePerSqm: u.rentPricePerSqm ?? p.rentPricePerSqm,
unitLabel: u.unitLabel, unitLabel: u.unitLabel,
propertyId: p.id, propertyId: p.id,
floor: floorLabel(u),
fitOut: p.hardFacts?.fitOut,
parking: p.hardFacts?.parking,
ceilingHeight: p.hardFacts?.ceilingHeightM,
mieterausbaubeitragPerSqm: p.hardFacts?.mieterausbaubeitragPerSqm,
isFlexible: u.isFlexible,
minLettableSqm: u.minLettableSqm,
availableFrom: u.listing?.availableFrom ?? p.availabilityDate,
}, },
}, },
})} })}
+9 -9
View File
@@ -109,19 +109,19 @@ export function useNewListingForm(pre: Prefill): NewListingFormState & NewListin
const [city, setCity] = useState(pre.city ?? '') const [city, setCity] = useState(pre.city ?? '')
const [areaSqm, setAreaSqm] = useState(pre.areaSqm ? String(pre.areaSqm) : '') const [areaSqm, setAreaSqm] = useState(pre.areaSqm ? String(pre.areaSqm) : '')
const [rentPerSqm, setRentPerSqm] = useState(pre.rentPricePerSqm ? String(pre.rentPricePerSqm) : '') const [rentPerSqm, setRentPerSqm] = useState(pre.rentPricePerSqm ? String(pre.rentPricePerSqm) : '')
const [availableFrom, setAvailableFrom] = useState('') const [availableFrom, setAvailableFrom] = useState(pre.availableFrom ?? '')
const [description, setDescription] = useState('') const [description, setDescription] = useState('')
const [contactName, setContactName] = useState('') const [contactName, setContactName] = useState('')
const [contactEmail, setContactEmail] = useState('') const [contactEmail, setContactEmail] = useState('')
const [contactPhone, setContactPhone] = useState('') const [contactPhone, setContactPhone] = useState('')
const [softLevels, setSoftLevels] = useState<Record<string, string>>(emptySoftLevels) const [softLevels, setSoftLevels] = useState<Record<string, string>>(() => ({ ...emptySoftLevels(), ...pre.softLevels }))
const [floor, setFloor] = useState('') const [floor, setFloor] = useState(pre.floor ?? '')
const [fitOut, setFitOut] = useState('') const [fitOut, setFitOut] = useState(pre.fitOut ?? '')
const [parking, setParking] = useState('') const [parking, setParking] = useState(pre.parking != null ? String(pre.parking) : '')
const [ceilingHeight, setCeilingHeight]= useState('') const [ceilingHeight, setCeilingHeight]= useState(pre.ceilingHeight != null ? String(pre.ceilingHeight) : '')
const [mieterausbaubeitrag, setMieterausbaubeitrag] = useState('') const [mieterausbaubeitrag, setMieterausbaubeitrag] = useState(pre.mieterausbaubeitragPerSqm != null ? String(pre.mieterausbaubeitragPerSqm) : '')
const [isFlexible, setIsFlexible] = useState(false) const [isFlexible, setIsFlexible] = useState(pre.isFlexible ?? false)
const [minLettableSqm, setMinLettableSqm] = useState('') const [minLettableSqm, setMinLettableSqm] = useState(pre.minLettableSqm != null ? String(pre.minLettableSqm) : '')
const [images, setImages] = useState<string[]>([]) const [images, setImages] = useState<string[]>([])
const [imageInput, setImageInput] = useState('') const [imageInput, setImageInput] = useState('')
const [floorPlanUrl, setFloorPlanUrl] = useState('') const [floorPlanUrl, setFloorPlanUrl] = useState('')
+9
View File
@@ -49,6 +49,15 @@ export interface LocationState {
rentPricePerSqm?: number rentPricePerSqm?: number
unitLabel?: string unitLabel?: string
propertyId?: string propertyId?: string
floor?: string
fitOut?: string
parking?: number
ceilingHeight?: number
mieterausbaubeitragPerSqm?: number
isFlexible?: boolean
minLettableSqm?: number
availableFrom?: string
softLevels?: Record<string, string>
} }
} }