Reflect navigation state in URL hash

#all, #type/<id>, #manage-types — back/forward works via popstate,
deep links work on load via apply_hash(location.hash)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-17 22:14:19 +00:00
parent b1221b06a8
commit c5a5966318

View File

@@ -427,21 +427,21 @@ function render_nav() {
const all_btn = document.createElement('button');
all_btn.className = 'nav-btn' + (state.active_view === 'entries' && state.active_type === null ? ' active' : '');
all_btn.textContent = 'All';
all_btn.addEventListener('click', () => { state.active_view = 'entries'; state.active_type = null; render(); });
all_btn.addEventListener('click', () => navigate('all'));
nav.appendChild(all_btn);
for (const et of state.entry_types) {
const btn = document.createElement('button');
btn.className = 'nav-btn' + (state.active_view === 'entries' && state.active_type === et.id ? ' active' : '');
btn.textContent = et.title;
btn.addEventListener('click', () => { state.active_view = 'entries'; state.active_type = et.id; render(); });
btn.addEventListener('click', () => navigate('type/' + et.id));
nav.appendChild(btn);
}
const manage_btn = document.createElement('button');
manage_btn.className = 'nav-btn' + (state.active_view === 'manage-types' ? ' active' : '');
manage_btn.textContent = 'Manage Types';
manage_btn.addEventListener('click', () => { state.active_view = 'manage-types'; render(); });
manage_btn.addEventListener('click', () => navigate('manage-types'));
nav.appendChild(manage_btn);
}
@@ -670,6 +670,34 @@ function render_manage_types(container) {
container.appendChild(list);
}
// ---------------------------------------------------------------------------
// Routing
// ---------------------------------------------------------------------------
function apply_hash(hash) {
if (hash === 'manage-types') {
state.active_view = 'manage-types';
state.active_type = null;
} else if (hash.startsWith('type/')) {
state.active_view = 'entries';
state.active_type = hash.slice(5);
} else {
state.active_view = 'entries';
state.active_type = null;
}
}
function navigate(hash) {
history.pushState(null, '', '#' + hash);
apply_hash(hash);
render();
}
window.addEventListener('popstate', () => {
apply_hash(location.hash.slice(1));
render();
});
// ---------------------------------------------------------------------------
// Main render
// ---------------------------------------------------------------------------
@@ -755,6 +783,7 @@ async function init() {
state.entry_types = types_res.entry_types;
state.entries = entries_res.entries;
apply_hash(location.hash.slice(1));
render();
}