// ── Undo system ── import { api } from './util.js'; const MAX_STACK = 30; const stack = []; export function pushUndo(label, restoreFn) { stack.push({ label, restore: restoreFn, time: Date.now() }); if (stack.length > MAX_STACK) stack.shift(); showHint(label); } export async function undo() { const entry = stack.pop(); if (!entry) return; await entry.restore(); await window._reloadAll(); showHint(`undo: ${entry.label}`); } export function canUndo() { return stack.length > 0; } export function lastLabel() { return stack.length ? stack[stack.length - 1].label : ''; } // Snapshot helpers export function snapshotCard(card) { return { ...card }; } export function snapshotCards(cards) { return cards.map(c => ({ ...c })); } export function pushCardEdit(label, cardId, prevData) { pushUndo(label, async () => { await api(`api/cards/${cardId}`, { method: 'PATCH', body: prevData }); }); } export function pushCardDelete(label, card) { pushUndo(label, async () => { await api('api/cards', { method: 'POST', body: { title: card.title, body: card.body, color: card.color, bucket_id: card.bucket_id, position: card.position, }}); }); } export function pushReorder(label, cards) { const prev = cards.map(c => ({ id: c.id, position: c.position })); pushUndo(label, async () => { await Promise.all(prev.map(p => api(`api/cards/${p.id}`, { method: 'PATCH', body: { position: p.position } }))); }); } export function pushBatch(label, patches) { // patches = [{cardId, prevData}, ...] pushUndo(label, async () => { await Promise.all(patches.map(p => api(`api/cards/${p.cardId}`, { method: 'PATCH', body: p.prevData }))); }); } // Toast hint let hintTimer = null; function showHint(text) { let el = document.getElementById('undo-hint'); if (!el) { el = document.createElement('div'); el.id = 'undo-hint'; el.className = 'fixed bottom-16 left-1/2 -translate-x-1/2 z-[95] bg-t-surface border border-t-border px-4 py-2 text-xs font-pixel text-t-muted shadow-lg transition-all'; document.body.appendChild(el); } el.textContent = text + ' (ctrl+z undo)'; el.style.opacity = '1'; el.style.transform = 'translateX(-50%) translateY(0)'; clearTimeout(hintTimer); hintTimer = setTimeout(() => { el.style.opacity = '0'; el.style.transform = 'translateX(-50%) translateY(8px)'; }, 2500); }