import { api } from "./api"; import { env } from "./env"; /** * Client API typé pour l'admin du blog. Toutes les routes nécessitent * `auth + is_admin` côté serveur (cf. apps/api/start/routes.ts). */ export type PostStatus = "draft" | "published"; export type AdminPost = { id: string; slug: string; title: string; excerpt: string; contentMd: string; contentHtml: string; authorName: string; tags: string[]; status: PostStatus; publishedAt: string | null; heroImageUrl: string | null; heroImageAlt: string | null; ogImageUrl: string | null; canonicalUrl: string | null; noindex: boolean; wordCount: number; readingTimeMinutes: number; createdAt: string; updatedAt: string | null; }; export type CreatePostInput = { slug: string; title: string; excerpt: string; contentMd: string; tags?: string[]; authorName?: string; heroImageUrl?: string | null; heroImageAlt?: string | null; ogImageUrl?: string | null; canonicalUrl?: string | null; noindex?: boolean; }; export type UpdatePostInput = Partial; export type UploadResult = { /** URL publique relative (ex: /api/v1/uploads/blog/{uuid}.jpg) — préfixée par VITE_API_URL pour usage navigateur. */ url: string; contentType: string; sizeBytes: number; }; /** Renvoie l'URL absolue exploitable côté navigateur depuis une URL relative API. */ export function absolutizeApiUrl(relativeOrAbsolute: string): string { if (!relativeOrAbsolute) return relativeOrAbsolute; if (relativeOrAbsolute.startsWith("http")) return relativeOrAbsolute; return `${env.VITE_API_URL}${relativeOrAbsolute}`; } export const adminBlogApi = { list: () => api.get("/api/v1/admin/posts"), get: (id: string) => api.get(`/api/v1/admin/posts/${id}`), create: (input: CreatePostInput) => api.post("/api/v1/admin/posts", input), update: (id: string, input: UpdatePostInput) => api.patch(`/api/v1/admin/posts/${id}`, input), publish: (id: string) => api.post(`/api/v1/admin/posts/${id}/publish`, {}), unpublish: (id: string) => api.post(`/api/v1/admin/posts/${id}/unpublish`, {}), delete: (id: string) => api.delete(`/api/v1/admin/posts/${id}`), suggestSlug: (title: string) => api.get<{ slug: string }>(`/api/v1/admin/posts/suggest-slug?title=${encodeURIComponent(title)}`), uploadImage: async (file: File): Promise => { const form = new FormData(); form.append("file", file); return api.post("/api/v1/admin/uploads", form); }, }; export const adminBlogQueryKeys = { all: () => ["admin", "blog"] as const, list: () => ["admin", "blog", "list"] as const, detail: (id: string) => ["admin", "blog", "detail", id] as const, };