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>
115 lines
3.5 KiB
TypeScript
115 lines
3.5 KiB
TypeScript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
import { propertyService } from '../services/propertyService'
|
|
import { unitService } from '../services/unitService'
|
|
import type { PropertyUnit } from '../domain/property'
|
|
import { matchService } from '../services/matchService'
|
|
import { futureSignalService } from '../services/futureSignalService'
|
|
import type { AssetType, ResultType } from '../domain/enums'
|
|
import type { CreatePropertyInput, UpdatePropertyInput } from '../domain/property'
|
|
import { STALE_PROPERTIES, STALE_MATCHES, STALE_SIGNALS } from '../lib/constants'
|
|
|
|
interface PropertyFilter {
|
|
assetType?: AssetType
|
|
resultType?: ResultType
|
|
city?: string
|
|
minAreaSqm?: number
|
|
maxRentPerSqm?: number
|
|
organizationId?: string
|
|
sourceType?: string
|
|
}
|
|
|
|
export function useProperties(filter?: PropertyFilter) {
|
|
return useQuery({
|
|
queryKey: ['properties', filter ?? {}],
|
|
queryFn: () => propertyService.getAll(filter),
|
|
staleTime: STALE_PROPERTIES,
|
|
select: (res) => res.data ?? [],
|
|
})
|
|
}
|
|
|
|
export function useProperty(id: string) {
|
|
return useQuery({
|
|
queryKey: ['property', id],
|
|
queryFn: () => propertyService.getById(id),
|
|
staleTime: STALE_PROPERTIES,
|
|
enabled: Boolean(id),
|
|
select: (res) => res.data ?? null,
|
|
})
|
|
}
|
|
|
|
export const usePropertyDetail = useProperty
|
|
|
|
export function usePropertyById(id: string | null) {
|
|
return useQuery({
|
|
queryKey: ['property', id],
|
|
queryFn: () => propertyService.getById(id!),
|
|
enabled: !!id,
|
|
staleTime: STALE_PROPERTIES,
|
|
select: (res) => res.data ?? null,
|
|
})
|
|
}
|
|
|
|
export function usePropertyMatches(propertyId: string | null) {
|
|
return useQuery({
|
|
queryKey: ['property-matches', propertyId],
|
|
queryFn: () => matchService.getMatchesForProperty(propertyId!),
|
|
enabled: !!propertyId,
|
|
staleTime: STALE_MATCHES,
|
|
select: (res) => res.data ?? [],
|
|
})
|
|
}
|
|
|
|
export function usePropertySignals(propertyId: string | null) {
|
|
return useQuery({
|
|
queryKey: ['property-signals', propertyId],
|
|
queryFn: () => futureSignalService.getSignalsForProperty(propertyId!),
|
|
enabled: !!propertyId,
|
|
staleTime: STALE_SIGNALS,
|
|
select: (res) => res.data ?? [],
|
|
})
|
|
}
|
|
|
|
export function useUpdateProperty() {
|
|
const queryClient = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: ({ id, input }: { id: string; input: UpdatePropertyInput }) =>
|
|
propertyService.update(id, input),
|
|
onSuccess: (_, { id }) => {
|
|
queryClient.invalidateQueries({ queryKey: ['properties'] })
|
|
queryClient.invalidateQueries({ queryKey: ['property', id] })
|
|
},
|
|
})
|
|
}
|
|
|
|
export function useCreateProperty() {
|
|
const queryClient = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (input: CreatePropertyInput) => propertyService.create(input),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['properties'] })
|
|
},
|
|
})
|
|
}
|
|
|
|
export function useUpdateUnit(propertyId: string) {
|
|
const queryClient = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: ({ unitId, data }: { unitId: string; data: Partial<PropertyUnit> }) =>
|
|
unitService.update(unitId, data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['properties'] })
|
|
queryClient.invalidateQueries({ queryKey: ['property', propertyId] })
|
|
},
|
|
})
|
|
}
|
|
|
|
export function useRemoveProperty() {
|
|
const queryClient = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (id: string) => propertyService.remove(id),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['properties'] })
|
|
},
|
|
})
|
|
}
|