// Capture sheet — quick-capture modal triggered by pull-down on Today or from FAB. function CaptureSheet({ visible, onClose }) { const [mode, setMode] = React.useState(null); const [text, setText] = React.useState(''); const [saving, setSaving] = React.useState(false); React.useEffect(() => { if (!visible) { setMode(null); setText(''); } }, [visible]); if (!visible) return null; const modes = [ { id: 'journal', icon: , label: 'Journal', sub: 'Mood + entities · local only', color: T.indigo }, { id: 'memory', icon: , label: 'Memory', sub: 'Save a fact for context', color: T.purple }, { id: 'task', icon: , label: 'Task', sub: 'With smart reminder', color: T.green }, { id: 'bill', icon: , label: 'Bill photo', sub: 'Auto-extract amount + due', color: T.red }, { id: 'voice', icon: , label: 'Voice note', sub: 'Transcribed locally', color: T.orange }, { id: 'remind', icon: , label: 'Remind me', sub: '"…when I get home"', color: T.blue }, ]; const activeMode = modes.find(m => m.id === mode); const handleSave = async () => { if (!text.trim() || saving) return; setSaving(true); try { if (mode === 'memory') { await fetch('/api/capture/memory', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ fact: text, user: LifeData.user, category: 'note' }), }); } else if (mode === 'task') { await fetch('/api/capture/task', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ description: text, user: LifeData.user }), }); } // journal stays local-only for now (no cloud endpoint) } catch (err) { console.error('Capture save failed:', err); } finally { setSaving(false); onClose(); } }; return (
e.stopPropagation()} style={{ background: T.bg, width: '100%', borderTopLeftRadius: 28, borderTopRightRadius: 28, padding: '8px 0 28px', maxHeight: '86%', overflowY: 'auto', boxShadow: '0 -8px 32px rgba(0,0,0,0.16)', animation: 'slideUp 0.3s cubic-bezier(.2,.8,.2,1)', }}>
{mode === null && ( <>
Capture
Quick add
{modes.map(m => ( ))}
Journal, bills & voice transcribed locally · never leave the Thinkpad
)} {mode && ( <>
{activeMode.icon}
{activeMode.label}
{activeMode.sub}