build 1
This commit is contained in:
101
frontend/src/api/client.ts
Normal file
101
frontend/src/api/client.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
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<T>(url: string, init?: RequestInit): Promise<T> {
|
||||
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<T>;
|
||||
}
|
||||
|
||||
export const api = {
|
||||
memes: {
|
||||
list(params: ListParams = {}): Promise<MemesResponse> {
|
||||
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<MemesResponse>(`/api/memes?${qs}`);
|
||||
},
|
||||
|
||||
get(id: string): Promise<Meme & { children: Meme[] }> {
|
||||
return apiFetch(`/api/memes/${id}`);
|
||||
},
|
||||
|
||||
upload(formData: FormData): Promise<Meme> {
|
||||
return apiFetch('/api/memes', { method: 'POST', body: formData });
|
||||
},
|
||||
|
||||
update(id: string, body: { title?: string; description?: string; tags?: string[] }): Promise<Meme> {
|
||||
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<Meme> {
|
||||
return apiFetch(`/api/memes/${id}/rescale`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
tags: {
|
||||
list(): Promise<Tag[]> {
|
||||
return apiFetch('/api/tags');
|
||||
},
|
||||
|
||||
delete(id: number): Promise<{ ok: boolean }> {
|
||||
return apiFetch(`/api/tags/${id}`, { method: 'DELETE' });
|
||||
},
|
||||
},
|
||||
|
||||
imageUrl(filePath: string): string {
|
||||
return `/images/${filePath}`;
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user