const API_BASE = "http://127.0.0.1:5000/api";
const THEME_STORAGE_KEY = "journey-theme";
const DEFAULT_THEME = "dark";
const VALID_THEMES = ["dark", "light", "system"];
let currentUser = null;
function getThemePreference() {
const storedTheme = localStorage.getItem(THEME_STORAGE_KEY);
return VALID_THEMES.includes(storedTheme) ? storedTheme : DEFAULT_THEME;
}
function applyThemePreference(theme = getThemePreference()) {
const selectedTheme = VALID_THEMES.includes(theme) ? theme : DEFAULT_THEME;
document.documentElement.dataset.theme = selectedTheme;
}
function setThemePreference(theme) {
const selectedTheme = VALID_THEMES.includes(theme) ? theme : DEFAULT_THEME;
localStorage.setItem(THEME_STORAGE_KEY, selectedTheme);
applyThemePreference(selectedTheme);
}
function getThemeControlHtml() {
return `
`;
}
function attachThemeControl(root = document) {
const select = root.querySelector("#theme-select");
if (!select) return;
select.value = getThemePreference();
select.addEventListener("change", () => setThemePreference(select.value));
}
function ensureStandaloneThemeControl() {
if (document.getElementById("user-menu") || document.getElementById("theme-switcher-floating")) return;
const container = document.createElement("div");
container.id = "theme-switcher-floating";
container.className = "theme-switcher-floating";
container.innerHTML = getThemeControlHtml();
document.body.appendChild(container);
attachThemeControl(container);
}
applyThemePreference();
async function checkAuth() {
try {
const res = await fetch(`${API_BASE}/me`, { credentials: "include" });
if (res.ok) {
currentUser = await res.json();
return true;
}
return false;
} catch (err) {
return false;
}
}
async function checkAuthAndRedirect() {
const ok = await checkAuth();
if (!ok) {
window.location.href = "login.html";
return false;
}
return true;
}
function updateUserMenu() {
const container = document.getElementById("user-menu");
if (!container) return;
if (currentUser) {
container.innerHTML = `
${getThemeControlHtml()}
${escapeHtml(currentUser.username)}
`;
attachThemeControl(container);
document.getElementById("logout-btn")?.addEventListener("click", logout);
} else {
container.innerHTML = `
${getThemeControlHtml()}
`;
attachThemeControl(container);
document.getElementById("login-open-btn")?.addEventListener("click", () => {
window.location.href = "login.html";
});
}
}
async function logout() {
await fetch(`${API_BASE}/logout`, { method: "POST", credentials: "include" });
window.location.href = "login.html";
}
function escapeHtml(str) {
if (!str) return "";
return str.replace(/[&<>]/g, function (m) {
if (m === "&") return "&";
if (m === "<") return "<";
if (m === ">") return ">";
return m;
});
}
function showToast(msg, isError = false) {
const toast = document.getElementById("toast");
if (!toast) return;
toast.textContent = msg;
toast.style.backgroundColor = isError ? "var(--red-7)" : "var(--green-7)";
toast.style.display = "block";
setTimeout(() => {
toast.style.display = "none";
}, 3000);
}
document.addEventListener("DOMContentLoaded", ensureStandaloneThemeControl);