File size: 6,785 Bytes
d8635c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
import { writable } from 'svelte/store'
import { backendService, type StoredDocument } from '../utils/backendService'

// Interface for reference documents stored in backend
export interface ReferenceDocument extends StoredDocument {
  // Inherits: id, name, category, fileType, uploadDate, size
}

// Interface for current RFP (metadata only, not stored in backend)
export interface CurrentRFPDocument {
  id: string
  name: string
  size: number
  uploadDate: string
  pageCount?: number
  quality?: string
  keyTopics?: string[]
  wordCount?: number
  fileType?: string
  // RFP specific metadata
  rfpName?: string
  bidNumber?: string
  // Note: No content field - this is metadata only
}

export interface Question {
  id: string
  text: string
  selected: boolean
  priority: 'high' | 'medium' | 'low'
  source?: string
}

export interface RFPAnswer {
  id: string
  question: string
  previousAnswer?: string
  aiGeneratedAnswer?: string
  finalAnswer?: string
  source?: string
  pageNumber?: number
  isFinalized: boolean
  isFormatted?: boolean
  hasAdditionalInfo?: boolean
  additionalInfo?: string
  citations: string[]
}

export interface RFPData {
  currentRFP: CurrentRFPDocument | null  // Changed from previousRFPs array
  newQuestions: File | null
  questions: string[]
  answers: RFPAnswer[]
  extractedData: any[]
}

export interface AppState {
  currentStep: number
  isLoading: boolean
  error: string | null
}

// App state stores
// LocalStorage keys
const STORAGE_KEYS = {
  CURRENT_STEP: 'rfp_current_step',
  CURRENT_RFP: 'rfp_current_rfp',  // Changed from PREVIOUS_RFPS
  QUESTIONS: 'rfp_questions',
  ANSWERS: 'rfp_answers',
  RFP_DATA: 'rfp_data'
}

// Load data from localStorage
function loadFromStorage<T>(key: string, defaultValue: T): T {
  if (typeof window === 'undefined') return defaultValue
  try {
    const stored = localStorage.getItem(key)
    return stored ? JSON.parse(stored) : defaultValue
  } catch (error) {
    console.warn(`Failed to load ${key} from localStorage:`, error)
    return defaultValue
  }
}

// Save data to localStorage
function saveToStorage<T>(key: string, value: T): void {
  if (typeof window === 'undefined') return
  try {
    localStorage.setItem(key, JSON.stringify(value))
  } catch (error) {
    console.warn(`Failed to save ${key} to localStorage:`, error)
  }
}

export const currentStep = writable<number>(loadFromStorage(STORAGE_KEYS.CURRENT_STEP, 1))
export const isLoading = writable<boolean>(false)
export const error = writable<string | null>(null)

// Store for reference documents (managed by backend)
export const referenceDocuments = writable<ReferenceDocument[]>([])

// Store for current RFP (metadata only, localStorage)
export const currentRfp = writable<CurrentRFPDocument | null>(loadFromStorage(STORAGE_KEYS.CURRENT_RFP, null))

// Other stores with localStorage persistence
export const questions = writable<Question[]>(loadFromStorage(STORAGE_KEYS.QUESTIONS, []))
export const answers = writable<RFPAnswer[]>(loadFromStorage(STORAGE_KEYS.ANSWERS, []))

// Legacy RFP data store (updated structure)
export const rfpData = writable<RFPData>(loadFromStorage(STORAGE_KEYS.RFP_DATA, {
  currentRFP: null,
  newQuestions: null,
  questions: [],
  answers: [],
  extractedData: []
}))

// Subscribe to store changes and save to localStorage
currentStep.subscribe(value => saveToStorage(STORAGE_KEYS.CURRENT_STEP, value))
currentRfp.subscribe(value => saveToStorage(STORAGE_KEYS.CURRENT_RFP, value))
questions.subscribe(value => saveToStorage(STORAGE_KEYS.QUESTIONS, value))
answers.subscribe(value => saveToStorage(STORAGE_KEYS.ANSWERS, value))
rfpData.subscribe(value => saveToStorage(STORAGE_KEYS.RFP_DATA, value))

// Helper functions
export function nextStep() {
  currentStep.update(step => Math.min(step + 1, 5))
}

export function prevStep() {
  currentStep.update(step => Math.max(step - 1, 1))
}

export function resetApp() {
  currentStep.set(1)
  isLoading.set(false)
  error.set(null)
  referenceDocuments.set([])
  currentRfp.set(null)
  questions.set([])
  answers.set([])
  rfpData.set({
    currentRFP: null,
    newQuestions: null,
    questions: [],
    answers: [],
    extractedData: []
  })
  
  // Clear localStorage
  if (typeof window !== 'undefined') {
    Object.values(STORAGE_KEYS).forEach(key => {
      localStorage.removeItem(key)
    })
  }
}

// Function to clear current RFP (keeping reference documents in backend)
export function clearCurrentRfp() {
  currentRfp.set(null)
  if (typeof window !== 'undefined') {
    localStorage.removeItem(STORAGE_KEYS.CURRENT_RFP)
  }
}

// Backend service functions
export async function loadReferenceDocuments() {
  try {
    isLoading.set(true)
    error.set(null)
    
    // Check backend health first
    const isHealthy = await backendService.healthCheck()
    if (!isHealthy) {
      throw new Error('Backend server is not responding')
    }
    
    const documents = await backendService.getPreviousRFPs()
    referenceDocuments.set(documents)
    
    console.log(`✅ Loaded ${documents.length} reference documents from backend`)
  } catch (err) {
    const errorMessage = err instanceof Error ? err.message : 'Failed to load reference documents'
    error.set(errorMessage)
    console.warn('❌ Failed to load reference documents:', errorMessage)
    
    // Set empty array if backend fails
    referenceDocuments.set([])
  } finally {
    isLoading.set(false)
  }
}

export async function uploadReferenceDocument(file: File, category: string) {
  try {
    isLoading.set(true)
    const document = await backendService.uploadPreviousRFP(file, category)
    
    // Add to current list
    referenceDocuments.update(docs => [...docs, document])
    
    return document
  } catch (err) {
    error.set(err instanceof Error ? err.message : 'Failed to upload document')
    throw err
  } finally {
    isLoading.set(false)
  }
}

export async function deleteReferenceDocument(id: string) {
  try {
    isLoading.set(true)
    await backendService.deleteDocument(id)
    
    // Remove from current list
    referenceDocuments.update(docs => docs.filter(doc => doc.id !== id))
  } catch (err) {
    error.set(err instanceof Error ? err.message : 'Failed to delete document')
    throw err
  } finally {
    isLoading.set(false)
  }
}

export async function getDocumentContent(id: string) {
  try {
    return await backendService.getDocumentContent(id)
  } catch (err) {
    error.set(err instanceof Error ? err.message : 'Failed to get document content')
    throw err
  }
}