Skip to content

Commit

Permalink
Merge pull request #68 from BUMETCS673/HW_104_View_Submitted_Health_Data
Browse files Browse the repository at this point in the history
can view and delete data and can only make one entry per day
  • Loading branch information
kenlight-bu authored Oct 7, 2024
2 parents e6f22ce + 4bee7b2 commit 9847dca
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 39 deletions.
2 changes: 1 addition & 1 deletion code/client/src/components/DailyData.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function DailyData() {
return (
<Box sx={box}>
<Typography variant="h6" gutterBottom sx={title}>
Enter your data here:
Enter your data for the day:
</Typography>

<form onSubmit={handleSubmit}>
Expand Down
68 changes: 51 additions & 17 deletions code/client/src/components/ManageDailyData.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,67 @@
//will update this file with better error handling as per Mosh video

import { useEffect, useState } from "react";
import apiClient from "../services/apiClient.js";
import { authenticated } from "../utils/authenticate.js";
import {
Box,
Typography
} from "@mui/material";
import { box, bigTitle } from "./style/styles.js";
import { box, bigTitle, dailyDataEntryCard, dailyDataEntryCardHeader, dailyDataEntryCardDelete } from "./style/styles.js";

function ManageDailyData() {
const token = authenticated()

const [data, setData] = useState([{}]);
const [error, setError] = useState(null);

useEffect(() => {
const token = authenticated()
fetchDailyData(); // Fetch daily data on component mount
}, [token]); // Add token as a dependency


const fetchDailyData = () => {
if (token) {
apiClient
.get("/api/daily-entry/view-daily-data", {
headers: { Authorization: `Bearer ${token}` }
}) // Fetch user profile data from the backend (e.g., /manage-profile)
})
.then((res) => {
setData(res.data);
})
.catch((err) => {
setError("Error fetching data. Try refreshing.");
console.log(err);
});
}
};


const formatDate = (dateString) => {
const dateObj = new Date(dateString)
const formattedDate = dateObj.toLocaleDateString('en-US', {
month: 'long', // Full month name (like "October")
day: 'numeric', // Day of the month (no leading zero needed)
year: 'numeric' // Full year
});
return formattedDate
}


const deleteEntry = (dailyEntryId) => {
if (token) {
apiClient
.delete("/api/daily-entry/delete-entry", {
headers: { Authorization: `Bearer ${token}` },
data: { dailyEntryId }
})
.then((res) => {
setData(res.data);
fetchDailyData();
})
.catch((err) => {
setError("Error fetching data. Try refreshing.");
console.log(err);
});
}

// apiClient
// .get("/api/daily-entry/view-daily-data")
// .then((res) => {
// setData(res.data);
// })
// .catch((err) => {
// console.log(err);
// });
}, []);
}

return (
<Box sx={box}>
Expand All @@ -49,7 +71,19 @@ function ManageDailyData() {
{typeof data === "undefined" ? (
<p>Loading...</p>
) : (
<p>`{JSON.stringify(data)}`</p>
data.map((dailyData, i) => (
<div style={dailyDataEntryCard} key={i}>
<div style={dailyDataEntryCardDelete} onClick={() => deleteEntry(dailyData.dailyEntryId)}>
DELETE
</div>
<div style={dailyDataEntryCardHeader}>
{formatDate(dailyData.entryDate)}:
</div>
<div>
Weight = {dailyData.weight} | Steps = {dailyData.steps} | Sleep = {dailyData.sleep} | Water = {dailyData.water} | Exercise = {dailyData.exercise}
</div>
</div>
))
)}
</Box>
);
Expand Down
27 changes: 27 additions & 0 deletions code/client/src/components/style/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,30 @@ export const calendarStyle = {
marginBottom: "4%",
};


//ManageDailyData
export const dailyDataEntryCard = {
marginBottom: "1em",
padding: ".5em",
borderColor: "gray",
borderWidth: "1px",
borderStyle: "solid",
borderRadius: "10px",
}

export const dailyDataEntryCardHeader = {
fontWeight: "bold"
}

export const dailyDataEntryCardDelete = {
color: "red",
fontSize: ".6em",
fontWeight: "bold",
cursor: 'pointer',
marginBottom: '.5em',
}


// DailyData - side menu
export const sideMenuBox = {
position: "absolute",
Expand Down Expand Up @@ -212,3 +236,6 @@ export const dashboardLineChartContainer = {
height: "200px",
marginBottom: "50px"
}



119 changes: 99 additions & 20 deletions code/server/controllers/dailyEntryController.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const jwt = require('jsonwebtoken');
// Enter daily data
exports.enterDailyData = async (req, res) => {
try {

// GET THE USER ID

// Get token from Authorization header
const authHeader = req.headers['authorization'];
if (!authHeader) {
Expand All @@ -22,28 +25,60 @@ exports.enterDailyData = async (req, res) => {
// Extract userId from the decoded token
const userId = decoded.userId;

// console.log("Request body: ", req.body);


//GET THE REQUEST BODY DATA

const { weight, steps, sleep, water, exercise, entryDate } = req.body;

let lastEntry = await DailyEntry.find().sort({ dailyEntryId: -1 }).limit(1);
let newEntryId = lastEntry.length > 0 ? lastEntry[0].dailyEntryId + 1 : 1;

const newDailyEntry = new DailyEntry({
dailyEntryId: newEntryId,

//EITHER update data (if an entry exists with the given day) or create a new daily entry

// Simplify entry date to the start of the day
const entryDateStart = new Date(entryDate ? entryDate : Date.now());
entryDateStart.setHours(0, 0, 0, 0);

// Check if an entry for this date already exists for this user
const existingEntry = await DailyEntry.findOne({
userId: userId,
// entryDate: new Date(), // Adjust according to your form logic
entryDate: entryDate ? new Date(entryDate) : new Date(),
weight,
steps,
sleep,
water,
exercise,
entryDate: {
$gte: entryDateStart, // Date should be >= 00:00:00 of the entry date
$lt: new Date(entryDateStart.getTime() + 24 * 60 * 60 * 1000) // Less than the start of the next day
}
});

await newDailyEntry.save();
res.status(201).json({ message: "Daily entry created successfully!" });
if (existingEntry) {
// If an entry exists, update it
existingEntry.weight = weight;
existingEntry.steps = steps;
existingEntry.sleep = sleep;
existingEntry.water = water;
existingEntry.exercise = exercise;

await existingEntry.save();
return res.status(200).json({ message: "Daily entry updated successfully!" });
} else {
// If no entry exists for this day, create a new one
let lastEntry = await DailyEntry.find().sort({ dailyEntryId: -1 }).limit(1);
let newEntryId = lastEntry.length > 0 ? lastEntry[0].dailyEntryId + 1 : 1;

const newDailyEntry = new DailyEntry({
dailyEntryId: newEntryId,
userId: userId,
entryDate: entryDateStart,
weight,
steps,
sleep,
water,
exercise,
});

await newDailyEntry.save();
return res.status(201).json({ message: "Daily entry created successfully!" });
}
} catch (error) {
res.status(500).json({ message: "Error creating daily entry" });
res.status(500).json({ message: "Error creating or updating daily entry" });
}
};

Expand Down Expand Up @@ -72,15 +107,59 @@ exports.viewDailyData = async (req,res) => {
// Extract userId from the decoded token
const userId = decoded.userId;

const userProfile = await User.findOne({ userId });
const userDailyData = await DailyEntry.find({ userId: userId });

if (!userProfile) {
return res.status(404).json({ message: 'User not found' });
if (!userDailyData) {
return res.status(404).json({ message: 'User daiy data not found' });
}

res.json(userProfile);
res.json(userDailyData);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server error' });
}
}
}

//Delete a daily entry
exports.deleteEntry = async (req, res) => {
try {
// 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;
const decoded = jwt.verify(token, secretKey);

// Extract userId from the decoded token
const userId = decoded.userId;

// Extract dailyEntryId from the request (passed in body, params, or query)
const { dailyEntryId } = req.body; // or req.params.dailyEntryId

if (!dailyEntryId) {
return res.status(400).json({ message: 'dailyEntryId is required' });
}

// Find and delete the entry by dailyEntryId and userId (to ensure user owns the entry)
const deletedEntry = await DailyEntry.findOneAndDelete({
dailyEntryId: dailyEntryId,
userId: userId
});

if (deletedEntry) {
return res.status(200).json({ message: 'Daily entry deleted successfully!' });
} else {
return res.status(404).json({ message: 'Daily entry not found' });
}

} catch (error) {
res.status(500).json({ message: 'Error deleting daily entry' });
}
};
3 changes: 2 additions & 1 deletion code/server/routes/dailyEntryRoutes.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// routes/dailyEntryRoutes.js
const express = require('express');
const { enterDailyData, viewDailyData } = require('../controllers/dailyEntryController');
const { enterDailyData, viewDailyData, deleteEntry } = require('../controllers/dailyEntryController');
const router = express.Router();

// Enter daily data
router.post('/enter-daily-data', enterDailyData);
router.get('/view-daily-data', viewDailyData);
router.delete('/delete-entry', deleteEntry)

module.exports = router;

0 comments on commit 9847dca

Please sign in to comment.