import { API_BASE_URL, API_TIMEOUT } from './config'; // Generic API request helper async function apiRequest(endpoint: string, options: RequestInit = {}): Promise { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT); try { const response = await fetch(`${API_BASE_URL}${endpoint}`, { headers: { 'Content-Type': 'application/json', ...options.headers, }, signal: controller.signal, ...options, }); clearTimeout(timeoutId); if (!response.ok) { const errorText = await response.text(); throw new Error(`API Error (${response.status}): ${errorText || response.statusText}`); } return response.json(); } catch (error) { clearTimeout(timeoutId); if (error instanceof Error) { if (error.name === 'AbortError') { throw new Error('Request timeout'); } throw error; } throw new Error('Unknown error occurred'); } } // Outlets API export const outletsApi = { getAll: async (category?: string, language = 'ko') => { const params = new URLSearchParams(); if (category) params.append('category', category); if (language) params.append('language', language); const response = await apiRequest(`/api/v1/outlets?${params}`); // API returns {"people": [...]} when category is specified // Extract the array from the categorized response if (category && response[category]) { return response[category]; } return response; }, getById: (id: string, language = 'ko') => { const params = new URLSearchParams({ language }); return apiRequest(`/api/v1/outlets/${id}?${params}`); }, }; // Articles API export const articlesApi = { getAll: (language = 'ko') => { const params = new URLSearchParams({ page_size: '50' }); return apiRequest(`/api/v1/${language}/articles?${params}`); }, getByOutlet: (outletId: string, language = 'ko') => { const params = new URLSearchParams({ page_size: '50' }); return apiRequest(`/api/v1/${language}/outlets/${encodeURIComponent(outletId)}/articles?${params}`); }, getFeatured: (limit = 10, language = 'ko') => { const params = new URLSearchParams({ page_size: limit.toString() }); return apiRequest(`/api/v1/${language}/articles?${params}`); }, getById: (id: string, language = 'ko', useNewsId = false) => { return apiRequest(`/api/v1/${language}/articles/${id}`); }, }; // Search API export const searchApi = { search: async ( query: string, type: 'all' | 'articles' | 'outlets' = 'all', language = 'en', outletId?: string ) => { const params = new URLSearchParams({ q: query, type, language, }); if (outletId) { params.append('outletId', outletId); } return apiRequest(`/api/v1/search?${params}`); }, articles: (query: string, language = 'en') => { const params = new URLSearchParams({ q: query, language, limit: '20' }); return apiRequest(`/api/v1/search/articles?${params}`); }, }; // Feed API for YouTube-style interface export const feedApi = { getFeed: (params: { cursor?: string; limit?: number; filter?: 'all' | 'people' | 'topics' | 'companies'; }) => { const searchParams = new URLSearchParams(); if (params.cursor) searchParams.set('cursor', params.cursor); if (params.limit) searchParams.set('limit', params.limit.toString()); if (params.filter) searchParams.set('filter', params.filter); return apiRequest(`/api/v1/feed?${searchParams.toString()}`); }, incrementView: (articleId: string) => apiRequest(`/api/v1/articles/${articleId}/view`, { method: 'POST', }), };