Skip to content

Commit 1a985a8

Browse files
committed
#2217 working prototype
1 parent dc0ef19 commit 1a985a8

3 files changed

Lines changed: 87 additions & 84 deletions

File tree

src/frontend/src/pages/CalendarPage/CalendarComponents/CalendarDayCard.tsx

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Box, Card, CardContent, Grid, IconButton, Stack, Typography } from '@mui/material';
1+
import { Box, Card, CardContent, Grid, IconButton, Link, Stack, Tooltip, Typography } from '@mui/material';
22
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
33
import { DesignReview } from 'shared';
44
import { meetingStartTimePipe } from '../../../utils/pipes';
@@ -8,15 +8,16 @@ import ElectricalServicesIcon from '@mui/icons-material/ElectricalServices';
88
import TerminalIcon from '@mui/icons-material/Terminal';
99
import { useState } from 'react';
1010
import DRCSummaryModal from '../DesignReviewSummaryModal';
11+
import DynamicTooltip from '../../../components/DynamicTooltip';
1112

12-
export const getTeamTypeIcon = (teamTypeId: string, isLarge?: boolean) => {
13+
export const getTeamTypeIcon = (teamTypeName: string, isLarge?: boolean) => {
1314
const teamIcons: Map<string, JSX.Element> = new Map([
1415
['Software', <TerminalIcon fontSize={isLarge ? 'large' : 'small'} />],
1516
['Business', <WorkOutlineIcon fontSize={isLarge ? 'large' : 'small'} />],
1617
['Electrical', <ElectricalServicesIcon fontSize={isLarge ? 'large' : 'small'} />],
1718
['Mechanical', <ConstructionIcon fontSize={isLarge ? 'large' : 'small'} />]
1819
]);
19-
return teamIcons.get(teamTypeId);
20+
return teamIcons.get(teamTypeName);
2021
};
2122

2223
interface CalendarDayCardProps {
@@ -49,24 +50,68 @@ const CalendarDayCard: React.FC<CalendarDayCardProps> = ({ cardDate, events }) =
4950
<Box marginLeft={0.5} marginBottom={0.5} onClick={() => setIsSummaryModalOpen(true)} sx={{ cursor: 'pointer' }}>
5051
<Card sx={{ backgroundColor: 'red', borderRadius: 1, minWidth: 140, maxWidth: 140, minHeight: 20, maxHeight: 20 }}>
5152
<Stack direction="row">
52-
{getTeamTypeIcon(event.teamType.teamTypeId)}
53-
<Typography marginLeft={0.5} marginBottom={0.3} fontSize={14}>
54-
{name + (event.meetingTimes.length > 0 ? ' ' + meetingStartTimePipe(event.meetingTimes) : '')}
55-
</Typography>
53+
{getTeamTypeIcon(event.teamType.name)}
54+
<DynamicTooltip
55+
title={name + (event.meetingTimes.length > 0 ? ' - ' + meetingStartTimePipe(event.meetingTimes) : '')}
56+
>
57+
<Typography marginLeft={0.5} marginBottom={0.3} fontSize={14} noWrap>
58+
{name + (event.meetingTimes.length > 0 ? ' ' + meetingStartTimePipe(event.meetingTimes) : '')}
59+
</Typography>
60+
</DynamicTooltip>
5661
</Stack>
5762
</Card>
5863
</Box>
5964
</>
6065
);
6166
};
6267

63-
const ExtraEventsCard = (extraEvents: number) => {
68+
const ExtraEventNote = (event: DesignReview) => {
69+
const [isSummaryModalOpen, setIsSummaryModalOpen] = useState(false);
70+
71+
return (
72+
<>
73+
<DRCSummaryModal open={isSummaryModalOpen} onHide={() => setIsSummaryModalOpen(false)} designReview={event} />
74+
<Link style={{ cursor: 'pointer' }} fontSize={15} onClick={() => setIsSummaryModalOpen(true)}>
75+
{event.wbsName + (event.meetingTimes.length > 0 ? ' - ' + meetingStartTimePipe(event.meetingTimes) : '')}
76+
</Link>
77+
</>
78+
);
79+
};
80+
81+
const ExtraEventsCard = (extraEvents: DesignReview[]) => {
6482
return (
6583
<Box marginLeft={0.5} marginBottom={0.2}>
6684
<Card sx={{ backgroundColor: 'grey', borderRadius: 1, minWidth: 140, maxWidth: 140, minHeight: 20, maxHeight: 20 }}>
67-
<Typography marginLeft={0.5} marginBottom={0.3} align="center">
68-
{'+' + extraEvents}
69-
</Typography>
85+
<Tooltip
86+
id="tooltip"
87+
placement="right"
88+
PopperProps={{
89+
popperOptions: {
90+
modifiers: [
91+
{
92+
name: 'flip',
93+
options: {
94+
fallbackPlacements: ['top', 'bottom'],
95+
padding: -1,
96+
rootBoundary: 'document'
97+
}
98+
},
99+
{
100+
name: 'offset',
101+
options: {
102+
offset: [0, -1]
103+
}
104+
}
105+
]
106+
}
107+
}}
108+
arrow
109+
title={<Stack direction="column">{extraEvents.map((event) => ExtraEventNote(event))}</Stack>}
110+
>
111+
<Typography marginLeft={0.5} marginBottom={0.3} align="center">
112+
{'+' + extraEvents.length}
113+
</Typography>
114+
</Tooltip>
70115
</Card>
71116
</Box>
72117
);
@@ -80,8 +125,8 @@ const CalendarDayCard: React.FC<CalendarDayCardProps> = ({ cardDate, events }) =
80125
events.map((event) => EventCard(event))
81126
) : (
82127
<>
83-
{EventCard(events[1])}
84-
{ExtraEventsCard(events.length - 1)}
128+
{EventCard(events[0])}
129+
{ExtraEventsCard(events.slice(1))}
85130
</>
86131
)}
87132
</CardContent>

src/frontend/src/pages/CalendarPage/CalendarPage.tsx

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import { Box, Grid, Stack, Typography, useTheme } from '@mui/material';
77
import PageLayout from '../../components/PageLayout';
88
import { DesignReview, DesignReviewStatus } from 'shared';
99
import MonthSelector from './CalendarComponents/MonthSelector';
10-
import CalendarDayCard from './CalendarComponents/CalendarDayCard';
10+
import CalendarDayCard, { getTeamTypeIcon } from './CalendarComponents/CalendarDayCard';
1111
import FillerCalendarDayCard from './CalendarComponents/FillerCalendarDayCard';
12-
import { DAY_NAMES, EnumToArray, calendarPaddingDays, daysInMonth } from '../../utils/design-review.utils';
12+
import { DAY_NAMES, EnumToArray, calendarPaddingDays, daysInMonth, isConfirmed } from '../../utils/design-review.utils';
1313
import ActionsMenu from '../../components/ActionsMenu';
1414
import { useAllDesignReviews } from '../../hooks/design-reviews.hooks';
1515
import LoadingIndicator from '../../components/LoadingIndicator';
@@ -20,37 +20,27 @@ import { datePipe } from '../../utils/pipes';
2020
const CalendarPage = () => {
2121
const theme = useTheme();
2222
const [displayMonthYear, setDisplayMonthYear] = useState<Date>(new Date());
23-
const { isLoading, isError, error, data: designReviews } = useAllDesignReviews();
23+
const { isLoading, isError, error, data: allDesignReviews } = useAllDesignReviews();
2424
const user = useCurrentUser();
2525

26-
if (isLoading || !designReviews) return <LoadingIndicator />;
26+
if (isLoading || !allDesignReviews) return <LoadingIndicator />;
2727
if (isError) return <ErrorPage message={error.message} />;
2828

29-
const EventDict = new Map<string, DesignReview[]>();
29+
const designReviews = allDesignReviews.filter(isConfirmed);
3030

31+
const eventDict = new Map<string, DesignReview[]>();
3132
designReviews.forEach((designReview) => {
32-
if (
33-
EventDict.has(
34-
datePipe(new Date(designReview.dateScheduled.getTime() - designReview.dateScheduled.getTimezoneOffset() * -60000))
35-
)
36-
) {
37-
EventDict.set(
38-
datePipe(designReview.dateScheduled),
39-
EventDict.get(
40-
datePipe(new Date(designReview.dateScheduled.getTime() - designReview.dateScheduled.getTimezoneOffset() * -60000))
41-
)!.concat(designReview)
42-
);
33+
const date = datePipe(
34+
new Date(designReview.dateScheduled.getTime() - designReview.dateScheduled.getTimezoneOffset() * -60000)
35+
);
36+
if (eventDict.has(date)) {
37+
eventDict.get(date)?.push(designReview);
4338
} else {
44-
EventDict.set(
45-
datePipe(new Date(designReview.dateScheduled.getTime() - designReview.dateScheduled.getTimezoneOffset() * -60000)),
46-
[designReview]
47-
);
39+
eventDict.set(date, [designReview]);
4840
}
49-
50-
console.log(designReview.wbsName);
5141
});
5242

53-
const unconfirmedDR = designReviews.filter(
43+
const unconfirmedDR = allDesignReviews.filter(
5444
(designReview) =>
5545
designReview.userCreated.userId === user.userId && designReview.status === DesignReviewStatus.UNCONFIRMED
5646
);
@@ -64,6 +54,7 @@ const CalendarPage = () => {
6454
const designReviewButtons = (designReviews: DesignReview[]) => {
6555
return designReviews.map((designReview) => {
6656
return {
57+
icon: getTeamTypeIcon(designReview.teamType.name),
6758
title: designReview.wbsName,
6859
onClick: () => {},
6960
disabled: false
@@ -122,7 +113,13 @@ const CalendarPage = () => {
122113
{isDayInDifferentMonth(day, week) ? (
123114
<FillerCalendarDayCard day={day} />
124115
) : (
125-
<CalendarDayCard cardDate={cardDate} events={EventDict.get(datePipe(cardDate)) ?? []} />
116+
<CalendarDayCard
117+
cardDate={cardDate}
118+
events={
119+
eventDict.get(datePipe(new Date(cardDate.getTime() - cardDate.getTimezoneOffset() * -60000))) ??
120+
[]
121+
}
122+
/>
126123
)}
127124
</Box>
128125
</Grid>

src/frontend/src/utils/design-review.utils.ts

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -80,53 +80,6 @@ export const calendarPaddingDays = (month: Date): number => {
8080
return new Date(month.getFullYear(), month.getMonth(), 0).getDay();
8181
};
8282

83-
// TODO remove during wire up ticket
84-
export const testDesignReview1: DesignReview = {
85-
designReviewId: 'Meeting',
86-
dateScheduled: new Date(),
87-
meetingTimes: [16],
88-
dateCreated: new Date(),
89-
userCreated: batman,
90-
status: DesignReviewStatus.UNCONFIRMED,
91-
teamType: { teamTypeId: 'Mechanical', name: 'Mechanical', iconName: '' },
92-
requiredMembers: [],
93-
optionalMembers: [],
94-
confirmedMembers: [],
95-
deniedMembers: [],
96-
isOnline: false,
97-
isInPerson: false,
98-
attendees: [],
99-
wbsName: 'bruh',
100-
wbsNum: { carNumber: 1, workPackageNumber: 1, projectNumber: 1 }
101-
};
102-
103-
// TODO remove during wire up ticket
104-
export const exampleDesignReview1: DesignReview = {
105-
designReviewId: 'Wiring',
106-
dateScheduled: new Date(),
107-
meetingTimes: [1, 2, 5],
108-
dateCreated: new Date(),
109-
userCreated: superman,
110-
status: DesignReviewStatus.DONE,
111-
teamType: {
112-
teamTypeId: 'Electrical',
113-
name: 'thisteam',
114-
iconName: ''
115-
},
116-
requiredMembers: [batman, superman, greenlantern, flash, aquaman],
117-
optionalMembers: [wonderwoman, alfred],
118-
confirmedMembers: [],
119-
deniedMembers: [],
120-
location: 'Room 101',
121-
isOnline: true,
122-
isInPerson: false,
123-
zoomLink: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
124-
attendees: [],
125-
wbsName: 'Battery',
126-
wbsNum: { carNumber: 1, projectNumber: 1, workPackageNumber: 1 },
127-
docTemplateLink: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
128-
};
129-
13083
// TODO: We will have to make a call to the backend to get this data
13184
export const usersToAvailabilities = new Map([
13285
[superman, [1, 2, 3, 4, 5, 6, 7]],
@@ -145,3 +98,11 @@ existingMeetingData.set(5, 'warning');
14598
existingMeetingData.set(10, 'build');
14699
existingMeetingData.set(20, 'computer');
147100
existingMeetingData.set(50, 'electrical');
101+
102+
export const isConfirmed = (designReview: DesignReview): boolean => {
103+
return (
104+
designReview.status === DesignReviewStatus.CONFIRMED ||
105+
designReview.status === DesignReviewStatus.SCHEDULED ||
106+
designReview.status === DesignReviewStatus.DONE
107+
);
108+
};

0 commit comments

Comments
 (0)