|
1 | | -import React, { useState, useEffect } from 'react'; |
| 1 | +import React, { useState, useEffect, useMemo } from 'react'; |
2 | 2 | import { |
3 | 3 | SafeAreaView, |
4 | 4 | View, |
@@ -65,7 +65,7 @@ const WorkoutItem = ({ workout, onPress }: WorkoutItemProps) => { |
65 | 65 |
|
66 | 66 |
|
67 | 67 | const ProgressScreen = () => { |
68 | | - const { workouts, currentWorkout, startWorkout, getWorkouts, getExercises} = useWorkout(); |
| 68 | + const { workouts, currentWorkout, startWorkout, getWorkouts, getExercises, completeWorkout} = useWorkout(); |
69 | 69 | const { isAuthenticated, isLoading } = useAuth(); |
70 | 70 | const [showNewWorkoutModal, setShowNewWorkoutModal] = useState(false); |
71 | 71 | const [newWorkoutName, setNewWorkoutName] = useState(''); |
@@ -137,6 +137,11 @@ const ProgressScreen = () => { |
137 | 137 | return Math.round(total / workouts.length); |
138 | 138 | }; |
139 | 139 |
|
| 140 | + const unfinishedCount = useMemo( |
| 141 | + () => workouts.filter(w => !w.is_completed).length, |
| 142 | + [workouts] |
| 143 | + ); |
| 144 | + |
140 | 145 | const weeklyData = getWeeklyWorkouts(); |
141 | 146 | const weeklyLabels = getWeeklyLabels(); |
142 | 147 |
|
@@ -225,16 +230,15 @@ const ProgressScreen = () => { |
225 | 230 | /> |
226 | 231 | </View> |
227 | 232 |
|
228 | | - {/*Finish Old Workout Button*/} |
229 | 233 | <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> |
238 | 242 |
|
239 | 243 | {/* Recent Workouts */} |
240 | 244 | <View style={styles.workoutHistoryContainer}> |
@@ -301,57 +305,65 @@ const ProgressScreen = () => { |
301 | 305 | </View> |
302 | 306 | </Modal> |
303 | 307 |
|
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> |
316 | 320 |
|
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?.() ?? '—'} |
320 | 351 | </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> |
345 | 353 |
|
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> |
355 | 367 | </SafeAreaView> |
356 | 368 | ); |
357 | 369 | }; |
|
0 commit comments