diff --git a/frontend/dashboard.css b/frontend/dashboard.css index 4f14881..1353074 100644 --- a/frontend/dashboard.css +++ b/frontend/dashboard.css @@ -506,6 +506,8 @@ textarea { resize: vertical; min-height: 120px; } .mobile-task-action { min-width:0; min-height:44px; padding:6px 2px; border:0; border-radius:8px; background:transparent; display:grid; place-items:center; gap:2px; font-size:12px; } .mobile-task-action[aria-current="page"] { color:#bfdbfe; background:#17365a; outline:1px solid #31577f; } .mobile-task-count { min-width:18px; min-height:18px; padding:1px 5px; border-radius:999px; background:#31577f; font-size:11px; line-height:16px; } +.attention-interruption:not([hidden]) { max-width:100%; display:flex; align-items:center; justify-content:space-between; gap:10px; margin:0 0 12px; padding:10px 12px; border:1px solid #31577f; border-radius:10px; background:#102641; } +.attention-interruption button { min-height:44px; flex:0 0 auto; } @media (max-width: 600px) { body { padding-bottom:calc(66px + env(safe-area-inset-bottom)); } header { min-height:56px; max-height:64px; padding:6px 10px; align-items:center; gap:8px; background:rgba(11,21,38,.98); } @@ -522,6 +524,7 @@ textarea { resize: vertical; min-height: 120px; } .device-setup-action { width:100%; } .device-readiness-card:not([hidden]) { display:grid; gap:12px; margin-left:max(0px,env(safe-area-inset-left)); margin-right:max(0px,env(safe-area-inset-right)); } .my-work { margin:0; } + .attention-interruption:not([hidden]) { position:sticky; top:64px; z-index:6; margin-inline:max(0px,env(safe-area-inset-left)) max(0px,env(safe-area-inset-right)); } .my-work-header { align-items:flex-start; } .my-work-actions { width:100%; flex-wrap:nowrap; } .my-work-actions button { min-height:44px; flex:1 1 0; padding-inline:6px; } diff --git a/frontend/dashboard.js b/frontend/dashboard.js index 98cf616..e89c158 100644 --- a/frontend/dashboard.js +++ b/frontend/dashboard.js @@ -44,12 +44,21 @@ Array.from(document.querySelectorAll('[data-mobile-task]')).map(button => [button.dataset.mobileTask, button]) ); const mobileTaskOverlays = Array.from(document.querySelectorAll('[role="dialog"], #whiteboard-modal, #markdown-modal')); + const attentionInterruption = qs('#attention-interruption'); + function renderAttentionInterruption() { + const pending = timer.attentionInterruption(); + attentionInterruption.hidden = !pending; + return pending; + } function openMobileWorkFallback() { qs('[data-work-filter="all"]').click(); qs('#my-work').scrollIntoView({block:'start'}); qs('#my-work').focus(); } function openMobileAttention() { + if (workSession.checkpointed()) timer.beginAttention(); + renderAttentionInterruption(); + timerView.render(); qs('[data-work-filter="attention"]').click(); qs('#my-work').scrollIntoView({block:'start'}); qs('#my-work').focus(); @@ -941,6 +950,17 @@ queryAll: s => document.querySelectorAll(s), formatEstimate: formatPlanMinutes, }); + renderAttentionInterruption(); + qs('#return-to-today').addEventListener('click', () => { + const returned = timer.returnFromAttention(); + renderAttentionInterruption(); + if (!returned) return; + selectTodayWork(); + const item = todayMyWork.find(entry => todayWork.identity(entry) === returned.identity); + if (item) workSession.reopen(item); + else continueTodaySession(); + timerView.render(); + }); const interruptionPrompt = createTodayInterruptionPrompt({ timer, sheet: qs('#today-interruption-sheet'), diff --git a/frontend/index.html b/frontend/index.html index 59b9ade..bef97e7 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -147,6 +147,10 @@ +