/** * Reporting API Client * * Client functions for the Executive Reporting module. * Communicates with the Go backend via Next.js API proxy at /api/sdk/v1/reporting/* */ import type { ExecutiveReport, ComplianceScoreResponse, Deadline, RiskOverview, } from './types' const BASE_URL = '/api/sdk/v1/reporting' /** * Rekursive snake_case -> camelCase Konvertierung fuer API-Responses. * Das Go-Backend liefert snake_case JSON, der TypeScript-Client erwartet camelCase. */ function snakeToCamel(str: string): string { return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()) } function transformKeys(obj: unknown): unknown { if (Array.isArray(obj)) { return obj.map(transformKeys) } if (obj !== null && typeof obj === 'object') { return Object.fromEntries( Object.entries(obj as Record).map(([key, value]) => [ snakeToCamel(key), transformKeys(value), ]) ) } return obj } async function apiFetch(path: string): Promise { const res = await fetch(`${BASE_URL}${path}`, { headers: { 'Content-Type': 'application/json', 'X-Tenant-ID': typeof window !== 'undefined' ? (localStorage.getItem('bp-tenant-id') || 'default') : 'default', }, }) if (!res.ok) { const error = await res.json().catch(() => ({ error: res.statusText })) throw new Error(error.error || `API Error: ${res.status}`) } const data = await res.json() return transformKeys(data) as T } /** * Vollstaendigen Executive Report abrufen * GET /sdk/v1/reporting/executive */ export async function getExecutiveReport(): Promise { return apiFetch('/executive') } /** * Nur den Compliance-Score abrufen (leichtgewichtig) * GET /sdk/v1/reporting/score */ export async function getComplianceScore(): Promise { return apiFetch('/score') } /** * Bevorstehende Fristen abrufen * GET /sdk/v1/reporting/deadlines */ export async function getUpcomingDeadlines(): Promise<{ deadlines: Deadline[]; total: number }> { return apiFetch<{ deadlines: Deadline[]; total: number }>('/deadlines') } /** * Risikouebersicht abrufen * GET /sdk/v1/reporting/risks */ export async function getRiskOverview(): Promise { return apiFetch('/risks') }