// Shared primitives for Dashy const USERS = [ { id: 'lani', name: 'Lani', role: 'Front of house', hue: 28, initials: 'LA' }, { id: 'kirra', name: 'Kirra', role: 'Workshop lead', hue: 145, initials: 'KI' }, { id: 'ayron', name: 'Ayron', role: 'Tech', hue: 215, initials: 'AY' }, { id: 'rod', name: 'ROD', role: 'Owner', hue: 280, initials: 'RO' }, ]; const PRIORITY = { high: { label: 'High', color: 'var(--prio-high)', dot: 'var(--prio-high)' }, med: { label: 'Med', color: 'var(--prio-med)', dot: 'var(--prio-med)' }, low: { label: 'Low', color: 'var(--prio-low)', dot: 'var(--prio-low)' }, }; const SOURCES = { manual: { label: 'Manual', glyph: '·' }, imessage: { label: 'iMessage', glyph: '✦' }, email: { label: 'Email', glyph: '✉' }, automation:{ label: 'Auto', glyph: '⚙' }, }; function Avatar({ user, size = 28, ring = false }) { if (!user) return null; const s = { width: size, height: size, fontSize: Math.round(size * 0.42) }; if (user.photo) { return ( ); } return ( {user.initials} ); } function PriorityDot({ priority, withLabel = false }) { const p = PRIORITY[priority]; if (!p) return null; return ( {withLabel && {p.label}} ); } function SourceTag({ source }) { const s = SOURCES[source]; if (!s || source === 'manual') return null; return ( {s.glyph} {s.label} ); } function relTime(iso) { const now = new Date('2026-05-08T10:30:00'); const then = new Date(iso); const diff = (now - then) / 1000; if (diff < 60) return 'just now'; if (diff < 3600) return Math.floor(diff/60) + 'm ago'; if (diff < 86400) return Math.floor(diff/3600) + 'h ago'; if (diff < 86400*7) return Math.floor(diff/86400) + 'd ago'; return then.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); } function fmtDateTime(iso) { const d = new Date(iso); return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) + ' · ' + d.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' }); } function findUser(id) { const live = window.dbUsers; if (live) return live.find(u => u.id === id); return USERS.find(u => u.id === id); } function TaskCard({ task, onOpen, density = 'cozy', dragging = false, onDragStart, onDragEnd, onDragOver }) { const author = findUser(task.addedBy); const isAuto = task.status === 'unsuccessful' || task.status === 'billing'; return (
{ e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/dashy-task', task.id); onDragStart && onDragStart(task); }} onDragEnd={() => onDragEnd && onDragEnd()} onDragOver={onDragOver} onClick={() => onOpen && onOpen(task)} data-comment-anchor={"task-" + task.id} >
); } function IconBtn({ children, onClick, label, variant = 'ghost' }) { return ( ); } // Tiny inline icons const Icon = { Plus: () => , Bell: () => , Search: () => , Logs: () => , Close: () => , Check: () => , Arrow: () => , Dot: () => , Pin: () => , iMessage: () => , }; Object.assign(window, { USERS, PRIORITY, SOURCES, Avatar, PriorityDot, SourceTag, TaskCard, IconBtn, Icon, relTime, fmtDateTime, findUser, });