Skip to content

Commit

Permalink
Merge pull request #61 from BUMETCS673/addUserIdToGoals
Browse files Browse the repository at this point in the history
Add user id to goals
  • Loading branch information
eddie27lee authored Oct 6, 2024
2 parents dc6c364 + 8a9c097 commit 001ceaa
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 66 deletions.
160 changes: 97 additions & 63 deletions code/client/src/components/CreateGoal.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React, { useState, useEffect } from "react"; // Added useEffect import
import apiClient from "../services/apiClient.js";
import React, { useState } from "react";
import { validateGoalForm } from '../utils/validateGoalForm.js';
import { authenticated } from "../utils/authenticate.js";

import {
Box,
Typography,
Expand All @@ -24,14 +23,43 @@ import {
} from "./style/styles.js";

function CreateGoal() {
authenticated();
// Profile Data State
const [profileData, setProfileData] = useState({
userId: "",
email: "",
name: "",
gender: "",
dob: { year: 1900, month: 1, day: 1 },
height: { feet: "", inches: "" },
});

const [goalFormData, setGoalFormData] = useState({
type: "",
targetValue: 0,
});

const [successMessage, setSuccessMessage] = useState('');
const [errorMessage, setErrorMessage] = useState('');
const [error, setError] = useState(null); // State for managing error when fetching profile

// useEffect to fetch profile data
useEffect(() => {
const token = authenticated();

if (token) {
apiClient
.get("/api/users/manage-profile", {
headers: { Authorization: `Bearer ${token}` },
}) // Fetch user profile data from the backend
.then((res) => {
setProfileData(res.data); // Set the fetched profile data
})
.catch((err) => {
setError("Error fetching profile data. Try refreshing.");
console.log(err);
});
}
}, []); // Empty dependency array to run only once after the component mounts

// Handle input changes
const handleChange = (e) => {
Expand All @@ -42,85 +70,86 @@ function CreateGoal() {
}));
};

// Function to handle the form submission event
const handleSubmit = (event) => {
event.preventDefault(); // Prevent default form submission behavior (e.g., page reload)

// Clear any existing messages before processing the form
clearMessages();

// Validate the form and, if valid, proceed with goal creation
if (validateAndSetMessages(goalFormData)) {
createGoal(goalFormData);
}
};

// Function to clear any success or error messages
const clearMessages = () => {
setSuccessMessage('');
setErrorMessage('');
};

// Function to validate the goal form and handle validation messages
const validateAndSetMessages = (formData) => {
const validationResult = validateGoalForm(formData);

if (!validationResult.isValid) {
setErrorMessage('Error: Please review your inputs and try again');
return false; // Prevent form submission if validation fails
}

return true;
};

// Function to create a new goal by making a POST request
const createGoal = async (formData) => {
try {
console.log("Creating new goal with data:", formData);
// Sends a POST request to the backend with the form data
await apiClient.post("/api/goals/create-goal", formData);
handleGoalSuccess(); // Handle the success case
} catch (error) {
handleGoalError(error); // Handle the error case
}
};

// Function to handle a successful goal creation
const handleGoalSuccess = () => {
console.log("Goal created successfully!");
setSuccessMessage('New goal successful!');
};

// Function to handle errors during goal creation
const handleGoalError = (error) => {
console.error("Error creating goal:", error);
setErrorMessage('Failed to create a new goal. Please try again.');
};
// Function to handle the form submission event
const handleSubmit = (event) => {
event.preventDefault(); // Prevent default form submission behavior
clearMessages();

if (validateAndSetMessages(goalFormData)) {
createGoal(goalFormData);
}
};

// Clear messages
const clearMessages = () => {
setSuccessMessage('');
setErrorMessage('');
};

// Validate form
const validateAndSetMessages = (formData) => {
const validationResult = validateGoalForm(formData);
if (!validationResult.isValid) {
setErrorMessage('Error: Please review your inputs and try again');
return false;
}
return true;
};

// Create goal
const createGoal = async (formData) => {
try {
console.log("Creating new goal with data:", formData);

const token = authenticated();
console.log("Token:", token);

await apiClient.post("/api/goals/create-goal", formData, {
headers: { Authorization: `Bearer ${token}` }, // Pass token
});

handleGoalSuccess();
} catch (error) {
handleGoalError(error);
}
};

// Handle success
const handleGoalSuccess = () => {
console.log("Goal created successfully!");
setSuccessMessage('New goal successful!');
};

// Handle error
const handleGoalError = (error) => {
console.error("Error creating goal:", error);
setErrorMessage('Failed to create a new goal. Please try again.');
};

return (
<Box sx={box}>
<Typography variant="h6" gutterBottom sx={title}>
Set up your goal here:
</Typography>
{/* Set up your goal here: */}
<form onSubmit={handleSubmit}>
<Grid2 container spacing={2}>
{/* Select a goal type */}
{/* Select a goal type */}
<Grid2 item xs={12} md={6}>
<FormControl fullWidth>
<InputLabel sx={inputLable}>Select a goal type</InputLabel>
<Select
data-testid="goal-type-select"
name="type" // Add name to ensure proper handling
name="type"
value={goalFormData.type}
onChange={handleChange}
label="Select a goal type"
sx={inputBackground}
MenuProps={menuPropsStyles}
>
<MenuItem value="sleep">Sleep (Hours)</MenuItem>
<MenuItem data-testid="goal-type-weight" value="weight">Weight (lbs)</MenuItem>
<MenuItem data-testid="goal-type-weight" value="weight">
Weight (lbs)
</MenuItem>
<MenuItem value="steps">Steps (Step Count)</MenuItem>
<MenuItem value="water">Water Intake (Glasses)</MenuItem>
<MenuItem value="exercise">Exercise (Minutes)</MenuItem>
Expand Down Expand Up @@ -156,9 +185,14 @@ const handleGoalError = (error) => {
</Grid2>
</Grid2>
</form>
{errorMessage && <p style={{ color: '#E95D5C', fontWeight: "bold"}}>{errorMessage}</p>}
{successMessage && <p style={{ color: '#008000', fontWeight: "bold" }}>{successMessage}</p>}
{errorMessage && (
<p style={{ color: "#E95D5C", fontWeight: "bold" }}>{errorMessage}</p>
)}
{successMessage && (
<p style={{ color: "#008000", fontWeight: "bold" }}>{successMessage}</p>
)}
</Box>
);
}

export default CreateGoal;
28 changes: 25 additions & 3 deletions code/server/controllers/goalController.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
// controllers/goalController.js
const Goal = require('../models/Goal');
const jwt = require('jsonwebtoken');

// Create a new goal
exports.createGoal = async (req, res) => {
try {
const { type, targetValue } = req.body;

// Get token from Authorization header
const authHeader = req.headers['authorization'];
if (!authHeader) {
return res.status(401).json({ message: 'Authorization header is missing' });
}

const token = authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ message: 'Token is missing' });
}

// Verify and decode the token
const secretKey = process.env.SECRET_KEY;
if (!secretKey) {
return res.status(500).json({ message: 'Secret key is missing in the environment variables' });
}

const decoded = jwt.verify(token, secretKey);
const userId = decoded.userId;

// Goal creation logic
let lastGoal = await Goal.find().sort({ goalId: -1 }).limit(1);
let newGoalId = lastGoal.length > 0 ? lastGoal[0].goalId + 1 : 1;

Expand All @@ -19,12 +41,12 @@ exports.createGoal = async (req, res) => {
default: unit = 'unknown';
}

const newGoal = new Goal({ goalId: newGoalId, type, targetValue, unit });
const newGoal = new Goal({ goalId: newGoalId, type, targetValue, unit, userId });
await newGoal.save();

res.status(201).json({ message: 'New goal created successfully', goalId: newGoalId });
} catch (error) {
console.error("Error creating goal:", error); // Log the actual error
res.status(500).json({ message: 'Failed to create goal' });
}
};

};
1 change: 1 addition & 0 deletions code/server/models/Goal.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const goalSchema = new Schema({
unit: { type: String, required: true },
createdAt: { type: Date, default: Date.now },
progress: { type: [progressSchema], default: [] }, // Array of progress entries
userId: { type: Number, required: false }
}, {
collection: 'goals', // Specify the collection name
});
Expand Down

0 comments on commit 001ceaa

Please sign in to comment.