Skip to content

Commit 253c57a

Browse files
authored
Prepared closest events and announcements sections on dashboard (#86)
1 parent 2162976 commit 253c57a

File tree

6 files changed

+252
-70
lines changed

6 files changed

+252
-70
lines changed

src/components/shared/appBar/AppBar.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ function AppBar() {
3434
position: 'sticky',
3535
background: 'white',
3636
top: 0,
37+
zIndex: '999',
3738
}}
3839
>
3940
<Box className="AppBarBox">

src/components/viewsComponents/dashboard/Dashboard.scss

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,4 @@
44
grid-template-columns: min-content auto;
55
gap: 16px;
66
margin-bottom: 16px;
7-
8-
.AvatarBox {
9-
display: grid;
10-
grid-template-columns: 1fr;
11-
justify-items: center;
12-
gap: 1rem;
13-
padding: 2rem;
14-
15-
}
16-
17-
@media (max-width: '700px') {
18-
grid-template-columns: 1fr;
19-
}
207
}

src/components/viewsComponents/dashboard/Dashboard.tsx

Lines changed: 28 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,54 @@
11
import { useSelector } from 'react-redux';
2-
import { useNavigate } from 'react-router-dom';
3-
import { Box, Button, Paper, Typography, useMediaQuery } from '@mui/material';
2+
import { Box, useMediaQuery } from '@mui/material';
43
import CenteredLoader from 'components/shared/centeredLoader/CenteredLoader';
54
import TodoListDrawer from 'components/shared/todoListDrawer/TodoListDrawer';
6-
import _ from 'lodash';
75
import { useGetStudentGradesQuery } from 'redux/apiSlices/academics/Grades.Api.Slice';
86
import { selectId, useGetLoggedAccountBasicDataQuery } from 'redux/apiSlices/loggedAccount/LoggedAccount.Api.Slice';
9-
import { calculateAverageGrade } from '../grades/elements/gradesInformationBoxes/GradesInformationBoxes';
10-
import GradesDonutChart from './elements/GradesDonutChart';
7+
import Announcements from './elements/Announcements';
8+
import ClosestEvents from './elements/ClosestEvents';
9+
import GradesSection from './elements/GradesSection';
1110
import type { IGetStudentGradesQueryParams } from 'contract/slices/academics/Grades.Interfaces';
1211
import './Dashboard.scss';
1312

1413
function Dashboard() {
15-
const navigate = useNavigate();
16-
const studentId = useSelector(selectId);
1714
const isMobile = useMediaQuery('(max-width: 500px)');
1815
const maxDrawerWidth = isMobile ? 280 : 450;
19-
const { data } = useGetLoggedAccountBasicDataQuery();
16+
17+
const { data: userData, isFetching: isFetchingUserData } = useGetLoggedAccountBasicDataQuery();
18+
19+
const studentId = useSelector(selectId);
2020
const initialQueryParams: IGetStudentGradesQueryParams = { studentId: studentId! };
21-
const { data: grades, isFetching } = useGetStudentGradesQuery(initialQueryParams, { skip: !studentId });
21+
const { data: grades, isFetching: isFetchingGrades } = useGetStudentGradesQuery(initialQueryParams, {
22+
skip: !studentId,
23+
});
24+
25+
const isFetching = isFetchingUserData || isFetchingGrades;
2226

23-
if (isFetching || !data) {
27+
if (isFetching || !userData) {
2428
return <CenteredLoader />;
2529
}
2630

27-
const averageGrade = calculateAverageGrade(grades ?? []);
28-
const gradeGroups = _.groupBy(grades, 'grade');
29-
const groupedData = [
30-
{ grade: '2', count: gradeGroups[2]?.length ?? 0, fill: '#c40101' },
31-
{ grade: '3', count: gradeGroups[3]?.length ?? 0, fill: '#ff9800' },
32-
{ grade: '4', count: gradeGroups[4]?.length ?? 0, fill: '#2196f3' },
33-
{ grade: '5', count: gradeGroups[5]?.length ?? 0, fill: '#09750d' },
34-
];
35-
3631
return (
37-
<Box>
38-
<Paper
32+
<Box sx={{ p: 5 }}>
33+
<Box
3934
sx={{
4035
display: 'flex',
4136
flexWrap: 'wrap',
42-
gap: 2,
43-
alignContent: 'center',
44-
p: 4,
45-
width: 'fit-content',
46-
47-
'@media (max-width: 650px)': {
48-
px: 2,
49-
},
37+
gap: 6,
5038
}}
5139
>
52-
<Box
53-
sx={{
54-
display: 'flex',
55-
flexDirection: 'column',
56-
justifyContent: 'center',
57-
gap: 3,
58-
flex: 1,
59-
minWidth: '180px',
60-
}}
61-
>
62-
<Typography variant="h4" color="#524e61" fontWeight="bold">
63-
Hi, <span style={{ whiteSpace: 'nowrap' }}> {`${data.name} ${data.surname}!`}</span>
64-
</Typography>
65-
<Typography variant="body1" color="text.secondary">
66-
Check your performance stats <br /> to make sure you are on track <br /> with your academic goals!
67-
</Typography>
68-
<Button
69-
variant="text"
70-
sx={{ whiteSpace: 'nowrap', maxWidth: '100px' }}
71-
onClick={() => {
72-
navigate('/postAuth/academics/grades');
73-
}}
74-
>
75-
See all Grades
76-
</Button>
40+
<Box>
41+
<GradesSection grades={grades} userData={userData} />
42+
</Box>
43+
<Box>
44+
<ClosestEvents />
7745
</Box>
78-
<GradesDonutChart groupedData={groupedData} averageGrade={averageGrade} />
79-
</Paper>
80-
<Typography variant="h5"> Due missing data, content will cooming soon!</Typography>
46+
47+
<Box>
48+
<Announcements />
49+
</Box>
50+
</Box>
51+
8152
<TodoListDrawer maxDrawerWidth={maxDrawerWidth} />
8253
</Box>
8354
);
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React from 'react';
2+
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
3+
import { Typography, List, ListItem, Paper, Box } from '@mui/material';
4+
5+
interface IMessage {
6+
id: number;
7+
title: string;
8+
body: string;
9+
date: string;
10+
}
11+
12+
const messages: IMessage[] = [
13+
{
14+
id: 1,
15+
title: 'Welcome to the Semester!',
16+
body: 'We hope you have a great start to the semester. Remember to check your schedules and prepare for the first week of classes.',
17+
date: '2024-01-15',
18+
},
19+
{
20+
id: 2,
21+
title: 'Library System Maintenance',
22+
body: 'The library system will be undergoing maintenance on January 20th from 8 PM to 12 AM. Please plan accordingly.',
23+
date: '2024-01-18',
24+
},
25+
{
26+
id: 3,
27+
title: 'Course Enrollment Deadline',
28+
body: 'The last date to add or drop courses for this semester is January 25th. Make sure to finalize your schedules.',
29+
date: '2024-01-22',
30+
},
31+
];
32+
33+
const Messages: React.FC = () => {
34+
return (
35+
<Paper
36+
sx={{
37+
display: 'flex',
38+
flexDirection: 'column',
39+
gap: 2,
40+
alignContent: 'center',
41+
p: 4,
42+
}}
43+
>
44+
<Typography variant="h5" color="#524e61" fontWeight="bold" gutterBottom>
45+
Latest Messages from Administration
46+
</Typography>
47+
<List>
48+
{messages.map(message => (
49+
<ListItem
50+
key={message.id}
51+
sx={{
52+
borderBottom: '1px solid #ddd',
53+
paddingLeft: 0,
54+
alignItems: 'flex-start',
55+
':last-child': {
56+
borderBottom: 'none',
57+
},
58+
flexDirection: 'column',
59+
gap: 1,
60+
}}
61+
>
62+
<Typography variant="subtitle1" component="div" sx={{ fontWeight: 'bold' }}>
63+
{message.title}
64+
</Typography>
65+
<Typography variant="body2" color="text.secondary" sx={{ color: '#555' }} component="div">
66+
{message.body}
67+
</Typography>
68+
<Box
69+
sx={{
70+
display: 'flex',
71+
alignItems: 'center',
72+
gap: 0.5,
73+
color: '#888',
74+
}}
75+
>
76+
<CalendarMonthIcon fontSize="small" />
77+
<Typography variant="caption" component="span">
78+
{new Date(message.date).toLocaleDateString()}
79+
</Typography>
80+
</Box>
81+
</ListItem>
82+
))}
83+
</List>
84+
</Paper>
85+
);
86+
};
87+
88+
export default Messages;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import React from 'react';
2+
import EventIcon from '@mui/icons-material/Event';
3+
import { Typography, List, ListItem, Paper, Box } from '@mui/material';
4+
5+
const calculateFutureDate = (daysToAdd: number): Date => {
6+
const today = new Date();
7+
today.setDate(today.getDate() + daysToAdd);
8+
return today;
9+
};
10+
11+
const events = [
12+
{ id: 1, title: 'Orientation Day', date: calculateFutureDate(2) },
13+
{ id: 2, title: 'Midterm Exams', date: calculateFutureDate(30) },
14+
{ id: 3, title: 'Career Fair', date: calculateFutureDate(50) },
15+
];
16+
17+
const ClosestEvents: React.FC = () => {
18+
return (
19+
<Paper
20+
sx={{
21+
display: 'flex',
22+
flexDirection: 'column',
23+
gap: 1,
24+
p: 2,
25+
width: 'fit-content',
26+
minHeight: '289px',
27+
}}
28+
>
29+
<Typography variant="h5" color="#524e61" fontWeight="bold">
30+
Closest Upcoming Events
31+
</Typography>
32+
<List>
33+
{events.map(event => (
34+
<ListItem
35+
key={event.id}
36+
sx={{
37+
borderBottom: '1px solid #ddd',
38+
paddingLeft: 0,
39+
alignItems: 'flex-start',
40+
':last-child': {
41+
borderBottom: 'none',
42+
},
43+
flexDirection: 'column',
44+
}}
45+
>
46+
<Typography variant="subtitle1" component="div" sx={{ fontWeight: 'bold' }}>
47+
{event.title}
48+
</Typography>
49+
<Box
50+
sx={{
51+
display: 'flex',
52+
alignItems: 'center',
53+
gap: 0.5,
54+
color: '#888',
55+
}}
56+
>
57+
<EventIcon fontSize="small" />
58+
<Typography variant="caption" component="span">
59+
{new Date(event.date).toLocaleDateString()}
60+
</Typography>
61+
</Box>
62+
</ListItem>
63+
))}
64+
</List>
65+
</Paper>
66+
);
67+
};
68+
69+
export default ClosestEvents;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { useNavigate } from 'react-router-dom';
2+
import { Typography, Paper, Box, Button } from '@mui/material';
3+
import { calculateAverageGrade } from 'components/viewsComponents/grades/elements/gradesInformationBoxes/GradesInformationBoxes';
4+
import _ from 'lodash';
5+
import GradesDonutChart from './GradesDonutChart';
6+
import type { IGrade } from 'contract/interfaces/academics/Academics';
7+
import type { IGetLoggedAccountBasicDataTransformedReponse } from 'contract/slices/loggedAccount/LoggedAccount';
8+
9+
interface GradesSectionProps {
10+
grades?: IGrade[];
11+
userData: IGetLoggedAccountBasicDataTransformedReponse;
12+
}
13+
14+
const GradesSection: React.FC<GradesSectionProps> = ({ grades, userData }) => {
15+
const navigate = useNavigate();
16+
17+
const averageGrade = calculateAverageGrade(grades ?? []);
18+
const gradeGroups = _.groupBy(grades, 'grade');
19+
const groupedData = [
20+
{ grade: '2', count: gradeGroups[2]?.length ?? 0, fill: '#c40101' },
21+
{ grade: '3', count: gradeGroups[3]?.length ?? 0, fill: '#ff9800' },
22+
{ grade: '4', count: gradeGroups[4]?.length ?? 0, fill: '#2196f3' },
23+
{ grade: '5', count: gradeGroups[5]?.length ?? 0, fill: '#09750d' },
24+
];
25+
26+
return (
27+
<Paper
28+
sx={{
29+
display: 'flex',
30+
flexWrap: 'wrap',
31+
gap: 2,
32+
p: 4,
33+
width: 'fit-content',
34+
}}
35+
>
36+
<Box
37+
sx={{
38+
display: 'flex',
39+
flexDirection: 'column',
40+
gap: 3,
41+
flex: 1,
42+
minWidth: '180px',
43+
}}
44+
>
45+
<Typography variant="h5" color="#524e61" fontWeight="bold">
46+
Hi, <span>{`${userData.name} ${userData.surname}!`}</span>
47+
</Typography>
48+
<Typography variant="body1" color="text.secondary">
49+
Check your performance stats <br /> to make sure you are on track <br /> with your academic goals!
50+
</Typography>
51+
<Button
52+
variant="text"
53+
sx={{ whiteSpace: 'nowrap', maxWidth: '100px' }}
54+
onClick={() => {
55+
navigate('/postAuth/academics/grades');
56+
}}
57+
>
58+
See all Grades
59+
</Button>
60+
</Box>
61+
<GradesDonutChart groupedData={groupedData} averageGrade={averageGrade} />
62+
</Paper>
63+
);
64+
};
65+
66+
export default GradesSection;

0 commit comments

Comments
 (0)