04bab32e26
- Add GET /api/exercises/:id/alternatives endpoint - Add GET /api/exercises/:id/last-workout endpoint - New AlternativeModal component for swapping exercises - WorkoutPage: single-tap logging, +/- buttons, rest timer - Updated Icons with new workout icons - Polish: card shadows, borders, micro-interactions - Tasks directory for project management
52 lines
1.7 KiB
React
52 lines
1.7 KiB
React
import { Icon } from './Icons'
|
|
|
|
function AlternativeModal({ exercise, alternatives, loading, error, onSelect, onClose }) {
|
|
if (!exercise) return null
|
|
|
|
return (
|
|
<div className="alternative-modal-overlay" onClick={onClose}>
|
|
<div className="alternative-modal" onClick={(event) => event.stopPropagation()}>
|
|
<div className="alternative-modal-header">
|
|
<div>
|
|
<h3>Alternativa övningar</h3>
|
|
<p>För {exercise.name}</p>
|
|
</div>
|
|
<button className="alternative-modal-close" onClick={onClose} aria-label="Stäng">
|
|
<Icon name="chevronDown" size={18} />
|
|
</button>
|
|
</div>
|
|
|
|
{loading && (
|
|
<div className="alternative-modal-state">Laddar alternativ...</div>
|
|
)}
|
|
|
|
{!loading && error && (
|
|
<div className="alternative-modal-state error">{error}</div>
|
|
)}
|
|
|
|
{!loading && !error && alternatives.length === 0 && (
|
|
<div className="alternative-modal-state">Inga alternativ hittades.</div>
|
|
)}
|
|
|
|
{!loading && !error && alternatives.length > 0 && (
|
|
<div className="alternative-list">
|
|
{alternatives.map((alt) => (
|
|
<div key={alt.id} className="alternative-item">
|
|
<div className="alternative-info">
|
|
<strong>{alt.name}</strong>
|
|
<span>{alt.description || 'Ingen beskrivning tillgänglig.'}</span>
|
|
</div>
|
|
<button className="alternative-select-btn" onClick={() => onSelect(alt)}>
|
|
Välj
|
|
</button>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default AlternativeModal
|