/** =============================================================================== FILE: modules/web_api/static/js/tasks.js ROLE: Управление боковой панелью задач (Drawer), фильтрация и рендеринг карточек. AI-CONTEXT-ANCHORS: - ANCHOR[DRAWER_TOGGLE]: Открытие и закрытие выезжающей панели. - ANCHOR[TASKS_FILTER]: Фильтрация списка (ALL, IN_PROGRESS, BACKLOG, COMPLETED). - ANCHOR[TASKS_LOAD_FETCH]: Асинхронная загрузка задач через /api/v1/tasks. - ANCHOR[TASKS_RENDER_DOM]: Генерация HTML-карточек в боковом меню. =============================================================================== */ let currentFilter = 'ALL'; let allTasks = []; // --- [SECTION 1: DRAWER TOGGLE] --- # ANCHOR[DRAWER_TOGGLE] function toggleDrawer() { if (typeof IS_GUEST !== 'undefined' && IS_GUEST) return; const drawer = document.getElementById("task-drawer"); const backdrop = document.getElementById("drawer-backdrop"); if (!drawer) return; const isHidden = drawer.classList.contains("translate-x-full"); if (isHidden) { drawer.classList.remove("translate-x-full"); if (backdrop) backdrop.classList.remove("hidden"); loadTasks(); } else { drawer.classList.add("translate-x-full"); if (backdrop) backdrop.classList.add("hidden"); } } // --- [SECTION 2: FILTER CONTROL] --- # ANCHOR[TASKS_FILTER] function setFilter(status) { currentFilter = status; ["ALL", "IN_PROGRESS", "BACKLOG", "COMPLETED"].forEach(f => { const btn = document.getElementById(`filter-${f}`); if (btn) { btn.className = (f === status) ? "px-3 py-1.5 rounded-t-lg border-b-2 border-indigo-600 text-indigo-600 font-bold whitespace-nowrap" : "px-3 py-1.5 rounded-t-lg border-b-2 border-transparent whitespace-nowrap"; } }); renderTasks(); } // --- [SECTION 3: ASYNC DATA FETCH] --- # ANCHOR[TASKS_LOAD_FETCH] async function loadTasks() { const badge = document.getElementById("task-count-badge"); const container = document.getElementById("tasks-container"); const token = typeof API_TOKEN !== 'undefined' && API_TOKEN ? API_TOKEN : localStorage.getItem("scud_api_auth_token"); const isGuest = typeof IS_GUEST !== 'undefined' ? IS_GUEST : (localStorage.getItem("scud_is_guest") === "true"); if (isGuest || !token) { if (badge) badge.innerText = "0"; return; } try { const res = await fetch("/api/v1/tasks", { headers: { "Authorization": "Bearer " + token, "Content-Type": "application/json" } }); if (res.status === 401) { if (typeof logout === 'function') logout(); return; } if (!res.ok) { throw new Error(`HTTP error! status: ${res.status}`); } const data = await res.json(); if (Array.isArray(data)) { allTasks = data; } else if (data && Array.isArray(data.tasks)) { allTasks = data.tasks; } else if (data && typeof data === 'object') { allTasks = Object.values(data).find(val => Array.isArray(val)) || []; } else { allTasks = []; } if (badge) { badge.innerText = allTasks.length.toString(); } renderTasks(); } catch (err) { console.error("[Tasks Error]", err); if (badge) badge.innerText = "0"; if (container) { container.innerHTML = `