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>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import type { IReviewProvider, ReviewFilters } from './IReviewProvider'
|
||||
import type { ReviewQueueItem } from '../domain/review'
|
||||
import { mockReviewQueue } from '../mock-data/reviewQueue'
|
||||
import { mockDelay } from '../lib/mockUtils'
|
||||
|
||||
const store: ReviewQueueItem[] = [...mockReviewQueue]
|
||||
|
||||
const priorityOrder: Record<string, number> = { HIGH: 0, MEDIUM: 1, LOW: 2 }
|
||||
|
||||
export const MockupReviewProvider: IReviewProvider = {
|
||||
async getQueue(filters?: ReviewFilters) {
|
||||
await mockDelay()
|
||||
let results = [...store]
|
||||
if (filters?.priority) results = results.filter(r => r.priority === filters.priority)
|
||||
if (filters?.status) results = results.filter(r => r.status === filters.status)
|
||||
if (filters?.assignedTo) results = results.filter(r => r.assignedTo === filters.assignedTo)
|
||||
if (filters?.organizationId) results = results.filter(r => r.organizationId === filters.organizationId)
|
||||
return results.sort((a, b) => (priorityOrder[a.priority] ?? 9) - (priorityOrder[b.priority] ?? 9))
|
||||
},
|
||||
async getById(id) {
|
||||
await mockDelay()
|
||||
return store.find(r => r.id === id) ?? null
|
||||
},
|
||||
async approve(id, _reviewedBy, notes?) {
|
||||
await mockDelay()
|
||||
const idx = store.findIndex(r => r.id === id)
|
||||
store[idx] = { ...store[idx], status: 'COMPLETED', notes, updatedAt: new Date().toISOString() }
|
||||
return store[idx]
|
||||
},
|
||||
async reject(id, _reviewedBy, notes?) {
|
||||
await mockDelay()
|
||||
const idx = store.findIndex(r => r.id === id)
|
||||
store[idx] = { ...store[idx], status: 'COMPLETED', notes, updatedAt: new Date().toISOString() }
|
||||
return store[idx]
|
||||
},
|
||||
async assign(id, assignTo) {
|
||||
await mockDelay()
|
||||
const idx = store.findIndex(r => r.id === id)
|
||||
store[idx] = { ...store[idx], assignedTo: assignTo, status: 'IN_REVIEW', updatedAt: new Date().toISOString() }
|
||||
return store[idx]
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user