Commit Graph

19 Commits

Author SHA1 Message Date
Benjamin Sutter e95490eb72 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>
2026-05-24 22:12:43 +02:00
Benjamin Sutter 128d28af8d feat: in-memory inquiry flow — send from card, pipeline, and detail
New inquiryStore (Zustand) holds sent inquiries for the session.
InquiryQuickDialog reads from the store (no props), renders wherever needed.
Sent inquiries appear immediately at the top of the Anfragen page.

Entry points:
- Match cards: "Anfrage" button on every card in the results feed
- MatchDetail: primary action in NextActionsPanel
- Pipeline: chat icon on every DraggableCard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 18:00:46 +02:00
Benjamin Sutter 99c26b5464 feat: Decision Intelligence simplification pass
Phase 1 — MatchDetail: collapse from 11 panels to 3 visible sections
(Warum dieser Match? / Nächste Aktion / toggle). All analysis panels
(ScoreBreakdown, Risk, MissingData, NeedAlignment, Location, Tradeoffs,
FutureAvailabilityContext) hidden behind "Vollständige Analyse anzeigen".
Removes 2-column sidebar layout for cleaner single-column reading flow.

Phase 2 — Supply Dashboard: replace data quality KPIs with demand
intelligence. Hero now shows "Starke Match-Anfragen", active properties,
and Zukunftssignale count. Top 4 matches listed with score + reason +
next action. Data quality demoted to secondary collapsed notice.

Phase 3 — Future Availability: add informational banner above the results
feed when Zukunftssignale are present. Framed as professional market
intelligence (contract expiries, construction signals) not as risk.
Removed Zukunftssignal from DecisionContextPanel risks array.

Phase 4 — Naming: standardise RESULT_TYPE_META to "Verifiziertes Objekt" /
"Externes Angebot" / "Maison Work" / "Zukunftssignal" across all screens.
EXTERNAL_MARKET gets distinct amber color (#d97706). Remove Gold/Silver/
Bronze tier label from match score badge — only the % number is shown.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 17:09:12 +02:00
Benjamin Sutter 7f090a48ff refactor: replace hardcoded hex colors with design tokens across priority components
- Add DS_COLORS.heat, DS_COLORS.futureCard, INQUIRY_STATUS_META tokens to ds.ts
- Eliminate 4 duplicate RESULT_TYPE_META / TYPE_META constants (now all use ds.ts)
- Eliminate 3 duplicate scoreColor / SCORE_COLOR functions (now all use matchScoreHex)
- HeatBadge: use DS_COLORS.heat.VERY_HOT / HOT tokens
- FutureAvailabilityCard: use DS_COLORS.futureCard.controlled / signal tokens
- IntelligenceMatchCard: import RESULT_TYPE_META from ds.ts, remove primary override
- MatchScoreDisplay: replace local scoreColor() with matchScoreHex()
- CompareColumnHeader: remove local TYPE_META + SCORE_COLOR, use ds.ts + utils.ts
- CompareTableBody: import RESULT_TYPE_META + matchScoreHex, fix #7c3aed → token
- compareUtils: remove TYPE_META + SCORE_COLOR, use dataQualityHex in scoreBar
- Anfragen + AnfragenInquiryItem: deduplicate STATUS_CONFIG → INQUIRY_STATUS_META
- Anfragen: #1e3a5f → 'primary.main', KI alert → futureCard.controlled tokens
- AnfragenMessageBubble: own-message bubble → 'primary.main', AI bubble → tokens
- ScoreBreakdownPanel: #1e3a5f → 'primary.main', #6d28d9 → futureCard.controlled
- ESLint: add warn rule against new hex colors in component sx props

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 13:02:01 +02:00
Benjamin Sutter 22c195b4a5 refactor: split large page components + taxonomy/HeatBadge/FutureAvailability improvements
- Taxonomy: merge VERIFIED_PORTFOLIO + EXTERNAL_MARKET display → 'Plattform' (dark blue) across all surfaces
- HeatBadge: new flame indicator for hot properties (grid, list, pipeline views)
- FutureAvailabilityContextPanel: richer detail page with AI summary, strategic assessment, sources
- Refactor Pipeline.tsx (630→152 lines) → pipeline/PipelineCard, PipelineColumn, PipelineDetailPanel, pipelineConstants, pipelineUtils
- Refactor IntelligenceMatchCard.tsx (483→179 lines) → FutureAvailabilityCard extracted
- Refactor MatchDetail.tsx (559→464 lines) → useMatchDetailData hook, MatchDetailPropertyDetails
- Refactor Compare.tsx (638→485 lines) → compareUtils, CompareCriteriaCard extracted

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:36:03 +02:00
Benjamin Sutter 76f9927c7c fix: UX polish — score formula, role badges, compare view, page titles
- Score: remove hidden dataQuality/confidence modifiers from finalScore;
  formula now correctly shows hard×60% + soft×40% = displayed total
- "Ihr Objekt" badge: only shown for PROPERTY_MANAGER/ORGANIZATION_ADMIN
  in both IntelligenceMatchCard and MatchCardHeader (DEMAND_USER sees
  Verified Portfolio as a normal listing without ownership indicator)
- Compare: fix factor lookup to use allFactors (includes mid-range 45–70
  scores) so Prestige, Erreichbarkeit etc. no longer show "Nicht verfügbar"
- Compare: richer AI summary with overallAssessment, perPropertyAssessment
  (strengths/weaknesses/bestFor/keyRisk per property), and recommendation
- Compare/Results: pb:10 so CompareTray never overlaps last row of content
- AppShell: dynamic route names for /demand/results/:id → "Match Detail"
  and /demand/property/:id → "Objekt Detail" (no more UUID in header)
- MatchDetail: remove "Match EF9" debug chip from sticky nav
- LocationIntelligencePanel: comparable listings are now clickable links
  navigating to /demand/property/:id
- Comparable links: blue text + hover highlight

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 21:05:36 +02:00
Benjamin Sutter 34a4dcfb29 feat: unit-first architecture — floor + street as primary card title
Every VERIFIED_PORTFOLIO property now has explicit units in mock data
(added to prop-002, prop-008, prop-009, prop-010, prop-011, prop-014).

PropertyUnit extracted to domain/unit.ts with formatFloorLabel,
formatUnitTitle, formatMultiUnitFloors helpers; re-exported from
property.ts so all existing imports are unaffected.

Cards now show floor + street as the primary title:
- Specific unit match: "1.OG Nord · Zollstrasse 12"
- Multi-unit (whole building): "1.OG–3.OG · Zollstrasse 12"
- EG retail: "EG Verkauf · Löwenplatz 3"
Building name (e.g. "Bürofläche Zollstrasse 12") appears as subtitle.
Both IntelligenceMatchCard (grid) and MatchCardCompact (list) updated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 11:19:13 +02:00
Benjamin Sutter a39c6ed200 fix: property-level scoring for multi-unit properties + multi-unit chip
For properties with explicit sub-units (e.g. prop-001: 280/310/260 m²),
synthetic matching now generates ONE property-level match using the aggregate
areaSqm (850 m²) instead of per-unit matches — ensuring a need for 800-1000 m²
correctly scores the whole floor as +20 (STRONG) rather than -10 each unit.

Pre-market unit-level matches are still generated per released unit so tenants
seeking smaller spaces still see the specific unit signals.

Card shows "X Einheiten · total Y m²" chip when a multi-unit property is matched
at property level (no specific unit assigned).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 00:30:03 +02:00
Benjamin Sutter 99e99d66c5 feat: unit-level matching architecture — match against Einheiten, not Objekte
- domain/property: add getEffectiveUnits() — returns explicit units or synthesises
  one from property-level data so all properties work uniformly at unit level
- domain/match: add unitId? field — every Match references a specific unit
- domain/unifiedResult: add unit? to VerifiedPortfolioResult + ExternalMarketResult
- MockupNeedProvider: generateSyntheticMatches iterates getEffectiveUnits(prop);
  computeScore uses unit-level areaSqm + rentPricePerSqm; resultId for PRE-MARKET
  signals matches useSchattenmarktSignals signal ID format
- useUnifiedResults: resolve unit from match.unitId for VERIFIED_PORTFOLIO/EXTERNAL_MARKET
- matchCardAdapter: unit now extracted for all result types; unitId from match.unitId
- IntelligenceMatchCard: regular cards show unit chip (floor + label + m²) when a
  named unit is known — only adds context, never shows for synthetic/whole-property units

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 20:03:54 +02:00
Benjamin Sutter d902feb6c0 feat: Objekt→Einheit architecture — unit-level pre-market, property detail page, click-through from cards
- Domain: PropertyUnit extended with propertyId + schattenmarktRelease per unit
- Domain: FutureAvailabilityResult carries resolved property + unit
- useSchattenmarktSignals: generates unit-level signals (schattenmarkt-{propId}-{unitId})
- useUnifiedResults: resolves backing property + unit on FUTURE_AVAILABILITY fast path
- IUnitProvider + MockupUnitProvider: first-class unit access and mutation
- matchCardAdapter: maps preMarketUnit, preMarketAllUnits, propertyId, unitId to ViewModel
- IntelligenceMatchCard: PRE-MARKET VERIFIED shows unit info strip + "Zur Einheit →" button
- PropertyDetailView: unit-level toggles + date pickers inside PreMarketPanel
- New page: /demand/property/:propertyId with unit table, status chips, inquiry form
- App.tsx: demand route /demand/property/:propertyId registered
- Mock data: prop-001/007/037 units updated with correct lease dates + unit-level schattenmarktRelease

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 19:47:59 +02:00
Benjamin Sutter 8f7372157c feat: Pre-Market Intelligence UX rework — institutional positioning
Redesign the Future Availability card system to clearly distinguish two classes:

PRE-MARKET VERIFIED (Verwaltung-controlled):
- Soft purple (#7c3aed) accent, institutional premium feel
- Badge: "PRE-MARKET VERIFIED" with shield icon
- "Direkte Verwaltungsquelle" attribution chip in header
- Shows confirmed ERP facts with green checkmarks

MARKET SIGNAL (crawler/probabilistic):
- Slate blue (#1d4ed8) accent, analytical feel
- Badge: "MARKET SIGNAL"
- Amber notice box: "Probabilistischer Marktindikator — kein bestätigtes Objekt"
- Shows market indicators and explicit probability %
- Source attribution (press, job posting, etc.)

Both cards answer: What? How reliable? Where from? Why relevant? Risks? Action?

PropertyDetailView: rename SchattenmarktReleasePanel → PreMarketPanel, update
toggle label to "Pre-Market Matching aktivieren", add Matching Demand Intelligence
block showing active search profile counts and early matching opportunity.

FutureAvailabilityContextPanel: update LEASE_EXPIRY signal type label and
relevance bridge text to remove "Schattenmarkt" references.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 17:50:37 +02:00
Benjamin Sutter 5fe15bac62 feat: Future Availability Intelligence — rebrand & card redesign
Replaces "Schattenmarkt" branding with professional Future Availability
Intelligence throughout the UI. Two distinct card types: Pre-Market
(LEASE_EXPIRY + verified, green accent) and Market Signal (probabilistic,
blue accent). Professioneller Data-Header replaces dark purple gradient.
New detail panel sections: Erkannte Marktindikatoren, Strategische
Interpretation, Bestätigt/Nicht bestätigt. All 15 mock signals enriched
with concrete Swiss CRE market indicators and strategic interpretations.
Signal quality shown as 4-dot indicator (Hoch/Mittel/Niedrig).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 13:06:16 +02:00
Benjamin Sutter d5a4862a28 feat: redesign Schattenmarkt card & detail view for explainability
- Remove abstract Konfidenz/DQ badges from match detail header
- Replace ScoreBreakdownPanel with 3-step Bewertungsherleitung for
  FUTURE_AVAILABILITY: Kriterien-Match per factor with bars, Signal-
  Abschlag (verified ERP = kein Abschlag / probabilistic = -N Punkte),
  Gesamt-Score
- Restructure FutureAvailabilityContextPanel: source section first,
  verified ERP box for LEASE_CONTRACT, remove Konfidenz row, disclaimer
  as grey footnote instead of yellow alert
- Add LEASE_EXPIRY to signal type/relevance bridge labels
- Show up to 3 match reasons with explanation on cards (was 1)
- matchCardAdapter: return top-3 positive factors as reasons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 12:39:12 +02:00
Benjamin Sutter 9f391d17cb feat: Reminder Manager + Schattenmarkt-Freigabe + mock data overhaul
- Add Reminder Manager page (/supply/reminder-manager) with KPI bar,
  filter bar, list/card feed, and detail drawer (7 sections incl.
  activity log, snooze, complete, dismiss actions)
- Add Schattenmarkt-Freigabe toggle on PropertyDetailView: Verwaltung
  can opt-in properties for early market exposure before contract expiry
- Auto-generate FutureSignal cards via useSchattenmarktSignals hook
  when leaseEndDate - leadTimeMonths <= MOCK_TODAY
- Fix useUnifiedResults: use property.resultType as fallback (was
  defaulting everything to VERIFIED_PORTFOLIO)
- Fix demand Results: hide VERIFIED_PORTFOLIO from non-manager users
  even when showOwnProperties toggle was previously enabled
- Fix AppShell: redirect to allowed workspace on user role switch
- Fix 3 wrong match scores (match-002: 93→62, match-009: 86→55,
  match-017: 87→52)
- Add 7 new match records (match-050–056) for need-001, need-002,
  need-011
- Add need-011 (Retail Bern Innenstadt)
- Add prop-031–036 (EXTERNAL_MARKET / MAISON_WORK / FUTURE_AVAILABILITY)
- Fix duplicate image URLs across all properties
- Add signal-011 (Bern Altstadt, Mode Boutique) + propertyId to
  signal-001

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 11:52:24 +02:00
Benjamin Sutter 3756675b6f feat: add Maison Work source type, rename ExternalMarket to Direktinserat, hide own portfolio from demand search by default
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 23:02:05 +02:00
Benjamin Sutter 9cf3e72033 feat: Schattenmarkt UX — separate section, relevance bridge, source links
Signals are now in their own feed section with an explanation banner
so users understand they are not confirmed properties. Each signal card
shows WHY it appears in their search (e.g. 'Fläche könnte frei werden').
Source pills are now clickable links. FutureAvailabilityContextPanel
redesigned with full AI summary, source button, and relevance bridge.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 21:59:08 +02:00
Benjamin Sutter b5cdb0353b feat: Schattenmarkt cards — source pills, probability bar, AI summary
Complete IntelligenceMatchCard redesign for FUTURE_AVAILABILITY signals:
purple gradient hero, source type pills, credibility indicators,
probability LinearProgress bar, market indicator badge, AI-generated
signal summary block. Added aiSummary field to FutureSignal domain
and rich German AI summaries to mock signals 001–005.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 21:49:27 +02:00
Benjamin Sutter 05ac0083b2 feat: Steuerlast-Kriterium, ImmoScout-Layout, Gold/Silver/Bronze-Trennung
- Flächensuche: Flexibilität durch Steuerlast (taxEnvironment) ersetzt
- MatchDetail: Bild als Hero-Banner oben, Karte eingebettet im Inhalt darunter
- Ergebnisliste: Gold/Silber/Bronze-Abschnitte mit farbigen Trennlinien
- ScoreBreakdown: KI-Steuerlast-Link zur kantonalen Steuerrechner-Seite
- Beispieldaten: alle Objekte mit passenden Bildern versehen
- locationIntelligence: taxCalculatorUrl pro Kanton ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:14:10 +02:00
Benjamin Sutter c75d3c8121 feat: F029 intelligence card system — premium AI-native CRE cards
Gold/Silver/Bronze FIFA-style score badges overlaid on location imagery.
List/grid view toggle on Results and Properties pages (persisted in
localStorage). IntelligenceMatchCard for match results grid view;
PropertyIntelligenceCard for property grid view with warm brown theme.
LocationPreview component with Google Maps link. 10 mock properties
enriched with Unsplash building images.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:25:27 +02:00