diff --git a/glance-system/glance-kisfenyo.yaml b/glance-system/glance-kisfenyo.yaml index 1227147..591a1c5 100644 --- a/glance-system/glance-kisfenyo.yaml +++ b/glance-system/glance-kisfenyo.yaml @@ -304,6 +304,235 @@ data: } }); })(); + + // ================================ + // Todo Widget Controller + // ================================ + (function() { + function initTodoWidgets() { + document.querySelectorAll('.todo-widget').forEach(function(widget) { + if (widget.dataset.initialized) return; + widget.dataset.initialized = 'true'; + + const API = widget.dataset.api; + const USER = widget.dataset.user; + const KEY = widget.dataset.key; + + function apiUrl(path) { + return API + path + (KEY ? '?key=' + KEY : ''); + } + + const input = widget.querySelector('.todo-add-input'); + const addBtn = widget.querySelector('.todo-add-btn'); + + async function addTodo() { + const text = input.value.trim(); + if (!text) return; + input.disabled = true; + try { + const r = await fetch(apiUrl('/userdata/' + USER + '/todos'), { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({text: text, done: false}) + }); + if (r.ok) location.reload(); + else console.error('Todo add failed:', await r.text()); + } catch(e) { console.error('Todo add error:', e); } + input.disabled = false; + } + + if (input) { + input.addEventListener('keydown', function(e) { + if (e.key === 'Enter') { e.preventDefault(); addTodo(); } + }); + } + if (addBtn) { + addBtn.addEventListener('click', function() { + if (input.value.trim()) addTodo(); + else input.focus(); + }); + } + + widget.addEventListener('click', async function(e) { + const item = e.target.closest('.todo-item'); + if (!item) return; + + if (e.target.closest('.todo-checkbox')) { + const id = item.dataset.id; + const text = item.dataset.text; + const newDone = item.dataset.done !== 'true'; + try { + const r = await fetch(apiUrl('/userdata/' + USER + '/todos/' + id), { + method: 'PUT', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({text: text, done: newDone}) + }); + if (r.ok) location.reload(); + } catch(e) { console.error('Todo toggle error:', e); } + } + + if (e.target.closest('.todo-delete')) { + const id = item.dataset.id; + try { + const r = await fetch(apiUrl('/userdata/' + USER + '/todos/' + id), { + method: 'DELETE' + }); + if (r.ok) location.reload(); + } catch(e) { console.error('Todo delete error:', e); } + } + }); + }); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initTodoWidgets); + } else { + initTodoWidgets(); + } + // Also run after a delay for dynamically loaded content + setTimeout(initTodoWidgets, 500); + setTimeout(initTodoWidgets, 1500); + })(); + + // ================================ + // Motivation Widget Controller + // ================================ + (function() { + function initMotivWidgets() { + document.querySelectorAll('.motiv-widget').forEach(function(widget) { + if (widget.dataset.initialized) return; + widget.dataset.initialized = 'true'; + + const API = widget.dataset.api; + const USER = widget.dataset.user; + const KEY = widget.dataset.key; + + const modal = widget.querySelector('.motiv-modal-overlay'); + const listEl = widget.querySelector('.motiv-list'); + const input = widget.querySelector('.motiv-modal-input'); + const addBtn = widget.querySelector('.motiv-modal-btn'); + const closeBtn = widget.querySelector('.motiv-modal-close'); + const gearBtn = widget.querySelector('.motiv-gear'); + + if (!modal || !listEl || !gearBtn) return; + + let quotes = []; + + function apiUrl(path) { + return API + path + (KEY ? '?key=' + KEY : ''); + } + + function esc(s) { + const d = document.createElement('div'); + d.textContent = s; + return d.innerHTML; + } + + async function loadQuotes() { + listEl.innerHTML = '