Álvaro Valenzuela Valdes
🚀 Fix: Export getAPIBase to resolve build error
c90dcb6
raw
history blame
6.46 kB
import type { AnalysisHistoryItem, AnalysisResult, CompanyProfile, Tender, PurchaseOrder } from "./types";
// Auto-detect API base URL based on environment
export function getAPIBase(): string {
// 1. Explicit env var (highest priority)
if (process.env.NEXT_PUBLIC_API_BASE) {
console.log('[API] Using explicit NEXT_PUBLIC_API_BASE:', process.env.NEXT_PUBLIC_API_BASE);
return process.env.NEXT_PUBLIC_API_BASE;
}
// Only works on client side
if (typeof window === 'undefined') {
return '';
}
const hostname = window.location.hostname;
const protocol = window.location.protocol;
// 2. Hugging Face Space detection (IMPROVED)
if (hostname.includes('.hf.space')) {
// If we are in the hackathon space or REWCHILE space
// Direct point to the backend we just created
const backendUrl = `https://rewchile-andesai-backend.hf.space`;
console.log('[API] Hugging Face Space detected. Frontend:', hostname);
console.log('[API] Connecting to Backend:', backendUrl);
return backendUrl;
}
// 3. Vercel/Production detection
if (hostname.includes('vercel.app')) {
const backendUrl = process.env.REACT_APP_API_BASE || `${protocol}//${hostname.replace('andesai', 'andesai-api')}`;
console.log('[API] Vercel environment detected. Using:', backendUrl);
return backendUrl;
}
// 4. GitHub Pages + external API
if (hostname.includes('github.io') || hostname.includes('github.dev')) {
const backendUrl = process.env.REACT_APP_API_BASE || 'https://andesai-backend.fly.dev';
console.log('[API] GitHub Pages detected. Using:', backendUrl);
return backendUrl;
}
// 5. Local development fallback
console.log('[API] Local development environment detected');
return 'http://localhost:8000';
}
const API_BASE = getAPIBase();
// Log API base for debugging
if (typeof window !== 'undefined') {
console.log('[API] Final API Base URL:', API_BASE, 'on hostname:', window.location.hostname);
}
const jsonHeaders = {
"Content-Type": "application/json",
};
export async function healthCheck() {
const res = await fetch(`${API_BASE}/api/health`);
if (!res.ok) {
throw new Error("Health check failed");
}
return res.json();
}
export async function fetchDbStatus() {
const res = await fetch(`${API_BASE}/api/health/db-status`);
if (!res.ok) return null;
return res.json();
}
export async function searchTenders(params: {
keyword?: string;
buyer?: string;
provider_code?: string;
org_code?: string;
status?: string;
code?: string;
date?: string;
type_code?: string;
skip?: number;
limit?: number;
}): Promise<Tender[]> {
const query = new URLSearchParams();
if (params.keyword) query.append("keyword", params.keyword);
if (params.buyer) query.append("buyer", params.buyer);
if (params.provider_code) query.append("provider_code", params.provider_code);
if (params.org_code) query.append("org_code", params.org_code);
if (params.status) query.append("status", params.status);
if (params.code) query.append("code", params.code);
if (params.date) query.append("date", params.date);
if (params.type_code) query.append("type_code", params.type_code);
if (params.skip !== undefined) query.append("skip", params.skip.toString());
if (params.limit !== undefined) query.append("limit", params.limit.toString());
const res = await fetch(`${API_BASE}/api/tenders?${query.toString()}`);
if (!res.ok) {
throw new Error("Error searching tenders");
}
return res.json();
}
export async function analyzeTender(
tender: Tender,
companyProfile: CompanyProfile,
documentText?: string,
models?: Record<string, string>
): Promise<AnalysisResult> {
const res = await fetch(`${API_BASE}/api/analyze`, {
method: "POST",
headers: jsonHeaders,
body: JSON.stringify({
tender,
company_profile: companyProfile,
document_text: documentText,
models: models
}),
});
if (!res.ok) {
throw new Error("Error analyzing tender");
}
return res.json();
}
export async function uploadDocument(file: File): Promise<{ text: string; filename: string }> {
const formData = new FormData();
formData.append("file", file);
const res = await fetch(`${API_BASE}/api/upload-document`, {
method: "POST",
body: formData,
});
if (!res.ok) {
throw new Error("Error uploading document");
}
return res.json();
}
export async function saveCompanyProfile(profile: CompanyProfile): Promise<CompanyProfile> {
const res = await fetch(`${API_BASE}/api/company-profile`, {
method: "POST",
headers: jsonHeaders,
body: JSON.stringify(profile),
});
if (!res.ok) {
throw new Error("Error saving company profile");
}
return res.json();
}
export async function fetchCompanyProfile(): Promise<CompanyProfile> {
const res = await fetch(`${API_BASE}/api/company-profile`);
if (!res.ok) {
throw new Error("No company profile available");
}
return res.json();
}
export async function fetchAnalysisHistory(): Promise<AnalysisHistoryItem[]> {
const res = await fetch(`${API_BASE}/api/analysis-history`);
if (!res.ok) {
throw new Error("Error fetching analysis history");
}
return res.json();
}
export async function syncDatabase() {
const res = await fetch(`${API_BASE}/api/tenders/sync`, { method: "POST" });
if (!res.ok) {
throw new Error("Error syncing database");
}
return res.json();
}
export async function scrapeTenders(keyword: string): Promise<Tender[]> {
const res = await fetch(`${API_BASE}/api/tenders/scrape?keyword=${encodeURIComponent(keyword)}`);
if (!res.ok) {
const errorText = await res.text();
throw new Error(`Scraper error (${res.status}): ${errorText || "Failed to scrape tenders"}`);
}
return res.json();
}
export async function fetchPurchaseOrders(date?: string, status: string = "todos"): Promise<PurchaseOrder[]> {
const query = new URLSearchParams();
if (date) query.append("date", date);
query.append("status", status);
const url = `${API_BASE}/api/purchase-orders?${query.toString()}`;
console.log("[API] Fetching purchase orders from:", url);
const res = await fetch(url);
if (!res.ok) {
const errorText = await res.text();
console.error("[API] Purchase orders error:", res.status, errorText);
throw new Error(`Failed to fetch purchase orders (${res.status}): Check if backend is running at ${API_BASE}`);
}
return res.json();
}