// assets/js/utils/api.js const ApiUtils = { call: async (endpoint, options = {}) => { const token = AuthUtils.getToken(); const defaultOptions = { headers: { "Content-Type": "application/json", ...(token && { Authorization: `Bearer ${token}` }), }, }; const finalOptions = { ...defaultOptions, ...options }; if (options.headers) { finalOptions.headers = { ...defaultOptions.headers, ...options.headers }; } try { const response = await fetch( `${CONFIG.API_URL}${endpoint}`, finalOptions ); // 1. Cek jika Unauthorized (401) if (response.status === 401) { AuthUtils.clearAuth(); window.location.href = "/login"; return; } // 2. Cek apakah response valid JSON const contentType = response.headers.get("content-type"); if (!contentType || !contentType.includes("application/json")) { // Jika bukan JSON (misal text "200 OK" atau HTML error page) const text = await response.text(); console.error("API Error (Non-JSON Response):", text); throw new Error("Server returned invalid response format"); } // 3. Parse JSON dengan aman const data = await response.json(); if (!response.ok) { throw new Error(data.error || data.message || "Request failed"); } return data; } catch (error) { console.error("Fetch error:", error); throw error; } }, get: async (endpoint) => { return ApiUtils.call(endpoint, { method: "GET" }); }, post: async (endpoint, body) => { return ApiUtils.call(endpoint, { method: "POST", body: JSON.stringify(body), }); }, put: async (endpoint, body) => { return ApiUtils.call(endpoint, { method: "PUT", body: JSON.stringify(body), }); }, patch: async (endpoint, body) => { return ApiUtils.call(endpoint, { method: "PATCH", body: JSON.stringify(body), }); }, delete: async (endpoint) => { return ApiUtils.call(endpoint, { method: "DELETE" }); }, uploadFile: async (endpoint, formData) => { const token = AuthUtils.getToken(); const response = await fetch(`${CONFIG.API_URL}${endpoint}`, { method: "POST", headers: { Authorization: `Bearer ${token}`, }, body: formData, }); const data = await response.json(); if (!response.ok) { if (response.status === 401) { AuthUtils.clearAuth(); window.location.href = "/login"; } throw new Error(data.error || "Upload failed"); } return data; }, };