import { useState } from 'react' import { useCreateProperty } from './useProperties' import { useParseListingText } from './useAI' import { SOFT_FACTORS } from '../pages/supply/newListingConstants' import { buildCreatePropertyInput } from '../pages/supply/newListingMapper' import type { Prefill } from '../pages/supply/newListingConstants' function emptySoftLevels(): Record { return Object.fromEntries(SOFT_FACTORS.map(f => [f.key, ''])) } function validate(fields: { street: string postalCode: string city: string areaSqm: string rentPerSqm: string fitOut: string fitOutByLandlord: boolean | undefined }): string | null { if (!fields.street.trim()) return 'Strasse erforderlich' if (!fields.postalCode.trim()) return 'PLZ erforderlich' if (!fields.city.trim()) return 'Ort erforderlich' if (!fields.areaSqm || isNaN(Number(fields.areaSqm)) || Number(fields.areaSqm) <= 0) return 'Gültige Fläche eingeben' if (!fields.rentPerSqm || isNaN(Number(fields.rentPerSqm)) || Number(fields.rentPerSqm) <= 0) return 'Gültigen Mietpreis eingeben' // Bei Rohbau/Edelrohbau muss der Ausbau-Träger aktiv gewählt werden if ((fields.fitOut === 'SHELL' || fields.fitOut === 'BASIC') && fields.fitOutByLandlord === undefined) return 'Bitte wählen, wer den Ausbau trägt (Vermieter oder Mieter)' return null } export interface NewListingFormState { // Core assetType: string areaSqm: string rentPerSqm: string availableFrom: string description: string // Address street: string houseNumber: string postalCode: string city: string // Soft factors softLevels: Record // Technical floor: string fitOut: string fitOutByLandlord: boolean | undefined parking: string ceilingHeight: string mieterausbaubeitrag: string isFlexible: boolean minLettableSqm: string // Contact contactName: string contactEmail: string contactPhone: string // Images images: string[] imageInput: string floorPlanUrl: string // AI aiText: string aiApplied: boolean // Status error: string | null created: boolean aiParsing: boolean submitting: boolean isPrefilled: boolean } export interface NewListingFormHandlers { setAssetType: (v: string) => void setAreaSqm: (v: string) => void setRentPerSqm: (v: string) => void setAvailableFrom: (v: string) => void setDescription: (v: string) => void setStreet: (v: string) => void setHouseNumber: (v: string) => void setPostalCode: (v: string) => void setCity: (v: string) => void setSoftLevel: (key: string, value: string) => void setFloor: (v: string) => void setFitOut: (v: string) => void setFitOutByLandlord: (v: boolean | undefined) => 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 setImageInput: (v: string) => void setFloorPlanUrl: (v: string) => void setAiText: (v: string) => void addImage: () => void removeImage: (index: number) => void handleAiParse: () => void handleSubmit: () => void resetForm: () => void } export function useNewListingForm(pre: Prefill): NewListingFormState & NewListingFormHandlers { const createProperty = useCreateProperty() const parseListingMutation = useParseListingText() const [assetType, setAssetType] = useState(pre.assetType ?? 'OFFICE') const [street, setStreet] = useState(pre.street ?? '') const [houseNumber, setHouseNumber] = useState(pre.houseNumber ?? '') const [postalCode, setPostalCode] = useState(pre.postalCode ?? '') const [city, setCity] = useState(pre.city ?? '') const [areaSqm, setAreaSqm] = useState(pre.areaSqm ? String(pre.areaSqm) : '') const [rentPerSqm, setRentPerSqm] = useState(pre.rentPricePerSqm ? String(pre.rentPricePerSqm) : '') const [availableFrom, setAvailableFrom] = useState(pre.availableFrom ?? '') const [description, setDescription] = useState('') const [contactName, setContactName] = useState('') const [contactEmail, setContactEmail] = useState('') const [contactPhone, setContactPhone] = useState('') const [softLevels, setSoftLevels] = useState>(() => ({ ...emptySoftLevels(), ...pre.softLevels })) const [floor, setFloor] = useState(pre.floor ?? '') const [fitOut, setFitOut] = useState(pre.fitOut ?? '') const [fitOutByLandlord, setFitOutByLandlord] = useState(pre.fitOutByLandlord) const [parking, setParking] = useState(pre.parking != null ? String(pre.parking) : '') const [ceilingHeight, setCeilingHeight]= useState(pre.ceilingHeight != null ? String(pre.ceilingHeight) : '') const [mieterausbaubeitrag, setMieterausbaubeitrag] = useState(pre.mieterausbaubeitragPerSqm != null ? String(pre.mieterausbaubeitragPerSqm) : '') const [isFlexible, setIsFlexible] = useState(pre.isFlexible ?? false) const [minLettableSqm, setMinLettableSqm] = useState(pre.minLettableSqm != null ? String(pre.minLettableSqm) : '') const [images, setImages] = useState([]) const [imageInput, setImageInput] = useState('') const [floorPlanUrl, setFloorPlanUrl] = useState('') const [aiText, setAiText] = useState('') const [aiApplied, setAiApplied] = useState(false) const [error, setError] = useState(null) const [created, setCreated] = useState(false) function setSoftLevel(key: string, value: string) { setSoftLevels(prev => ({ ...prev, [key]: value })) } function addImage() { const url = imageInput.trim() if (url && !images.includes(url)) setImages(prev => [...prev, url]) setImageInput('') } function removeImage(index: number) { setImages(prev => prev.filter((_, i) => i !== index)) } function handleAiParse() { if (!aiText.trim()) return parseListingMutation.mutate(aiText, { onSuccess: (parsed) => { if (parsed.assetType) setAssetType(parsed.assetType) if (parsed.areaSqm) setAreaSqm(String(parsed.areaSqm)) if (parsed.rentPerSqm) setRentPerSqm(String(parsed.rentPerSqm)) if (parsed.city && !city) setCity(parsed.city) if (parsed.fitOut) setFitOut(parsed.fitOut) if (parsed.parking) setParking(String(parsed.parking)) if (parsed.softLevels) setSoftLevels(prev => ({ ...prev, ...parsed.softLevels })) setAiApplied(true) }, }) } function handleSubmit() { const err = validate({ street, postalCode, city, areaSqm, rentPerSqm, fitOut, fitOutByLandlord }) if (err) { setError(err); return } setError(null) createProperty.mutate( buildCreatePropertyInput({ assetType, street, houseNumber, postalCode, city, areaSqm: Number(areaSqm), rentPerSqm: Number(rentPerSqm), availableFrom, description, softLevels, floor, fitOut, fitOutByLandlord, parking, ceilingHeight, images, floorPlanUrl, mieterausbaubeitrag, isFlexible, minLettableSqm, }), { onSuccess: () => setCreated(true), onError: () => setError('Fehler beim Erstellen des Inserats. Bitte erneut versuchen.'), }, ) } function resetForm() { setAssetType('OFFICE') setStreet(''); setHouseNumber(''); setPostalCode(''); setCity('') setAreaSqm(''); setRentPerSqm(''); setAvailableFrom(''); setDescription('') setContactName(''); setContactEmail(''); setContactPhone('') setSoftLevels(emptySoftLevels()) setFloor(''); setFitOut(''); setFitOutByLandlord(undefined); setParking(''); setCeilingHeight('') setMieterausbaubeitrag(''); setIsFlexible(false); setMinLettableSqm('') setImages([]); setImageInput(''); setFloorPlanUrl('') setAiText(''); setAiApplied(false) setCreated(false); setError(null) } return { assetType, areaSqm, rentPerSqm, availableFrom, description, street, houseNumber, postalCode, city, softLevels, floor, fitOut, fitOutByLandlord, parking, ceilingHeight, mieterausbaubeitrag, isFlexible, minLettableSqm, contactName, contactEmail, contactPhone, images, imageInput, floorPlanUrl, aiText, aiApplied, error, created, aiParsing: parseListingMutation.isPending, submitting: createProperty.isPending, isPrefilled: !!pre.propertyId, setAssetType, setAreaSqm, setRentPerSqm, setAvailableFrom, setDescription, setStreet, setHouseNumber, setPostalCode, setCity, setSoftLevel, setFloor, setFitOut, setFitOutByLandlord, setParking, setCeilingHeight, setMieterausbaubeitrag, setIsFlexible, setMinLettableSqm, setContactName, setContactEmail, setContactPhone, setImageInput, setFloorPlanUrl, setAiText, addImage, removeImage, handleAiParse, handleSubmit, resetForm, } }