- Add centralized API type definitions (types/api.d.ts) - Interfaces for all API responses matching Go handler JSON - Snake_case field names matching actual API responses - Source file references in comments for verification - Add API client module (api.ts) - Procedural get/post/put/delete functions - Automatic auth header injection - Exported to window for cross-module access - Add DOM utilities (dom.ts) - escapeHtml for safe HTML rendering - querySelector wrappers with null checks - Element creation helpers - Add event delegation helpers (events.ts) - Reusable event delegation pattern - Data attribute selectors for dynamic content - Add localStorage wrapper (storage.ts) - Type-safe token management - Theme persistence helpers
102 lines
2.6 KiB
TypeScript
102 lines
2.6 KiB
TypeScript
function getAuthHeader(): string {
|
|
const token = localStorage.getItem('token');
|
|
return token ? `Bearer ${token}` : '';
|
|
}
|
|
|
|
async function apiGet(url: string): Promise<Response> {
|
|
return fetch(`/api${url}`, {
|
|
headers: {
|
|
'Authorization': getAuthHeader(),
|
|
'Content-Type': 'application/json'
|
|
}
|
|
});
|
|
}
|
|
|
|
async function apiPost(url: string, data?: unknown): Promise<Response> {
|
|
return fetch(`/api${url}`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': getAuthHeader(),
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: data ? JSON.stringify(data) : undefined
|
|
});
|
|
}
|
|
|
|
async function apiPut(url: string, data?: unknown): Promise<Response> {
|
|
return fetch(`/api${url}`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'Authorization': getAuthHeader(),
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: data ? JSON.stringify(data) : undefined
|
|
});
|
|
}
|
|
|
|
async function apiDelete(url: string): Promise<Response> {
|
|
return fetch(`/api${url}`, {
|
|
method: 'DELETE',
|
|
headers: {
|
|
'Authorization': getAuthHeader()
|
|
}
|
|
});
|
|
}
|
|
|
|
async function apiPatch(url: string, data?: unknown): Promise<Response> {
|
|
return fetch(`/api${url}`, {
|
|
method: 'PATCH',
|
|
headers: {
|
|
'Authorization': getAuthHeader(),
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: data ? JSON.stringify(data) : undefined
|
|
});
|
|
}
|
|
|
|
async function handleResponse<T>(response: Response): Promise<T> {
|
|
if (!response.ok) {
|
|
const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
throw new Error(errorData.error || `HTTP ${response.status}`);
|
|
}
|
|
return response.json();
|
|
}
|
|
|
|
async function handleVoidResponse(response: Response): Promise<void> {
|
|
if (!response.ok) {
|
|
const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
throw new Error(errorData.error || `HTTP ${response.status}`);
|
|
}
|
|
}
|
|
|
|
function handleError(error: unknown, context: string): void {
|
|
console.error(`${context}:`, error);
|
|
const message = error instanceof Error ? error.message : 'An unexpected error occurred';
|
|
if ((window as any).showToast?.error) {
|
|
(window as any).showToast.error(message);
|
|
}
|
|
}
|
|
|
|
(window as any).api = {
|
|
get: apiGet,
|
|
post: apiPost,
|
|
put: apiPut,
|
|
delete: apiDelete,
|
|
patch: apiPatch,
|
|
handleResponse,
|
|
handleVoidResponse,
|
|
handleError
|
|
};
|
|
|
|
export {
|
|
getAuthHeader,
|
|
apiGet,
|
|
apiPost,
|
|
apiPut,
|
|
apiDelete,
|
|
apiPatch,
|
|
handleResponse,
|
|
handleVoidResponse,
|
|
handleError
|
|
};
|