Commit Graph

9 Commits

Author SHA1 Message Date
Benjamin Sutter 7a0909e36a feat: saved profiles — per-profile notifications, real match scores, action buttons
- Add per-profile notification config (toggle, score threshold, email) with Accordion UI in SavedNeedDetail
- NotificationButton: badge only lights up for unseen matches, dismisses on open (localStorage), uses per-profile minScore
- SavedNeedDetail: replace deterministicMatchScore with real match data (useMatchesByNeed), sort by score desc, deduplicate by property
- SavedProfilesTab & SavedNeedCard: top score bar now shows best real match score instead of criteria confidence
- "Treffer" count uses per-profile notificationConfig.minScore (≥80 default) consistently across card, panel, and notification badge
- Extract PropertyMatchRow to own file with Anfrage/Merken/Vergleichen/Details→/Zur Einheit→ action buttons
- Details → navigates to /demand/results/:matchId using real match ID format (m__propId__prop__needId)
- Add InquiryQuickDialog + AddToPipelineDialog to AISearch.tsx so dialogs work from SavedProfilesTab
- Org-isolation: useNeeds filters by organizationId, org-mobimo gets 4 own search profiles
- Mock data: all 18 org-wincasa need names changed to descriptive profile names; 4 new org-mobimo needs added
- useUpdateNeed mutation hook for updating need fields (notificationConfig etc.)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 20:53:49 +02:00
Benjamin Sutter b2530f9e20 feat: Reale Jahresbelastung, must-have fixes, fitOut data coverage
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>
2026-06-06 20:09:55 +02:00
Benjamin Sutter cd220ed282 feat: Suchabo inline contact flow — chip opens need detail + OfferWizard
- Add >80% STRONG matches for all 6 direct listings (match-072–075)
- Add 4 new Needs (need-012–015) tailored to each previously unmatched listing
- Add 8 new LatentNeeds (lneed-007–014) for all needs in direct listing matches
- Add need→latentNeed mapping (src/lib/needToLatentNeedMap.ts)
- MyListings: clicking Suchabo chip opens dialog with company name, score,
  PublicNeedDetail view and OfferWizard — no navigation to Anfragencenter needed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 23:08:41 +02:00
Benjamin Sutter 9f7062d137 feat: UC-A/B/C demo — 50 mock properties, district scoring, gold/silver cards visible
- 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>
2026-05-22 20:31:30 +02:00
Benjamin Sutter ba910806d6 feat: expose all 13 scoring criteria as weighting sliders
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>
2026-05-21 20:58:01 +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 920ce8eb09 feat: Verwaltungszugang refactor — lease data, 3-tab detail, market signals
- Dashboard: remove QuickActionPanel, StrongMatchOverview, FutureSignalWidget,
  DataQualityWidget, header buttons, Marktchancen nav; KpiGrid → 4 cards
- Property domain: 9 new fields (leaseTerm, leaseStartDate/End, breakoutOption,
  currentTenant, importedFrom, importedAt, lastUpdatedAt)
- Mock data: annual CHF/m²/Jahr prices (×12), Swiss images, tenant/lease data
  for all 10 VERIFIED_PORTFOLIO properties; need budgets updated to annual
- PropertyTable: swap columns — add Aktueller Mieter, Mietlaufzeit,
  Breakoutoption, Breakoutoption Zeitpunkt; remove Verfügbarkeit, Konfidenz, Quelle
- PropertyDetailView: 3 tabs (Übersicht, Matchability, Marktsignale) with
  inline edit mode, NeedMatchCard list, PropertyMarketSignalsTab
- New: marketReport domain + mock data + service, NeedMatchCard,
  PropertyMarketSignalsTab with 4 sections + PDF button
- matchService: getNeedMatchesForProperty(propertyId, {minScore})

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 15:43:52 +02:00
Benjamin Sutter efc406ace9 feat: role-aware UX, market intelligence, score fix & layout scroll
- Role-based workspace access: Property Manager gets Supply+Demand,
  Operations restricted to Super Admin + Reviewer only
- Root redirect routes each persona to their first workspace
- Match Center: replaced 3-panel with auto-sorted flat list + drawer
- AI Search: unified form with dual-action (Jetzt suchen / Als Suchprofil speichern)
- CompareTray hidden on non-Demand routes; Vergleichen removed from Supply
- LocationIntelligencePanel: city KPIs, rent trends, soft factors, comparables
- NegotiationInsightsPanel: price positioning, active demand, selling arguments
- scoreCalculator: cap hardMatchScore and softFactorScore to max 100
- Layout: add display:flex to overflow:hidden wrappers so inner scroll works
  (MatchCenter drawer, MarketIntelligence, SourceMonitoring, SignalPipeline)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 00:58:10 +02:00
Benjamin Sutter 9e827c50f9 Initial commit 2026-05-15 00:48:18 +02:00