Files
property-match/src/provider/MockupReviewProvider.ts
T
Benjamin Sutter 5d3323617c feat: F018 human review queue — 2-panel governance workspace
Replaces the old ad-hoc ReviewQueue page with a full governance-compliant
workflow: filterable task list, detail panel with confidence/risk context,
role-aware approve/reject/escalate/more-data actions, and persistent notes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:03:34 +02:00

77 lines
2.6 KiB
TypeScript

import type { IReviewProvider, ReviewFilters } from './IReviewProvider'
import type { ReviewTask, ReviewNote } from '../domain/review'
import { mockReviewQueue } from '../mock-data/reviewQueue'
import { mockDelay } from '../lib/mockUtils'
const store: ReviewTask[] = [...mockReviewQueue]
const priorityOrder: Record<string, number> = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3 }
function makeNote(content: string, createdBy: string): ReviewNote {
return {
id: `note-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
content,
createdBy,
createdAt: new Date().toISOString(),
}
}
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?.entityType) results = results.filter(r => r.entityType === filters.entityType)
if (filters?.assignedTo) results = results.filter(r => r.assignedTo === filters.assignedTo)
if (filters?.organizationId) results = results.filter(r => r.relatedOrganizationId === 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 updateStatus(id, status, userId, note?) {
await mockDelay()
const idx = store.findIndex(r => r.id === id)
const notes = [...store[idx].reviewNotes]
if (note) notes.push(makeNote(note, userId))
store[idx] = { ...store[idx], status, reviewNotes: notes, updatedAt: new Date().toISOString() }
return store[idx]
},
async addNote(id, note) {
await mockDelay()
const idx = store.findIndex(r => r.id === id)
const newNote: ReviewNote = { id: `note-${Date.now()}`, ...note }
store[idx] = {
...store[idx],
reviewNotes: [...store[idx].reviewNotes, newNote],
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: store[idx].status === 'PENDING' ? 'IN_REVIEW' : store[idx].status,
updatedAt: new Date().toISOString(),
}
return store[idx]
},
async approve(id, reviewedBy, notes?) {
return this.updateStatus(id, 'APPROVED', reviewedBy, notes)
},
async reject(id, reviewedBy, notes?) {
return this.updateStatus(id, 'REJECTED', reviewedBy, notes)
},
}