feat: Add new Alpine.js component TypeScript files
Extracted inline JavaScript from templates into proper TypeScript modules: - api-explorer-docs.ts: API explorer page functionality - collection-rules.ts: Collection rules management page - index.ts: Homepage theme and auth redirect - login.ts: Login page theme initialization - profile-modal.ts: Profile modal close and escape key - profile.ts: Profile page delete account - register.ts: Registration page theme init - toast-error.ts: Error toast with retry button - unlinked_books.ts: Unlinked books management page Each file: - Uses ES imports (showToast, getToken, etc.) - Has proper TypeScript types - Registers with Alpine.js via Alpine.global() - Uses async/await for API calls
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
import { Alpine } from "./alpine";
|
||||
import { getToken } from "./storage";
|
||||
|
||||
let endpointPath = "";
|
||||
let exampleResponse: unknown = null;
|
||||
|
||||
function initAPIExplorerDoc(path: string, request: string, response: string): void {
|
||||
endpointPath = path;
|
||||
exampleResponse = JSON.parse(response);
|
||||
}
|
||||
|
||||
function showDocMode(mode: "mock" | "real"): void {
|
||||
const mockBtn = document.getElementById("mock-btn");
|
||||
const realBtn = document.getElementById("real-btn");
|
||||
const responseBody = document.getElementById("response-body");
|
||||
const responseStatus = document.getElementById("response-status");
|
||||
const responseTime = document.getElementById("response-time");
|
||||
const apiResponse = document.querySelector(".api-response");
|
||||
const requestBody = document.getElementById("request-body") as HTMLTextAreaElement;
|
||||
const tryItOut = document.getElementById("try-it-out");
|
||||
|
||||
if (!mockBtn || !realBtn || !responseBody || !responseStatus || !responseTime || !apiResponse || !requestBody || !tryItOut) return;
|
||||
|
||||
if (mode === "mock") {
|
||||
mockBtn.classList.add("bg-accent", "text-white");
|
||||
mockBtn.classList.remove("bg-background-primary", "text-text-primary");
|
||||
realBtn.classList.remove("bg-accent", "text-white");
|
||||
realBtn.classList.add("bg-background-primary", "text-text-primary");
|
||||
|
||||
apiResponse.classList.remove("hidden");
|
||||
requestBody.readOnly = true;
|
||||
tryItOut.classList.add("hidden");
|
||||
responseBody.textContent = JSON.stringify(exampleResponse, null, 2);
|
||||
responseStatus.textContent = "200 OK";
|
||||
responseTime.textContent = "Mock";
|
||||
} else {
|
||||
realBtn.classList.add("bg-accent", "text-white");
|
||||
realBtn.classList.remove("bg-background-primary", "text-text-primary");
|
||||
mockBtn.classList.remove("bg-accent", "text-white");
|
||||
mockBtn.classList.add("bg-background-primary", "text-text-primary");
|
||||
|
||||
apiResponse.classList.add("hidden");
|
||||
requestBody.readOnly = false;
|
||||
tryItOut.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
async function tryDocEndpoint(): Promise<void> {
|
||||
const methodSelect = document.getElementById("http-method") as HTMLSelectElement;
|
||||
const requestBody = document.getElementById("request-body") as HTMLTextAreaElement;
|
||||
const responseBody = document.getElementById("response-body");
|
||||
const responseStatus = document.getElementById("response-status");
|
||||
const responseTime = document.getElementById("response-time");
|
||||
const apiResponse = document.querySelector(".api-response");
|
||||
|
||||
if (!methodSelect || !requestBody || !responseBody || !responseStatus || !responseTime || !apiResponse) return;
|
||||
|
||||
const method = methodSelect.value;
|
||||
const body = requestBody.value;
|
||||
|
||||
const startTime = Date.now();
|
||||
try {
|
||||
const token = getToken();
|
||||
if (!token) {
|
||||
throw new Error("No authentication token found");
|
||||
}
|
||||
|
||||
const response = await fetch(endpointPath, {
|
||||
method: method,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: ["GET", "DELETE"].includes(method) ? undefined : body,
|
||||
});
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
const data = await response.json();
|
||||
|
||||
responseStatus.textContent = `${response.status} (${response.statusText})`;
|
||||
responseTime.textContent = `${duration}ms`;
|
||||
responseBody.textContent = JSON.stringify(data, null, 2);
|
||||
apiResponse.classList.remove("hidden");
|
||||
} catch (error) {
|
||||
responseStatus.textContent = "Error";
|
||||
responseBody.textContent = (error as Error).message;
|
||||
apiResponse.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
function copyDocRequest(): void {
|
||||
const requestBody = document.getElementById("request-body") as HTMLTextAreaElement;
|
||||
if (requestBody) {
|
||||
navigator.clipboard.writeText(requestBody.value);
|
||||
}
|
||||
}
|
||||
|
||||
function copyDocResponse(): void {
|
||||
const responseBody = document.getElementById("response-body");
|
||||
if (responseBody) {
|
||||
navigator.clipboard.writeText(responseBody.textContent || "");
|
||||
}
|
||||
}
|
||||
|
||||
function generateDocCURL(): void {
|
||||
const methodSelect = document.getElementById("http-method") as HTMLSelectElement;
|
||||
const requestBody = document.getElementById("request-body") as HTMLTextAreaElement;
|
||||
|
||||
if (!methodSelect || !requestBody) return;
|
||||
|
||||
const method = methodSelect.value;
|
||||
const body = requestBody.value;
|
||||
const token = getToken();
|
||||
|
||||
let curl = `curl -X ${method} \\n -H "Content-Type: application/json" \\n -H "Authorization: Bearer ${token}"`;
|
||||
|
||||
if (!["GET", "DELETE"].includes(method) && body.trim()) {
|
||||
curl += ` \\n -d '${body}'`;
|
||||
}
|
||||
|
||||
curl += ` \\n ${endpointPath}`;
|
||||
|
||||
navigator.clipboard.writeText(curl);
|
||||
}
|
||||
|
||||
export {
|
||||
copyDocRequest,
|
||||
copyDocResponse,
|
||||
generateDocCURL,
|
||||
initAPIExplorerDoc,
|
||||
showDocMode,
|
||||
tryDocEndpoint,
|
||||
};
|
||||
|
||||
Alpine.global("apiExplorerDoc", {
|
||||
copyDocRequest,
|
||||
copyDocResponse,
|
||||
generateDocCURL,
|
||||
initAPIExplorerDoc,
|
||||
showDocMode,
|
||||
tryDocEndpoint,
|
||||
});
|
||||
Reference in New Issue
Block a user