feat: Grundriss-Feature, Listenansicht mit Bildern, Gewerbe-Label, Image-Pool

- Grundriss (FloorPlanSection): PropertyUnit.floorPlanUrl?, Property.floorPlanUrl?;
  FloorPlanSection in MatchDetail + PropertyDetail; FloorPlanUrlSection in NewListing-Formular
- Listenansicht (MatchCardCompact): horizontales Layout mit 120px Bildstreifen,
  Score-Badge, Asset-Label-Overlay, alle 3 grünen Punkte, Anfrage-Button
- Light Industrial → "Gewerbe" überall (NeedInput, NeedCardPreview, CriteriaReviewPanel,
  newListingConstants, MyListings, propertyHelpers)
- "Zum Originalinserat"-Button nur bei Maison-Work-Objekten
- Image-Pool: propertyImageResolver mit sequentiellem Pool-Index (keine doppelten Bilder),
  nur Innenaufnahmen, rotate()-Trick für Sub-Pools
- Overlay-Labels (Objekttyp + Stadtteil) in LocationPreview + IntelligenceMatchCard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-24 22:12:43 +02:00
parent 3ab6eeccf2
commit e95490eb72
39 changed files with 685 additions and 147 deletions
+13 -1
View File
@@ -4,10 +4,22 @@ import { mockPipelineItems } from '../mock-data/pipelineItems'
const STORAGE_KEY = 'property_match_pipeline_items'
const STAGE_MIGRATION: Record<string, PipelineStage> = {
DISCOVERED: 'CONTACTED',
QUALIFIED: 'CONTACTED',
}
function migrateStage(stage: string): PipelineStage {
return (STAGE_MIGRATION[stage] ?? stage) as PipelineStage
}
function load(): PipelineItem[] {
try {
const raw = localStorage.getItem(STORAGE_KEY)
if (raw) return JSON.parse(raw) as PipelineItem[]
if (raw) {
const items = JSON.parse(raw) as PipelineItem[]
return items.map(i => ({ ...i, stage: migrateStage(i.stage) }))
}
} catch { /* ignore */ }
return [...mockPipelineItems]
}