41 lines
2.2 KiB
TypeScript
41 lines
2.2 KiB
TypeScript
import type { AuthorData, AuthorProfile, LegalDocument } from "../types";
|
|
|
|
export class AdminApiError extends Error {
|
|
constructor(message: string, public readonly status: number) {
|
|
super(message);
|
|
}
|
|
}
|
|
|
|
async function request<T>(url: string, init?: RequestInit): Promise<T> {
|
|
const response = await fetch(url, init);
|
|
const payload = await response.json().catch(() => ({})) as { error?: string };
|
|
if (!response.ok) {
|
|
if (response.status === 401 && url !== "/api/admin/login") window.dispatchEvent(new Event("admin-session-expired"));
|
|
throw new AdminApiError(payload.error || `Anfrage fehlgeschlagen (HTTP ${response.status}).`, response.status);
|
|
}
|
|
return payload as T;
|
|
}
|
|
|
|
const jsonPost = (body: unknown): RequestInit => ({
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(body),
|
|
});
|
|
|
|
export const adminApi = {
|
|
session: () => request<{ success: true }>("/api/admin/session"),
|
|
login: (password: string) => request<{ success: true }>("/api/admin/login", jsonPost({ password })),
|
|
logout: () => request<{ success: true }>("/api/admin/logout", { method: "POST" }),
|
|
loadData: () => request<AuthorData>("/api/admin/author-data"),
|
|
saveProfile: (profileKey: "scifi" | "erotica" | "clara" | "renee", profileData: AuthorProfile, expectedRevision: number) =>
|
|
request<{ success: true; revision: number }>("/api/admin/save-profile", jsonPost({ profileKey, profileData, expectedRevision })),
|
|
saveLegal: (legalDocuments: LegalDocument[], expectedRevision: number) =>
|
|
request<{ success: true; revision: number }>("/api/admin/save-legal", jsonPost({ legalDocuments, expectedRevision })),
|
|
generateBlurb: (input: { title: string; genre: string; ideas: string; tone: string }) =>
|
|
request<{ success: true; text: string }>("/api/admin/generate-blurb", jsonPost(input)),
|
|
listUploads: () => request<{ success: true; files: Array<{ name: string; url: string }> }>("/api/admin/list-uploads"),
|
|
upload: (fileName: string, base64Data: string) =>
|
|
request<{ success: true; url: string }>("/api/admin/upload-file", jsonPost({ fileName, base64Data })),
|
|
deleteUpload: (name: string) =>
|
|
request<{ success: true }>(`/api/admin/uploads/${encodeURIComponent(name)}`, { method: "DELETE" }),
|
|
};
|