diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 6a58420..33d7ebb 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -1,9 +1,24 @@ -const API_BASE_URL = (import.meta.env.VITE_API_URL as string | undefined) ?? 'http://localhost:8081' +export const API_BASE_URL = (import.meta.env.VITE_API_URL as string | undefined) ?? 'http://localhost:8081' -function buildUrl(path: string) { +export function buildUrl(path: string) { return `${API_BASE_URL}${path}` } +export function getAuthToken(): string | null { + const storedUser = localStorage.getItem('user') + if (storedUser) { + try { + const userData = JSON.parse(storedUser) + if (userData?.jwt) { + return userData.jwt + } + } catch { + // Ignora erro de parsing + } + } + return null +} + type RequestOptions = Omit & { body?: unknown skipAuth?: boolean @@ -14,16 +29,9 @@ export async function apiFetch(path: string, options: RequestOptions = {}): P let authHeader: Record = {} if (!skipAuth) { - const storedUser = localStorage.getItem('user') - if (storedUser) { - try { - const userData = JSON.parse(storedUser) - if (userData?.jwt) { - authHeader = { Authorization: `Bearer ${userData.jwt}` } - } - } catch { - // Ignora erro de parsing - } + const token = getAuthToken() + if (token) { + authHeader = { Authorization: `Bearer ${token}` } } } diff --git a/frontend/src/services/reportService.ts b/frontend/src/services/reportService.ts index 224df46..ddb9773 100644 --- a/frontend/src/services/reportService.ts +++ b/frontend/src/services/reportService.ts @@ -1,4 +1,4 @@ -import { apiFetch } from '../lib/api' +import { apiFetch, getAuthToken, buildUrl } from '../lib/api' export interface ReportSectionOutput { id: number @@ -69,23 +69,10 @@ export const reportService = { }, async createTemplate(orgId: number, formData: FormData): Promise { - const token = localStorage.getItem('token') - const apiUrl = import.meta.env.VITE_API_URL || 'https://api-task.beetech.dev' - - const res = await fetch(`${apiUrl}/organizations/${orgId}/reports/templates`, { + return apiFetch(`/organizations/${orgId}/reports/templates`, { method: 'POST', - headers: { - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, body: formData, }) - - if (!res.ok) { - const err = await res.json().catch(() => ({ message: 'Erro ao criar modelo de relatório' })) - throw new Error(err.message || 'Erro ao criar modelo de relatório') - } - - return res.json() }, async deleteTemplate(orgId: number, templateId: number): Promise { @@ -95,10 +82,9 @@ export const reportService = { }, async generateReport(orgId: number, payload: GenerateReportPayload): Promise<{ blob: Blob; fileName: string }> { - const token = localStorage.getItem('token') - const apiUrl = import.meta.env.VITE_API_URL || 'https://api-task.beetech.dev' + const token = getAuthToken() - const res = await fetch(`${apiUrl}/organizations/${orgId}/reports/generate`, { + const res = await fetch(buildUrl(`/organizations/${orgId}/reports/generate`), { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -108,8 +94,16 @@ export const reportService = { }) if (!res.ok) { - const err = await res.json().catch(() => ({ message: 'Erro ao gerar relatório' })) - throw new Error(err.message || 'Erro ao gerar relatório') + const text = await res.text() + let message = text || 'Erro ao gerar relatório' + try { + const err = JSON.parse(text) + if (err.message) message = err.message + if (err.error) message = err.error + } catch { + // Ignora erro de parsing + } + throw new Error(message) } // Obter nome do arquivo do header Content-Disposition ou gerar fallback