| import type { AnalysisHistoryItem, AnalysisResult, CompanyProfile, Tender, PurchaseOrder, TenderDetailInfo } from "./types"; |
|
|
| |
| export function getAPIBase(): string { |
| |
| if (process.env.NEXT_PUBLIC_API_BASE) { |
| return process.env.NEXT_PUBLIC_API_BASE; |
| } |
|
|
| if (typeof window === 'undefined') return ''; |
|
|
| const hostname = window.location.hostname; |
| |
| |
| if (hostname === 'localhost' || hostname === '127.0.0.1') { |
| return 'http://localhost:8000'; |
| } |
|
|
| |
| if (typeof window !== 'undefined') { |
| const origin = window.location.origin; |
| console.log('[ANDES-DEBUG] API Origin detected:', origin); |
| return origin; |
| } |
|
|
| return ''; |
| } |
|
|
| const API_BASE = getAPIBase(); |
|
|
| |
| 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/admin/db-stats`); |
| 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>, |
| tenderDetails?: TenderDetailInfo | null |
| ): 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, |
| tender_details: tenderDetails |
| }), |
| }); |
| 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 saveSearchHistory(query: string, resultsCount: number, isAgile: boolean = false) { |
| return fetch(`${API_BASE}/api/search-history`, { |
| method: "POST", |
| headers: jsonHeaders, |
| body: JSON.stringify({ |
| query, |
| results_count: resultsCount, |
| searched_at: new Date().toISOString(), |
| is_agile: isAgile |
| }) |
| }); |
| } |
|
|
| export async function fetchSearchHistory(): Promise<any[]> { |
| const res = await fetch(`${API_BASE}/api/search-history`); |
| if (!res.ok) return []; |
| return res.json(); |
| } |
|
|
| export async function syncDatabase() { |
| const res = await fetch(`${API_BASE}/api/admin/sync-all`, { method: "POST" }); |
| if (!res.ok) { |
| throw new Error("Error syncing database"); |
| } |
| return res.json(); |
| } |
|
|
| export async function clearDatabase() { |
| const res = await fetch(`${API_BASE}/api/admin/db-clear`, { method: "DELETE" }); |
| if (!res.ok) { |
| throw new Error("Error clearing database"); |
| } |
| return res.json(); |
| } |
|
|
| export async function fetchDetailedDbStats() { |
| const res = await fetch(`${API_BASE}/api/admin/db-stats`); |
| if (!res.ok) return null; |
| return res.json(); |
| } |
|
|
| export async function fetchRecommendations() { |
| const res = await fetch(`${API_BASE}/api/tenders/recommendations`); |
| if (!res.ok) return []; |
| 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(); |
| } |
|
|
| export async function fetchTenderDetails(code: string, qs?: string): Promise<TenderDetailInfo> { |
| const query = new URLSearchParams(); |
| if (qs) query.append("qs", qs); |
| |
| const res = await fetch(`${API_BASE}/api/tenders/${code}/detail-tabs?${query.toString()}`); |
| if (!res.ok) { |
| throw new Error("Error fetching tender details"); |
| } |
| return res.json(); |
| } |
|
|
| export async function extractTenderDetails(code: string, qs?: string): Promise<any> { |
| const query = new URLSearchParams(); |
| if (qs) query.append("qs", qs); |
| |
| const res = await fetch(`${API_BASE}/api/tenders/${code}/extract-details?${query.toString()}`, { |
| method: "POST" |
| }); |
| if (!res.ok) { |
| throw new Error("Error extracting tender details"); |
| } |
| return res.json(); |
| } |
|
|