Skip to content

Commit

Permalink
Merge pull request #37 from BUMETCS673/hw27_edit_profile
Browse files Browse the repository at this point in the history
Hw27 edit profile
  • Loading branch information
amanda-yee authored Oct 5, 2024
2 parents 4a61a23 + 4277238 commit fb62037
Show file tree
Hide file tree
Showing 4 changed files with 290 additions and 2 deletions.
14 changes: 13 additions & 1 deletion code/client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Home from "./components/Home.js";
import Login from "./components/Login.js";
import CreateUser from "./components/CreateUser.js";
import ViewUsers from "./components/ViewUsers.js";
import ManageProfile from "./components/ManageProfile.js";
import DailyData from "./components/DailyData.js";
import CreateGoal from "./components/CreateGoal.js";
import React, { useState, useEffect } from 'react';
Expand All @@ -28,7 +29,7 @@ import {

import HomeIcon from "@mui/icons-material/Home";
import LoginIcon from "@mui/icons-material/Login";
// import AccountCircleIcon from "@mui/icons-material/AccountCircle";
import AccountCircleIcon from "@mui/icons-material/AccountCircle";
import EditNoteIcon from "@mui/icons-material/EditNote";
import TrackChangesIcon from "@mui/icons-material/TrackChanges";
import CloseIcon from "@mui/icons-material/Close";
Expand Down Expand Up @@ -170,6 +171,16 @@ function App() {
</ListItemButton>
</ListItem>

<ListItem disablePadding>
<ListItemButton component={Link} to="/manage-profile">
<ListItemIcon>
{" "}
<AccountCircleIcon />{" "}
</ListItemIcon>
<ListItemText primary="Manage Profile" />
</ListItemButton>
</ListItem>

<ListItem disablePadding>
<ListItemButton component={Link} to="/view-users">
<ListItemIcon>
Expand Down Expand Up @@ -202,6 +213,7 @@ function App() {
<Route path="/" element={<Home />} />
<Route path="/create-user" element={<CreateUser />} />
<Route path="/view-users" element={<ViewUsers />} />
<Route path="/manage-profile" element={<ManageProfile />} />
<Route path="/login" element={<Login setIsAuthenticated={setIsAuthenticated} />} />
<Route path="/enter-daily-data" element={<DailyData />} />
<Route path="/create-goal" element={<CreateGoal />} />
Expand Down
223 changes: 223 additions & 0 deletions code/client/src/components/ManageProfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
import { useEffect, useState } from "react";
import apiClient from "../services/apiClient.js";
import { Box, Typography, TextField, MenuItem, Button } from "@mui/material";
import { box, bigTitle, inputBackground, menuPropsStyles, submitButton } from "./style/styles.js";

function ManageProfile() {

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

const [error, setError] = useState(null);
const [successMessage, setSuccessMessage] = useState('');
const [errorMessage, setErrorMessage] = useState('');

useEffect(() => {
apiClient
.get("/manage-profile") // Fetch user profile data from the backend (e.g., /manage-profile)
.then((res) => {
setProfileData(res.data);
})
.catch((err) => {
setError("Error fetching profile data. Try refreshing.");
console.log(err);
});
}, []);

// Handle input changes
const handleChange = (e) => {
const { name, value } = e.target;
setProfileData((prevData) => ({
...prevData,
[name]: value,
}));
};

// Handle input change for height
const handleHeightChange = (e) => {
const { name, value } = e.target;
setProfileData((prevData) => ({
...prevData,
height: { ...prevData.height, [name]: value },
}));
};

const handleDobChange = (e) => {
const { name, value } = e.target;
setProfileData((prevData) => ({
...prevData,
dob: { ...prevData.dob, [name]: Number(value) }, // Convert to Number
}));
};

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

// Clear any existing messages before processing the form
setSuccessMessage('');
setErrorMessage('');

try {
await apiClient.post("/manage-profile", profileData);
console.log("Updating profile")
setSuccessMessage('Profile updated!');
} catch (err) {
console.log("Error updating profile", err);
setErrorMessage('Error: Failed to update profile. Please try again');
}
};

return (
<Box sx={box}>
<Typography variant="h6" gutterBottom sx={bigTitle}>
Manage Profile
</Typography>
{/* If there is data returned, renders in below section */}
{error ? (
<p>{error}</p>
) : (
<form>
<TextField
label="User ID"
name="userId"
value={profileData.userId}
fullWidth
margin="normal"
InputProps={{
readOnly: true, // Makes it non-editable
}}
// sx={inputBackground}
menuprops={menuPropsStyles}
/>
<TextField
label="Email"
name="email"
value={profileData.email}
onChange={handleChange}
fullWidth
margin="normal"
InputProps={{
readOnly: true, // Makes it non-editable
}}
// sx={inputBackground}
menuprops={menuPropsStyles}
/>
<TextField
label="Name"
name="name"
value={profileData.name}
onChange={handleChange}
fullWidth
margin="normal"
sx={inputBackground}
menuprops={menuPropsStyles}
/>
<TextField
select
label="Gender"
name="gender"
value={profileData.gender}
onChange={handleChange}
fullWidth
margin="normal"
sx={inputBackground}
menuprops={menuPropsStyles}
>
<MenuItem value="male">Male</MenuItem>
<MenuItem value="female">Female</MenuItem>
<MenuItem value="nonbinary">Non-Binary</MenuItem>
<MenuItem value="na">Prefer not to disclose</MenuItem>
</TextField>
<TextField
label="Year of Birth"
name="year"
type="number"
value={profileData.dob.year}
onChange={handleDobChange}
margin="normal"
sx={inputBackground}
menuprops={menuPropsStyles}
/>
<TextField
select
label="Month of Birth"
name="month"
value={profileData.dob.month}
onChange={handleDobChange}
margin="normal"
sx={inputBackground}
menuprops={menuPropsStyles}
>
{Array.from({ length: 12 }, (_, index) => {
const monthNumber = index + 1; // Month numbers range from 1 to 12
return (
<MenuItem key={monthNumber} value={monthNumber}>
{monthNumber < 10 ? `0${monthNumber}` : monthNumber} {/* Format month as 01, 02, ... */}
</MenuItem>
);
})}
</TextField>
<TextField
select
label="Day of Birth"
name="day"
value={profileData.dob.day}
onChange={handleDobChange}
margin="normal"
sx={inputBackground}
menuprops={menuPropsStyles}
>
{Array.from({ length: 31 }, (_, index) => {
const dayNumber = index + 1; // Day numbers range from 1 to 31
return (
<MenuItem key={dayNumber} value={dayNumber}>
{dayNumber < 10 ? `0${dayNumber}` : dayNumber} {/* Format day as 01, 02, ... */}
</MenuItem>
);
})}
</TextField>
<br></br>
<TextField
label="Height (Feet)"
name="feet"
value={profileData.height.feet}
onChange={handleHeightChange}
type="number"
margin="normal"
sx={inputBackground}
menuprops={menuPropsStyles}
/>
<TextField
label="Height (Inches)"
name="inches"
value={profileData.height.inches}
onChange={handleHeightChange}
type="number"
margin="normal"
sx={inputBackground}
menuprops={menuPropsStyles}
/>
<Button
variant="contained"
color="primary"
onClick={handleSubmit}
fullWidth
sx={submitButton}
>
Update Profile
</Button>
</form>
)}
{errorMessage && <p style={{ color: '#E95D5C', fontWeight: "bold"}}>{errorMessage}</p>}
{successMessage && <p style={{ color: '#008000', fontWeight: "bold" }}>{successMessage}</p>}
</Box>
);
}

export default ManageProfile;
10 changes: 10 additions & 0 deletions code/server/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ let userSchema = new Schema({
email: { type: String, required: true },
passwordHashed: { type: String, required: true },
name: { type: String, required: true },
gender: { type: String, default: "na" },
dob: {
year: { type: Number, default: 1900, min: 1900, max: 2024 },
month: { type: Number, default: 1, min: 1, max: 12 },
day: { type: Number, default: 1, min: 1, max: 31 },
},
height: {
feet: { type: Number, default: 0, min: 0, max: 7 },
inches: { type: Number, default: 0, min: 0, max: 12 }
},
createdAt: { type: Date, default: Date.now },
goals: {type: [goalSchema], default: [] }
}, {
Expand Down
45 changes: 44 additions & 1 deletion code/server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,53 @@ app.get('/check-connection', async (req, res) => {
})

app.get('/view-users', async (req, res) => {
allUsers = await User.find({})
const allUsers = await User.find({})
res.json(allUsers)
})

app.get('/manage-profile', async (req, res) => {
try {
// TO DO: UPDATE THIS TO GRAB USER ID FROM LOCAL STORAGE, rather than hardcode
const userId = 10001 // req.userId;
const userProfile = await User.findOne({ userId });
if (!userProfile) {
return res.status(404).json({ error: "User not found" });
}
res.json(userProfile);
} catch (error) {
res.status(500).json({ error: "Server error" });
}
});

app.post('/manage-profile', async (req, res) => {
try {
const { userId, name, gender, dob, height } = req.body;

// Find user in the database using userId
const userProfile = await User.findOne({ userId });

// Check if user exists
if (!userProfile) {
return res.status(404).json({ error: "User not found" });
}

// Update the profile with the new values
userProfile.name = name;
userProfile.gender = gender;
userProfile.dob = dob;
userProfile.height = height;

// Save the updated user profile
await userProfile.save();

// Send a success response
res.status(200).json({ message: "Profile updated successfully", userProfile });
} catch (error) {
console.error(error); // Log the error for debugging
res.status(500).json({ message: "Error updating profile" });
}
});

app.post('/create-user', async (req, res) => {

try {
Expand Down

0 comments on commit fb62037

Please sign in to comment.