diff --git a/App.tsx b/App.tsx index d146437..27d6080 100644 --- a/App.tsx +++ b/App.tsx @@ -235,6 +235,7 @@ function App() { userWeight={currentUser.profile?.weight} activeSession={activeSession} activePlan={activePlan} + sporadicSets={sporadicSets} onSessionStart={handleStartSession} onSessionEnd={handleEndSession} onSessionQuit={handleQuitSession} diff --git a/components/Tracker/SporadicView.tsx b/components/Tracker/SporadicView.tsx index abf8ece..895aab9 100644 --- a/components/Tracker/SporadicView.tsx +++ b/components/Tracker/SporadicView.tsx @@ -1,6 +1,6 @@ -import React from 'react'; -import { Dumbbell, Scale, Activity, Timer as TimerIcon, ArrowRight, ArrowUp, Plus, CheckCircle } from 'lucide-react'; -import { ExerciseType, Language } from '../../types'; +import React, { useState, useEffect } from 'react'; +import { Dumbbell, Scale, Activity, Timer as TimerIcon, ArrowRight, ArrowUp, Plus, CheckCircle, Edit, Trash2 } from 'lucide-react'; +import { ExerciseType, Language, SporadicSet } from '../../types'; import { t } from '../../services/i18n'; import FilledInput from '../FilledInput'; import ExerciseModal from '../ExerciseModal'; @@ -9,9 +9,10 @@ import { useTracker } from './useTracker'; interface SporadicViewProps { tracker: ReturnType; lang: Language; + sporadicSets?: SporadicSet[]; } -const SporadicView: React.FC = ({ tracker, lang }) => { +const SporadicView: React.FC = ({ tracker, lang, sporadicSets }) => { const { searchQuery, setSearchQuery, @@ -40,6 +41,27 @@ const SporadicView: React.FC = ({ tracker, lang }) => { resetForm } = tracker; + const [todaysSets, setTodaysSets] = useState([]); + + useEffect(() => { + if (sporadicSets) { + const startOfDay = new Date(); + startOfDay.setHours(0, 0, 0, 0); + const todayS = sporadicSets.filter(s => s.timestamp >= startOfDay.getTime()); + setTodaysSets(todayS.sort((a, b) => b.timestamp - a.timestamp)); + } + }, [sporadicSets]); + + const renderSetMetrics = (set: SporadicSet) => { + const metrics: string[] = []; + if (set.weight) metrics.push(`${set.weight} ${t('weight_kg', lang)}`); + if (set.reps) metrics.push(`${set.reps} ${t('reps', lang)}`); + if (set.durationSeconds) metrics.push(`${set.durationSeconds} ${t('time_sec', lang)}`); + if (set.distanceMeters) metrics.push(`${set.distanceMeters} ${t('dist_m', lang)}`); + if (set.height) metrics.push(`${set.height} ${t('height_cm', lang)}`); + return metrics.join(' / '); + }; + return (
@@ -50,7 +72,7 @@ const SporadicView: React.FC = ({ tracker, lang }) => { }} className="text-error font-medium text-sm hover:opacity-80 transition-opacity" > - {t('cancel', lang)} + {t('quit', lang)}

@@ -102,7 +124,7 @@ const SporadicView: React.FC = ({ tracker, lang }) => {

)} + + {/* History Section */} + {todaysSets.length > 0 && ( +
+

{t('history_section', lang)}

+
+ {todaysSets.map(set => ( +
+
+

{set.exerciseName}

+

{renderSetMetrics(set)}

+
+
+ {/* Edit and Delete buttons can be added here in the future */} +
+
+ ))} +
+
+ )}
{isCreating && ( diff --git a/components/Tracker/index.tsx b/components/Tracker/index.tsx index 09897ad..a5f9572 100644 --- a/components/Tracker/index.tsx +++ b/components/Tracker/index.tsx @@ -1,5 +1,6 @@ + import React from 'react'; -import { WorkoutSession, WorkoutSet, WorkoutPlan, Language } from '../../types'; +import { WorkoutSession, WorkoutSet, WorkoutPlan, Language, SporadicSet } from '../../types'; import { useTracker } from './useTracker'; import IdleView from './IdleView'; import SporadicView from './SporadicView'; @@ -10,6 +11,7 @@ interface TrackerProps { userWeight?: number; activeSession: WorkoutSession | null; activePlan: WorkoutPlan | null; + sporadicSets?: SporadicSet[]; onSessionStart: (plan?: WorkoutPlan, startWeight?: number) => void; onSessionEnd: () => void; onSessionQuit: () => void; @@ -23,7 +25,7 @@ interface TrackerProps { const Tracker: React.FC = (props) => { const tracker = useTracker(props); const { isSporadicMode } = tracker; - const { activeSession, lang, onSessionEnd, onSessionQuit, onRemoveSet } = props; + const { activeSession, lang, onSessionEnd, onSessionQuit, onRemoveSet, sporadicSets } = props; if (activeSession) { return ( @@ -39,7 +41,7 @@ const Tracker: React.FC = (props) => { } if (isSporadicMode) { - return ; + return ; } return ; diff --git a/server/prisma/dev.db b/server/prisma/dev.db index fc734bd..4f42691 100644 Binary files a/server/prisma/dev.db and b/server/prisma/dev.db differ diff --git a/services/i18n.ts b/services/i18n.ts index b7acc13..70378b9 100644 --- a/services/i18n.ts +++ b/services/i18n.ts @@ -48,6 +48,7 @@ const translations = { prep_title: 'Preparation', prep_no_instructions: 'No specific instructions.', cancel: 'Cancel', + quit: 'Quit', start: 'Start', finish: 'Finish', finish_confirm_title: 'Finish Workout?', @@ -104,7 +105,7 @@ const translations = { // Plans plans_empty: 'No plans created', plan_editor: 'Plan Editor', - plan_name_ph: 'E.g. Leg Day', + plan_name_ph: 'E.g. Full-body Routine', plan_desc_ph: 'Describe preparation...', exercises_list: 'Exercises', weighted: 'Weighted', @@ -263,7 +264,7 @@ const translations = { // Plans plans_empty: 'Нет созданных планов', plan_editor: 'Редактор плана', - plan_name_ph: 'Например: День ног', + plan_name_ph: 'Например: Комплекс на всё тело', plan_desc_ph: 'Опишите подготовку...', exercises_list: 'Упражнения', weighted: 'С отягощением',