import { Alpine } from "./alpine"; import { showToast } from "./toast"; function getAuthHeader(): string { const token = localStorage.getItem("token"); return token ? `Bearer ${token}` : ""; } async function apiGet(url: string): Promise { return fetch(`/api${url}`, { headers: { Authorization: getAuthHeader(), "Content-Type": "application/json", }, }); } async function apiPost(url: string, data?: unknown): Promise { 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 { return fetch(`/api${url}`, { method: "PUT", headers: { Authorization: getAuthHeader(), "Content-Type": "application/json", }, body: data ? JSON.stringify(data) : undefined, }); } async function apiDelete( url: string, data?: T, ): Promise { return fetch(`/api${url}`, { method: "DELETE", headers: { Authorization: getAuthHeader(), "Content-Type": "application/json", }, body: data ? JSON.stringify(data) : undefined, }); } async function apiPatch(url: string, data?: unknown): Promise { return fetch(`/api${url}`, { method: "PATCH", headers: { Authorization: getAuthHeader(), "Content-Type": "application/json", }, body: data ? JSON.stringify(data) : undefined, }); } async function handleResponse(response: Response): Promise { 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 { 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"; showToast(message, "error"); } // ============================================================ // Reader API Functions // ============================================================ interface ReadingProgress { current_page: number; total_pages: number; cfi?: string; percentage?: number; last_read_at: string; } async function getReaderMetadata(mediaItemId: string): Promise { const response = await apiGet(`/media-items/${mediaItemId}`); return handleResponse(response); } async function updateReadingProgress( mediaItemId: string, progress: ReadingProgress, ): Promise { const response = await apiPut( `/media-items/${mediaItemId}/progress`, progress, ); await handleVoidResponse(response); } async function getReadingProgress( mediaItemId: string, ): Promise { const response = await apiGet(`/media-items/${mediaItemId}/progress`); if (response.status === 404) { return null; } return handleResponse(response); } export { apiGet, apiPost, apiPut, apiDelete, apiPatch, handleResponse, handleVoidResponse, handleError, getReaderMetadata, getReadingProgress, // ADD THIS updateReadingProgress, ReadingProgress, }; Alpine.data("api", () => ({ get: apiGet, post: apiPost, put: apiPut, delete: apiDelete, patch: apiPatch, handleResponse: handleResponse, handleVoidResponse: handleVoidResponse, handleError: handleError, }));