import { create } from 'zustand' import { api } from './api' import type { FieldEntry, FieldProvenance, ReviewAction, ReviewState, SessionData } from './types' interface AppState { // Session data sessionData: SessionData | null reviewState: ReviewState // UI state activePdfFile: string | null // filename of the PDF currently displayed activeFieldPath: string | null // field path the user clicked activeProvenance: FieldProvenance | null // Actions setSession: (data: SessionData) => void loadReviewState: (sessionId: string) => Promise setActiveField: (entry: FieldEntry | null) => void verifyField: (sessionId: string, fieldPath: string) => Promise overrideField: (sessionId: string, fieldPath: string, newValue: string) => Promise rejectField: (sessionId: string, fieldPath: string) => Promise setActivePdf: (filename: string) => void } export const useStore = create((set, get) => ({ sessionData: null, reviewState: {}, activePdfFile: null, activeFieldPath: null, activeProvenance: null, setSession(data) { // Set default active PDF to the first source file found in provenance const firstPdf = data.provenance[0]?.source_filename ?? null set({ sessionData: data, activePdfFile: firstPdf }) }, async loadReviewState(sessionId) { const state = await api.getReviewState(sessionId) set({ reviewState: state }) }, setActiveField(entry) { if (!entry) { set({ activeFieldPath: null, activeProvenance: null }) return } const { sessionData } = get() const provenance = sessionData?.provenance.find( (p) => p.field_path === entry.fieldPath, ) ?? null set({ activeFieldPath: entry.fieldPath, activeProvenance: provenance, // Switch PDF pane to the file that contains this field activePdfFile: provenance?.source_filename ?? get().activePdfFile, }) }, async verifyField(sessionId, fieldPath) { await _applyReview(sessionId, fieldPath, 'verify', undefined, set) }, async overrideField(sessionId, fieldPath, newValue) { await _applyReview(sessionId, fieldPath, 'override', newValue, set) }, async rejectField(sessionId, fieldPath) { await _applyReview(sessionId, fieldPath, 'reject', undefined, set) }, setActivePdf(filename) { set({ activePdfFile: filename }) }, })) async function _applyReview( sessionId: string, fieldPath: string, action: ReviewAction, overriddenValue: string | undefined, set: (partial: Partial) => void, ) { await api.updateReview(sessionId, fieldPath, action, overriddenValue) const fresh = await api.getReviewState(sessionId) set({ reviewState: fresh }) }