Frontend:
 LOG  Token loaded from SecureStore: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NmZhMTJiMmU1MTUzNjhlYjUxZTE1MGUiLCJpYXQiOjE3Mjc5OTA2MTEsImV4cCI6MTcyNzk5NDIxMX0.x4q7koRCNJGdONp2IiNTscpbsyO3wJUMbMK0NQzXetM
 LOG  ProgressScreen - Received Token: undefined
 LOG  Fetching progress data with token: undefined
 ERROR  Error Response: {"message": "Token is not valid"}
Backend:
Token verification failed: JsonWebTokenError: jwt malformed
    at module.exports [as verify] (D:\apps\Fitness-app\backend\node_modules\jsonwebtoken\verify.js:70:17)
    at auth (D:\apps\Fitness-app\backend\middleware\auth.js:26:29)
    at Layer.handle [as handle_request] (D:\apps\Fitness-app\backend\node_modules\express\lib\router\layer.js:95:5)
    at next (D:\apps\Fitness-app\backend\node_modules\express\lib\router\route.js:149:13)
    at Route.dispatch (D:\apps\Fitness-app\backend\node_modules\express\lib\router\route.js:119:3)
    at Layer.handle [as handle_request] (D:\apps\Fitness-app\backend\node_modules\express\lib\router\layer.js:95:5)
    at D:\apps\Fitness-app\backend\node_modules\express\lib\router\index.js:284:15
    at Function.process_params (D:\apps\Fitness-app\backend\node_modules\express\lib\router\index.js:346:12)
    at next (D:\apps\Fitness-app\backend\node_modules\express\lib\router\index.js:280:10)
    at Function.handle (D:\apps\Fitness-app\backend\node_modules\express\lib\router\index.js:175:3)

// screens/ProgressScreen.js
import React from 'react';
import { ScrollView, StyleSheet, Alert } from 'react-native';
import ProgressInput from '../Components/ProgressInput';
import ProgressChart from '../Components/ProgressChart';

const ProgressScreen = ({ token }) => {
    console.log("ProgressScreen - Received Token:", token); // Debugging

    if (!token) {
        Alert.alert('Authentication Error', 'No valid token provided.');
        // Optionally, navigate the user to the login screen or take other actions
    }

    return (
        <ScrollView contentContainerStyle={styles.container}>
            <ProgressInput token={token} />
            <ProgressChart token={token} />
        </ScrollView>
    );
};

const styles = StyleSheet.create({
    container: { padding: 20 },
});

export default ProgressScreen;

// components/ProgressChart.js
import React, { useEffect, useState } from 'react';
import { View, Text, Dimensions, StyleSheet, ActivityIndicator, Alert } from 'react-native';
import axios from 'axios';
import { LineChart } from 'react-native-chart-kit';

const screenWidth = Dimensions.get('window').width;

const ProgressChart = ({ token }) => {
    const [progressData, setProgressData] = useState([]);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        const fetchProgress = async () => {
            try {
                console.log("Fetching progress data with token:", token); // Debugging
                const res = await axios.get('http://10.0.0.203:5000/api/progress', {
                    headers: {
                        'Authorization': `Bearer ${token}`,
                        'Content-Type': 'application/json',
                    }
                });
                console.log("Progress data received:", res.data); // Debugging
                setProgressData(res.data);
            } catch (err) {
                if (err.response) {
                    // Server responded with a status other than 2xx
                    console.error('Error Response:', err.response.data);
                    Alert.alert('Error', `Failed: ${err.response.data.message || 'Unknown error'}`);
                } else if (err.request) {
                    // Request was made but no response received
                    console.error('Error Request:', err.request);
                    Alert.alert('Error', 'No response from server.');
                } else {
                    // Something else happened
                    console.error('Error Message:', err.message);
                    Alert.alert('Error', 'An unexpected error occurred.');
                }
            } finally {
                setLoading(false);
            }
        };

        fetchProgress();
    }, [token]);

    if (loading) {
        return <ActivityIndicator size="large" color="#0000ff" />;
    }

    if (!progressData || progressData.length === 0) {
        return <Text>No progress data available.</Text>;
    }

    // Prepare data for charts
    const labels = progressData.map(entry => new Date(entry.date).toLocaleDateString());
    const weights = progressData.map(entry => entry.weight);
    const muscleMass = progressData.map(entry => entry.muscleMass);
    const fatPercentage = progressData.map(entry => entry.fatPercentage);

    return (
        <View style={styles.container}>
            <Text style={styles.title}>Weight Tracking</Text>
            <LineChart
                data={{
                    labels,
                    datasets: [
                        { data: weights }
                    ]
                }}
                width={screenWidth - 40}
                height={220}
                yAxisSuffix="kg"
                chartConfig={chartConfig}
                bezier
                style={styles.chart}
            />

            <Text style={styles.title}>Muscle Mass</Text>
            <LineChart
                data={{
                    labels,
                    datasets: [
                        { data: muscleMass }
                    ]
                }}
                width={screenWidth - 40}
                height={220}
                yAxisSuffix="kg"
                chartConfig={chartConfig}
                bezier
                style={styles.chart}
            />

            <Text style={styles.title}>Fat Percentage</Text>
            <LineChart
                data={{
                    labels,
                    datasets: [
                        { data: fatPercentage }
                    ]
                }}
                width={screenWidth - 40}
                height={220}
                yAxisSuffix="%"
                chartConfig={chartConfig}
                bezier
                style={styles.chart}
            />
        </View>
    );
};

const chartConfig = {
    backgroundGradientFrom: "#ffffff",
    backgroundGradientTo: "#ffffff",
    decimalPlaces: 1, // optional, defaults to 2dp
    color: (opacity = 1) => `rgba(0, 123, 255, ${opacity})`,
    labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
    style: { borderRadius: 16 },
    propsForDots: { r: "6", strokeWidth: "2", stroke: "#ffa726" }
};

const styles = StyleSheet.create({
    container: { alignItems: 'center', padding: 20 },
    title: { fontSize: 18, fontWeight: 'bold', marginTop: 20, marginBottom: 10 },
    chart: { borderRadius: 16 },
});

export default ProgressChart;

// components/ProgressInput.js
import React, { useState } from 'react';
import { View, TextInput, Button, StyleSheet, Alert, ScrollView, Text, KeyboardAvoidingView, Platform } from 'react-native';
import axios from 'axios';

const ProgressInput = ({ token }) => {
    const [weight, setWeight] = useState('');
    const [muscleMass, setMuscleMass] = useState('');
    const [fatPercentage, setFatPercentage] = useState('');
    const [chest, setChest] = useState('');
    const [waist, setWaist] = useState('');
    const [hips, setHips] = useState('');
    const [submitting, setSubmitting] = useState(false); // To handle multiple submissions

    const submitProgress = async () => {
        if (!weight || !muscleMass || !fatPercentage) {
            Alert.alert('Missing Data', 'Please fill in all required fields.');
            return;
        }

        const payload = {
            weight: parseFloat(weight),
            muscleMass: parseFloat(muscleMass),
            fatPercentage: parseFloat(fatPercentage),
            measurements: {
                chest: chest ? parseFloat(chest) : undefined,
                waist: waist ? parseFloat(waist) : undefined,
                hips: hips ? parseFloat(hips) : undefined,
            }
        };

        try {
            setSubmitting(true);
            console.log("Submitting progress with payload:", payload); // Debugging
            await axios.post('http://10.0.0.203:5000/api/progress', payload, {
                headers: {
                    'Authorization': `Bearer ${token}`,
                    'Content-Type': 'application/json'
                }
            });
            Alert.alert('Success', 'Progress recorded successfully!');
            // Reset form
            setWeight('');
            setMuscleMass('');
            setFatPercentage('');
            setChest('');
            setWaist('');
            setHips('');
        } catch (err) {
            if (err.response) {
                console.error('Error Response:', err.response.data);
                Alert.alert('Error', `Failed: ${err.response.data.message || 'Unknown error'}`);
            } else if (err.request) {
                console.error('Error Request:', err.request);
                Alert.alert('Error', 'No response from server.');
            } else {
                console.error('Error Message:', err.message);
                Alert.alert('Error', 'An unexpected error occurred.');
            }
        } finally {
            setSubmitting(false);
        }
    };

    return (
        <KeyboardAvoidingView
            behavior={Platform.OS === "ios" ? "padding" : "height"}
            style={{ flex: 1 }}
        >
            <ScrollView contentContainerStyle={styles.container}>
                <Text style={styles.label}>Weight (kg/lbs) *</Text>
                <TextInput
                    style={styles.input}
                    value={weight}
                    onChangeText={setWeight}
                    keyboardType="numeric"
                    placeholder="e.g., 70"
                />

                <Text style={styles.label}>Muscle Mass (kg) *</Text>
                <TextInput
                    style={styles.input}
                    value={muscleMass}
                    onChangeText={setMuscleMass}
                    keyboardType="numeric"
                    placeholder="e.g., 30"
                />

                <Text style={styles.label}>Fat Percentage (%) *</Text>
                <TextInput
                    style={styles.input}
                    value={fatPercentage}
                    onChangeText={setFatPercentage}
                    keyboardType="numeric"
                    placeholder="e.g., 15"
                />

                <Text style={styles.label}>Chest (cm/in)</Text>
                <TextInput
                    style={styles.input}
                    value={chest}
                    onChangeText={setChest}
                    keyboardType="numeric"
                    placeholder="Optional"
                />

                <Text style={styles.label}>Waist (cm/in)</Text>
                <TextInput
                    style={styles.input}
                    value={waist}
                    onChangeText={setWaist}
                    keyboardType="numeric"
                    placeholder="Optional"
                />

                <Text style={styles.label}>Hips (cm/in)</Text>
                <TextInput
                    style={styles.input}
                    value={hips}
                    onChangeText={setHips}
                    keyboardType="numeric"
                    placeholder="Optional"
                />

                <View style={styles.buttonContainer}>
                    <Button
                        title={submitting ? "Submitting..." : "Submit Progress"}
                        onPress={submitProgress}
                        disabled={submitting}
                        color="#007BFF"
                    />
                </View>
            </ScrollView>
        </KeyboardAvoidingView>
    );
};

const styles = StyleSheet.create({
    container: { padding: 20 },
    input: {
        borderWidth: 1,
        borderColor: '#ccc',
        padding: 10,
        marginBottom: 15,
        borderRadius: 5,
    },
    label: {
        marginBottom: 5,
        fontWeight: 'bold',
    },
    buttonContainer: {
        marginTop: 10,
    },
});

export default ProgressInput;

// context/AuthContext.js

import React, { createContext, useState, useEffect } from 'react';
import * as SecureStore from 'expo-secure-store';

export const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
    const [authToken, setAuthToken] = useState(null);
    const [loading, setLoading] = useState(true);

    const SIGNIN_KEY = 'authToken';

    const signIn = async (token) => {
        setAuthToken(token);
        try {
            await SecureStore.setItemAsync(SIGNIN_KEY, token);
            console.log('Token stored successfully.');
        } catch (error) {
            console.error('Error storing the token:', error);
        }
    };

    const signOut = async () => {
        setAuthToken(null);
        try {
            await SecureStore.deleteItemAsync(SIGNIN_KEY);
            console.log('Token removed successfully.');
        } catch (error) {
            console.error('Error removing the token:', error);
        }
    };

    const loadToken = async () => {
        try {
            const token = await SecureStore.getItemAsync(SIGNIN_KEY);
            if (token) {
                setAuthToken(token);
                console.log('Token loaded from SecureStore:', token);
            } else {
                console.log('No token found.');
            }
        } catch (e) {
            console.log('Failed to load token:', e);
        } finally {
            setLoading(false);
        }
    };

    useEffect(() => {
        loadToken();
    }, []);

    return (
        <AuthContext.Provider value={{ authToken, signIn, signOut }}>
            {!loading && children}
        </AuthContext.Provider>
    );
};

backend

// middleware/auth.js
const jwt = require('jsonwebtoken');
require('dotenv').config(); // Ensure environment variables are loaded

/**
 * Authentication middleware to verify JWT tokens.
 */
const auth = (req, res, next) => {
    const authHeader = req.header('Authorization');

    if (!authHeader) {
        console.warn('No Authorization header provided.');
        return res.status(401).json({ message: 'No token, authorization denied' });
    }

    // The expected format is "Bearer <token>"
    const parts = authHeader.split(' ');
    if (parts.length !== 2 || parts[0] !== 'Bearer') {
        console.warn('Invalid Authorization header format.');
        return res.status(401).json({ message: 'Token is not valid' });
    }

    const token = parts[1];

    try {
        const decoded = jwt.verify(token, process.env.JWT_SECRET);
        req.user = decoded.userId; // Ensure your JWT payload contains `userId`
        console.log('Token verified. User ID:', req.user);
        next();
    } catch (err) {
        console.error('Token verification failed:', err);
        res.status(401).json({ message: 'Token is not valid' });
    }
}

module.exports = auth;

// controllers/authController.js

const jwt = require('jsonwebtoken');
const User = require('../models/User'); // Adjust the path as necessary

// Function to generate JWT
const generateToken = (userId) => {
    return jwt.sign(
        { userId },
        process.env.JWT_SECRET, // Ensure this matches the secret in auth.js
        { expiresIn: '1h' }      // Token validity duration
    );
};

// Login Function
const login = async (req, res) => {
    const { username, password } = req.body;

    try {
        // Find user by username
        const user = await User.findOne({ username });
        if (!user) {
            return res.status(400).json({ message: 'Invalid credentials' });
        }

        // Check if password matches
        const isMatch = await user.comparePassword(password); // Implement comparePassword in your User model
        if (!isMatch) {
            return res.status(400).json({ message: 'Invalid credentials' });
        }

        // Generate token
        const token = generateToken(user._id);

        // Return token to client
        res.json({ token });
    } catch (err) {
        console.error('Login error:', err);
        res.status(500).json({ message: 'Server error' });
    }
};

// Register Function (Optional)
const register = async (req, res) => {
    const { username, password } = req.body;

    try {
        // Check if user already exists
        let user = await User.findOne({ username });
        if (user) {
            return res.status(400).json({ message: 'User already exists' });
        }

        // Create new user
        user = new User({ username, password });
        await user.save();

        // Generate token
        const token = generateToken(user._id);

        // Return token to client
        res.json({ token });
    } catch (err) {
        console.error('Registration error:', err);
        res.status(500).json({ message: 'Server error' });
    }
};

module.exports = { login, register };

// models/Progress.js
const mongoose = require('mongoose');

const ProgressSchema = new mongoose.Schema({
    user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
    date: { type: Date, default: Date.now },
    weight: { type: Number }, // in kg or lbs
    muscleMass: { type: Number }, // in kg or appropriate unit
    fatPercentage: { type: Number },
    measurements: {
        chest: { type: Number },
        waist: { type: Number },
        hips: { type: Number },
        // Add more as needed
    },
}, { timestamps: true });

module.exports = mongoose.model('Progress', ProgressSchema);

// routes/auth.js
const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const User = require('../models/User');

// Register Route
router.post('/register', async (req, res) => {
    const { username, email, password, desiredPhysique, fitnessGoals, dietaryPreferences, dietaryRestrictions } = req.body;
    try {
        const existingUser = await User.findOne({ email });
        if (existingUser) {
            return res.status(400).json({ message: 'Email already in use' });
        }

        const newUser = new User({
            username,
            email,
            password,
            desiredPhysique,
            fitnessGoals,
            dietaryPreferences,
            dietaryRestrictions,
        });
        await newUser.save();

        const payload = { userId: newUser._id };
        const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '1h' });

        res.status(201).json({ token, message: 'User registered successfully' });
    } catch (err) {
        res.status(500).json({ error: err.message });
    }
});

// Login Route
router.post('/login', async (req, res) => {
    const { email, password } = req.body; // Changed from username to email for consistency
    try {
        const user = await User.findOne({ email });
        if (!user) return res.status(400).json({ message: 'Invalid credentials' });

        const isMatch = await user.comparePassword(password);
        if (!isMatch) return res.status(400).json({ message: 'Invalid credentials' });

        const payload = { userId: user._id };
        const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '1h' });

        res.json({ token, message: 'Login successful' });
    } catch(err) {
        res.status(500).json({ error: err.message });
    }
});

module.exports = router;

// routes/progress.js
const express = require('express');
const router = express.Router();
const Progress = require('../models/Progress');
const auth = require('../middleware/auth');

// Add Progress Entry
router.post('/', auth, async (req, res) => {
    const { weight, muscleMass, fatPercentage, measurements } = req.body;
    try {
        const progress = new Progress({
            user: req.user,
            weight,
            muscleMass,
            fatPercentage,
            measurements
        });
        await progress.save();
        res.status(201).json(progress);
    } catch (err) {
        res.status(500).json({ error: err.message });
    }
});

// Get Progress Entries
router.get('/', auth, async (req, res) => {
    try {
        const progresses = await Progress.find({ user: req.user }).sort({ date: 1 });
        res.json(progresses);
    } catch (err) {
        res.status(500).json({ error: err.message });
    }
});

module.exports = router;