// Consumer / Device component const Consumer = ({ consumer, supplied, onChange, onDelete, onCardMouseDown, selected, period, hoveredAsTarget }) => { const { id, name, amount, x, y, icon } = consumer; const fundedPct = amount > 0 ? Math.min(1, supplied / amount) : 0; const isFullyPowered = supplied >= amount && amount > 0; const isPartial = supplied > 0 && supplied < amount; const isUnpowered = supplied === 0; const periodSuffix = period === 'monthly' ? '/mo' : period === 'biweekly' ? '/2wk' : '/wk'; const statusColor = isFullyPowered ? 'var(--green)' : isPartial ? 'var(--amber)' : 'var(--ink-3)'; const statusLabel = isFullyPowered ? 'POWERED' : isPartial ? 'LOW PWR' : 'OFFLINE'; // Heartbeat pulse when receiving any power const pulseClass = isFullyPowered ? 'pulse-green' : isPartial ? 'pulse-amber' : ''; return (
onCardMouseDown(e, id, 'consumer')} onTouchStart={(e) => onCardMouseDown(e, id, 'consumer')} > {/* status strip */}
{statusLabel}
{/* device icon + name */}
{icon || (name[0] || '?').toUpperCase()}
onChange(id, { name: e.target.value })} onMouseDown={(e) => e.stopPropagation()} onFocus={(e) => e.target.select()} style={{ background: 'transparent', border: 'none', outline: 'none', color: 'var(--ink-0)', fontSize: 14, fontWeight: 600, width: '100%', padding: '2px 0', borderBottom: '1px dashed transparent' }} onMouseEnter={(e) => e.target.style.borderBottomColor = 'var(--line-2)'} onMouseLeave={(e) => e.target.style.borderBottomColor = 'transparent'} />
{/* power draw */}
{/* fill bar */}
DRAW $ onChange(id, { amount: parseFloat(e.target.value) || 0 })} onMouseDown={(e) => e.stopPropagation()} onFocus={(e) => e.target.select()} style={{ background: 'transparent', border: 'none', outline: 'none', color: 'var(--ink-0)', fontSize: 16, fontWeight: 700, fontFamily: 'JetBrains Mono, monospace', flex: 1, padding: 0, minWidth: 0 }} /> {periodSuffix}
{/* funded readout */} {amount > 0 && (
Supplied: ${supplied.toFixed(0)} {Math.round(fundedPct * 100)}%
)} {/* input plug — left edge */}
{/* plug prongs */}
{/* powered glow overlay */} {isFullyPowered && (
)}
); }; window.Consumer = Consumer;