Files
Estacion-de-Documentos/frontend/lib/api.ts
T
2026-05-19 14:21:56 -06:00

156 lines
6.9 KiB
TypeScript

const configuredApiUrl = process.env.NEXT_PUBLIC_API_URL;
export const API_URL = configuredApiUrl === undefined ? "http://127.0.0.1:8000" : configuredApiUrl || "/api";
export type Subject = { id: number; name: string; slug: string; created_at: string };
export type Week = { id: number; subject_id: number; number: number; title?: string | null; created_at: string };
export type Source = {
id: number;
week_id: number;
original_name: string;
stored_path: string;
source_type: string;
status: string;
file_size?: number | null;
sha256?: string | null;
mime_type?: string | null;
processor?: string | null;
page_ranges?: string | null;
processed_at?: string | null;
document_id?: number | null;
document_title?: string | null;
document_markdown_path?: string | null;
document_created_at?: string | null;
created_at: string;
};
export type Job = { id: number; status: string; message: string; source_id?: number | null; document_id?: number | null; created_at: string; updated_at: string };
export type DocumentItem = {
id: number;
source_id: number;
title: string;
markdown_path: string;
source_original_name?: string | null;
source_type?: string | null;
source_status?: string | null;
source_processor?: string | null;
source_page_ranges?: string | null;
created_at: string;
};
export type SettingsStatus = { mistral_configured: boolean; deepgram_configured: boolean; data_dir: string; database_path: string };
async function parseResponse<T>(response: Response): Promise<T> {
if (!response.ok) {
const detail = await response.json().catch(() => null);
throw new Error(detail?.detail || `Error ${response.status}`);
}
return response.json() as Promise<T>;
}
export const api = {
async health() {
return parseResponse<{ status: string }>(await fetch(`${API_URL}/health`, { cache: "no-store" }));
},
async settings() {
return parseResponse<SettingsStatus>(await fetch(`${API_URL}/settings/status`, { cache: "no-store" }));
},
async subjects() {
return parseResponse<Subject[]>(await fetch(`${API_URL}/subjects`, { cache: "no-store" }));
},
async subject(id: number) {
return parseResponse<Subject>(await fetch(`${API_URL}/subjects/${id}`, { cache: "no-store" }));
},
async createSubject(name: string) {
return parseResponse<Subject>(await fetch(`${API_URL}/subjects`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name }),
}));
},
async updateSubject(id: number, name: string) {
return parseResponse<Subject>(await fetch(`${API_URL}/subjects/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name }),
}));
},
async deleteSubject(id: number) {
return parseResponse<{ status: string }>(await fetch(`${API_URL}/subjects/${id}`, { method: "DELETE" }));
},
async weeks(subjectId: number) {
return parseResponse<Week[]>(await fetch(`${API_URL}/subjects/${subjectId}/weeks`, { cache: "no-store" }));
},
async week(subjectId: number, weekNumber: number) {
return parseResponse<Week>(await fetch(`${API_URL}/subjects/${subjectId}/weeks/${weekNumber}`, { cache: "no-store" }));
},
async createWeek(subjectId: number, number: number, title: string) {
return parseResponse<Week>(await fetch(`${API_URL}/subjects/${subjectId}/weeks`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ number, title: title || null }),
}));
},
async updateWeek(subjectId: number, currentNumber: number, number: number, title: string) {
return parseResponse<Week>(await fetch(`${API_URL}/subjects/${subjectId}/weeks/${currentNumber}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ number, title: title || null }),
}));
},
async deleteWeek(subjectId: number, weekNumber: number) {
return parseResponse<{ status: string }>(await fetch(`${API_URL}/subjects/${subjectId}/weeks/${weekNumber}`, { method: "DELETE" }));
},
async sources(subjectId: number, weekNumber: number) {
return parseResponse<Source[]>(await fetch(`${API_URL}/subjects/${subjectId}/weeks/${weekNumber}/sources`, { cache: "no-store" }));
},
async jobs(subjectId: number, weekNumber: number) {
return parseResponse<Job[]>(await fetch(`${API_URL}/subjects/${subjectId}/weeks/${weekNumber}/jobs`, { cache: "no-store" }));
},
async documents(subjectId: number, weekNumber: number) {
return parseResponse<DocumentItem[]>(await fetch(`${API_URL}/subjects/${subjectId}/weeks/${weekNumber}/documents`, { cache: "no-store" }));
},
async deleteSource(sourceId: number) {
return parseResponse<{ status: string }>(await fetch(`${API_URL}/sources/${sourceId}`, { method: "DELETE" }));
},
async deleteDocument(documentId: number) {
return parseResponse<{ status: string }>(await fetch(`${API_URL}/documents/${documentId}`, { method: "DELETE" }));
},
async reprocessSource(sourceId: number, useOcr: boolean, pageRanges?: string) {
const params = new URLSearchParams({ use_ocr: String(useOcr) });
if (pageRanges?.trim()) params.set("page_ranges", pageRanges.trim());
return parseResponse<{ source: Source; job: Job }>(await fetch(`${API_URL}/sources/${sourceId}/reprocess?${params.toString()}`, { method: "POST" }));
},
async upload(subjectId: number, weekNumber: number, file: File, useOcr: boolean, pageRanges?: string) {
const form = new FormData();
form.append("file", file);
const params = new URLSearchParams({ use_ocr: String(useOcr) });
if (pageRanges?.trim()) params.set("page_ranges", pageRanges.trim());
return parseResponse<{ source: Source; job: Job }>(await fetch(`${API_URL}/subjects/${subjectId}/weeks/${weekNumber}/files?${params.toString()}`, {
method: "POST",
body: form,
}));
},
async markdown(documentId: number) {
const response = await fetch(`${API_URL}/documents/${documentId}/markdown`, { cache: "no-store" });
if (!response.ok) throw new Error(`Error ${response.status}`);
return response.text();
},
async document(documentId: number) {
return parseResponse<DocumentItem>(await fetch(`${API_URL}/documents/${documentId}`, { cache: "no-store" }));
},
async saveMarkdown(documentId: number, content: string) {
return parseResponse<DocumentItem>(await fetch(`${API_URL}/documents/${documentId}/markdown`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content }),
}));
},
downloadDocumentUrl(documentId: number) {
return `${API_URL}/documents/${documentId}/download`;
},
exportWeekUrl(subjectId: number, weekNumber: number) {
return `${API_URL}/subjects/${subjectId}/weeks/${weekNumber}/export`;
},
exportWeekZipUrl(subjectId: number, weekNumber: number) {
return `${API_URL}/subjects/${subjectId}/weeks/${weekNumber}/export.zip`;
},
};