migrated to react

This commit is contained in:
2026-03-27 22:15:50 +01:00
parent 11ac1e008f
commit 176f821598
24 changed files with 2281 additions and 888 deletions
+61
View File
@@ -0,0 +1,61 @@
import type { Post, SiteConfig, Asset } from './types';
function getToken(): string | null {
if (typeof window === 'undefined') return null;
return localStorage.getItem('admin_token');
}
async function apiFetch<T>(path: string, options: RequestInit = {}): Promise<T> {
const headers: Record<string, string> = {
...(options.headers as Record<string, string> || {}),
};
const token = getToken();
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
if (!(options.body instanceof FormData)) {
headers['Content-Type'] = headers['Content-Type'] || 'application/json';
}
const res = await fetch(`/api${path}`, { ...options, headers });
if (!res.ok) {
const body = await res.json().catch(() => ({}));
throw new ApiError(res.status, body.error || res.statusText);
}
const text = await res.text();
return text ? JSON.parse(text) : (undefined as T);
}
export class ApiError extends Error {
constructor(public status: number, message: string) {
super(message);
this.name = 'ApiError';
}
}
// Posts
export const getPosts = () => apiFetch<Post[]>('/posts');
export const getPost = (slug: string) => apiFetch<Post>(`/posts/${encodeURIComponent(slug)}`);
export const savePost = (data: { slug: string; old_slug?: string | null; summary?: string | null; content: string }) =>
apiFetch<Post>('/posts', { method: 'POST', body: JSON.stringify(data) });
export const deletePost = (slug: string) =>
apiFetch<void>(`/posts/${encodeURIComponent(slug)}`, { method: 'DELETE' });
// Config
export const getConfig = () => apiFetch<SiteConfig>('/config');
export const updateConfig = (data: Partial<SiteConfig>) =>
apiFetch<SiteConfig>('/config', { method: 'POST', body: JSON.stringify(data) });
// Assets
export const getAssets = () => apiFetch<Asset[]>('/uploads');
export const uploadAsset = (file: File) => {
const form = new FormData();
form.append('file', file);
return apiFetch<Asset>('/upload', { method: 'POST', body: form });
};
export const deleteAsset = (name: string) =>
apiFetch<void>(`/uploads/${encodeURIComponent(name)}`, { method: 'DELETE' });