import axios from 'axios' import { ref } from 'vue' const api = axios.create({ baseURL: '/api', timeout: 30000 }) export function useApi() { const loading = ref(false) const error = ref(null) const handleError = (e, fallback = null) => { const status = e?.response?.status const message = e?.response?.data?.error || e?.message || 'Request failed' error.value = { status, message } console.error(`API error [${status}]:`, message) if (fallback !== null) return fallback throw e } // ============== Projects ============== const fetchProjects = async () => { loading.value = true error.value = null try { const response = await api.get('/projects') return response.data } catch (e) { handleError(e, []) return [] } finally { loading.value = false } } const fetchProject = async (id) => { loading.value = true error.value = null try { const response = await api.get(`/projects/${id}`) return response.data } catch (e) { handleError(e, null) return null } finally { loading.value = false } } const createProject = async (data) => { loading.value = true error.value = null try { const response = await api.post('/projects', data) return response.data } catch (e) { handleError(e, null) return null } finally { loading.value = false } } const updateProject = async (id, data) => { loading.value = true error.value = null try { let response if (data instanceof FormData) { response = await api.put(`/projects/${id}`, data, { headers: { 'Content-Type': 'multipart/form-data' } }) } else { // Wrap in FormData for multipart backend endpoint const formData = new FormData() if (data.name != null) formData.append('name', data.name) if (data.description != null) formData.append('description', data.description) response = await api.put(`/projects/${id}`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }) } return response.data } catch (e) { handleError(e, null) return null } finally { loading.value = false } } const deleteProject = async (id) => { loading.value = true error.value = null try { await api.delete(`/projects/${id}`) return true } catch (e) { handleError(e, false) return false } finally { loading.value = false } } // ============== Reports ============== const fetchReports = async (projectId) => { loading.value = true error.value = null try { const response = await api.get(`/reports`, { params: projectId ? { projectId } : {} }) return response.data } catch (e) { handleError(e, []) return [] } finally { loading.value = false } } const fetchReportContent = async (reportId) => { loading.value = true error.value = null try { const response = await api.get(`/reports/${reportId}`) return { content: response.data.fileContent, type: response.data.fileType } } catch (e) { handleError(e, null) return null } finally { loading.value = false } } const fetchReportBytes = async (reportId) => { try { const response = await api.get(`/reports/${reportId}/download`, { responseType: 'arraybuffer' }) return response.data } catch (e) { handleError(e, null) return null } } const fetchReportPdf = async (reportId) => { try { const response = await api.get(`/reports/${reportId}/pdf`, { responseType: 'arraybuffer' }) return new Blob([response.data], { type: 'application/pdf' }) } catch (e) { handleError(e, null) return null } } const uploadReport = async (file, projectId, fileType) => { loading.value = true error.value = null try { const formData = new FormData() formData.append('file', file) formData.append('projectId', projectId) formData.append('fileType', fileType) const response = await api.post('/reports', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) return response.data } catch (e) { handleError(e, null) return null } finally { loading.value = false } } const deleteReport = async (id) => { loading.value = true error.value = null try { await api.delete(`/reports/${id}`) return true } catch (e) { handleError(e, false) return false } finally { loading.value = false } } return { loading, error, // projects fetchProjects, fetchProject, createProject, updateProject, deleteProject, // reports fetchReports, fetchReportContent, fetchReportBytes, fetchReportPdf, uploadReport, deleteReport } }