/** * Typed API functions for Fotos (GerbilPhoto). (FEAT-6) * * Contract (FEAT-1b Phase 2, Pam): * GET /gerbils/{id}/photos -> [{id, fileName, caption, sortOrder, url}] * POST /gerbils/{id}/photos -> multipart, Feld 'file' (+ optional 'caption') * DELETE /photos/{id} * Erstes Foto nach sortOrder = Profilfoto. * * Der Upload geht NICHT über api.post (das setzt Content-Type: application/json); * bei FormData muss der Browser den multipart-Boundary-Header selbst setzen. */ import { API_BASE_URL, ApiError, api } from './client' import { de } from '../strings/de' export interface GerbilPhoto { id: string fileName: string caption: string | null sortOrder: number /** Absoluter oder API-relativer Pfad zur Bilddatei. */ url: string } export function listGerbilPhotos(gerbilId: string): Promise { return api.get(`/gerbils/${gerbilId}/photos`) } export async function uploadGerbilPhoto( gerbilId: string, file: File, caption: string | null, ): Promise { const form = new FormData() form.append('file', file) if (caption) form.append('caption', caption) let response: Response try { response = await fetch(`${API_BASE_URL}/gerbils/${gerbilId}/photos`, { method: 'POST', body: form, }) } catch { throw new ApiError(de.api.errors.network, null) } if (!response.ok) { const message = response.status === 404 ? de.api.errors.notFound : response.status >= 500 ? de.api.errors.server : de.api.errors.unknown throw new ApiError(message, response.status) } return (await response.json()) as GerbilPhoto } export function deleteGerbilPhoto(photoId: string): Promise { return api.delete(`/photos/${photoId}`) } /** Bild-URL auflösen: API liefert ggf. einen API-relativen Pfad. */ export function photoSrc(photo: GerbilPhoto): string { return photo.url.startsWith('http') ? photo.url : `${API_BASE_URL}${photo.url}` } /** Profilfoto = erstes Foto nach sortOrder (null, wenn keine Fotos). */ export function profilePhoto(photos: GerbilPhoto[]): GerbilPhoto | null { if (photos.length === 0) return null return [...photos].sort((a, b) => a.sortOrder - b.sortOrder)[0] }