import { ApiError } from "@/types"; const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"; class ApiClient { private baseUrl: string; constructor(baseUrl: string) { this.baseUrl = baseUrl; } private async request( method: string, path: string, options?: { body?: unknown; params?: Record; } ): Promise { const url = new URL(`${this.baseUrl}${path}`); if (options?.params) { Object.entries(options.params).forEach(([key, value]) => { if (value !== undefined && value !== null) { url.searchParams.set(key, String(value)); } }); } const res = await fetch(url.toString(), { method, headers: { "Content-Type": "application/json", }, body: options?.body ? JSON.stringify(options.body) : undefined, }); if (res.status === 204) { return undefined as T; } if (!res.ok) { const error = await res .json() .catch(() => ({ detail: "알 수 없는 오류가 발생했습니다" })); throw { detail: error.detail || `HTTP ${res.status} Error`, status: res.status, } as ApiError; } return res.json(); } get( path: string, params?: Record ) { return this.request("GET", path, { params }); } post(path: string, body?: unknown) { return this.request("POST", path, { body }); } put(path: string, body?: unknown) { return this.request("PUT", path, { body }); } patch(path: string, body?: unknown) { return this.request("PATCH", path, { body }); } delete(path: string) { return this.request("DELETE", path); } async uploadFiles(path: string, files: File[]): Promise { const url = new URL(`${this.baseUrl}${path}`); const formData = new FormData(); files.forEach((file) => formData.append("files", file)); const res = await fetch(url.toString(), { method: "POST", body: formData, }); if (!res.ok) { const error = await res .json() .catch(() => ({ detail: "파일 업로드에 실패했습니다" })); throw { detail: error.detail || `HTTP ${res.status} Error`, status: res.status, } as ApiError; } return res.json(); } async downloadFile(path: string, filename: string): Promise { const url = new URL(`${this.baseUrl}${path}`); const res = await fetch(url.toString()); if (!res.ok) { throw new Error("다운로드에 실패했습니다"); } const blob = await res.blob(); const downloadUrl = window.URL.createObjectURL(blob); const link = document.createElement("a"); link.href = downloadUrl; link.download = filename; document.body.appendChild(link); link.click(); link.remove(); window.URL.revokeObjectURL(downloadUrl); } } export const apiClient = new ApiClient(API_BASE_URL);