// 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 */}
{/* 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 */}
{/* powered glow overlay */}
{isFullyPowered && (
)}
);
};
window.Consumer = Consumer;