Frontend : squelette React + Vite + TS + Tailwind
Scaffold de base en attendant l'intégration du design Claude Design (« Bénévoles Festival.dc.html ») : routage, plomberie i18n (t() + locales/fr.json), client API avec proxy Vite vers le backend. Build et lint passent. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AwswqSChc3Rwtu61pRXiY2
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
49ac6a4726
commit
5154a3c61b
@@ -0,0 +1,42 @@
|
||||
// Client HTTP minimal. En dev, Vite proxifie `/api` vers le backend (:8000).
|
||||
const BASE_URL = import.meta.env.VITE_API_BASE_URL ?? '/api';
|
||||
|
||||
export class ApiError extends Error {
|
||||
constructor(
|
||||
public readonly status: number,
|
||||
public readonly body: unknown,
|
||||
) {
|
||||
super(`API ${status}`);
|
||||
this.name = 'ApiError';
|
||||
}
|
||||
}
|
||||
|
||||
async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${BASE_URL}${path}`, {
|
||||
...init,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...init?.headers,
|
||||
},
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
const isJson = res.headers.get('content-type')?.includes('application/json');
|
||||
const body = isJson ? await res.json() : await res.text();
|
||||
|
||||
if (!res.ok) {
|
||||
throw new ApiError(res.status, body);
|
||||
}
|
||||
return body as T;
|
||||
}
|
||||
|
||||
export const api = {
|
||||
get: <T>(path: string) => request<T>(path),
|
||||
post: <T>(path: string, data?: unknown) =>
|
||||
request<T>(path, { method: 'POST', body: data === undefined ? undefined : JSON.stringify(data) }),
|
||||
patch: <T>(path: string, data?: unknown) =>
|
||||
request<T>(path, { method: 'PATCH', body: data === undefined ? undefined : JSON.stringify(data) }),
|
||||
put: <T>(path: string, data?: unknown) =>
|
||||
request<T>(path, { method: 'PUT', body: data === undefined ? undefined : JSON.stringify(data) }),
|
||||
delete: <T>(path: string) => request<T>(path, { method: 'DELETE' }),
|
||||
};
|
||||
Reference in New Issue
Block a user