Skip to content

Commit

Permalink
Merge pull request #31 from csci5117s24/dev_final
Browse files Browse the repository at this point in the history
final optimization
  • Loading branch information
May-Wang-666 authored May 6, 2024
2 parents 65bb48d + 0a9b134 commit 51c6213
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 246 deletions.
39 changes: 18 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,34 @@ CSCI 5117, Spring 2024, [assignment description](https://canvas.umn.edu/courses/

## App Info:

* Team Name: WASD
* App Name: ???????
* App Link: <https://TODO.com/>
- Team Name: WASD
- App Name: Health Tracker
- App Link: <https://black-bay-07d1c5410.5.azurestaticapps.net/>

### Students

* Maurice Yu, [email protected]
* Dominic Deiman, [email protected]
* Ling Wang, [email protected]
* Salma Abdi, [email protected]
* Stuti Shah, [email protected]

- Maurice Yu, [email protected]
- Dominic Deiman, [email protected]
- Ling Wang, [email protected]
- Salma Abdi, [email protected]
- Stuti Shah, [email protected]

## Key Features

**Describe the most challenging features you implemented
(one sentence per bullet, maximum 4 bullets):**

* ...
- Using Cloudinary to store user pictures.
- Enabling unit switch for water log.
- Calculating and formatting statistic data.

Which (if any) device integration(s) does your app support?

* ...
- Camera

Which (if any) progressive web app feature(s) does your app support?

* ...


- ...

## Mockup images

Expand All @@ -44,9 +43,7 @@ Which (if any) progressive web app feature(s) does your app support?

**Is there anything special we need to know in order to effectively test your app? (optional):**

* ...


- ...

## Screenshots of Site (complete)

Expand All @@ -55,15 +52,15 @@ along with a very brief caption:**

![](https://media.giphy.com/media/o0vwzuFwCGAFO/giphy.gif)



## External Dependencies

**Document integrations with 3rd Party code or services here.
Please do not document required libraries (e.g., React, Azure serverless functions, Azure nosql).**

* Library or service name: description of use
* ...
- cloudinary/react & cloudinary/url-gen: for image storage
- react-chartjs-2: for displaying graphs
- react-liquid-gauge: beautiful UI for displaying progress
- react-loading: for displaying of loading state

**If there's anything else you would like to disclose about how your project
relied on external code, expertise, or anything else, please disclose that
Expand Down
9 changes: 4 additions & 5 deletions app/api/src/biz/exercise.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ async function GetWeeklyCalorieStats(userId, endDateStr) {
const calorieLogs = await FindFromMongo(collectionCalorieLog, {userId: userId, createdAt: {$gte: startTime, $lt: endTime}});
let calorieGoals = await FindFromMongo(collectionCalorieGoal, {userId: userId, createdAt: {$gte: startTime, $lt: endTime}});
if (!calorieGoals || calorieGoals.length === 0) {
let latestGoal = await GetLatestCalorieGoal();
let latestGoal = await GetLatestCalorieGoal(userId);
if (!latestGoal) {
latestGoal = {
goal: 0,
Expand All @@ -127,20 +127,19 @@ async function GetWeeklyCalorieStats(userId, endDateStr) {
}
calorieGoals = [latestGoal];
}

const stats = formatCalorieStats(calorieLogs, calorieGoals);

let res = [];
let j = calorieGoals.length-1;
let j = 0;
for (let i = 6; i >= 0; i--) {
let theDay = new Date(endDateStr);
theDay.setDate(theDay.getDate() - i);
const key = theDay.toLocaleDateString();
if (key in stats) {
res.push(stats[key]);
} else {
while (j > 0 && calorieGoals[j].createdAt > theDay) {
j--;
while (j < calorieGoals.length-1 && calorieGoals[j+1].createdAt > theDay) {
j++;
}
res.push({
date: FormatDate(theDay),
Expand Down
41 changes: 41 additions & 0 deletions app/api/src/biz/weight.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const { FindFromMongo } = require('../common/mongo');
const { FormatDate } = require('../common/utils');

const collectionWeightLog = "weightlog";
const oneDayInMilliSec = 1000 * 24 * 60 * 60;

module.exports = {
GetWeeklyWeightStats,
}


async function GetWeeklyWeightStats(userId, endDateStr) {
let startTime = new Date(endDateStr);
startTime.setDate(startTime.getDate() - 6);
let endTime = new Date(endDateStr);
endTime.setDate(endTime.getDate() + 1);
const weightLogs = await FindFromMongo(collectionWeightLog, {userId: userId, timestamp: {$gte: startTime.getTime(), $lt: endTime.getTime()}});
return formatStats(startTime, weightLogs);
}

async function formatStats(startTime, weightLogs) {
let stats = [];
let j = 0;
for (let i = 0; i < 7; i++) {
let theDay = new Date(startTime.toLocaleDateString());
theDay.setDate(theDay.getDate() + i);
const begin = startTime.getTime() + i * oneDayInMilliSec;
const end = startTime.getTime() + (i+1) * oneDayInMilliSec;
let stat = {
date: FormatDate(theDay),
unit: "kg"
};
if (j < weightLogs.length && weightLogs[j].timestamp >= begin && weightLogs[j].timestamp < end) {
stat.value = weightLogs[j].value;
stat.unit = weightLogs[j].unit;
j++
}
stats.push(stat);
}
return stats;
}
23 changes: 23 additions & 0 deletions app/api/src/functions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { app } = require('@azure/functions');
const { MongoClient, ObjectID} = require('mongodb');
const { FindByIDFromMongo, UpdateMongo, DeleteFromMongo, FindFromMongo } = require('../common/mongo');
const { FormatWaterLogs, GetWaterLogStatistics} = require('../biz/water');
const { GetWeeklyWeightStats } = require('../biz/weight');
const {
AddExerciseLog, UpdateExerciseLog, DeleteExerciseLog,
SetDailyCalorieGoal, GetDailyCalorieGoal, AddCalorieLog, DeleteCalorieLog,GetCalorieLogs, GetWeeklyCalorieStats,
Expand Down Expand Up @@ -867,3 +868,25 @@ app.http('getWaterLogStats', {
}
}
})


app.http('getWeeklyWeightStats', {
methods: ["GET"],
authLevel: "anonymous",
route: "weight/stats",
handler: async (request, context) => {
const token = await authenticate(request);
if (!token) {
return { status: 401 }
}
let endDateStr = request.query.get("endDate");
if (!endDateStr) {
endDateStr = new Date().toLocaleDateString();
}
const stats = await GetWeeklyWeightStats(token.userId, endDateStr);
return {
status: 200,
jsonBody: {stats: stats}
}
}
});
6 changes: 6 additions & 0 deletions app/src/css/theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
margin-bottom: 2rem;
}

@media all and (max-width:800px) {
.primary-title {
font-size: 1.5rem;
}
}

.secondary-title {
font-size: 2rem;
font-style: italic;
Expand Down
33 changes: 18 additions & 15 deletions app/src/routes/PageCalorie.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,20 @@ function PageCalorie() {

useEffect(()=>{
async function fetchData() {
const workoutList = await getWorkouts();
const calorieGoal = await getCalorieGoal();
const calorieLogs = await getCalorieLogs();
let curAchieved = 0;
if (calorieGoal) {
curAchieved = calAchieved(calorieLogs, calorieGoal.goal)
setGoal(calorieGoal.goal);
} else {
setEditGoal(true);
}
setWorkouts(workoutList);
setCalorieLogs(calorieLogs);
setAchieved(curAchieved);
Promise.all([
getWorkouts(),
getCalorieGoal(),
getCalorieLogs()
]).then(([workoutList, calorieGoal, calorieLogs]) => {
let curAchieved = 0;
if (calorieGoal) {
curAchieved = calAchieved(calorieLogs, calorieGoal.goal)
setGoal(calorieGoal.goal);
}
setWorkouts(workoutList);
setCalorieLogs(calorieLogs);
setAchieved(curAchieved);
}).catch(error=>{console.error(error)});
}
fetchData();
}, [])
Expand Down Expand Up @@ -136,6 +137,7 @@ function PageCalorie() {
<img src="/quote-right.svg" alt="quote"></img>
</div>
<div>
<div className='section'>
{editGoal ?
<div className='calorie-goal'>
<input type='text' value={goal} onChange={(e) => {handleGoalChange(e)}}></input>
Expand All @@ -144,13 +146,14 @@ function PageCalorie() {
<div className='calorie-goal'>
<span>Daily Calorie Goal: <span style={{fontWeight: 'bold'}}>{goal}</span></span> <button onClick={()=>{setEditGoal(true)}}>edit</button>
</div>}
<ProgressBar completed={achieved} bgColor="#836FFF"/>
<Link to="/exercise/calendar"> History</Link>
<div style={{padding: '0 10%'}}><ProgressBar completed={achieved} bgColor="#836FFF"/></div>
</div>
<h1 className='third-title'>You Workouts
<span className='title-link'><Link className='title-link' to="/exercise/workout"> Manage</Link></span>
</h1>
<WorkoutList workouts={workouts} addCalorieLog={addCalorieLog}/>
<h1 className='third-title'>You Exercise Log for Today</h1>
<Link to="/exercise/calendar" style={{color: 'var(--my-blue)'}}> History</Link>
<CaloriesLogList calorieLogs={calorieLogs} deleteLog={removeCalorieLog}/>
</div>
</div>
Expand Down
72 changes: 33 additions & 39 deletions app/src/routes/PageMain.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,54 +64,48 @@ function NotLoggedInMainPage() {
}

function DailyCharts() {
const [waterData, setWaterData] = useState({});
const [weightData, setWeightData] = useState({});
const [exerciseData, setExerciseData] = useState({});
const [loading, setLoading] = useState(true);
const placeHolderData = [ {label: "", value: 0},
{label: "", value: 0},
{label: "", value: 0},
{label: "", value: 0},
{label: "", value: 0},
{label: "", value: 0},
{label: "", value: 0}]

const mockdata = [ {label: "Apr 1", value: 2000},
{label: "Apr 2", value: 3000},
{label: "Apr 3", value: 3000},
{label: "Apr 4", value: 2500},
{label: "Apr 5", value: 0},
{label: "Apr 6", value: 300},
{label: "Apr 7", value: 3000},]
const [waterData, setWaterData] = useState(placeHolderData);
const [weightData, setWeightData] = useState(placeHolderData);
const [exerciseData, setExerciseData] = useState(placeHolderData);

useEffect(()=>{
async function fetchData() {
setLoading(true);

const today = new Date().toLocaleDateString();
const water = await SendGet("/api/water/stats", {rangeType: "days", dateStr: today});
setWaterData(water.dataset);
setWaterData(water.dataset);
setWeightData(mockdata);
const exercise = await SendGet("/api/calorie/stats", {endDate: today});
const chartData = exercise.stats.map((stat) => {return {label: stat.date, value: stat.calories}})
setExerciseData(chartData);
setLoading(false);
Promise.all([
SendGet("/api/water/stats", {rangeType: "days", dateStr: today}),
SendGet("/api/weight/stats", {endDate: today}),
SendGet("/api/calorie/stats", {endDate: today}),
]).then(([water, weight, exercise]) => {
const weightData = weight.stats.map((stat) => {return {label: stat.date, value: stat.value}});
const exerciseData = exercise.stats.map((stat) => {return {label: stat.date, value: stat.calories}})
setWaterData(water.dataset);
setWeightData(weightData);
setExerciseData(exerciseData);
}).catch(error=>{console.log(error)});
}
fetchData();
}, [])

if (loading) {
return (
<div className="main-page-body">
<ReactLoading type="bars" color="#14F3CB" />
return (
<div className="columns">
<div className="column is-one-third">
<LineChart dataset={waterData} title={"water drinking"}></LineChart>
</div>
)
} else {
return (
<div className="columns">
<div className="column is-one-third">
<LineChart dataset={waterData} title={"water drinking"}></LineChart>
</div>
<div className="column is-one-third">
<LineChart dataset={weightData} title={"weight change"}></LineChart>
</div>
<div className="column is-one-third">
<LineChart dataset={exerciseData} title={"calorie consumed"}></LineChart>
</div>
<div className="column is-one-third">
<LineChart dataset={weightData} title={"weight change"}></LineChart>
</div>
)
}
<div className="column is-one-third">
<LineChart dataset={exerciseData} title={"calorie consumed"}></LineChart>
</div>
</div>
)
}
7 changes: 6 additions & 1 deletion app/src/routes/PageWaterGoal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const WaterGoalRoute = {
const cmToInCoefficient = 0.3937007874;
const kgToLbsCoefficient = 2.20462;
const ozToMlCoefficient = 29.5735;
const mlToOzCoefficient = 0.033814;

async function getWaterGoal() {
const goal = await SendGet("/api/water/goal", {});
Expand All @@ -39,7 +40,11 @@ function PageWaterGoal() {
var weightInKg = weight.unit === "kg" ? weight.value : weight.value * (1.0/kgToLbsCoefficient);
var heightInCm = height.unit === "cm" ? height.value : height.value * (1.0/cmToInCoefficient);
var intakeInMl = Math.round((weightInKg + heightInCm) * 10);
setGoal({value: intakeInMl, unit: "ml"});
if(goal.unit === 'oz') {
setGoal({value: Math.round(intakeInMl*mlToOzCoefficient), unit: goal.unit})
} else {
setGoal({value: intakeInMl, unit: "ml"});
}
}

async function setWaterGoal() {
Expand Down
Loading

0 comments on commit 51c6213

Please sign in to comment.