Side attribute editable for Unilateral exercises

This commit is contained in:
AG
2025-12-10 19:58:42 +02:00
parent 9243fec947
commit 3df4abba47
11 changed files with 190 additions and 52 deletions

View File

@@ -4,6 +4,8 @@ import { WorkoutSession, ExerciseType, WorkoutSet, Language } from '../types';
import { t } from '../services/i18n';
import { formatSetMetrics } from '../utils/setFormatting';
import { useSession } from '../context/SessionContext';
import { useAuth } from '../context/AuthContext';
import { getExercises } from '../services/storage';
import { Button } from './ui/Button';
import { Card } from './ui/Card';
import { Modal } from './ui/Modal';
@@ -15,11 +17,20 @@ interface HistoryProps {
const History: React.FC<HistoryProps> = ({ lang }) => {
const { sessions, updateSession, deleteSession } = useSession();
const { currentUser } = useAuth();
const userId = currentUser?.id || '';
const [exercises, setExercises] = useState<import('../types').ExerciseDef[]>([]);
const [editingSession, setEditingSession] = useState<WorkoutSession | null>(null);
const [deletingId, setDeletingId] = useState<string | null>(null);
const [deletingSetInfo, setDeletingSetInfo] = useState<{ sessionId: string, setId: string } | null>(null);
React.useEffect(() => {
if (!userId) return;
getExercises(userId).then(exs => setExercises(exs));
}, [userId]);
const calculateSessionWork = (session: WorkoutSession) => {
const bw = session.userBodyWeight || 70;
@@ -455,25 +466,36 @@ const History: React.FC<HistoryProps> = ({ lang }) => {
)}
</div>
{/* Side Selector - Full width on mobile, 1 col on desktop if space */}
{set.side && (
<div className="bg-surface-container-high rounded px-2 py-1 col-span-2 sm:col-span-1 border border-outline-variant/30">
<label className="text-[10px] text-on-surface-variant font-bold block mb-1">{t('unilateral', lang)}</label>
<div className="flex bg-surface-container-low rounded p-0.5">
{(['LEFT', 'RIGHT', 'ALTERNATELY'] as const).map((sideOption) => (
<button
key={sideOption}
onClick={() => handleUpdateSet(set.id, 'side', sideOption)}
className={`flex-1 text-[10px] py-1 rounded transition-colors ${set.side === sideOption
? 'bg-primary/10 text-primary font-bold'
: 'text-on-surface-variant hover:bg-surface-container'
}`}
>
{t(sideOption.toLowerCase() as any, lang).slice(0, 3)}
</button>
))}
{(() => {
const exDef = exercises.find(e => e.id === set.exerciseId);
const showSide = set.side || exDef?.isUnilateral;
if (!showSide) return null;
return (
<div className="bg-surface-container-high rounded px-2 py-1 col-span-2 sm:col-span-1 border border-outline-variant/30">
<label className="text-[10px] text-on-surface-variant font-bold block mb-1">{t('unilateral', lang)}</label>
<div className="flex bg-surface-container-low rounded p-0.5">
{(['LEFT', 'ALTERNATELY', 'RIGHT'] as const).map((sideOption) => {
const labelMap: Record<string, string> = { LEFT: 'L', RIGHT: 'R', ALTERNATELY: 'A' };
return (
<button
key={sideOption}
onClick={() => handleUpdateSet(set.id, 'side', sideOption)}
title={t(sideOption.toLowerCase() as any, lang)}
className={`flex-1 text-[10px] py-1 rounded transition-colors ${set.side === sideOption
? 'bg-primary/10 text-primary font-bold'
: 'text-on-surface-variant hover:bg-surface-container'
}`}
>
{labelMap[sideOption]}
</button>
);
})}
</div>
</div>
</div>
)}
);
})()}
</div>
))}
</div>