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:
@@ -0,0 +1,11 @@
|
||||
import type { Reminder } from '../domain/reminder'
|
||||
|
||||
export interface IReminderProvider {
|
||||
getAll(): Promise<Reminder[]>
|
||||
getById(id: string): Promise<Reminder | null>
|
||||
update(id: string, data: Partial<Reminder>): Promise<Reminder>
|
||||
complete(id: string, note?: string): Promise<Reminder>
|
||||
dismiss(id: string, note?: string): Promise<Reminder>
|
||||
snooze(id: string, until: string): Promise<Reminder>
|
||||
create(data: Omit<Reminder, 'id' | 'activity' | 'createdAt' | 'updatedAt'>): Promise<Reminder>
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { mockReminders } from '../mock-data/reminders'
|
||||
import type { Reminder, ReminderActivity } from '../domain/reminder'
|
||||
import { ReminderStatus } from '../domain/reminder'
|
||||
import type { IReminderProvider } from './IReminderProvider'
|
||||
|
||||
let store: Reminder[] = [...mockReminders]
|
||||
|
||||
function now(): string {
|
||||
return new Date().toISOString()
|
||||
}
|
||||
|
||||
function addActivity(reminder: Reminder, entry: ReminderActivity): Reminder {
|
||||
return { ...reminder, activity: [...reminder.activity, entry], updatedAt: now() }
|
||||
}
|
||||
|
||||
export const MockupReminderProvider: IReminderProvider = {
|
||||
async getAll() {
|
||||
return [...store]
|
||||
},
|
||||
|
||||
async getById(id) {
|
||||
return store.find(r => r.id === id) ?? null
|
||||
},
|
||||
|
||||
async update(id, data) {
|
||||
const idx = store.findIndex(r => r.id === id)
|
||||
if (idx === -1) throw new Error(`Reminder ${id} not found`)
|
||||
store[idx] = { ...store[idx], ...data, updatedAt: now() }
|
||||
return store[idx]
|
||||
},
|
||||
|
||||
async complete(id, note) {
|
||||
const idx = store.findIndex(r => r.id === id)
|
||||
if (idx === -1) throw new Error(`Reminder ${id} not found`)
|
||||
store[idx] = addActivity(
|
||||
{ ...store[idx], status: ReminderStatus.COMPLETED },
|
||||
{ at: now(), by: 'current-user', action: 'COMPLETED', note },
|
||||
)
|
||||
return store[idx]
|
||||
},
|
||||
|
||||
async dismiss(id, note) {
|
||||
const idx = store.findIndex(r => r.id === id)
|
||||
if (idx === -1) throw new Error(`Reminder ${id} not found`)
|
||||
store[idx] = addActivity(
|
||||
{ ...store[idx], status: ReminderStatus.DISMISSED },
|
||||
{ at: now(), by: 'current-user', action: 'DISMISSED', note },
|
||||
)
|
||||
return store[idx]
|
||||
},
|
||||
|
||||
async snooze(id, until) {
|
||||
const idx = store.findIndex(r => r.id === id)
|
||||
if (idx === -1) throw new Error(`Reminder ${id} not found`)
|
||||
store[idx] = addActivity(
|
||||
{ ...store[idx], status: ReminderStatus.SNOOZED, snoozedUntil: until },
|
||||
{ at: now(), by: 'current-user', action: 'SNOOZED', note: `Snoozed until ${until}` },
|
||||
)
|
||||
return store[idx]
|
||||
},
|
||||
|
||||
async create(data) {
|
||||
const reminder: Reminder = {
|
||||
...data,
|
||||
id: crypto.randomUUID(),
|
||||
activity: [{ at: now(), by: 'current-user', action: 'CREATED' }],
|
||||
createdAt: now(),
|
||||
updatedAt: now(),
|
||||
}
|
||||
store.push(reminder)
|
||||
return reminder
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user