client.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. const BASE = `${import.meta.env.BASE_URL}api/v1`.replace(/\/+$/, "");
  2. async function request<T>(url: string, options?: RequestInit): Promise<T> {
  3. const res = await fetch(`${BASE}${url}`, {
  4. headers: { "Content-Type": "application/json" },
  5. ...options,
  6. });
  7. if (!res.ok) {
  8. const body = await res.json().catch(() => ({}));
  9. throw new Error(body.error?.message || `HTTP ${res.status}`);
  10. }
  11. return res.json();
  12. }
  13. export const api = {
  14. // Templates
  15. getTemplates: () => request<{ data: any[] }>("/templates"),
  16. getTemplate: (id: string) => request<{ data: any }>(`/templates/${id}`),
  17. // Creatives
  18. getCreatives: (params?: { status?: string }) => {
  19. const qs = params ? "?" + new URLSearchParams(params).toString() : "";
  20. return request<{ data: any[] }>(`/creatives${qs}`);
  21. },
  22. createCreative: (body: { name: string; templateId: string }) =>
  23. request<{ data: any }>("/creatives", {
  24. method: "POST",
  25. body: JSON.stringify(body),
  26. }),
  27. getCreative: (id: string) => request<{ data: any }>(`/creatives/${id}`),
  28. updateCreative: (id: string, body: { name?: string; theme?: Record<string, string> }) =>
  29. request<{ data: any }>(`/creatives/${id}`, {
  30. method: "PATCH",
  31. body: JSON.stringify(body),
  32. }),
  33. deleteCreative: (id: string) =>
  34. request<{ data: any }>(`/creatives/${id}`, { method: "DELETE" }),
  35. // Assets
  36. uploadAssets: (creativeId: string, file: File) => {
  37. const formData = new FormData();
  38. formData.append("file", file);
  39. return fetch(`${BASE}/creatives/${creativeId}/assets/upload`, {
  40. method: "POST",
  41. body: formData,
  42. }).then((res) => {
  43. if (!res.ok) return res.json().then((b) => { throw new Error(b.error?.message); });
  44. return res.json();
  45. });
  46. },
  47. importFromUrl: (creativeId: string, url: string) =>
  48. request<{ data: any }>(`/creatives/${creativeId}/assets/upload`, {
  49. method: "POST",
  50. body: JSON.stringify({ url }),
  51. }),
  52. clearAssets: (creativeId: string) =>
  53. request<{ data: any }>(`/creatives/${creativeId}/assets`, { method: "DELETE" }),
  54. // Preview
  55. startPreview: (creativeId: string, theme?: Record<string, string>) =>
  56. request<{ data: { url: string } }>(`/creatives/${creativeId}/preview/start`, {
  57. method: "POST",
  58. body: theme ? JSON.stringify({ theme }) : undefined,
  59. }),
  60. stopPreview: (creativeId: string) =>
  61. request<{ data: any }>(`/creatives/${creativeId}/preview/stop`, { method: "POST" }),
  62. // Builds
  63. triggerBuild: (creativeId: string, body: { platforms: string[]; theme: Record<string, string> }) =>
  64. request<{ data: any }>(`/creatives/${creativeId}/builds`, {
  65. method: "POST",
  66. body: JSON.stringify(body),
  67. }),
  68. getBuilds: (creativeId: string) =>
  69. request<{ data: any[] }>(`/creatives/${creativeId}/builds`),
  70. getBuildStatus: (buildId: string) =>
  71. request<{ data: any }>(`/builds/${buildId}/status`),
  72. };