af32a0bb7f
- Silver/bronze medals (not just gold) on route & segment leaderboards - Colour HRV nightly-avg trend dots: orange unbalanced, red low - Project segment-hover dot smoothly along the track line (interpolated) - Show map and activity timeline side by side, half width each - Show time spent in each HR zone next to the percentage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
51 lines
1.8 KiB
React
51 lines
1.8 KiB
React
import { formatDuration } from '../../utils/format'
|
|
|
|
const ZONE_CONFIG = [
|
|
{ key: 'z1', label: 'Z1 Recovery', color: '#60a5fa' },
|
|
{ key: 'z2', label: 'Z2 Base', color: '#34d399' },
|
|
{ key: 'z3', label: 'Z3 Tempo', color: '#fbbf24' },
|
|
{ key: 'z4', label: 'Z4 Threshold', color: '#f97316' },
|
|
{ key: 'z5', label: 'Z5 Max', color: '#f43f5e' },
|
|
]
|
|
|
|
// zones holds the % of time in each zone; multiply by the activity's active time
|
|
// to show the approximate time spent in each.
|
|
export default function HRZoneBar({ zones, totalSeconds }) {
|
|
return (
|
|
<div className="space-y-2">
|
|
{/* Stacked bar */}
|
|
<div className="flex h-4 rounded-full overflow-hidden gap-0.5">
|
|
{ZONE_CONFIG.map(({ key, color }) => {
|
|
const pct = zones[key] || 0
|
|
if (pct < 0.5) return null
|
|
return (
|
|
<div
|
|
key={key}
|
|
style={{ width: `${pct}%`, backgroundColor: color }}
|
|
className="h-full"
|
|
title={`${key.toUpperCase()}: ${pct}%`}
|
|
/>
|
|
)
|
|
})}
|
|
</div>
|
|
|
|
{/* Legend */}
|
|
<div className="flex flex-wrap gap-4">
|
|
{ZONE_CONFIG.map(({ key, label, color }) => {
|
|
const pct = zones[key] || 0
|
|
return (
|
|
<div key={key} className="flex items-center gap-1.5">
|
|
<div className="w-2.5 h-2.5 rounded-sm" style={{ backgroundColor: color }} />
|
|
<span className="text-xs text-gray-400">{label}</span>
|
|
<span className="text-xs font-medium text-white">{pct}%</span>
|
|
{totalSeconds > 0 && (
|
|
<span className="text-xs text-gray-500">{formatDuration(Math.round((pct / 100) * totalSeconds))}</span>
|
|
)}
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|