chore: initial commit — existing single-user document scanner codebase
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* API client using native Fetch API.
|
||||
* All requests go to /api (proxied to backend by Vite in dev, or nginx in prod).
|
||||
*/
|
||||
|
||||
async function request(path, options = {}) {
|
||||
const res = await fetch(path, options)
|
||||
if (!res.ok) {
|
||||
let msg = `HTTP ${res.status}`
|
||||
try { msg = (await res.json()).detail || msg } catch {}
|
||||
throw new Error(msg)
|
||||
}
|
||||
return res.json()
|
||||
}
|
||||
|
||||
// ── Documents ────────────────────────────────────────────────────────────────
|
||||
|
||||
export function uploadDocument(file, autoClassify = true) {
|
||||
const form = new FormData()
|
||||
form.append('file', file)
|
||||
form.append('auto_classify', autoClassify ? 'true' : 'false')
|
||||
return request('/api/documents/upload', { method: 'POST', body: form })
|
||||
}
|
||||
|
||||
export function listDocuments({ topic, page = 1, perPage = 20 } = {}) {
|
||||
const params = new URLSearchParams({ page, per_page: perPage })
|
||||
if (topic) params.set('topic', topic)
|
||||
return request(`/api/documents?${params}`)
|
||||
}
|
||||
|
||||
export function getDocument(id) {
|
||||
return request(`/api/documents/${id}`)
|
||||
}
|
||||
|
||||
export function deleteDocument(id) {
|
||||
return request(`/api/documents/${id}`, { method: 'DELETE' })
|
||||
}
|
||||
|
||||
export function classifyDocument(id, topics = null) {
|
||||
return request(`/api/documents/${id}/classify`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(topics ? { topics } : {}),
|
||||
})
|
||||
}
|
||||
|
||||
// ── Topics ───────────────────────────────────────────────────────────────────
|
||||
|
||||
export function listTopics() {
|
||||
return request('/api/topics')
|
||||
}
|
||||
|
||||
export function createTopic({ name, description = '', color = '#6366f1' }) {
|
||||
return request('/api/topics', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name, description, color }),
|
||||
})
|
||||
}
|
||||
|
||||
export function updateTopic(id, patch) {
|
||||
return request(`/api/topics/${id}`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(patch),
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteTopic(id) {
|
||||
return request(`/api/topics/${id}`, { method: 'DELETE' })
|
||||
}
|
||||
|
||||
export function suggestTopics(documentId) {
|
||||
return request('/api/topics/suggest', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ document_id: documentId }),
|
||||
})
|
||||
}
|
||||
|
||||
// ── Settings ─────────────────────────────────────────────────────────────────
|
||||
|
||||
export function getSettings() {
|
||||
return request('/api/settings')
|
||||
}
|
||||
|
||||
export function patchSettings(patch) {
|
||||
return request('/api/settings', {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(patch),
|
||||
})
|
||||
}
|
||||
|
||||
export function testProvider(provider) {
|
||||
return request('/api/settings/test-provider', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ provider }),
|
||||
})
|
||||
}
|
||||
|
||||
export function getDefaultPrompt() {
|
||||
return request('/api/settings/default-prompt')
|
||||
}
|
||||
Reference in New Issue
Block a user