Set logging is now a united. Sporadic set table removed.
This commit is contained in:
@@ -1,24 +1,20 @@
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { Calendar, Clock, TrendingUp, Gauge, Pencil, Trash2, X, Save, ArrowRight, ArrowUp, Timer, Activity, Dumbbell, Percent } from 'lucide-react';
|
||||
import { WorkoutSession, ExerciseType, WorkoutSet, Language, SporadicSet } from '../types';
|
||||
import { WorkoutSession, ExerciseType, WorkoutSet, Language } from '../types';
|
||||
import { t } from '../services/i18n';
|
||||
|
||||
interface HistoryProps {
|
||||
sessions: WorkoutSession[];
|
||||
sporadicSets?: SporadicSet[];
|
||||
onUpdateSession?: (session: WorkoutSession) => void;
|
||||
onDeleteSession?: (sessionId: string) => void;
|
||||
onUpdateSporadicSet?: (set: SporadicSet) => void;
|
||||
onDeleteSporadicSet?: (setId: string) => void;
|
||||
lang: Language;
|
||||
}
|
||||
|
||||
const History: React.FC<HistoryProps> = ({ sessions, sporadicSets, onUpdateSession, onDeleteSession, onUpdateSporadicSet, onDeleteSporadicSet, lang }) => {
|
||||
const History: React.FC<HistoryProps> = ({ sessions, onUpdateSession, onDeleteSession, lang }) => {
|
||||
const [editingSession, setEditingSession] = useState<WorkoutSession | null>(null);
|
||||
const [deletingId, setDeletingId] = useState<string | null>(null);
|
||||
const [editingSporadicSet, setEditingSporadicSet] = useState<SporadicSet | null>(null);
|
||||
const [deletingSporadicId, setDeletingSporadicId] = useState<string | null>(null);
|
||||
|
||||
|
||||
const calculateSessionWork = (session: WorkoutSession) => {
|
||||
const bw = session.userBodyWeight || 70;
|
||||
@@ -93,26 +89,9 @@ const History: React.FC<HistoryProps> = ({ sessions, sporadicSets, onUpdateSessi
|
||||
}
|
||||
}
|
||||
|
||||
const handleSaveSporadicEdit = () => {
|
||||
if (editingSporadicSet && onUpdateSporadicSet) {
|
||||
onUpdateSporadicSet(editingSporadicSet);
|
||||
setEditingSporadicSet(null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleUpdateSporadicField = (field: keyof SporadicSet, value: number) => {
|
||||
if (!editingSporadicSet) return;
|
||||
setEditingSporadicSet({ ...editingSporadicSet, [field]: value });
|
||||
};
|
||||
|
||||
const handleConfirmDeleteSporadic = () => {
|
||||
if (deletingSporadicId && onDeleteSporadicSet) {
|
||||
onDeleteSporadicSet(deletingSporadicId);
|
||||
setDeletingSporadicId(null);
|
||||
}
|
||||
};
|
||||
|
||||
if (sessions.length === 0 && (!sporadicSets || sporadicSets.length === 0)) {
|
||||
if (sessions.length === 0) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full text-on-surface-variant p-8 text-center">
|
||||
<Clock size={48} className="mb-4 opacity-50" />
|
||||
@@ -128,7 +107,8 @@ const History: React.FC<HistoryProps> = ({ sessions, sporadicSets, onUpdateSessi
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-y-auto p-4 space-y-4 pb-20">
|
||||
{sessions.map((session) => {
|
||||
{/* Regular Workout Sessions */}
|
||||
{sessions.filter(s => s.type === 'STANDARD').map((session) => {
|
||||
const totalWork = calculateSessionWork(session);
|
||||
|
||||
return (
|
||||
@@ -198,30 +178,35 @@ const History: React.FC<HistoryProps> = ({ sessions, sporadicSets, onUpdateSessi
|
||||
)
|
||||
})}
|
||||
|
||||
{/* Sporadic Sets Section */}
|
||||
{sporadicSets && sporadicSets.length > 0 && (
|
||||
{/* Quick Log Sessions */}
|
||||
{sessions.filter(s => s.type === 'QUICK_LOG').length > 0 && (
|
||||
<div className="mt-8">
|
||||
<h3 className="text-xl font-medium text-on-surface mb-4 px-2">{t('sporadic_sets_title', lang)}</h3>
|
||||
<h3 className="text-xl font-medium text-on-surface mb-4 px-2">{t('quick_log', lang)}</h3>
|
||||
{Object.entries(
|
||||
sporadicSets.reduce((groups: Record<string, SporadicSet[]>, set) => {
|
||||
const date = new Date(set.timestamp).toISOString().split('T')[0];
|
||||
if (!groups[date]) groups[date] = [];
|
||||
groups[date].push(set);
|
||||
return groups;
|
||||
}, {})
|
||||
sessions
|
||||
.filter(s => s.type === 'QUICK_LOG')
|
||||
.reduce((groups: Record<string, WorkoutSession[]>, session) => {
|
||||
const date = new Date(session.startTime).toISOString().split('T')[0];
|
||||
if (!groups[date]) groups[date] = [];
|
||||
groups[date].push(session);
|
||||
return groups;
|
||||
}, {})
|
||||
)
|
||||
.sort(([a], [b]) => b.localeCompare(a))
|
||||
.map(([date, sets]) => (
|
||||
.map(([date, daySessions]) => (
|
||||
<div key={date} className="mb-4">
|
||||
<div className="text-sm text-on-surface-variant px-2 mb-2 font-medium">{date}</div>
|
||||
<div className="space-y-2">
|
||||
{(sets as SporadicSet[]).map(set => (
|
||||
{daySessions.flatMap(session => session.sets).map((set, idx) => (
|
||||
<div
|
||||
key={set.id}
|
||||
className="bg-surface-container-low rounded-xl p-4 border border-outline-variant/10 flex justify-between items-center"
|
||||
>
|
||||
<div className="flex-1">
|
||||
<div className="font-medium text-on-surface">{set.exerciseName}</div>
|
||||
<div className="font-medium text-on-surface">
|
||||
{set.exerciseName}
|
||||
{set.side && <span className="ml-2 text-xs font-medium text-on-surface-variant">{t(set.side.toLowerCase() as any, lang)}</span>}
|
||||
</div>
|
||||
<div className="text-sm text-on-surface-variant mt-1">
|
||||
{set.type === ExerciseType.STRENGTH && `${set.weight || 0}kg x ${set.reps || 0}`}
|
||||
{set.type === ExerciseType.BODYWEIGHT && `${set.weight ? `+${set.weight}kg` : 'BW'} x ${set.reps || 0}`}
|
||||
@@ -237,13 +222,26 @@ const History: React.FC<HistoryProps> = ({ sessions, sporadicSets, onUpdateSessi
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
<button
|
||||
onClick={() => setEditingSporadicSet(JSON.parse(JSON.stringify(set)))}
|
||||
onClick={() => {
|
||||
// Find the session this set belongs to and open edit mode
|
||||
const parentSession = daySessions.find(s => s.sets.some(st => st.id === set.id));
|
||||
if (parentSession) {
|
||||
setEditingSession(JSON.parse(JSON.stringify(parentSession)));
|
||||
}
|
||||
}}
|
||||
className="p-2 text-on-surface-variant hover:text-primary hover:bg-surface-container-high rounded-full transition-colors"
|
||||
>
|
||||
<Pencil size={18} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setDeletingSporadicId(set.id)}
|
||||
onClick={() => {
|
||||
// Find the session and set up for deletion
|
||||
const parentSession = daySessions.find(s => s.sets.some(st => st.id === set.id));
|
||||
if (parentSession) {
|
||||
setEditingSession(JSON.parse(JSON.stringify(parentSession)));
|
||||
setDeletingId(set.id); // Use set ID for deletion
|
||||
}
|
||||
}}
|
||||
className="p-2 text-on-surface-variant hover:text-error hover:bg-surface-container-high rounded-full transition-colors"
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
@@ -256,6 +254,7 @@ const History: React.FC<HistoryProps> = ({ sessions, sporadicSets, onUpdateSessi
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
{/* DELETE CONFIRMATION DIALOG (MD3) */}
|
||||
@@ -336,7 +335,7 @@ const History: React.FC<HistoryProps> = ({ sessions, sporadicSets, onUpdateSessi
|
||||
<div className="flex justify-between items-center border-b border-outline-variant pb-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="w-6 h-6 rounded-full bg-secondary-container text-on-secondary-container text-xs font-bold flex items-center justify-center">{idx + 1}</span>
|
||||
<span className="font-medium text-on-surface text-sm">{set.exerciseName}</span>
|
||||
<span className="font-medium text-on-surface text-sm">{set.exerciseName}{set.side && <span className="ml-2 text-xs font-medium text-on-surface-variant">{t(set.side.toLowerCase(), lang)}</span>}</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => handleDeleteSet(set.id)}
|
||||
@@ -422,29 +421,7 @@ const History: React.FC<HistoryProps> = ({ sessions, sporadicSets, onUpdateSessi
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Sporadic Set Delete Confirmation */}
|
||||
{deletingSporadicId && (
|
||||
<div className="fixed inset-0 z-[60] flex items-center justify-center bg-black/60 backdrop-blur-sm p-4">
|
||||
<div className="bg-surface-container w-full max-w-xs rounded-[28px] p-6 shadow-elevation-3">
|
||||
<h3 className="text-xl font-normal text-on-surface mb-2">{t('delete', lang)}</h3>
|
||||
<p className="text-sm text-on-surface-variant mb-8">{t('delete_confirm', lang)}</p>
|
||||
<div className="flex justify-end gap-2">
|
||||
<button
|
||||
onClick={() => setDeletingSporadicId(null)}
|
||||
className="px-4 py-2 rounded-full text-primary font-medium hover:bg-white/5"
|
||||
>
|
||||
{t('cancel', lang)}
|
||||
</button>
|
||||
<button
|
||||
onClick={handleConfirmDeleteSporadic}
|
||||
className="px-4 py-2 rounded-full bg-error-container text-on-error-container font-medium"
|
||||
>
|
||||
{t('delete', lang)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user