feat(ui): unify header and implement navigation drawer (Task 17)
- Redesign top header into clean, uncluttered layout with hamburger drawer trigger, clickable logo, central SRS focus badge, theme toggle and profile avatar - Implement unified responsive Navigation Drawer for both desktop and mobile with touch swipe-to-dismiss, backdrop blur, keyboard Esc support and background scroll lock - Streamline mobile bottom tab bar to 4 core actions (Dictionary, SRS, Reader, Menu) with Menu opening the unified drawer - Synchronize real-time SRS due badges and dictionary word statistics between header, bottom tabs, and drawer - Eliminate obsolete separate mobile-menu-modal in favor of unified drawer - Bump Service Worker cache version to notes-v5.7
This commit is contained in:
@@ -96,6 +96,7 @@ export function initDictionary() {
|
||||
const moveColConfirmBtn = document.getElementById('move-col-confirm-btn');
|
||||
|
||||
const exportOpenBtn = document.getElementById('export-open-btn');
|
||||
const drawerNavExport = document.getElementById('drawer-nav-export');
|
||||
const exportModal = document.getElementById('export-modal');
|
||||
const closeExportModalBtn = document.getElementById('close-export-modal-btn');
|
||||
const exportCancelBtn = document.getElementById('export-cancel-btn');
|
||||
@@ -556,6 +557,9 @@ export function initDictionary() {
|
||||
if (exportOpenBtn) {
|
||||
exportOpenBtn.addEventListener('click', () => openModal(exportModal));
|
||||
}
|
||||
if (drawerNavExport) {
|
||||
drawerNavExport.addEventListener('click', () => openModal(exportModal));
|
||||
}
|
||||
closeExportModalBtn.addEventListener('click', () => closeModal(exportModal));
|
||||
exportCancelBtn.addEventListener('click', () => closeModal(exportModal));
|
||||
|
||||
@@ -687,12 +691,22 @@ export function initDictionary() {
|
||||
if (stats) {
|
||||
const due = stats.due_cards || 0;
|
||||
const srsBadge = document.getElementById('srs-badge');
|
||||
if (srsBadge) srsBadge.textContent = due;
|
||||
if (srsBadge) {
|
||||
srsBadge.textContent = due;
|
||||
srsBadge.style.display = due > 0 ? 'inline-block' : 'none';
|
||||
}
|
||||
const tabSrsBadge = document.getElementById('tab-srs-badge');
|
||||
if (tabSrsBadge) {
|
||||
tabSrsBadge.textContent = due;
|
||||
tabSrsBadge.classList.toggle('hidden', due === 0);
|
||||
}
|
||||
const drawerSrsBadge = document.getElementById('drawer-srs-badge');
|
||||
if (drawerSrsBadge) {
|
||||
drawerSrsBadge.textContent = due;
|
||||
drawerSrsBadge.classList.toggle('hidden', due === 0);
|
||||
}
|
||||
const drawerStatDue = document.getElementById('drawer-stat-due');
|
||||
if (drawerStatDue) drawerStatDue.textContent = due;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ export function initSrs() {
|
||||
// Stats & Heatmap Modal
|
||||
const statsOpenBtn = document.getElementById('stats-open-btn');
|
||||
const mobileStatsBtn = document.getElementById('mobile-stats-btn');
|
||||
const drawerNavStats = document.getElementById('drawer-nav-stats');
|
||||
const statsModal = document.getElementById('stats-modal');
|
||||
const closeStatsModalBtn = document.getElementById('close-stats-modal-btn');
|
||||
const closeStatsBtn = document.getElementById('close-stats-btn');
|
||||
@@ -646,6 +647,7 @@ export function initSrs() {
|
||||
// -----------------------------------------------------------------------
|
||||
if (statsOpenBtn) statsOpenBtn.addEventListener('click', openStatsDashboard);
|
||||
if (mobileStatsBtn) mobileStatsBtn.addEventListener('click', openStatsDashboard);
|
||||
if (drawerNavStats) drawerNavStats.addEventListener('click', openStatsDashboard);
|
||||
closeStatsModalBtn.addEventListener('click', () => closeModal(statsModal));
|
||||
closeStatsBtn.addEventListener('click', () => closeModal(statsModal));
|
||||
|
||||
|
||||
@@ -139,13 +139,32 @@ export function updateHeaderStats(total = 0, today = 0, srsCount = 0) {
|
||||
const statTotal = document.getElementById('stat-total');
|
||||
const statToday = document.getElementById('stat-today');
|
||||
const srsBadge = document.getElementById('srs-badge');
|
||||
const tabSrsBadge = document.getElementById('tab-srs-badge');
|
||||
const drawerSrsBadge = document.getElementById('drawer-srs-badge');
|
||||
const drawerStatTotal = document.getElementById('drawer-stat-total');
|
||||
const drawerStatToday = document.getElementById('drawer-stat-today');
|
||||
const drawerStatDue = document.getElementById('drawer-stat-due');
|
||||
|
||||
const formattedToday = today > 0 ? `+${today}` : today;
|
||||
|
||||
if (statTotal) statTotal.textContent = total;
|
||||
if (statToday) statToday.textContent = today;
|
||||
if (statToday) statToday.textContent = formattedToday;
|
||||
if (drawerStatTotal) drawerStatTotal.textContent = total;
|
||||
if (drawerStatToday) drawerStatToday.textContent = formattedToday;
|
||||
if (drawerStatDue) drawerStatDue.textContent = srsCount;
|
||||
|
||||
if (srsBadge) {
|
||||
srsBadge.textContent = srsCount;
|
||||
srsBadge.style.display = srsCount > 0 ? 'inline-block' : 'none';
|
||||
}
|
||||
if (tabSrsBadge) {
|
||||
tabSrsBadge.textContent = srsCount;
|
||||
tabSrsBadge.classList.toggle('hidden', srsCount === 0);
|
||||
}
|
||||
if (drawerSrsBadge) {
|
||||
drawerSrsBadge.textContent = srsCount;
|
||||
drawerSrsBadge.classList.toggle('hidden', srsCount === 0);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user