File size: 2,734 Bytes
be54038
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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<void>
  setActiveField: (entry: FieldEntry | null) => void
  verifyField: (sessionId: string, fieldPath: string) => Promise<void>
  overrideField: (sessionId: string, fieldPath: string, newValue: string) => Promise<void>
  rejectField: (sessionId: string, fieldPath: string) => Promise<void>
  setActivePdf: (filename: string) => void
}

export const useStore = create<AppState>((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<AppState>) => void,
) {
  await api.updateReview(sessionId, fieldPath, action, overriddenValue)
  const fresh = await api.getReviewState(sessionId)
  set({ reviewState: fresh })
}