Dentime
Dental Recare Planning for the Office of Dr. John Burch of Mountain View | 650.965.1234
Thinking Shift Dashboard
Thinking Shift Dashboard
Send dashboard to:
Use Gmail web compose
Send to Email
Capture and organize shifts in thinking across old assumptions, emerging perspectives, and the implications of new ideas.
Export Web Page
Print All Categories
Total New Ideas
0
Open Entries
0
Completed Entries
0
1. Old Thinking
Open Ideas: 0
0 items
Print Category
Add
Theme
Source/Context
Date
Summary
Ideas
Done
Notes
Edit
Duplicate
Delete
2. New Thinking
Open Ideas: 0
0 items
Print Category
Add
Theme
Source/Context
Date
Summary
Ideas
Done
Notes
Edit
Duplicate
Delete
3. Implications of the New Thinking
Open Ideas: 0
0 items
Print Category
Add
Theme
Source/Context
Date
Implication
Ideas
Done
Notes
Edit
Duplicate
Delete
Notes
Close
Edit Entry
Close
\n'; return html; } function exportWebPage() { const htmlContent = buildWebHtml(); const blob = new Blob([htmlContent], { type: 'text/html' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'thinking-shift-dashboard-web.html'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); showToast('Web page exported successfully!'); } function buildEmailBody() { let lines = []; lines.push('Thinking Shift Dashboard'); lines.push('Generated: ' + new Date().toLocaleString()); lines.push(''); lines.push('Total New Ideas: ' + formatIdeas(getOutstandingTotal())); lines.push('Open Entries: ' + getOpenItemsCount()); lines.push('Completed Entries: ' + getCompletedItemsCount()); lines.push(''); ['oldThinking', 'newThinking', 'implications'].forEach(function(section) { const items = (data[section] || []).filter(function(item) { return !item.done; }); lines.push(sectionTitles[section]); lines.push('Category Total Ideas: ' + formatIdeas( items.reduce(function(sum, item) { return sum + roundIdeas(item.fee); }, 0) )); lines.push(''); if (items.length === 0) { lines.push('No open items in this category.'); lines.push(''); return; } items.forEach(function(item, index) { lines.push((index + 1) + '. Theme: ' + (item.name || '')); lines.push(' Source/Context: ' + (item.contact || '')); lines.push(' Date: ' + formatDate(item.date)); lines.push(' Summary: ' + (item.treatment || '')); lines.push(' New Ideas: ' + formatIdeas(item.fee)); lines.push(' Notes: ' + (item.notes || '')); lines.push(''); }); }); return lines.join('\n'); } function showToast(msg, ms) { ms = ms || 2500; const toastEl = document.getElementById('toast'); if (toastEl) { toastEl.textContent = msg; toastEl.classList.add('show'); setTimeout(function() { toastEl.classList.remove('show'); }, ms); } } function toUnicodeBold(str) { const out = []; for (const ch of String(str)) { const cp = ch.codePointAt(0); if (cp >= 0x41 && cp <= 0x5A) { out.push(String.fromCodePoint(0x1D400 + (cp - 0x41))); } else if (cp >= 0x61 && cp <= 0x7A) { out.push(String.fromCodePoint(0x1D41A + (cp - 0x61))); } else if (cp >= 0x30 && cp <= 0x39) { out.push(String.fromCodePoint(0x1D7CE + (cp - 0x30))); } else { out.push(ch); } } return out.join(''); } async function copyBodyToClipboard(body) { try { if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(body); return true; } else { const ta = document.createElement('textarea'); ta.value = body; ta.setAttribute('readonly', ''); ta.style.position = 'fixed'; ta.style.opacity = '0'; document.body.appendChild(ta); ta.select(); const success = document.execCommand('copy'); document.body.removeChild(ta); return success; } } catch (e) { return false; } } async function copyHtmlToClipboard(html, plain) { if (navigator.clipboard && window.isSecureContext && 'ClipboardItem' in window) { try { const item = new ClipboardItem({ 'text/html': new Blob([html], { type: 'text/html' }), 'text/plain': new Blob([plain], { type: 'text/plain' }) }); await navigator.clipboard.write([item]); return 'html'; } catch (e) { console.error(e); } } const ok = await copyBodyToClipboard(plain); return ok ? 'text' : ''; } function buildMailtoLink(to, subject, body) { const toAddr = String(to || '').trim(); const crlfBody = String(body || '').replace(/\r?\n/g, '\r\n'); return 'mailto:' + toAddr + '?subject=' + encodeURIComponent(subject || '') + '&body=' + encodeURIComponent(crlfBody); } function buildGmailComposeUrl(to, subject, body) { const crlfBody = String(body || '').replace(/\r?\n/g, '\r\n'); const params = new URLSearchParams({ to: String(to || '').trim(), su: subject || '', body: crlfBody }); return 'https://mail.google.com/mail/?view=cm&fs=1&tf=1&' + params.toString(); } function openMailClient(url, useNewTab) { const a = document.createElement('a'); a.href = url; a.target = useNewTab ? '_blank' : '_self'; a.rel = 'noopener'; a.style.display = 'none'; document.body.appendChild(a); a.click(); document.body.removeChild(a); } async function sendDashboardEmail() { const emailInput = document.getElementById('emailAddress'); const email = emailInput.value.trim(); if (!email) { alert('Please enter your email address first.'); emailInput.focus(); return; } saveEmailAddress(); const subject = 'Thinking Shift Dashboard'; const plainBody = buildEmailBody(); const htmlBody = buildPrintHtml(['oldThinking', 'newThinking', 'implications']); const gmailPlainBody = toUnicodeBold(subject) + '\n\n' + plainBody; const useGmailCheckbox = document.getElementById('useGmailCheckbox'); const useGmail = useGmailCheckbox ? useGmailCheckbox.checked : false; if (useGmail) { const copyMode = await copyHtmlToClipboard(htmlBody, gmailPlainBody); if (copyMode) { showToast('Formatted email copied! Please paste it into the Gmail window.'); } else { showToast('Could not copy. Opening Gmail anyway…'); } const gmailUrl = buildGmailComposeUrl(email, subject, ''); openMailClient(gmailUrl, true); } else { const copied = await copyBodyToClipboard(plainBody); showToast(copied ? 'Copied to clipboard. Opening email…' : 'Opening email…'); const mailto = buildMailtoLink(email, subject, plainBody); openMailClient(mailto, false); } } function printReport(sections) { const printArea = document.getElementById('printArea'); printArea.innerHTML = buildPrintHtml(sections); printArea.style.display = 'block'; window.print(); setTimeout(function() { printArea.style.display = 'none'; printArea.innerHTML = ''; }, 300); } window.addEventListener('click', function(event) { const notesModal = document.getElementById('notesModal'); const editModal = document.getElementById('editModal'); if (event.target === notesModal) closeNotesModal(); if (event.target === editModal) closeEditModal(); }); window.addEventListener('keydown', function(event) { if (event.key === 'Escape') { closeNotesModal(); closeEditModal(); } }); window.addEventListener('DOMContentLoaded', function() { loadData(); renderAll(); loadSavedEmail(); document.getElementById('emailAddress').addEventListener('input', function() { saveEmailAddress(); }); });