Skip to content

Commit

Permalink
final push for tests and fixing minor bugs with code
Browse files Browse the repository at this point in the history
  • Loading branch information
Cabin320 committed May 17, 2024
1 parent 057462f commit bee73a5
Show file tree
Hide file tree
Showing 18 changed files with 384 additions and 165 deletions.
51 changes: 41 additions & 10 deletions client/src/pages/DashboardAppPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ import {useAuth} from '../context/AuthContext';
import {useEffect, useState} from "react";
import {FetchUserId, FetchCollection} from '../../src/sections/@dashboard/app/utils/index';


/**
* DashboardAppPage component renders the main dashboard page for authenticated users.
* It displays various sections of user data, including meals, exercise, goals, and more.
* If the user is an admin, it redirects to the AdminPage component.
* @returns {JSX.Element}
*/
export default function DashboardAppPage() {
const theme = useTheme();
const {email, name, isLoggedIn, isAdmin} = useAuth();
Expand All @@ -29,6 +36,7 @@ export default function DashboardAppPage() {
const [weightData, setWeightData] = useState([]);
const [isLoading, setIsLoading] = useState(true);

// Function to filter data by user ID
const filterDataByUserId = async (collection) => {
try {
const userId = await FetchUserId(email);
Expand All @@ -42,6 +50,7 @@ export default function DashboardAppPage() {
}
};

// Function to sum up calories in daily intake data
const sumCalories = () => {
return calorieBreakdown.reduce((total, item) => total + item.value, 0);
};
Expand All @@ -53,8 +62,9 @@ export default function DashboardAppPage() {
startDate.setDate(endDate.getDate() - 6);

const data = await FetchCollection("food");
const filteredData = data.filter(item => item.userEmail === email);

const allTimeMealCounts = data.reduce((counts, item) => {
const allTimeMealCounts = filteredData.reduce((counts, item) => {
counts[item.mealType] = (counts[item.mealType] || 0) + 1;
return counts;
}, {});
Expand All @@ -63,7 +73,7 @@ export default function DashboardAppPage() {
setMostCommonMealType(allTimeMostCommonMealType ? allTimeMostCommonMealType.charAt(0).toUpperCase() + allTimeMostCommonMealType.slice(1) : null);

const currentDate = new Date().toISOString().slice(0, 10);
const getDailyIntake = data.filter(item => item.userEmail === email && item.dateAdded === currentDate);
const getDailyIntake = filteredData.filter(item => item.dateAdded === currentDate);

setDailyIntake(getDailyIntake);
} catch (error) {
Expand Down Expand Up @@ -97,7 +107,11 @@ export default function DashboardAppPage() {
const exerciseData = await FetchCollection("exercises");
const mostCommonExerciseData = exerciseData.find(exercise => exercise._id === mostCommonExercise);

setMostCommonExerciseName(mostCommonExerciseData.exerciseName);
if (mostCommonExerciseData && mostCommonExerciseData.exerciseName) {
setMostCommonExerciseName(mostCommonExerciseData.exerciseName);
} else {
setMostCommonExerciseName('N/A');
}

} else if (collection === 'workoutHistory') {
setWorkoutHistoryData(filteredData);
Expand Down Expand Up @@ -153,18 +167,34 @@ export default function DashboardAppPage() {

const fetchGoals = async () => {
try {
const filteredData = await filterDataByUserId("goals");
const userId = await FetchUserId(email);

const fetchedGoals = filteredData.map(item => ({
goalName: item.goalName, achieveByDate: item.achieveByDate
}));
const data = await FetchCollection("goals");

if (data === null || !Array.isArray(data)) {
setGoals([]);
return;
}

const filteredData = data.filter(item => item.userId === userId);

if (filteredData.length === 0) {
setGoals([]);

setGoals(fetchedGoals);
} else {
const fetchedGoals = filteredData.map(item => ({
goalName: item.goalName, achieveByDate: item.achieveByDate,
}));

setGoals(fetchedGoals);
}
} catch (error) {
console.error("Error fetching goals:", error);
setGoals([]);
}
};


const fetchWeight = async () => {
try {
const data = await FetchCollection("weight");
Expand All @@ -191,7 +221,7 @@ export default function DashboardAppPage() {
}
};


// useEffect hook to calculate calorie breakdown when daily intake data changes
useEffect(() => {
if (dailyIntakeData.length > 0) {
const calorieCounts = dailyIntakeData.reduce((counts, item) => {
Expand All @@ -206,7 +236,7 @@ export default function DashboardAppPage() {
}
}, [dailyIntakeData]);


// useEffect hook to fetch data when component mounts or dependencies change
useEffect(() => {
Promise.all([fetchWorkout('workouts'), fetchWorkout('workoutHistory'), fetchFood(), fetchWeight(), fetchGoals(), fetchWorkoutHistory()])
.then(() => {
Expand All @@ -217,6 +247,7 @@ export default function DashboardAppPage() {
});
}, [email, goals,]);

// Conditional rendering based on isAdmin and isLoggedIn states
if (isAdmin) {
return <AdminPage/>;
}
Expand Down
27 changes: 21 additions & 6 deletions client/src/sections/@dashboard/app/AppCalorieBreakdown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ AppCalorieBreakdown.propTypes = {
chartData: PropTypes.array,
};

/**
* AppCalorieBreakdown component for displaying calorie breakdown data in a pie chart.
* @param {string} title - The title of the card.
* @param {string} subheader - The subheader of the card.
* @param {array} chartColors - Array of colors for the chart.
* @param {array} chartData - Array of objects containing data points for the chart.
* @returns {JSX.Element} - React component representing the calorie breakdown card.
*/
export default function AppCalorieBreakdown({title, subheader, chartColors, chartData, ...other}) {
const theme = useTheme();
const [loading, setLoading] = useState(true);
Expand Down Expand Up @@ -89,11 +97,18 @@ export default function AppCalorieBreakdown({title, subheader, chartColors, char
subheader={subheader}
action={<Button onClick={exportToCSV} variant="contained" color="primary">Export to CSV</Button>}
/>
{loading ? ( // Conditional rendering based on loading state
<div style={{display: 'flex', justifyContent: 'center', alignItems: 'center', height: CHART_HEIGHT}}>
<CircularProgress data-testid="loading-indicator"/>
</div>) : (<StyledChartWrapper dir="ltr">
<ReactApexChart type="pie" data-testid="chart" series={chartSeries} options={chartOptions} height={180}/>
</StyledChartWrapper>)}
<StyledChartWrapper dir="ltr">
{chartData.length === 0 ? ( // Check if chart data is empty
<div style={{display: 'flex', justifyContent: 'center', alignItems: 'center', height: CHART_HEIGHT}}>
No data available
</div>) : (loading ? ( // Conditional rendering based on loading state
<div
style={{display: 'flex', justifyContent: 'center', alignItems: 'center', height: CHART_HEIGHT}}>
<CircularProgress data-testid="loading-indicator"/>
</div>) : (
<ReactApexChart type="pie" data-testid="chart" series={chartSeries} options={chartOptions}
height={180}/>))}
</StyledChartWrapper>
</Card>);
}

20 changes: 16 additions & 4 deletions client/src/sections/@dashboard/app/AppDietaryTracking.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ AppDietaryTracking.propTypes = {
title: PropTypes.string, subheader: PropTypes.string, chartData: PropTypes.array.isRequired,
};

/**
* AppDietaryTracking component for displaying dietary tracking data.
* @param {string} title - The title of the card.
* @param {string} subheader - The subheader of the card.
* @param {array} chartData - Array of objects containing data points for the chart.
* @returns {JSX.Element} - React component representing the dietary tracking card.
*/
export default function AppDietaryTracking({title, subheader, chartData, ...other}) {
const [loading, setLoading] = useState(true);

Expand Down Expand Up @@ -49,16 +56,21 @@ export default function AppDietaryTracking({title, subheader, chartData, ...othe
link.click();
};

return (<Card {...other}>
return (<Card {...other} sx={{width: '100%', height: '100%'}}>
<CardHeader
title={title}
subheader={subheader}
action={<Button onClick={exportToCSV} variant="contained" color="primary">Export to CSV</Button>}
/>
{loading ? (<Box sx={{display: 'flex', justifyContent: 'center', alignItems: 'center', height: 364}}>
<CircularProgress data-testid="loading-indicator"/>
</Box>) : (<Box sx={{mx: 3}} dir="ltr">
<ReactApexChart type="line" data-testid="chart" series={[{data: chartSeries}]} options={chartOptions} height={364}/>
</Box>)}
</Box>) : (chartData.length === 0 ? (
<Box sx={{display: 'flex', justifyContent: 'center', alignItems: 'center', height: 364}}>
No data available
</Box>) : (<Box sx={{mx: 3}} dir="ltr">
<ReactApexChart type="line" data-testid="chart" series={[{data: chartSeries}]}
options={chartOptions} height={364}/>
</Box>))}
</Card>);
}

49 changes: 30 additions & 19 deletions client/src/sections/@dashboard/app/AppExerciseTracking.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ AppExerciseTracking.propTypes = {
chartLabels: PropTypes.arrayOf(PropTypes.string).isRequired,
};

/**
* AppExerciseTracking component for displaying exercise tracking data.
* @param {string} title - The title of the card.
* @param {string} subheader - The subheader of the card.
* @param {array} chartLabels - Array of labels for the tabs.
* @param {array} chartData - Array of objects containing data points for each tab.
* @returns {JSX.Element} - React component representing the exercise tracking card.
*/
export default function AppExerciseTracking({title, subheader, chartLabels, chartData, ...other}) {
const [tabIndex, setTabIndex] = useState(0);
const [loading, setLoading] = useState(true);
Expand Down Expand Up @@ -46,7 +54,7 @@ export default function AppExerciseTracking({title, subheader, chartLabels, char
const exportToCSV = () => {
const csvContent = 'data:text/csv;charset=utf-8,' + chartData.map((data, index) => {
const label = chartLabels[index];
const csvData = data.data.map((point) => `"${label}",${point.y}`);
const csvData = data.data.map((point) => `"${label}",${point}`);
return csvData.join('\n');
}).join('\n');
const encodedUri = encodeURI(csvContent);
Expand All @@ -57,29 +65,32 @@ export default function AppExerciseTracking({title, subheader, chartLabels, char
link.click();
};


return (<Card {...other}>
<CardHeader title={title}
subheader={subheader}
action={<Button onClick={exportToCSV} variant="contained" color="primary">Export to CSV</Button>}
/>
<Box sx={{p: 3, pb: 1}} dir="ltr">
<Tabs value={tabIndex} onChange={handleChangeTab} data-testid="chart-tab">
{chartLabels.map((label, index) => (<Tab key={index} label={label}/>))}
</Tabs>
{loading ? (<Box sx={{display: 'flex', justifyContent: 'center', alignItems: 'center', height: 300}}>
<CircularProgress data-testid="loading-indicator"/>
</Box>) : (<>
{chartData.map((data, index) => (<Box key={index} hidden={tabIndex !== index}>
return (<Box sx={{width: '100%', height: '100%'}}>
<Card {...other} sx={{width: '100%', height: '100%'}}>
<CardHeader
title={title}
subheader={subheader}
action={<Button onClick={exportToCSV} variant="contained" color="primary">Export to CSV</Button>}
/>
<Box sx={{p: 3, pb: 1}} dir="ltr">
<Tabs value={tabIndex} onChange={handleChangeTab} data-testid="chart-tab">
{chartLabels.map((label, index) => (<Tab key={index} label={label}/>))}
</Tabs>
{loading ? (<Box sx={{display: 'flex', justifyContent: 'center', alignItems: 'center', height: 300}}>
<CircularProgress data-testid="loading-indicator"/>
</Box>) : (chartData.length === 0 ? (
<Box sx={{display: 'flex', justifyContent: 'center', alignItems: 'center', height: 300}}>
No data available
</Box>) : (chartData.map((data, index) => (<Box key={index} hidden={tabIndex !== index}>
{tabIndex === index && (<ReactApexChart
type="bar"
series={[{data: data.data}]}
options={chartOptions}
height={300}
data-testid="bar-chart"
/>)}
</Box>))}
</>)}
</Box>
</Card>);
</Box>))))}
</Box>
</Card>
</Box>);
}
Loading

0 comments on commit bee73a5

Please sign in to comment.