feat: Reale Jahresbelastung, must-have fixes, fitOut data coverage

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>
This commit is contained in:
Benjamin Sutter
2026-06-06 20:09:55 +02:00
parent a825672197
commit b2530f9e20
40 changed files with 1755 additions and 733 deletions
+13 -2
View File
@@ -45,6 +45,9 @@ export interface NewListingFormState {
fitOut: string
parking: string
ceilingHeight: string
mieterausbaubeitrag: string
isFlexible: boolean
minLettableSqm: string
// Contact
contactName: string
contactEmail: string
@@ -79,6 +82,9 @@ export interface NewListingFormHandlers {
setFitOut: (v: string) => void
setParking: (v: string) => void
setCeilingHeight: (v: string) => void
setMieterausbaubeitrag: (v: string) => void
setIsFlexible: (v: boolean) => void
setMinLettableSqm: (v: string) => void
setContactName: (v: string) => void
setContactEmail: (v: string) => void
setContactPhone: (v: string) => void
@@ -113,6 +119,9 @@ export function useNewListingForm(pre: Prefill): NewListingFormState & NewListin
const [fitOut, setFitOut] = useState('')
const [parking, setParking] = useState('')
const [ceilingHeight, setCeilingHeight]= useState('')
const [mieterausbaubeitrag, setMieterausbaubeitrag] = useState('')
const [isFlexible, setIsFlexible] = useState(false)
const [minLettableSqm, setMinLettableSqm] = useState('')
const [images, setImages] = useState<string[]>([])
const [imageInput, setImageInput] = useState('')
const [floorPlanUrl, setFloorPlanUrl] = useState('')
@@ -161,6 +170,7 @@ export function useNewListingForm(pre: Prefill): NewListingFormState & NewListin
areaSqm: Number(areaSqm), rentPerSqm: Number(rentPerSqm),
availableFrom, description, softLevels,
floor, fitOut, parking, ceilingHeight, images, floorPlanUrl,
mieterausbaubeitrag, isFlexible, minLettableSqm,
}),
{
onSuccess: () => setCreated(true),
@@ -176,6 +186,7 @@ export function useNewListingForm(pre: Prefill): NewListingFormState & NewListin
setContactName(''); setContactEmail(''); setContactPhone('')
setSoftLevels(emptySoftLevels())
setFloor(''); setFitOut(''); setParking(''); setCeilingHeight('')
setMieterausbaubeitrag(''); setIsFlexible(false); setMinLettableSqm('')
setImages([]); setImageInput(''); setFloorPlanUrl('')
setAiText(''); setAiApplied(false)
setCreated(false); setError(null)
@@ -184,7 +195,7 @@ export function useNewListingForm(pre: Prefill): NewListingFormState & NewListin
return {
assetType, areaSqm, rentPerSqm, availableFrom, description,
street, houseNumber, postalCode, city,
softLevels, floor, fitOut, parking, ceilingHeight,
softLevels, floor, fitOut, parking, ceilingHeight, mieterausbaubeitrag, isFlexible, minLettableSqm,
contactName, contactEmail, contactPhone,
images, imageInput, floorPlanUrl, aiText, aiApplied,
error, created,
@@ -194,7 +205,7 @@ export function useNewListingForm(pre: Prefill): NewListingFormState & NewListin
setAssetType, setAreaSqm, setRentPerSqm, setAvailableFrom, setDescription,
setStreet, setHouseNumber, setPostalCode, setCity,
setSoftLevel,
setFloor, setFitOut, setParking, setCeilingHeight,
setFloor, setFitOut, setParking, setCeilingHeight, setMieterausbaubeitrag, setIsFlexible, setMinLettableSqm,
setContactName, setContactEmail, setContactPhone,
setImageInput, setFloorPlanUrl, setAiText,
addImage, removeImage,