'use server'; /** * Patient CRUD Server Actions (FHIR-based) * * Server-side actions that interact with FHIR Patient API */ import { revalidatePath } from 'next/cache'; import { headers, cookies } from 'next/headers'; import type { FHIRPatient, FHIRBundle } from '@/lib/fhir'; /** * Get the base URL for API calls in server actions * Uses headers() to get the host from the request */ function getBaseUrl(): string { // Try environment variable first if (process.env.NEXT_PUBLIC_APP_URL) { return process.env.NEXT_PUBLIC_APP_URL; } // Try to get from headers (works in server components/actions) try { const headersList = headers(); const host = headersList.get('host'); const protocol = headersList.get('x-forwarded-proto') || 'http'; if (host) { return `${protocol}://${host}`; } } catch { // Headers not available, fallback to localhost } // Fallback to localhost return 'http://localhost:3000'; } /** * Get cookies as a string for fetch headers */ async function getCookieHeader(): Promise { try { const cookieStore = await cookies(); return cookieStore .getAll() .map((cookie) => `${cookie.name}=${cookie.value}`) .join('; '); } catch { return ''; } } /** * Get all patients via FHIR API */ export async function getPatients(filters?: { search?: string; status?: string; gender?: string; page?: number; pageSize?: number; sortBy?: string; sortOrder?: 'asc' | 'desc'; }) { try { const baseUrl = getBaseUrl(); const url = new URL('/api/fhir/Patient', baseUrl); // Search filter if (filters?.search) { url.searchParams.set('name', filters.search); } // Status filter if (filters?.status) { url.searchParams.set('status', filters.status); } // Gender filter if (filters?.gender) { url.searchParams.set('gender', filters.gender); } // Pagination (default: 50 per page) const page = filters?.page || 1; const pageSize = filters?.pageSize || 50; url.searchParams.set('_count', pageSize.toString()); url.searchParams.set('_offset', ((page - 1) * pageSize).toString()); // Sorting if (filters?.sortBy) { const sortOrder = filters?.sortOrder === 'desc' ? '-' : ''; url.searchParams.set('_sort', `${sortOrder}${filters.sortBy}`); } // Get cookies to pass authentication const cookieHeader = await getCookieHeader(); const response = await fetch(url.toString(), { cache: 'no-store', headers: { 'Content-Type': 'application/json', ...(cookieHeader && { Cookie: cookieHeader }), }, }); if (!response.ok) { const errorText = await response.text(); let errorMessage = `Failed to fetch patients: ${response.status} ${response.statusText}`; // Check if we got HTML (likely a redirect to login) if (errorText.trim().startsWith(' = await response.json(); return { patients: bundle.entry?.map((entry) => entry.resource).filter(Boolean) as FHIRPatient[] || [], total: bundle.total || 0, page, pageSize, }; } catch (error) { console.error('Error fetching patients:', error); // Provide more context in error message if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('Kon geen verbinding maken met de server. Controleer of de applicatie draait.'); } throw error instanceof Error ? error : new Error('Failed to fetch patients'); } } /** * Get single patient by ID via FHIR API */ export async function getPatient(id: string) { try { const baseUrl = getBaseUrl(); const cookieHeader = await getCookieHeader(); const response = await fetch(`${baseUrl}/api/fhir/Patient/${id}`, { cache: 'no-store', headers: { ...(cookieHeader && { Cookie: cookieHeader }), }, }); if (!response.ok) { const errorText = await response.text(); // Check if we got HTML (likely a redirect to login) if (errorText.trim().startsWith('