'use client' /** * Vendor Compliance Context - API Actions * * Extracted from context.tsx to stay under 500 LOC hard cap. * Contains loadData, refresh, and all CRUD API action hooks. */ import { useCallback } from 'react' import type { Dispatch } from 'react' import type { ProcessingActivity, VendorComplianceAction } from './types' const API_BASE = '/api/sdk/v1/vendor-compliance' export function useContextApiActions( state: { processingActivities: ProcessingActivity[]; contracts: Array<{ id: string; vendorId: string; expirationDate?: Date | null; status: string }>; vendors: Array<{ id: string; contracts: string[] }> }, dispatch: Dispatch ) { const loadData = useCallback(async () => { dispatch({ type: 'SET_LOADING', payload: true }) dispatch({ type: 'SET_ERROR', payload: null }) try { const [ activitiesRes, vendorsRes, contractsRes, findingsRes, controlsRes, controlInstancesRes, ] = await Promise.all([ fetch(`${API_BASE}/processing-activities`), fetch(`${API_BASE}/vendors`), fetch(`${API_BASE}/contracts`), fetch(`${API_BASE}/findings`), fetch(`${API_BASE}/controls`), fetch(`${API_BASE}/control-instances`), ]) if (activitiesRes.ok) { const data = await activitiesRes.json() dispatch({ type: 'SET_PROCESSING_ACTIVITIES', payload: data.data || [] }) } if (vendorsRes.ok) { const data = await vendorsRes.json() dispatch({ type: 'SET_VENDORS', payload: data.data || [] }) } if (contractsRes.ok) { const data = await contractsRes.json() dispatch({ type: 'SET_CONTRACTS', payload: data.data || [] }) } if (findingsRes.ok) { const data = await findingsRes.json() dispatch({ type: 'SET_FINDINGS', payload: data.data || [] }) } if (controlsRes.ok) { const data = await controlsRes.json() dispatch({ type: 'SET_CONTROLS', payload: data.data || [] }) } if (controlInstancesRes.ok) { const data = await controlInstancesRes.json() dispatch({ type: 'SET_CONTROL_INSTANCES', payload: data.data || [] }) } } catch (error) { console.error('Failed to load vendor compliance data:', error) dispatch({ type: 'SET_ERROR', payload: 'Fehler beim Laden der Daten', }) } finally { dispatch({ type: 'SET_LOADING', payload: false }) } }, [dispatch]) const refresh = useCallback(async () => { await loadData() }, [loadData]) const createProcessingActivity = useCallback( async ( data: Omit ): Promise => { const response = await fetch(`${API_BASE}/processing-activities`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }) if (!response.ok) { const error = await response.json() throw new Error(error.error || 'Fehler beim Erstellen der Verarbeitungstätigkeit') } const result = await response.json() const activity = result.data dispatch({ type: 'ADD_PROCESSING_ACTIVITY', payload: activity }) return activity }, [dispatch] ) const deleteProcessingActivity = useCallback( async (id: string): Promise => { const response = await fetch(`${API_BASE}/processing-activities/${id}`, { method: 'DELETE', }) if (!response.ok) { const error = await response.json() throw new Error(error.error || 'Fehler beim Löschen der Verarbeitungstätigkeit') } dispatch({ type: 'DELETE_PROCESSING_ACTIVITY', payload: id }) }, [dispatch] ) const duplicateProcessingActivity = useCallback( async (id: string): Promise => { const original = state.processingActivities.find((a) => a.id === id) if (!original) { throw new Error('Verarbeitungstätigkeit nicht gefunden') } const { id: _id, vvtId: _vvtId, createdAt: _createdAt, updatedAt: _updatedAt, tenantId: _tenantId, ...rest } = original const newActivity = await createProcessingActivity({ ...rest, vvtId: '', name: { de: `${original.name.de} (Kopie)`, en: `${original.name.en} (Copy)`, }, status: 'DRAFT', }) return newActivity }, [state.processingActivities, createProcessingActivity] ) const deleteVendor = useCallback( async (id: string): Promise => { const response = await fetch(`${API_BASE}/vendors/${id}`, { method: 'DELETE', }) if (!response.ok) { const error = await response.json() throw new Error(error.error || 'Fehler beim Löschen des Vendors') } dispatch({ type: 'DELETE_VENDOR', payload: id }) }, [dispatch] ) const deleteContract = useCallback( async (id: string): Promise => { const contract = state.contracts.find((c) => c.id === id) const response = await fetch(`${API_BASE}/contracts/${id}`, { method: 'DELETE', }) if (!response.ok) { const error = await response.json() throw new Error(error.error || 'Fehler beim Löschen des Vertrags') } dispatch({ type: 'DELETE_CONTRACT', payload: id }) if (contract) { const vendor = state.vendors.find((v) => v.id === contract.vendorId) if (vendor) { dispatch({ type: 'UPDATE_VENDOR', payload: { id: vendor.id, data: { contracts: vendor.contracts.filter((cId) => cId !== id) }, }, }) } } }, [dispatch, state.contracts, state.vendors] ) const startContractReview = useCallback( async (contractId: string): Promise => { dispatch({ type: 'UPDATE_CONTRACT', payload: { id: contractId, data: { reviewStatus: 'IN_PROGRESS' } }, }) const response = await fetch(`${API_BASE}/contracts/${contractId}/review`, { method: 'POST', }) if (!response.ok) { dispatch({ type: 'UPDATE_CONTRACT', payload: { id: contractId, data: { reviewStatus: 'FAILED' } }, }) const error = await response.json() throw new Error(error.error || 'Fehler beim Starten der Vertragsprüfung') } const result = await response.json() dispatch({ type: 'UPDATE_CONTRACT', payload: { id: contractId, data: { reviewStatus: 'COMPLETED', reviewCompletedAt: new Date(), complianceScore: result.data.complianceScore, }, }, }) if (result.data.findings && result.data.findings.length > 0) { dispatch({ type: 'ADD_FINDINGS', payload: result.data.findings }) } }, [dispatch] ) return { loadData, refresh, createProcessingActivity, deleteProcessingActivity, duplicateProcessingActivity, deleteVendor, deleteContract, startContractReview, } }