diff --git a/src/frontend/src/pages/HomePage/LeadHomePage.tsx b/src/frontend/src/pages/HomePage/LeadHomePage.tsx
index e927f9adf9..5466cdc285 100644
--- a/src/frontend/src/pages/HomePage/LeadHomePage.tsx
+++ b/src/frontend/src/pages/HomePage/LeadHomePage.tsx
@@ -11,6 +11,7 @@ import PageLayout, { PAGE_GRID_HEIGHT } from '../../components/PageLayout';
import { AuthenticatedUser } from 'shared';
import ChangeRequestsToReview from './components/ChangeRequestsToReview';
import MyTeamsOverdueTasks from './components/MyTeamsOverdueTasks';
+import UpcomingDesignReviews from './components/UpcomingDesignReviews';
interface LeadHomePageProps {
user: AuthenticatedUser;
@@ -39,10 +40,13 @@ const LeadHomePage = ({ user }: LeadHomePageProps) => {
-
+
+
+
+
diff --git a/src/frontend/src/pages/HomePage/components/ChangeRequestsToReview.tsx b/src/frontend/src/pages/HomePage/components/ChangeRequestsToReview.tsx
index e7161db966..148ed6c822 100644
--- a/src/frontend/src/pages/HomePage/components/ChangeRequestsToReview.tsx
+++ b/src/frontend/src/pages/HomePage/components/ChangeRequestsToReview.tsx
@@ -19,7 +19,7 @@ const NoChangeRequestsToReview: React.FC = () => {
}
heading={`You're all caught up!`}
- message={'You have no unreviewed changre requests!'}
+ message={'You have no unreviewed change requests!'}
/>
);
};
diff --git a/src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx b/src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx
new file mode 100644
index 0000000000..7ecf0dac6a
--- /dev/null
+++ b/src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx
@@ -0,0 +1,117 @@
+import { Box, Card, CardContent, Link, Stack, Typography, useTheme } from '@mui/material';
+import { DesignReview, User } from 'shared';
+import { datePipe, projectWbsPipe } from '../../../utils/pipes';
+import { routes } from '../../../utils/routes';
+import { Link as RouterLink } from 'react-router-dom';
+import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
+import { LocationOnOutlined, Computer } from '@mui/icons-material';
+import { useHistory } from 'react-router-dom';
+import { NERButton } from '../../../components/NERButton';
+import { meetingStartTimePipe } from '../../../../../backend/src/utils/design-reviews.utils';
+import { timezoneOffset } from '../../../utils/datetime.utils';
+
+interface DesignReviewProps {
+ designReview: DesignReview;
+ user: User;
+}
+
+const DesignReviewInfo = ({ icon, text, link }: { icon: React.ReactNode; text: string; link?: boolean }) => {
+ return (
+
+ {icon}
+ {link ? (
+
+
+ {text}
+
+
+ ) : (
+
+ {text}
+
+ )}
+
+ );
+};
+
+const DisplayStatus: React.FC = ({ designReview, user }) => {
+ const history = useHistory();
+ const confirmedMemberIds = designReview.confirmedMembers.map((user) => user.userId);
+
+ return (
+ <>
+ {!confirmedMemberIds.includes(user.userId) ? (
+ {
+ history.push(`${routes.SETTINGS_PREFERENCES}?drId=${designReview.designReviewId}`);
+ }}
+ component={RouterLink}
+ >
+ Confirm Availibility
+
+ ) : (
+ {designReview.status}
+ )}
+ >
+ );
+};
+
+const getWeekday = (date: Date): string => {
+ const weekdays: string[] = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+ return weekdays[date.getDay()];
+};
+
+const removeYear = (str: string): string => {
+ return str.substring(0, str.length - 5);
+};
+
+const UpcomingDesignReviewsCard: React.FC = ({ designReview, user }) => {
+ const theme = useTheme();
+ const timezoneAdjustedDate = timezoneOffset(designReview.dateScheduled);
+ return (
+
+
+
+
+
+
+ {designReview.wbsName}
+
+
+
+ {}
+
+ {getWeekday(timezoneAdjustedDate) +
+ ', ' +
+ removeYear(datePipe(timezoneAdjustedDate)) +
+ ' @ ' +
+ meetingStartTimePipe(designReview.meetingTimes)}
+
+
+ {designReview.isInPerson && !!designReview.location && (
+ } text={designReview.location} />
+ )}
+ {designReview.isOnline && !!designReview.zoomLink && (
+ } text={designReview.zoomLink} link />
+ )}
+
+
+
+
+
+ );
+};
+
+export default UpcomingDesignReviewsCard;
diff --git a/src/frontend/src/pages/HomePage/components/OverdueWorkPackageView.tsx b/src/frontend/src/pages/HomePage/components/OverdueWorkPackageView.tsx
index 4686213017..d0d42294b1 100644
--- a/src/frontend/src/pages/HomePage/components/OverdueWorkPackageView.tsx
+++ b/src/frontend/src/pages/HomePage/components/OverdueWorkPackageView.tsx
@@ -1,4 +1,4 @@
-import { Box, Card, CardContent, Stack, Typography, useTheme } from '@mui/material';
+import { Box, Card, CardContent, Typography, useTheme } from '@mui/material';
import { WorkPackage } from 'shared';
import EmptyPageBlockDisplay from './EmptyPageBlockDisplay';
import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
@@ -57,32 +57,36 @@ const OverdueWorkPackagesView: React.FC = ({ workP
-
{isEmpty ? : workPackages.map((wp) => )}
-
+
diff --git a/src/frontend/src/pages/HomePage/components/ScrollablePageBlock.tsx b/src/frontend/src/pages/HomePage/components/ScrollablePageBlock.tsx
index 25045b6d39..54b11ce434 100644
--- a/src/frontend/src/pages/HomePage/components/ScrollablePageBlock.tsx
+++ b/src/frontend/src/pages/HomePage/components/ScrollablePageBlock.tsx
@@ -34,23 +34,26 @@ const ScrollablePageBlock: React.FC = ({ children, tit
sx={{
mt: 2,
display: 'flex',
- flexDirection: horizontal ? 'row' : 'column',
+ flexDirection: 'row',
+ flexWrap: 'wrap',
gap: 2,
height: '100%',
overflowX: horizontal ? 'auto' : 'hidden',
overflowY: horizontal ? 'hidden' : 'auto',
'&::-webkit-scrollbar': {
- height: '20px'
+ width: '20px'
},
'&::-webkit-scrollbar-track': {
backgroundColor: 'transparent'
},
'&::-webkit-scrollbar-thumb': {
- backgroundColor: theme.palette.error.dark,
+ backgroundColor: theme.palette.primary.main,
borderRadius: '20px',
border: '6px solid transparent',
backgroundClip: 'content-box'
- }
+ },
+ scrollbarWidth: 'auto',
+ scrollbarColor: `${theme.palette.primary.main} transparent`
}}
>
{children}
diff --git a/src/frontend/src/pages/HomePage/components/TeamTaskCard.tsx b/src/frontend/src/pages/HomePage/components/TeamTaskCard.tsx
index 76b80e93c3..dfd1485e64 100644
--- a/src/frontend/src/pages/HomePage/components/TeamTaskCard.tsx
+++ b/src/frontend/src/pages/HomePage/components/TeamTaskCard.tsx
@@ -28,7 +28,7 @@ const TeamTaskCard: React.FC = ({ task, taskNumber }) => {
{
+ return (
+ }
+ heading={'No Upcoming Design Reviews'}
+ message={'There are no Upcoming Design Reviews to Display'}
+ />
+ );
+};
+
+const UpcomingDesignReviews: React.FC = ({ user }) => {
+ const { data: designReviews, isLoading, isError, error } = useAllDesignReviews();
+
+ if (isLoading || !designReviews) return ;
+ if (isError) return ;
+
+ const filteredDesignReviews = designReviews.filter((review) => {
+ const scheduledDate = review.dateScheduled;
+ const currentDate = new Date();
+ const inTwoWeeks = new Date();
+ inTwoWeeks.setDate(currentDate.getDate() + 14);
+ const memberUserIds = [
+ ...review.requiredMembers.map((user) => user.userId),
+ ...review.optionalMembers.map((user) => user.userId)
+ ];
+ // added in case the person who created the design review forgets to add their name onto the required members
+ memberUserIds.concat(review.userCreated.userId);
+ return (
+ scheduledDate >= currentDate &&
+ scheduledDate <= inTwoWeeks &&
+ review.status !== DesignReviewStatus.DONE &&
+ memberUserIds.includes(user.userId)
+ );
+ });
+
+ const fullDisplay = (
+
+ {filteredDesignReviews.length === 0 ? (
+
+ ) : (
+ filteredDesignReviews.map((d) => )
+ )}
+
+ );
+
+ return fullDisplay;
+};
+
+export default UpcomingDesignReviews;
diff --git a/src/frontend/src/utils/datetime.utils.ts b/src/frontend/src/utils/datetime.utils.ts
index e728bb5cbf..1b23c43118 100644
--- a/src/frontend/src/utils/datetime.utils.ts
+++ b/src/frontend/src/utils/datetime.utils.ts
@@ -34,3 +34,8 @@ export const formatDate = (date: Date) => {
export const daysOverdue = (deadline: Date) => {
return Math.round((new Date().getTime() - deadline.getTime()) / (1000 * 60 * 60 * 24));
};
+
+export const timezoneOffset = (date: Date) => {
+ const timestamp = new Date(date).getTime() - new Date(date).getTimezoneOffset() * -60000;
+ return new Date(timestamp);
+};