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>
This commit is contained in:
@@ -161,6 +161,7 @@ export const SignalType = {
|
||||
RESTRUCTURING: 'RESTRUCTURING',
|
||||
PROJECT_DEVELOPMENT: 'PROJECT_DEVELOPMENT',
|
||||
SPACE_CONSOLIDATION: 'SPACE_CONSOLIDATION',
|
||||
LEASE_EXPIRY: 'LEASE_EXPIRY',
|
||||
} as const
|
||||
export type SignalType = typeof SignalType[keyof typeof SignalType]
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { SignalType, RiskLevel, ReviewStatus } from './enums'
|
||||
|
||||
export interface SignalSource {
|
||||
type: 'PRESS' | 'CONSTRUCTION_PERMIT' | 'JOB_POSTING' | 'COMPANY_REPORT' | 'MARKET_DATA' | 'MANUAL'
|
||||
type: 'PRESS' | 'CONSTRUCTION_PERMIT' | 'JOB_POSTING' | 'COMPANY_REPORT' | 'MARKET_DATA' | 'MANUAL' | 'LEASE_CONTRACT'
|
||||
url?: string
|
||||
publishedAt?: string
|
||||
credibility: 'LOW' | 'MEDIUM' | 'HIGH'
|
||||
|
||||
@@ -180,6 +180,8 @@ export interface Property {
|
||||
importedAt?: string
|
||||
lastUpdatedAt?: string
|
||||
|
||||
schattenmarktRelease?: { enabled: boolean; leadTimeMonths: number }
|
||||
|
||||
status?: 'ACTIVE' | 'INACTIVE' | 'DRAFT' | 'ARCHIVED'
|
||||
lastReviewedAt?: string
|
||||
createdAt: string
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
export const ReminderType = {
|
||||
LEASE_EXPIRY: 'LEASE_EXPIRY',
|
||||
BREAK_OPTION: 'BREAK_OPTION',
|
||||
RENT_REVIEW: 'RENT_REVIEW',
|
||||
INSPECTION: 'INSPECTION',
|
||||
INSURANCE_RENEWAL: 'INSURANCE_RENEWAL',
|
||||
MAINTENANCE: 'MAINTENANCE',
|
||||
SCHATTENMARKT_RELEASE: 'SCHATTENMARKT_RELEASE',
|
||||
CUSTOM: 'CUSTOM',
|
||||
} as const
|
||||
export type ReminderType = typeof ReminderType[keyof typeof ReminderType]
|
||||
|
||||
export const ReminderPriority = {
|
||||
URGENT: 'URGENT', // ≤14 days
|
||||
HIGH: 'HIGH', // 15–30 days
|
||||
MEDIUM: 'MEDIUM', // 31–60 days
|
||||
LOW: 'LOW', // >60 days
|
||||
} as const
|
||||
export type ReminderPriority = typeof ReminderPriority[keyof typeof ReminderPriority]
|
||||
|
||||
export const ReminderStatus = {
|
||||
ACTIVE: 'ACTIVE',
|
||||
SNOOZED: 'SNOOZED',
|
||||
COMPLETED: 'COMPLETED',
|
||||
DISMISSED: 'DISMISSED',
|
||||
} as const
|
||||
export type ReminderStatus = typeof ReminderStatus[keyof typeof ReminderStatus]
|
||||
|
||||
export const ShadowMarketRisk = {
|
||||
NONE: 'NONE',
|
||||
LOW: 'LOW',
|
||||
MEDIUM: 'MEDIUM',
|
||||
HIGH: 'HIGH',
|
||||
} as const
|
||||
export type ShadowMarketRisk = typeof ShadowMarketRisk[keyof typeof ShadowMarketRisk]
|
||||
|
||||
export interface ReminderActivity {
|
||||
at: string // ISO date
|
||||
by: string // user display name
|
||||
action: 'CREATED' | 'SNOOZED' | 'COMPLETED' | 'DISMISSED' | 'NOTED'
|
||||
note?: string
|
||||
}
|
||||
|
||||
export interface Reminder {
|
||||
id: string
|
||||
type: ReminderType
|
||||
priority: ReminderPriority
|
||||
status: ReminderStatus
|
||||
|
||||
propertyId: string
|
||||
propertyTitle: string
|
||||
propertyCity: string
|
||||
propertyDistrict?: string
|
||||
tenantName: string
|
||||
|
||||
dueDate: string // ISO date — when action must be taken
|
||||
eventDate: string // ISO date — contract event date (expiry / review / etc.)
|
||||
contractEndDate?: string // ISO date — lease end
|
||||
breakOptionDate?: string // ISO date
|
||||
|
||||
areaSqm: number
|
||||
currentRentPerSqm: number
|
||||
currency: 'CHF'
|
||||
|
||||
shadowMarketRisk: ShadowMarketRisk
|
||||
schattenmarktEnabled: boolean
|
||||
|
||||
note?: string
|
||||
snoozedUntil?: string // ISO date
|
||||
|
||||
activity: ReminderActivity[]
|
||||
|
||||
organizationId: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
Reference in New Issue
Block a user