mirror of
https://git.victorphan.net/basketballcantho/ten-project.git
synced 2026-08-05 13:03:10 +07:00
hoàn thành bước3.2. PDF Gallery (Dashboard)
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Thin fetch wrapper — always sends cookies (HttpOnly JWT).
|
||||
* All paths are relative so Next.js rewrites proxy them to the backend.
|
||||
*/
|
||||
|
||||
async function request<T>(path: string, init: RequestInit = {}): Promise<T> {
|
||||
const res = await fetch(path, {
|
||||
...init,
|
||||
credentials: "include",
|
||||
headers: {
|
||||
...(init.body instanceof FormData ? {} : { "Content-Type": "application/json" }),
|
||||
...init.headers,
|
||||
},
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const detail = await res.json().catch(() => ({ detail: res.statusText }));
|
||||
throw new Error(detail?.detail ?? "Request failed");
|
||||
}
|
||||
|
||||
if (res.status === 204) return undefined as T;
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export const api = {
|
||||
// Auth
|
||||
me: () => request<import("@/types").User>("/api/auth/me"),
|
||||
login: (body: { username: string; password: string }) =>
|
||||
request<import("@/types").User>("/api/auth/login", { method: "POST", body: JSON.stringify(body) }),
|
||||
register: (body: { username: string; email: string; password: string }) =>
|
||||
request<import("@/types").User>("/api/auth/register", { method: "POST", body: JSON.stringify(body) }),
|
||||
logout: () => request<void>("/api/auth/logout", { method: "POST" }),
|
||||
|
||||
// PDFs
|
||||
listPdfs: () => request<import("@/types").PDFItem[]>("/api/pdfs"),
|
||||
uploadPdfs: (formData: FormData) =>
|
||||
request<import("@/types").PDFUploadResult[]>("/api/pdfs/upload", { method: "POST", body: formData }),
|
||||
deletePdf: (id: number) => request<void>(`/api/pdfs/${id}`, { method: "DELETE" }),
|
||||
};
|
||||
Reference in New Issue
Block a user