67 lines
1.5 KiB
TypeScript
67 lines
1.5 KiB
TypeScript
interface SupplyBarProps {
|
|
days: number;
|
|
maxDays?: number;
|
|
}
|
|
|
|
type Level = 'ok' | 'low' | 'critical';
|
|
|
|
function getLevel(days: number): Level {
|
|
if (days <= 7) return 'critical';
|
|
if (days <= 14) return 'low';
|
|
return 'ok';
|
|
}
|
|
|
|
const FILL_COLOR: Record<Level, string> = {
|
|
ok: 'var(--brand)',
|
|
low: 'var(--warn)',
|
|
critical: 'var(--danger)',
|
|
};
|
|
|
|
const NUM_COLOR: Record<Level, string> = {
|
|
ok: 'var(--ink)',
|
|
low: 'var(--warn)',
|
|
critical: 'var(--danger)',
|
|
};
|
|
|
|
export function SupplyBar({ days, maxDays = 60 }: SupplyBarProps) {
|
|
const pct = Math.min(100, (days / maxDays) * 100);
|
|
const level = getLevel(days);
|
|
|
|
return (
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
|
<div
|
|
style={{
|
|
flex: 1,
|
|
height: 6,
|
|
background: 'var(--bg-inset)',
|
|
borderRadius: 3,
|
|
overflow: 'hidden',
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
height: '100%',
|
|
width: `${pct}%`,
|
|
background: FILL_COLOR[level],
|
|
borderRadius: 3,
|
|
transition: 'width 0.3s',
|
|
}}
|
|
/>
|
|
</div>
|
|
<div
|
|
className="num"
|
|
style={{
|
|
fontSize: 11,
|
|
display: 'flex',
|
|
alignItems: 'baseline',
|
|
gap: 2,
|
|
minWidth: 42,
|
|
justifyContent: 'flex-end',
|
|
}}
|
|
>
|
|
<span style={{ fontWeight: 600, fontSize: 13, color: NUM_COLOR[level] }}>{days}</span>
|
|
<span style={{ color: 'var(--ink-muted)', fontSize: 10 }}>d</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|