diff --git a/frontend/dashboard.css b/frontend/dashboard.css index 5ede2b1..fe1c74f 100644 --- a/frontend/dashboard.css +++ b/frontend/dashboard.css @@ -138,6 +138,12 @@ textarea { resize: vertical; min-height: 120px; } .plan-preview-actions button { min-height:44px; } .plan-today-actions { position:sticky; bottom:0; display:grid; grid-template-columns:1fr 1fr; gap:8px; margin:16px -6px -6px; padding:12px 6px; padding-bottom:calc(12px + env(safe-area-inset-bottom)); background:rgba(11,21,38,.98); border-top:1px solid #2a496e; } .plan-today-actions button { min-height:44px; width:100%; } +.today-interruption-sheet { position:fixed; inset:0; z-index:92; display:flex; align-items:flex-end; justify-content:center; background:rgba(5,12,21,.82); backdrop-filter:blur(4px); } +.today-interruption-sheet[hidden] { display:none; } +.today-interruption-panel { box-sizing:border-box; width:min(620px,100%); max-height:100dvh; overflow:auto; overflow-x:hidden; padding:18px; padding-bottom:calc(18px + env(safe-area-inset-bottom)); border:1px solid #b45309; border-radius:18px 18px 0 0; background:#0b1526; } +.today-interruption-panel h2 { margin:.25rem 0; overflow-wrap:anywhere; } +.today-interruption-actions { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:16px; } +.today-interruption-actions button { min-height:44px; width:100%; } .today-recap-sheet { position:fixed; inset:0; z-index:88; display:flex; align-items:flex-end; justify-content:center; background:rgba(5,12,21,.82); backdrop-filter:blur(4px); } .today-recap-sheet[hidden] { display:none; } .today-recap-panel { box-sizing:border-box; width:min(620px,100%); max-height:100%; overflow:auto; overflow-x:hidden; padding:18px; padding-bottom:calc(18px + env(safe-area-inset-bottom)); border:1px solid #2a496e; border-radius:18px 18px 0 0; background:#0b1526; } @@ -158,6 +164,7 @@ textarea { resize: vertical; min-height: 120px; } .today-recap-actions { position:sticky; bottom:0; display:grid; grid-template-columns:1fr 1fr; gap:8px; margin:16px -6px -6px; padding:12px 6px; padding-bottom:calc(12px + env(safe-area-inset-bottom)); background:rgba(11,21,38,.98); border-top:1px solid #2a496e; } .today-recap-actions button { min-height:44px; width:100%; } @media (max-width:420px) { + .today-interruption-actions { grid-template-columns:1fr; } .today-recap-actions { grid-template-columns:1fr; } .today-recap-row { grid-template-columns:1fr; } .today-recap-row input { width:min(100%,8rem); } diff --git a/frontend/dashboard.js b/frontend/dashboard.js index e27ea34..35072dd 100644 --- a/frontend/dashboard.js +++ b/frontend/dashboard.js @@ -219,6 +219,8 @@ }); laterSync.startLifecycle({ window, document }); document.addEventListener('visibilitychange', () => { + if (document.hidden) interruptionPrompt.background(); + else interruptionPrompt.foreground(); if (!document.hidden) refreshMyWorkView(); }); @@ -935,6 +937,23 @@ queryAll: s => document.querySelectorAll(s), formatEstimate: formatPlanMinutes, }); + const interruptionPrompt = createTodayInterruptionPrompt({ + timer, + sheet: qs('#today-interruption-sheet'), + description: qs('#today-interruption-description'), + getItemLabel: identity => { + const item = [...todayMyWork, ...activeMyWork].find(entry => todayWork.identity(entry) === identity); + return item?.title || ''; + }, + onResolved: () => timerView.render(), + }); + window.addEventListener('pagehide', () => interruptionPrompt.background()); + interruptionPrompt.restore(); + document.querySelectorAll('[data-today-interruption]').forEach(button => { + button.addEventListener('click', () => + interruptionPrompt.resolve(button.dataset.todayInterruption) + ); + }); const todayRecapView = setupTodayRecap( timer, timerView, todayWork, api, qs, escapeHtml, closeOpenWorkSheets, updateWorkSessionActions, () => planningOwnerLogin, @@ -3481,6 +3500,7 @@ if (activeFlushLogin) { confirmedOwnerLogin = activeFlushLogin; updateDeliveryReceiptControls(); + interruptionPrompt.restore(); } snapshot.context.notifications = lastNotifications; renderContextSnapshot(snapshot.context); @@ -5097,6 +5117,7 @@ const outage = mode === 'outage'; confirmedOwnerLogin = String(saved.user?.login || '').trim(); planningOwnerLogin = confirmedOwnerLogin; + interruptionPrompt.restore(); updatePlanningAvailability(); saved.notifications = notificationReadOutbox.suppress(saved.notifications || []); lastNotifications = saved.notifications; diff --git a/frontend/index.html b/frontend/index.html index 1373aca..1d8b1e7 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -267,6 +267,19 @@ +
Choose once before the timer continues. You can include the full interval or remove it from your recap.
+