(function () { function getToken() { return localStorage.getItem("access_token") || ""; } function authHeaders(extra) { var headers = extra || {}; var token = getToken(); if (token) { headers.Authorization = "Bearer " + token; } return headers; } async function loadSkills() { var grid = document.getElementById("skill-grid"); if (!grid) return; var res = await fetch("/api/skills", { headers: authHeaders() }); if (!res.ok) { grid.innerHTML = '

Set `access_token` in localStorage with a valid OIDC JWT.

'; return; } var data = await res.json(); grid.innerHTML = ""; data.skills.forEach(function (s) { var card = document.createElement("article"); card.className = "card"; card.innerHTML = "

" + escapeHtml(s.title) + "

" + "

" + escapeHtml(s.description) + "

" + "

Seller: " + escapeHtml(s.owner_email || "unknown") + "

" + "

$" + (s.price_cents / 100).toFixed(2) + "

" + ""; grid.appendChild(card); }); grid.querySelectorAll("[data-skill-id]").forEach(function (btn) { btn.addEventListener("click", onBuy); }); } async function onBuy(event) { var skillId = event.currentTarget.getAttribute("data-skill-id"); var body = new URLSearchParams(); body.set("skill_id", skillId); var res = await fetch("/api/purchase", { method: "POST", headers: authHeaders({ "Content-Type": "application/x-www-form-urlencoded" }), body: body.toString() }); if (!res.ok) { alert("Purchase failed."); return; } window.location.href = "/purchase"; } async function loadMySkills() { var grid = document.getElementById("my-skill-grid"); if (!grid) return; var res = await fetch("/api/my-skills", { headers: authHeaders() }); if (!res.ok) { grid.innerHTML = '

Set `access_token` in localStorage with a valid OIDC JWT.

'; return; } var data = await res.json(); grid.innerHTML = ""; data.skills.forEach(function (s) { var card = document.createElement("article"); card.className = "card"; card.innerHTML = "

" + escapeHtml(s.title) + "

" + "

" + escapeHtml(s.description) + "

" + "

Purchased from: " + escapeHtml(s.owner_email || "unknown") + "

" + "
" + "Download" + "" + "
"; grid.appendChild(card); }); grid.querySelectorAll("[data-copy-id]").forEach(function (btn) { btn.addEventListener("click", function (event) { var id = event.currentTarget.getAttribute("data-copy-id"); var link = window.location.origin + "/uploads/" + id; navigator.clipboard.writeText(link); event.currentTarget.textContent = "Copied"; }); }); } function uploadInit() { var form = document.getElementById("upload-form"); if (!form) return; var status = document.getElementById("upload-status"); form.addEventListener("submit", async function (event) { event.preventDefault(); var data = new FormData(form); var res = await fetch("/api/upload", { method: "POST", headers: authHeaders(), body: data }); if (!res.ok) { status.textContent = "Upload failed. Check token and required fields."; return; } status.textContent = "Upload complete. Your skill is live in the marketplace."; form.reset(); }); } function escapeHtml(value) { return String(value || "") .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } uploadInit(); loadSkills(); loadMySkills(); })();