Skip to content

Commit 14a68fc

Browse files
committed
Finishing Workout and History updated now, works
1 parent 02dc835 commit 14a68fc

File tree

3 files changed

+114
-71
lines changed

3 files changed

+114
-71
lines changed

KonditionExpo/app/(tabs)/history.tsx

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export type WorkoutResponse = {
3232
created_at: string;
3333
completed_date?: string;
3434
duration_minutes?: number;
35+
scheduled_date?: number;
3536
exercises: Exercise[]; // <-- include this
3637
};
3738

@@ -97,15 +98,25 @@ const WorkoutHistoryScreen = () => {
9798
});
9899
};
99100

100-
const formatDuration = (minutes?: number) => {
101-
if (!minutes) return 'N/A';
102-
const hours = Math.floor(minutes / 60);
103-
const mins = minutes % 60;
104-
if (hours > 0) {
105-
return `${hours}h ${mins}m`;
106-
}
107-
return `${mins}m`;
101+
const formatDuration = (workout: WorkoutResponse): string => {
102+
if (!workout.is_completed) return 'N/A';
103+
104+
const start = workout.scheduled_date ? new Date(workout.scheduled_date) : null;
105+
const end = workout.completed_date ? new Date(workout.completed_date) : null;
106+
107+
if (!start || !end || isNaN(start.getTime()) || isNaN(end.getTime())) return 'N/A';
108+
109+
const diffMs = end.getTime() - start.getTime();
110+
if (diffMs <= 0) return 'N/A';
111+
112+
const totalSeconds = Math.floor(diffMs / 1000);
113+
const hours = Math.floor(totalSeconds / 3600);
114+
const minutes = Math.floor((totalSeconds % 3600) / 60);
115+
const seconds = totalSeconds % 60;
116+
117+
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
108118
};
119+
109120

110121
const getCompletionStatus = (workout: WorkoutResponse) => {
111122
return workout.is_completed ? 'Completed' : 'Incomplete';
@@ -140,10 +151,10 @@ const WorkoutHistoryScreen = () => {
140151

141152
{/* Workout Metadata */}
142153
<View style={styles.workoutDetails}>
143-
<View style={styles.detailItem}>
144-
<Text style={styles.detailLabel}>Duration</Text>
145-
<Text style={styles.detailValue}>{formatDuration(workout.duration_minutes)}</Text>
146-
</View>
154+
<View style={styles.detailItem}>
155+
<Text style={styles.detailLabel}>Duration</Text>
156+
<Text style={styles.detailValue}>{formatDuration(workout)}</Text>
157+
</View>
147158

148159
<View style={styles.detailItem}>
149160
<Text style={styles.detailLabel}>Exercises</Text>

KonditionExpo/app/(tabs)/progress.tsx

Lines changed: 71 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect } from 'react';
1+
import React, { useState, useEffect, useMemo } from 'react';
22
import {
33
SafeAreaView,
44
View,
@@ -65,7 +65,7 @@ const WorkoutItem = ({ workout, onPress }: WorkoutItemProps) => {
6565

6666

6767
const ProgressScreen = () => {
68-
const { workouts, currentWorkout, startWorkout, getWorkouts, getExercises} = useWorkout();
68+
const { workouts, currentWorkout, startWorkout, getWorkouts, getExercises, completeWorkout} = useWorkout();
6969
const { isAuthenticated, isLoading } = useAuth();
7070
const [showNewWorkoutModal, setShowNewWorkoutModal] = useState(false);
7171
const [newWorkoutName, setNewWorkoutName] = useState('');
@@ -137,6 +137,11 @@ const ProgressScreen = () => {
137137
return Math.round(total / workouts.length);
138138
};
139139

140+
const unfinishedCount = useMemo(
141+
() => workouts.filter(w => !w.is_completed).length,
142+
[workouts]
143+
);
144+
140145
const weeklyData = getWeeklyWorkouts();
141146
const weeklyLabels = getWeeklyLabels();
142147

@@ -225,16 +230,15 @@ const ProgressScreen = () => {
225230
/>
226231
</View>
227232

228-
{/*Finish Old Workout Button*/}
229233
<View style={styles.actionContainer}>
230-
<Button
231-
title="Finish Old Workout"
232-
onPress={() => setShowFinishModal(true)}
233-
size="lg"
234-
fullWidth
235-
style={{ backgroundColor: '#FFA07A' }}
236-
/>
237-
</View>
234+
<Button
235+
title={`Finish Old Workout (${unfinishedCount})`}
236+
onPress={() => setShowFinishModal(true)}
237+
size="lg"
238+
fullWidth
239+
style={{ backgroundColor: '#FFA07A' }}
240+
/>
241+
</View>
238242

239243
{/* Recent Workouts */}
240244
<View style={styles.workoutHistoryContainer}>
@@ -301,57 +305,65 @@ const ProgressScreen = () => {
301305
</View>
302306
</Modal>
303307

304-
{/* Finish Workout Modal*/}
305-
<Modal
306-
visible={showFinishModal}
307-
transparent
308-
animationType="slide"
309-
onRequestClose={() => setShowFinishModal(false)}
310-
>
311-
<View style={styles.modalOverlay}>
312-
<View style={[styles.modalContent, { backgroundColor }]}>
313-
<Text style={[styles.modalTitle, { color: textColor }]}>
314-
Unfinished Workouts
315-
</Text>
308+
{/* Finish Workout Modal */}
309+
<Modal
310+
visible={showFinishModal}
311+
transparent
312+
animationType="slide"
313+
onRequestClose={() => setShowFinishModal(false)}
314+
>
315+
<View style={styles.modalOverlay}>
316+
<View style={[styles.modalContent, { backgroundColor }]}>
317+
<Text style={[styles.modalTitle, { color: textColor }]}>
318+
Unfinished Workouts
319+
</Text>
316320

317-
{workouts.filter(w => !w.is_completed).length === 0 ? (
318-
<Text style={{ textAlign: 'center', color: textColor }}>
319-
No incomplete workouts.
321+
<ScrollView
322+
style={{ maxHeight: 300, marginBottom: 12 }}
323+
showsVerticalScrollIndicator={false}
324+
>
325+
{workouts.filter(w => !w.is_completed).length === 0 ? (
326+
<Text style={{ textAlign: 'center', color: textColor }}>
327+
No incomplete workouts.
328+
</Text>
329+
) : (
330+
workouts
331+
.filter(w => !w.is_completed)
332+
.map((workout) => (
333+
<TouchableOpacity
334+
key={workout.id}
335+
onPress={async () => {
336+
await completeWorkout(workout.id);
337+
setShowFinishModal(false);
338+
}}
339+
style={{
340+
padding: 14,
341+
backgroundColor: '#E5F1FF',
342+
borderRadius: 10,
343+
marginBottom: 10,
344+
borderWidth: 1,
345+
borderColor: '#D0E2FF',
346+
}}
347+
>
348+
<Text style={{ color: '#333', fontWeight: '600' }}>{workout.name}</Text>
349+
<Text style={{ fontSize: 12, color: '#666' }}>
350+
{workout.date.toDateString?.() ?? '—'}
320351
</Text>
321-
) : (
322-
workouts
323-
.filter(w => !w.is_completed)
324-
.map((workout) => (
325-
<TouchableOpacity
326-
key={workout.id}
327-
onPress={() => {
328-
setShowFinishModal(false);
329-
router.push({
330-
pathname: '/finish',
331-
params: { workoutId: workout.id },
332-
});
333-
}}
334-
style={{
335-
padding: 12,
336-
backgroundColor: '#F5F8FF',
337-
borderRadius: 10,
338-
marginBottom: 10,
339-
}}
340-
>
341-
<Text style={{ color: textColor }}>{workout.name}</Text>
342-
</TouchableOpacity>
343-
))
344-
)}
352+
</TouchableOpacity>
345353

346-
<Button
347-
title="Close"
348-
onPress={() => setShowFinishModal(false)}
349-
variant="outline"
350-
style={{ marginTop: 10 }}
351-
/>
352-
</View>
353-
</View>
354-
</Modal>
354+
))
355+
)}
356+
</ScrollView>
357+
358+
<Button
359+
title="Close"
360+
onPress={() => setShowFinishModal(false)}
361+
variant="outline"
362+
style={{ marginTop: 10 }}
363+
/>
364+
</View>
365+
</View>
366+
</Modal>
355367
</SafeAreaView>
356368
);
357369
};

KonditionExpo/contexts/WorkoutContext.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ interface WorkoutContextType {
5959
updateSet: (exerciseId: string, setId: string, updatedSet: Partial<WorkoutSet>) => void;
6060
getExercises: (workoutID: string) => void;
6161
getExercises_2: () => Exercise[];
62+
completeWorkout: (workoutId: string) => void;
6263
}
6364

6465
const WorkoutContext = createContext<WorkoutContextType | undefined>(undefined);
@@ -94,6 +95,24 @@ export const WorkoutProvider = ({ children }: { children: ReactNode }) => {
9495
})),
9596
});
9697

98+
const completeWorkout = async (workoutId: string) => {
99+
try {
100+
const response = await axios.put(
101+
`http://localhost:8000/api/v1/workouts/${workoutId}/complete`,
102+
{},
103+
{
104+
headers: {
105+
Authorization: `Bearer ${token}`,
106+
},
107+
}
108+
);
109+
console.log("Workout marked as complete:", response.data);
110+
await getWorkouts(); // Refresh updated workouts
111+
} catch (error) {
112+
console.error("Failed to complete workout", error);
113+
}
114+
};
115+
97116
const addWorkout = async (workout: Workout) => {
98117
try {
99118
const payload = transformWorkoutForBackend(workout);
@@ -281,6 +300,7 @@ export const WorkoutProvider = ({ children }: { children: ReactNode }) => {
281300
updateSet,
282301
getWorkouts,
283302
getExercises,
303+
completeWorkout
284304
}}>
285305
{children}
286306
</WorkoutContext.Provider>

0 commit comments

Comments
 (0)