Teil A — GenericBadge:
- Neue src/components/shared/GenericBadge.tsx mit zwei Varianten:
transparent (${color}18 Hintergrund, farbiger Text, opt. Border)
solid (gefüllte Farbe, weisser Text)
- Props: label, color, variant, showBorder, bold, icon, size, tooltip, ariaLabel
- 7 Badges auf GenericBadge refactored (Config-Objekt + 1-Zeiler):
ReviewStatusBadge, ReviewPriorityBadge, ReviewEntityTypeBadge,
AIOutputStatusBadge, AIErrorBadge, MatchStatusBadge, ShortlistStatusBadge
- Barrel-Export in src/components/shared/index.ts
Teil B — Provider-Isolation:
- src/mock-data/propertyStore.ts als neutrales Daten-Modul erstellt
- MockupPropertyProvider: importiert aus mock-data statt selbst zu definieren
- MockupUnitProvider: importiert aus mock-data statt aus MockupPropertyProvider
- matchSyncService: importiert aus mock-data statt aus MockupPropertyProvider
- Kein Provider importiert mehr einen anderen Provider
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
IAIService:
+ generateMatchExplanation, summarizeTradeOffs, generateDataQualitySummary,
classifyMarketSignal (4 new methods covering all documented AI output types)
OpenRouterAIService:
- All 11 methods now make real API calls via withFallback() pattern
- Every fallback is explicit (console.warn/error) — no silent mock bleed-through
- Proper JSON extraction with type-safe parsers, no any casts
- parseNeed: AI JSON → ParseNeedResult mapping (no TODO stubs)
- generateFollowUpQuestions, generateMatchExplanation, summarizeTradeOffs,
generateDataQualitySummary, classifyMarketSignal, generateOfferEmail,
extractCriteria, generateFollowUp: fully implemented
Prompts: +followUpQuestionsPrompt, +tradeOffPrompt, +dataQualityPrompt, +marketSignalPrompt
Factory (index.ts):
- VITE_AI_PROVIDER=mock|openrouter (new, takes priority)
- VITE_USE_REAL_AI=true still supported (legacy compat)
- Missing API key → explicit console.warn + MockAIService fallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PipelineItems are domain data and must not live in Zustand. Moves the
full stack to the correct layer: MockupPipelineProvider (localStorage
persistence + seed fallback) → pipelineService → usePipeline hooks
(useQuery for reads, useMutation for writes with cache invalidation).
pipelineStore is now UI-only: dialogOpen, pendingItem, openSavedDialog,
closeSavedDialog. All consumers updated to use the new hooks.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Complete rewrite of CLAUDE.md with full binding rules (vision, architecture layers,
component limits, state management, design system, AI integration, performance,
security). New ARCHITECTURE.md covers folder structure, all data flows with ASCII
diagrams, scoring pipeline, AI flow, unified result feed, and workspace routing.
New CODE_REVIEW_CHECKLIST.md provides a 10-section review guide and pre-commit
quick checklist.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Results.tsx:
- useMemo: filter + sort in one pass (was 7 separate array iterations per render)
- useMemo: platform/maison/future/missingData counts in single for-loop
- Fix: move queryClient.invalidateQueries from render body into useEffect
Properties.tsx:
- useMemo: wrap applyFilters() call (was full copy+sort on every render)
- useMemo: compute matchReady/criticalGaps/lowConfidence/staleOrOutdated/
allMissingFields in a single for-loop (was 5 separate filter passes)
ReminderFeed.tsx:
- useMemo: wrap applyFilters() call
- useCallback: resetFilters (passed to ReminderEmptyState)
PropertyIntelligenceCard, ReminderListRow:
- React.memo: grid/list items no longer re-render when unrelated parent
state changes (e.g. selectedId, filter UI state)
tsc --noEmit passes with zero errors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add matchScoreHex(), criterionScoreColor(), criterionScoreTextColor() to lib/utils.ts
- Add RESULT_TYPE_META (labels + colors) to lib/ds.ts as single source of truth
- Remove 5 local scoreColor() functions: StrongMatchMiniCard, MatchListCard,
pipelineUtils (re-exported as matchScoreHex), CriterionRow, ScoreBreakdownPanel,
ScoreInlineBreakdown
- Remove local RESULT_TYPE_META/TYPE_META from MatchCardHeader, ResultTypeBadge;
remove RESULT_TYPE_LABEL/COLOR from pipelineConstants — all now use lib/ds.ts
- Replace local confidenceColor() in MatchCardHeader, ConfidenceFieldBadge,
ReliabilityScorePanel with confidenceHex() from lib/utils.ts
- Replace local qualityColor() in propertyHelpers, DataQualityWidget with
dataQualityColor() from lib/utils.ts
- Fix FUTURE_AVAILABILITY label inconsistency ('Future'/'Zukunft' → 'Zukunftssignal')
- Fix EXTERNAL_MARKET label inconsistency ('Direktinserat' → 'Plattform')
- tsc --noEmit passes with zero errors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- layoutStore: remove 4 dead field groups (pinnedPanels, selectedResultId,
compareTrayVisible, notificationsOpen) — none were read outside the store
- CompareTray: drop dead useLayoutStore side-effect (state was write-only)
- 8 components: replace bare useStore() with explicit selectors / useShallow
to prevent unnecessary re-renders on unrelated state mutations
- lib/constants: add STALE_MARKET_SIGNALS + STALE_REVIEW_QUEUE (30s each)
- useMarketSignals, useReviewQueue: use global constants instead of
hook-local magic numbers
- Add STATE_MANAGEMENT.md: decision tree + rules for RQ/Zustand/local/derived
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- scoreCalculator: apply dataQuality/confidence modifiers to finalScore (were computed but hardcoded to 0)
- authService: call queryClient.clear() on logout to prevent cross-session data leakage
- queryClient: extract to src/lib/queryClient.ts singleton so services can access it without circular imports
- matchSyncService: new service layer owns match-generation logic; MockupNeedProvider no longer imports other providers directly
- hooks (11 files): add onError + German toast feedback to every useMutation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove CompareTray fixed bottom bar; replace with compare count badge on Vergleich nav item
- Pipeline cards redesigned to match search result card visual style (MatchScoreDisplay, type chip, stage chip, MapPin layout)
- CompareColumnHeader: redesigned with proper Details/Merken action buttons, clickable title
- AddToPipelineDialog now mounted on Compare page (was missing — bookmark had no effect)
- Pipeline card ExternalLink icon navigates to property detail page; detailPath prefers stable propertyId over volatile session matchId
- Add matchId field to PipelineItem domain; pipelineStore stores it on save
- All 8 mock pipeline items now have propertyId for reliable cross-session navigation
- Remove GlobalAIAssistantButton floating overlay (was blocking form submissions and clicks)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Navigation: Deal Pipeline moved after Vergleich (before Anfragen)
Compare → Pipeline:
- Bookmark icon per column header; BookmarkCheck when already in pipeline
- Passes propertyId, propertyAddress, area/rent labels on save
Pipeline cards now unit-level:
- propertyAddress shown with MapPin on every card
- Chat icon (MessageSquare) on cards with linked inquiry → navigates to /demand/anfragen?inquiry=xxx
- Detail panel: Chat chip links to specific inquiry thread, propertyAddress displayed
Anfragen → Pipeline KI detection:
- Keyword scan on every sent message (besichtigung → VISITED, mietvertrag → NEGOTIATION, unterschrieben → CLOSED_WON)
- Only advances stage, never goes back
- Purple KI alert banner with direct Pipeline link, auto-dismisses after 6s
- Pipeline badge in inquiry list + stage chip in chat header with nav link
- URL param ?inquiry=xxx pre-selects inquiry (used from Pipeline chat button)
Domain: PipelineItem gains propertyId, unitId, propertyAddress, inquiryId
Mock data: pl-001/pl-002/pl-004 linked to inq-001/inq-005/inq-004
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cards can be dragged between all 7 stages. Drop target highlights with
a dashed border + tinted background. A floating card overlay follows
the cursor during drag. Click-to-select still works (fires only when
no drag occurred, guarded by activeId check).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- Add 50 mock properties (prop-050–099) tuned for UC-A (Fahrradhändler RETAIL),
UC-B (Umzugsfirma OFFICE Zürich-West) and UC-C (Vermögensverwalter PREMIUM)
- District-aware scoreLocation: district match→100, city-only→70 when need
specifies districts, canton→60, no match→35; fixes UC-C prop-001 over-scoring
- mustHaveScorer: add klimatisierung keyword; parking minimum count logic
- Soft factor scale fix: integer 0–100 values no longer multiplied ×100
- footfall: map passerbyFrequency string (HIGH→85, MEDIUM_HIGH→68…) before
enrichment fallback so RETAIL properties score correctly
- Parser: Kreis list extraction ("Kreis 3, 4, 5, und 8" → 4 district entries),
neighbourhood→district map (Seefeld, Bahnhofstrasse), prestige signals
- Results: remove VERIFIED_PORTFOLIO role gate — all users see portfolio cards,
enabling gold (85+) and silver (70–84) cards for every demo use case
- Fix flash of wrong cards on NeedBuilder nav (effectiveNeedId not activeNeed?.id)
- needs.ts: UC-A preferredLocations now includes Kreis 3/4/5/8 entries
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously factors with weight=0 (e.g. Steuerlast for Innovatech)
were invisible. Now all 9 factors appear in allSoftFactors; only
weighted ones contribute to the score calculation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Hard criteria (Fläche, Standort, Budget, Verfügbarkeit) in dark blue,
soft criteria (Prestige, Erreichbarkeit, …) in purple — separated by
a divider with group labels.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
LOW=0.30 / MEDIUM=0.55 / HIGH=0.85 — previously 3/5/8 which clamped
every soft factor to 100 regardless of level chosen.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without this, navigating to Meine Inserate within 5 min of visiting
it previously would show a stale empty list.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New /supply/new-listing page (Path A: pre-filled from portfolio unit,
Path B: standalone blank form); creates EXTERNAL_MARKET + sourceType DIRECT
- "+ Inserat" button on available units in PropertyDetailView navigates
with prefilled address/area/rent
- Nav entry "Neues Inserat" added to supply sidebar
- SourceProvenancePanel hidden for DIRECT source listings (no external source)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously only 8 of the 13 engine criteria had sliders — flexibility,
visibility, footfall, talentAccess, esg were scored using fixed defaults
with no user control. Now all 13 criteria appear in the WeightingEditor.
- needBuilder.ts: WEIGHTING_KEYS and WEIGHTING_LABELS extended to all 13
- scoreCalculator.ts: CORE array in resolveProfile now includes all 13
- need.ts: WeightingProfile interface explicit for all 13 fields
- needs.ts: all 11 mock need profiles updated with asset-type-appropriate
weights (RETAIL needs high footfall/visibility; LOGISTICS low; OFFICE
high talentAccess; TechStart high taxEnvironment for Zug, etc.)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Only named needs (company name != 'Neue Suche') appear in the chip strip.
Default active need is also the first named need, not the most-recently-created
test search.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Results page: chip strip shows all saved searches — click to switch without
creating a new search. Defaults to first need instead of most-recently-created
so pre-existing mock needs load immediately on navigation.
- AI parser: asset-type-aware monthly budget threshold (RETAIL: 500, others: 150)
so "150 CHF/m²" for retail is correctly converted to 1800 CHF/m²/year instead
of being stored as an impossibly low annual value that excludes all properties.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Single scoring system: MockupNeedProvider rewrites matches via calculateScore
exclusively — allFactors always populated, no more dual-system (computeScore
removed), weights from weightingProfile reflected in every breakdown
- ScoreInlineBreakdown: new component shows hard/soft criteria with importance
labels (Entscheidend/Sehr wichtig/…) and formula on compact + expanded cards
- MatchCardAdapter: passes scoreBreakdown + allFactors to ViewModel
- MatchDetail: 'Zukunftssignal' label replaced with 'Future Availability'
- aiService budget parser: values < 100 treated as monthly and multiplied by 12
to produce correct annual CHF/m²/year value — fixes 0-result searches
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
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>
Every portfolio match card now shows a primary 'Zur Einheit →' button
that navigates to /demand/property/:propertyId?unit=:unitId, where the
user can see the unit table and contact management via the inquiry form.
'Details →' is demoted to secondary for portfolio cards (match analysis
still accessible, but unit/contact page is the primary action).
EXTERNAL_MARKET and MAISON_WORK cards are unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
Two root causes prevented gold and PRE-MARKET VERIFIED cards from showing
in wizard-created searches:
1. computeScore compared annual property rates (e.g. 1080 CHF/m²/year)
against monthly AI-extracted budget (e.g. 150 CHF/m²/month), causing
a constant -8 penalty and capping Bern retail at ~79%. Fix: divide
rentPricePerSqm by 12 before comparing.
2. generateSyntheticMatches set resultType: VERIFIED_PORTFOLIO for
schattenmarktRelease-enabled properties, which Results.tsx filters
out for demand users. Fix: set resultType: FUTURE_AVAILABILITY for
these properties so the schattenmarkt signal is resolved and the
PRE-MARKET VERIFIED card is rendered.
Also adds a score discount (×0.82 for probabilistic FUTURE_AVAILABILITY,
×0.92 for PRE-MARKET) to keep tier distribution realistic.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds VERIFIED_PORTFOLIO retail property (Spitalgasse 18, Bern Innenstadt)
with schattenmarktRelease enabled, completing card-type coverage for
need-011 (Stadtladen Bern GmbH): now has VERIFIED_PORTFOLIO, PRE-MARKET
VERIFIED, EXTERNAL_MARKET, MAISON_WORK, and MARKET SIGNAL cards across
gold/silver/bronze score tiers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Activated schattenmarktRelease on prop-008 through prop-014 with realistic
future lease end dates (2026–2027) and appropriate lead times so all
trigger dates fall before MOCK_TODAY (2026-05-20).
Active PRE-MARKET VERIFIED signals: prop-001, 002, 007, 008, 009, 010, 011, 012, 013, 014
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Deleted prop-005, prop-026, prop-028, prop-030 (resultType FUTURE_AVAILABILITY
but representing demand-side Expansion signals) and the 6 associated matches
(match-007, match-018, match-029, match-047, match-054, match-055).
These fake properties bypassed the signalDirection filter in useUnifiedResults,
causing EXPANSION signals to appear in the demand search feed. Future
Availability in the demand feed now contains only genuine supply-side signals.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MockupFutureSignalProvider kopierte mockFutureSignals einmalig in einen
store-Array beim Modulload. Vite HMR und React Query Cache (staleTime 5min)
führten dazu, dass signalDirection-Feld in gecachten Resultaten fehlte.
Lösung: Provider liest jetzt immer direkt aus dem lebenden mockFutureSignals-
Import via resolve()-Helper. Mutationen (verify, updateStatus) werden in einer
Map gespeichert und beim Lesen überlagert. Damit sind HMR-Änderungen an
Mock-Daten sofort sichtbar ohne Browser-Neustart.
Ausserdem: irreführenden CircularProgress aus Empty-State entfernt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
EXPANSION-Signale (Unternehmen sucht Fläche) sind Nachfragesignale und
gehören nicht in den Demand-Feed. Neue Architektur:
- signalDirection: 'SUPPLY' | 'DEMAND' auf FutureSignal-Domain
- SUPPLY-Signale: POSSIBLE_MOVE_OUT / CONSTRUCTION_PROJECT (Crawler)
und LEASE_EXPIRY+isVerified (Verwaltung ERP) → Demand-Feed wie bisher
- DEMAND-Signale: EXPANSION → aus Demand-Feed gefiltert
- Neues useMarketLeads-Hook + /supply/market-leads Seite für Verwaltung:
zeigt EXPANSION-Signale als potenzielle Mieter mit Portfolio-Matching
- Alle 15 Signale in futureSignals.ts inhaltlich bereinigt und
mit korrekter signalDirection versehen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
- 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>
- 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>
- PropertyUnit: add isFlexible, minLettableSqm, offeredSqm fields
- New UnitBundle + UnitNeedMatch domain types
- unitMatchService: match individual units or bundles against LatentNeeds
(exact, partial/Teilfläche, bundle match types with area scoring)
- Mock units updated: prop-001/007/012/013 free units flagged as flexible
with minimum lettable areas
- UnitStructurePanel replaces old Stockwerkstruktur table:
- Checkboxes on free units (when ≥2 exist) for bundle selection
- Inline match pills per free unit (top need + score)
- Expand row to see all matching needs with area details
- 'Teilfläche möglich' chip for flexible units with min sqm
- Bundle panel appears when 2+ units selected: shows combined sqm,
bundle matches, and note about remaining area after contract
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dialog now opens at md size (88vh), shows a progress bar while
generating, then reveals the full report document: header, all 4
signal sections with colour-coded separators, confidence scores,
sources, dates. Document is blurred during generation and sharpens
when ready. Herunterladen button stays disabled until preview is ready.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- BerichtDialog: conditionally mount instead of always-mounted with
open prop; starts in 'generating' state immediately on open
- Images: fix all 6 wrong VERIFIED_PORTFOLIO and EXTERNAL_MARKET photos
to match spec per assetType (OFFICE/RETAIL/LOGISTICS/PRODUCTION/MIXED)
- Domain: add PropertyUnit interface + propertyNumber field to Property
- Mock data: propertyNumber + units[] for prop-001/007/012/013
- UI: Stockwerkstruktur section in Übersicht tab (floor/unit table with
availability, tenant, area); Objekt-Nr. shown below key metrics
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Clicking a need card in the Matchability tab pre-selects the property
and navigates to Anfragencenter → Latente Anfragen tab. Angebot creation
lives here (demand-side), not in Marktsignale. NeedMatchCard gains
onClick prop with navy hover + shadow treatment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
'Angebot erstellen' button in Marktsignale tab pre-selects the property
in the offer store and navigates to /supply/anfragen on the Latente
Anfragen tab. Also fixes offerWizardStore.open() to preserve
selectedPropertyIds so pre-selection survives the wizard open call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BerichtDialog now animates a progress bar (idle → generating → ready),
then triggers a blob download of Marktsignal-Bericht_{id}.pdf on confirm.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Offer wizard: 4→3 steps by merging 'Prüfen' into PDF review step
- Search mask: quick-select chips for area ranges, budget, and city presets
- Onboarding: WelcomeDialog (3 slides, localStorage) on first visit
- Deal Pipeline: Kanban board (6 stages, 8 mock items, advance-to-next-stage)
added to demand workspace navigation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
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>
- AppShell: permanent sidebar on desktop, temporary drawer + hamburger on mobile (<md)
- TopBar: hamburger icon on mobile, AI-Assistent als Icon-Button auf kleinen Screens
- MatchDetail: Sidebar stacks below content on mobile, key facts wrap, px responsive
- Properties: Drawer fullscreen (100vw) on mobile, 650px on desktop
- ActiveInquiriesTab: mobile shows list → tap opens detail with back button
- LatentInquiriesTab: mobile sequential navigation (list → detail → own properties), tablet 2-col, desktop 3-col
- PublicNeedList: fullWidth prop for mobile layout
- InquiryDetailPanel: property card stacks below chat on mobile
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a new "Aktivitätslog" tab (9th tab) to the supply-side property
drawer. Shows match approvals/rejections, need registrations, data
quality flags, and governance actions linked to this specific property.
Only visible to Verwaltung users in their own property view.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
Integrates react-leaflet with OpenStreetMap tiles. PropertyDetailView
and MatchDetail now show property photo + zoomable/pannable map above
the tabs/content — always visible on card click, no redirect. Map
renders at correct lat/lng with a location marker and popup.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
- Replace ActivityTimeline stub with full vertical timeline page:
grouped by day, filterable by workflow category (Suche/Matching/
Intelligence/Review/Governance), KPI strip, AI vs human distinction
- Expand governanceService mock data from 3 → 24 events covering the
full demo storyline (source crawl → signal detection → need creation →
AI parse → match generation → review → shortlist → decision brief)
- Add 11 new ActivityEventTypes: AI_PARSE_COMPLETED, MATCH_GENERATED,
FUTURE_SIGNAL_DETECTED/CONVERTED, SHORTLIST_CREATED/FINALIZED,
DECISION_BRIEF_CREATED, SOURCE_CRAWLED, DATA_QUALITY_FLAGGED,
REVIEW_COMPLETED, AI_OUTPUT_REVIEWED
- Update Governance.tsx switch statements to handle all new types
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add ToastProvider (global MUI Snackbar stack) + toastStore (Zustand)
- Add ConfirmDialog reusable component for destructive actions
- Wire toast feedback to all async mutations: review status, AI output status,
match approval, shortlist add/remove/title/finalize, signal review actions
- Fix dead UserMenu buttons (Profil, Einstellungen) — show info toast
- Migrate local Snackbar instances in AddToShortlistDialog and
FutureSignalDetailPanel to global toast store
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wires the existing "AI Assistent" button in the TopBar and adds a 420px
slide-in drawer with context-aware suggestions, message thread, loading
animation, and action cards requiring manual confirmation. Template-based
mock service returns German-language answers keyed by route + question
keywords — no real LLM calls, no invented facts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full 2-panel workspace at /ops/ai-monitoring: metrics strip (total, failed,
pending, approval rate, top prompt version, active model), filterable output
table by type/status/error, and detail panel with output preview, prompt
versioning, error details, and role-aware review actions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the old ad-hoc ReviewQueue page with a full governance-compliant
workflow: filterable task list, detail panel with confidence/risk context,
role-aware approve/reject/escalate/more-data actions, and persistent notes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>