document.addEventListener("DOMContentLoaded", () => { const profilesButton = document.getElementById("profiles-btn"); const profilesModal = document.getElementById("profiles-modal"); const profilesCloseButton = document.getElementById("profiles-close-btn"); const profilesList = document.getElementById("profiles-list"); const newProfileInput = document.getElementById("new-profile-name"); const createProfileButton = document.getElementById("create-profile-btn"); if (!profilesButton || !profilesModal || !profilesList) { return; } const openModal = () => { profilesModal.classList.add("active"); loadProfiles(); }; const closeModal = () => { profilesModal.classList.remove("active"); }; const renderProfiles = (profiles, currentProfileId) => { profilesList.innerHTML = ""; let entries = []; if (Array.isArray(profiles)) { entries = profiles.map((profileId) => [profileId, {}]); } else if (profiles && typeof profiles === "object") { // Make sure we're iterating over profile entries, not metadata entries = Object.entries(profiles).filter(([key]) => { // Skip metadata keys like 'current_profile_id' if they exist return key !== 'current_profile_id' && key !== 'profiles'; }); } if (entries.length === 0) { const empty = document.createElement("p"); empty.className = "muted-text"; empty.textContent = "No profiles found."; profilesList.appendChild(empty); return; } entries.forEach(([profileId, profile]) => { const row = document.createElement("div"); row.className = "profiles-row"; const label = document.createElement("span"); label.textContent = (profile && profile.name) || profileId; if (String(profileId) === String(currentProfileId)) { label.textContent = `✓ ${label.textContent}`; label.style.fontWeight = "bold"; label.style.color = "#FFD700"; } const applyButton = document.createElement("button"); applyButton.className = "btn btn-secondary btn-small profiles-apply-btn"; applyButton.textContent = "Apply"; applyButton.addEventListener("click", async () => { try { const response = await fetch(`/profiles/${profileId}/apply`, { method: "POST", headers: { Accept: "application/json" }, }); if (!response.ok) { throw new Error("Failed to apply profile"); } await loadProfiles(); document.body.dispatchEvent(new Event("tabs-updated")); } catch (error) { console.error("Apply profile failed:", error); alert("Failed to apply profile."); } }); const cloneButton = document.createElement("button"); cloneButton.className = "btn btn-secondary btn-small"; cloneButton.textContent = "Clone"; cloneButton.addEventListener("click", async () => { const baseName = (profile && profile.name) || profileId; const suggested = `${baseName}`; const name = prompt("New profile name:", suggested); if (name === null) { return; } const trimmed = String(name).trim(); if (!trimmed) { alert("Profile name cannot be empty."); return; } try { const response = await fetch(`/profiles/${profileId}/clone`, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: JSON.stringify({ name: trimmed }), }); if (!response.ok) { throw new Error("Failed to clone profile"); } const data = await response.json().catch(() => null); let newProfileId = null; if (data && typeof data === "object") { if (data.id) { newProfileId = String(data.id); } else { const ids = Object.keys(data); if (ids.length > 0) { newProfileId = String(ids[0]); } } } if (newProfileId) { await fetch(`/profiles/${newProfileId}/apply`, { method: "POST", headers: { Accept: "application/json" }, }); } document.cookie = "current_tab=; path=/; max-age=0"; await loadProfiles(); if (typeof window.loadTabs === "function") { await window.loadTabs(); } if (typeof window.loadTabsModal === "function") { await window.loadTabsModal(); } const tabContent = document.getElementById("tab-content"); if (tabContent) { tabContent.innerHTML = `
Select a tab to get started
`; } } catch (error) { console.error("Clone profile failed:", error); alert("Failed to clone profile."); } }); const deleteButton = document.createElement("button"); deleteButton.className = "btn btn-danger btn-small"; deleteButton.textContent = "Delete"; deleteButton.addEventListener("click", async () => { const confirmed = confirm(`Delete profile "${label.textContent}"?`); if (!confirmed) { return; } try { const response = await fetch(`/profiles/${profileId}`, { method: "DELETE", headers: { Accept: "application/json" }, }); if (!response.ok) { throw new Error("Failed to delete profile"); } await loadProfiles(); } catch (error) { console.error("Delete profile failed:", error); alert("Failed to delete profile."); } }); row.appendChild(label); row.appendChild(applyButton); row.appendChild(cloneButton); row.appendChild(deleteButton); profilesList.appendChild(row); }); }; const loadProfiles = async () => { profilesList.innerHTML = ""; const loading = document.createElement("p"); loading.className = "muted-text"; loading.textContent = "Loading profiles..."; profilesList.appendChild(loading); try { const response = await fetch("/profiles", { headers: { Accept: "application/json" }, }); if (!response.ok) { throw new Error("Failed to load profiles"); } const data = await response.json(); // Handle both old format (just profiles object) and new format (with current_profile_id) const profiles = data.profiles || data; const currentProfileId = data.current_profile_id || null; renderProfiles(profiles, currentProfileId); } catch (error) { console.error("Load profiles failed:", error); profilesList.innerHTML = ""; const errorMessage = document.createElement("p"); errorMessage.className = "muted-text"; errorMessage.textContent = "Failed to load profiles."; profilesList.appendChild(errorMessage); } }; const createProfile = async () => { if (!newProfileInput) { return; } const name = newProfileInput.value.trim(); if (!name) { alert("Profile name cannot be empty."); return; } try { const response = await fetch("/profiles", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name }), }); if (!response.ok) { throw new Error("Failed to create profile"); } const data = await response.json().catch(() => null); let newProfileId = null; if (data && typeof data === "object") { if (data.id) { newProfileId = String(data.id); } else { const ids = Object.keys(data); if (ids.length > 0) { newProfileId = String(ids[0]); } } } if (newProfileId) { await fetch(`/profiles/${newProfileId}/apply`, { method: "POST", headers: { Accept: "application/json" }, }); } newProfileInput.value = ""; // Clear current tab and refresh the UI so the new profile starts empty. document.cookie = "current_tab=; path=/; max-age=0"; await loadProfiles(); if (typeof window.loadTabs === "function") { await window.loadTabs(); } if (typeof window.loadTabsModal === "function") { await window.loadTabsModal(); } const tabContent = document.getElementById("tab-content"); if (tabContent) { tabContent.innerHTML = `
Select a tab to get started
`; } } catch (error) { console.error("Create profile failed:", error); alert("Failed to create profile."); } }; profilesButton.addEventListener("click", openModal); if (profilesCloseButton) { profilesCloseButton.addEventListener("click", closeModal); } if (createProfileButton) { createProfileButton.addEventListener("click", createProfile); } if (newProfileInput) { newProfileInput.addEventListener("keypress", (event) => { if (event.key === "Enter") { createProfile(); } }); } profilesModal.addEventListener("click", (event) => { if (event.target === profilesModal) { closeModal(); } }); });