Files
property-match/src/provider/MockupDashboardProvider.ts
T
Benjamin Sutter 5ef8b9d69d feat(services): F005 – complete service layer
New domain types:
- shortlist.ts: Shortlist, ShortlistItem, CreateShortlistInput
- review.ts: ReviewQueueItem, ReviewPriority, ReviewQueueStatus

New mock data:
- shortlists.ts: 2 sample shortlists
- reviewQueue.ts: 3 pending review items

New providers (interface + mockup):
- IShortlistProvider / MockupShortlistProvider (with 150ms latency)
- IReviewProvider / MockupReviewProvider (priority-sorted, with latency)
- IDashboardProvider / MockupDashboardProvider (computed from all mock data)

New services:
- reviewService: getQueue, approve, reject, assign
- shortlistService: CRUD + addItem/removeItem
- authService: wraps sessionStore, swappable for real auth
- dashboardService: getStats(organizationId?)

Enhancements:
- types.ts: typed ServiceErrorCode + ServiceError, Pagination alias
- aiService.ts: openRouterAIService stub (throws ai_generation_failed)
- lib/mockUtils.ts: mockDelay(ms) utility

New hooks:
- useUnifiedResults(needId?): joins matches+properties+signals → UnifiedMatchResult[]
- useReviewQueue: + useApproveReviewItem + useRejectReviewItem
- useMatchDetail, usePropertyDetail, useNeedProfiles aliases

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 11:12:06 +02:00

49 lines
2.0 KiB
TypeScript

import type { IDashboardProvider, DashboardStats } from './IDashboardProvider'
import { mockProperties } from '../mock-data/properties'
import { mockMatches } from '../mock-data/matches'
import { mockNeeds } from '../mock-data/needs'
import { mockFutureSignals } from '../mock-data/futureSignals'
import { mockReviewQueue } from '../mock-data/reviewQueue'
import { mockDelay } from '../lib/mockUtils'
export const MockupDashboardProvider: IDashboardProvider = {
async getStats(organizationId?) {
await mockDelay()
let props = mockProperties
let matches = mockMatches
let needs = mockNeeds
let signals = mockFutureSignals
let queue = mockReviewQueue
if (organizationId) {
props = props.filter(p => p.organizationId === organizationId)
matches = matches.filter(m => m.organizationId === organizationId)
needs = needs.filter(n => n.organizationId === organizationId)
signals = signals.filter(s => s.organizationId === organizationId)
queue = queue.filter(r => r.organizationId === organizationId)
}
const avgScore =
matches.length > 0
? matches.reduce((sum, m) => sum + m.matchScore, 0) / matches.length
: 0
const stats: DashboardStats = {
totalProperties: props.length,
verifiedProperties: props.filter(p => p.resultType === 'VERIFIED_PORTFOLIO').length,
externalMarketProperties: props.filter(p => p.resultType === 'EXTERNAL_MARKET').length,
futureSignalProperties: props.filter(p => p.resultType === 'FUTURE_AVAILABILITY').length,
totalMatches: matches.length,
pendingReviews: queue.filter(r => r.status === 'PENDING').length,
approvedMatches: matches.filter(m => m.isApproved === true).length,
activeNeeds: needs.length,
totalSignals: signals.length,
verifiedSignals: signals.filter(s => s.isVerified).length,
averageMatchScore: Math.round(avgScore),
highConfidenceMatches: matches.filter(m => m.confidenceLevel >= 0.75).length,
}
return stats
},
}