Skip to content

Commit 01da743

Browse files
committed
Added backend logic to workouts, workin on testing it and PB
1 parent 4493370 commit 01da743

File tree

6 files changed

+207
-37
lines changed

6 files changed

+207
-37
lines changed

KonditionExpo/app/(tabs)/progress.tsx

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import {
33
SafeAreaView,
44
View,
@@ -15,7 +15,7 @@ import { useWorkout, Workout } from '@/contexts/WorkoutContext';
1515
import { Button } from '@/components/ui/Button';
1616
import { Input } from '@/components/ui/Input';
1717
import { router } from 'expo-router';
18-
18+
import { useAuth } from '@/contexts/AuthContext';
1919
const { width } = Dimensions.get('window');
2020

2121
interface WorkoutItemProps {
@@ -51,14 +51,31 @@ const WorkoutItem = ({ workout, onPress }: WorkoutItemProps) => {
5151
);
5252
};
5353

54+
55+
5456
const ProgressScreen = () => {
55-
const { workouts, currentWorkout, startWorkout } = useWorkout();
57+
const { workouts, currentWorkout, startWorkout, getWorkouts } = useWorkout();
58+
const { isAuthenticated, isLoading } = useAuth();
5659
const [showNewWorkoutModal, setShowNewWorkoutModal] = useState(false);
5760
const [newWorkoutName, setNewWorkoutName] = useState('');
58-
5961
const backgroundColor = '#FFFFFF';
6062
const textColor = '#333';
6163
const tintColor = '#70A1FF';
64+
65+
// ⬇️ Load backend workouts once auth is ready
66+
useEffect(() => {
67+
if (isAuthenticated && !isLoading) {
68+
getWorkouts();
69+
}
70+
}, [isAuthenticated, isLoading]);
71+
72+
if (isLoading || !isAuthenticated) {
73+
return (
74+
<SafeAreaView style={styles.container}>
75+
<Text style={{ textAlign: 'center', marginTop: 100 }}>Loading your progress...</Text>
76+
</SafeAreaView>
77+
);
78+
}
6279

6380
const handleStartWorkout = () => {
6481
if (!newWorkoutName.trim()) {

KonditionExpo/app/workout.tsx

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -149,25 +149,21 @@ const WorkoutScreen = () => {
149149
addSetToExercise(exerciseId, newSet);
150150
};
151151

152-
const handleFinishWorkout = () => {
152+
const handleFinishWorkout = async () => {
153153
if (!currentWorkout) return;
154-
155-
Alert.alert(
156-
'Finish Workout',
157-
'Are you sure you want to finish this workout?',
158-
[
159-
{ text: 'Cancel', style: 'cancel' },
160-
{
161-
text: 'Finish',
162-
onPress: () => {
163-
const duration = Math.round((new Date().getTime() - startTime.getTime()) / 60000);
164-
const updatedWorkout = { ...currentWorkout, duration };
165-
endWorkout();
166-
router.replace('/(tabs)');
167-
},
168-
},
169-
]
170-
);
154+
155+
const duration = Math.round((new Date().getTime() - startTime.getTime()) / 60000);
156+
const updatedWorkout = { ...currentWorkout, duration };
157+
158+
console.log("FinishWorkout-UpdatedWorkout: ", updatedWorkout);
159+
160+
try {
161+
await endWorkout(updatedWorkout); // wait for backend POST to complete
162+
router.replace('/(tabs)');
163+
} catch (error) {
164+
console.error("Error finishing workout:", error);
165+
// Optionally show UI feedback
166+
}
171167
};
172168

173169
if (!currentWorkout) {

KonditionExpo/contexts/WorkoutContext.tsx

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import React, { createContext, useContext, useState, ReactNode } from 'react';
2+
import axios from 'axios';
3+
import { useAuth } from '@/contexts/AuthContext'; // adjust if needed
24

35
export interface Exercise {
46
id: string;
@@ -34,11 +36,12 @@ export interface Workout {
3436
interface WorkoutContextType {
3537
workouts: Workout[];
3638
currentWorkout: Workout | null;
37-
addWorkout: (workout: Workout) => void;
39+
addWorkout: (workout: Workout) => Promise<void>; // <-- async now
3840
updateWorkout: (workoutId: string, workout: Workout) => void;
41+
getWorkouts: () => void;
3942
deleteWorkout: (workoutId: string) => void;
4043
startWorkout: (name: string) => void;
41-
endWorkout: () => void;
44+
endWorkout: (updatedWorkout: Workout) => Promise<void>; // <-- async now
4245
addExerciseToCurrentWorkout: (exercise: Exercise) => void;
4346
addSetToExercise: (exerciseId: string, set: Omit<WorkoutSet, 'id'>) => void;
4447
removeSetFromExercise: (exerciseId: string, setId: string) => void;
@@ -50,18 +53,72 @@ const WorkoutContext = createContext<WorkoutContextType | undefined>(undefined);
5053
export const WorkoutProvider = ({ children }: { children: ReactNode }) => {
5154
const [workouts, setWorkouts] = useState<Workout[]>([]);
5255
const [currentWorkout, setCurrentWorkout] = useState<Workout | null>(null);
56+
const { token, isAuthenticated, isLoading } = useAuth(); //token of user
57+
58+
59+
// Early return while loading or not authenticated
60+
if (isLoading || !isAuthenticated || !token) {
61+
return null; // or <LoadingIndicator />
62+
}
63+
console.log("In WorkoutContext - Current User token is: ", token);
5364

5465
const generateId = () => Math.random().toString(36).substr(2, 9);
5566

56-
const addWorkout = (workout: Workout) => {
57-
setWorkouts(prev => [...prev, workout]);
67+
const addWorkout = async (workout: Workout) => {
68+
try {
69+
const response = await axios.post(
70+
'http://localhost:8000/api/v1/workouts/', // Replace with deployment endpoint
71+
workout,
72+
{
73+
headers: {
74+
Authorization: `Bearer ${token}`,
75+
},
76+
}
77+
);
78+
console.log("Response from POST /workouts: ", response);
79+
const savedWorkout = response.data;
80+
setWorkouts(prev => [...prev, savedWorkout]);
81+
} catch (error) {
82+
console.error('Failed to save workout to backend:', error.response?.data || error.message);
83+
}
5884
};
5985

60-
const updateWorkout = (workoutId: string, updatedWorkout: Workout) => {
86+
const getWorkouts = async () => {
87+
try {
88+
const response = await axios.get('http://localhost:8000/api/v1/workouts/', {
89+
headers: {
90+
Authorization: `Bearer ${token}`,
91+
},
92+
});
93+
94+
// Extract array properly
95+
const workoutArray = response.data.data;
96+
97+
// Convert string dates to Date objects
98+
const parsed = workoutArray.map((w: any) => ({
99+
...w,
100+
date: new Date(w.created_at),
101+
exercises: w.exercises || [], // fallback to empty array
102+
duration: w.duration_minutes || 0,
103+
}));
104+
105+
setWorkouts(parsed);
106+
} catch (error) {
107+
console.error('Failed to load workouts:', error.response?.data || error.message);
108+
}
109+
};
110+
const endWorkout = async (updatedWorkout: Workout) => {
111+
await addWorkout(updatedWorkout);
112+
setCurrentWorkout(null);
113+
};
114+
115+
//Everything below this is old - only updates local state rather than send backend requests
116+
117+
const updateWorkout = (workoutId: string, updatedWorkout: Workout) => { //Old
61118
setWorkouts(prev => prev.map(w => w.id === workoutId ? updatedWorkout : w));
62119
};
63120

64-
const deleteWorkout = (workoutId: string) => {
121+
const deleteWorkout = (workoutId: string) => { // Old
65122
setWorkouts(prev => prev.filter(w => w.id !== workoutId));
66123
};
67124

@@ -76,13 +133,6 @@ export const WorkoutProvider = ({ children }: { children: ReactNode }) => {
76133
setCurrentWorkout(newWorkout);
77134
};
78135

79-
const endWorkout = () => {
80-
if (currentWorkout) {
81-
addWorkout(currentWorkout);
82-
setCurrentWorkout(null);
83-
}
84-
};
85-
86136
const addExerciseToCurrentWorkout = (exercise: Exercise) => {
87137
if (!currentWorkout) return;
88138

@@ -155,11 +205,12 @@ export const WorkoutProvider = ({ children }: { children: ReactNode }) => {
155205
updateWorkout,
156206
deleteWorkout,
157207
startWorkout,
158-
endWorkout,
208+
endWorkout,
159209
addExerciseToCurrentWorkout,
160210
addSetToExercise,
161211
removeSetFromExercise,
162212
updateSet,
213+
getWorkouts,
163214
}}>
164215
{children}
165216
</WorkoutContext.Provider>

KonditionExpo/package-lock.json

Lines changed: 81 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

KonditionExpo/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"@react-navigation/bottom-tabs": "^7.3.10",
2020
"@react-navigation/elements": "^2.3.8",
2121
"@react-navigation/native": "^7.1.6",
22+
"axios": "^1.9.0",
2223
"d3-shape": "^3.2.0",
2324
"expo": "^53.0.9",
2425
"expo-blur": "~14.1.4",
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""merge post_privacy and cascade heads
2+
3+
Revision ID: feaaa16caba8
4+
Revises: 1a31ce608336, 20250604_add_post_privacy
5+
Create Date: 2025-06-05 12:15:19.781955
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
import sqlmodel.sql.sqltypes
11+
12+
13+
# revision identifiers, used by Alembic.
14+
revision = 'feaaa16caba8'
15+
down_revision = ('1a31ce608336', '20250604_add_post_privacy')
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
pass
22+
23+
24+
def downgrade():
25+
pass

0 commit comments

Comments
 (0)