export interface Meme { id: string; title: string; description: string | null; file_path: string; file_name: string; file_size: number; mime_type: string; width: number; height: number; parent_id: string | null; created_at: string; tags: string[]; children?: Meme[]; } export interface Tag { id: number; name: string; meme_count: number; } export interface MemesResponse { memes: Meme[]; total: number; page: number; limit: number; } export interface ListParams { tag?: string; q?: string; page?: number; limit?: number; parent_only?: boolean; } async function apiFetch(url: string, init?: RequestInit): Promise { const res = await fetch(url, init); if (!res.ok) { const err = await res.json().catch(() => ({ error: res.statusText })); throw new Error(err.error ?? res.statusText); } return res.json() as Promise; } export const api = { memes: { list(params: ListParams = {}): Promise { const qs = new URLSearchParams(); if (params.tag) qs.set('tag', params.tag); if (params.q) qs.set('q', params.q); if (params.page) qs.set('page', String(params.page)); if (params.limit) qs.set('limit', String(params.limit)); if (params.parent_only !== undefined) qs.set('parent_only', String(params.parent_only)); return apiFetch(`/api/memes?${qs}`); }, get(id: string): Promise { return apiFetch(`/api/memes/${id}`); }, upload(formData: FormData): Promise { return apiFetch('/api/memes', { method: 'POST', body: formData }); }, update(id: string, body: { title?: string; description?: string; tags?: string[] }): Promise { return apiFetch(`/api/memes/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); }, delete(id: string): Promise<{ ok: boolean }> { return apiFetch(`/api/memes/${id}`, { method: 'DELETE' }); }, rescale(id: string, body: { width?: number; height?: number; quality?: number; label?: string }): Promise { return apiFetch(`/api/memes/${id}/rescale`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); }, }, tags: { list(): Promise { return apiFetch('/api/tags'); }, delete(id: number): Promise<{ ok: boolean }> { return apiFetch(`/api/tags/${id}`, { method: 'DELETE' }); }, }, imageUrl(filePath: string): string { return `/images/${filePath}`; }, };