FinSight / frontend /src /api /client.ts
Sanjam19's picture
Deploy FinSight demo (single-container Docker Space)
d4f8959 verified
Raw
History Blame Contribute Delete
4.35 kB
import type {
UploadResponse,
Report,
RedFlagsResponse,
RecommendationResponse,
QueryRequest,
QueryResponse,
CompareRequest,
CompareResponse,
CompaniesResponse,
} from '../types/api';
// Dev: '/api' is proxied to the backend by Vite (vite.config.ts).
// Production (single-container deploy): built with VITE_API_BASE='' so
// requests hit the same origin that serves the static bundle.
const BASE_URL =
(import.meta as ImportMeta & { env?: Record<string, string | undefined> })
.env?.VITE_API_BASE ?? '/api';
async function request<T>(path: string, options?: RequestInit): Promise<T> {
const res = await fetch(`${BASE_URL}${path}`, {
headers: { 'Content-Type': 'application/json', ...options?.headers },
...options,
});
if (!res.ok) {
if (res.status === 404) {
throw new NotFoundError('No filing found. Upload a filing first.');
}
const text = await res.text();
throw new Error(`API error ${res.status}: ${text}`);
}
return res.json() as Promise<T>;
}
export class NotFoundError extends Error {
constructor(message: string) {
super(message);
this.name = 'NotFoundError';
}
}
// ─── Upload ───────────────────────────────────────────────────────────────────
export async function uploadFiling(
file: File,
company: string,
year: string
): Promise<UploadResponse> {
const form = new FormData();
form.append('file', file);
form.append('company', company);
form.append('year', year);
const res = await fetch(`${BASE_URL}/upload`, {
method: 'POST',
body: form,
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Upload failed (${res.status}): ${text}`);
}
return res.json() as Promise<UploadResponse>;
}
// ─── Report ───────────────────────────────────────────────────────────────────
export async function getReport(company: string, year: string): Promise<Report> {
return request<Report>(`/report/${encodeURIComponent(company)}/${encodeURIComponent(year)}`);
}
// ─── Red Flags ────────────────────────────────────────────────────────────────
export async function getRedFlags(
company: string,
year: string
): Promise<RedFlagsResponse> {
return request<RedFlagsResponse>(
`/red_flags/${encodeURIComponent(company)}/${encodeURIComponent(year)}`
);
}
// ─── Recommendation ───────────────────────────────────────────────────────────
export async function getRecommendation(
company: string,
year: string
): Promise<RecommendationResponse> {
return request<RecommendationResponse>(
`/recommendation/${encodeURIComponent(company)}/${encodeURIComponent(year)}`
);
}
// ─── Query ────────────────────────────────────────────────────────────────────
export async function queryFiling(payload: QueryRequest): Promise<QueryResponse> {
return request<QueryResponse>('/query', {
method: 'POST',
body: JSON.stringify(payload),
});
}
// ─── Compare ─────────────────────────────────────────────────────────────────
export async function compareFilers(payload: CompareRequest): Promise<CompareResponse> {
return request<CompareResponse>('/compare', {
method: 'POST',
body: JSON.stringify(payload),
});
}
// ─── Companies ────────────────────────────────────────────────────────────────
export async function getCompanies(): Promise<CompaniesResponse> {
return request<CompaniesResponse>('/companies');
}