71 lines
1.9 KiB
React
71 lines
1.9 KiB
React
import './exerciseRecommendations.css'
|
|
|
|
const resolveStatus = (level, index, activeIndex) => {
|
|
if (level.status) return level.status
|
|
if (activeIndex == null) return 'available'
|
|
if (index < activeIndex) return 'completed'
|
|
if (index === activeIndex) return 'current'
|
|
return 'locked'
|
|
}
|
|
|
|
function ProgressionTracker({
|
|
title = 'Progression Path',
|
|
levels = [],
|
|
activeLevelId,
|
|
activeIndex,
|
|
onSelect,
|
|
className = ''
|
|
}) {
|
|
const resolvedActiveIndex = activeIndex != null
|
|
? activeIndex
|
|
: levels.findIndex(level => level.id === activeLevelId)
|
|
|
|
return (
|
|
<section className={`progression-tracker ${className}`}>
|
|
<header className="progression-tracker-header">
|
|
<h2>{title}</h2>
|
|
</header>
|
|
|
|
<div className="progression-track">
|
|
{levels.map((level, index) => {
|
|
const status = resolveStatus(level, index, resolvedActiveIndex)
|
|
const levelClass = `progression-level is-${status}`
|
|
const content = (
|
|
<>
|
|
<div className="progression-node" aria-hidden="true">
|
|
{index + 1}
|
|
</div>
|
|
<div className="progression-info">
|
|
<h3>{level.label}</h3>
|
|
{level.description && <p>{level.description}</p>}
|
|
</div>
|
|
</>
|
|
)
|
|
|
|
return (
|
|
<div
|
|
key={level.id || level.label}
|
|
className={levelClass}
|
|
aria-current={status === 'current' ? 'step' : undefined}
|
|
>
|
|
{onSelect ? (
|
|
<button
|
|
type="button"
|
|
className="progression-level-button"
|
|
onClick={() => onSelect(level, index)}
|
|
>
|
|
{content}
|
|
</button>
|
|
) : (
|
|
content
|
|
)}
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|
|
|
|
export default ProgressionTracker
|