Skip to content

Commit 879edd8

Browse files
committed
Merge branch 'develop' into #2131-drc-create-modal
2 parents 1173c25 + c70c875 commit 879edd8

7 files changed

Lines changed: 214 additions & 116 deletions

File tree

src/frontend/src/apis/transformers/design-reviews.tranformers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const designReviewTransformer = (designReview: DesignReview) => {
44
return {
55
...designReview,
66
dateCreated: new Date(designReview.dateCreated),
7-
dateDeleted: designReview.dateDeleted ? new Date(designReview.dateDeleted) : undefined
7+
dateDeleted: designReview.dateDeleted ? new Date(designReview.dateDeleted) : undefined,
8+
dateScheduled: designReview.dateScheduled ? new Date(designReview.dateScheduled) : undefined
89
};
910
};

src/frontend/src/hooks/change-requests.hooks.ts

Lines changed: 66 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,22 @@ export const useSingleChangeRequest = (id: number) => {
3939
});
4040
};
4141

42+
export interface ReviewPayload {
43+
reviewerId: number;
44+
crId: number;
45+
accepted: boolean;
46+
reviewNotes: string;
47+
psId: string;
48+
}
49+
4250
/**
4351
* Custom React Hook to review a change request.
4452
*/
4553
export const useReviewChangeRequest = () => {
4654
const queryClient = useQueryClient();
47-
return useMutation<{ message: string }, Error, any>(
55+
return useMutation<{ message: string }, Error, ReviewPayload>(
4856
['change requests', 'review'],
49-
async (reviewPayload: any) => {
57+
async (reviewPayload: ReviewPayload) => {
5058
const { data } = await reviewChangeRequest(
5159
reviewPayload.reviewerId,
5260
reviewPayload.crId,
@@ -69,7 +77,7 @@ export const useReviewChangeRequest = () => {
6977
*/
7078
export const useDeleteChangeRequest = () => {
7179
const queryClient = useQueryClient();
72-
return useMutation<{ message: string }, Error, any>(
80+
return useMutation<{ message: string }, Error, number>(
7381
['change requests', 'delete'],
7482
async (id: number) => {
7583
const { data } = await deleteChangeRequest(id);
@@ -103,41 +111,73 @@ export const useCreateStandardChangeRequest = () => {
103111
);
104112
};
105113

114+
export interface CreateActivationChangeRequestPayload {
115+
submitterId: number;
116+
wbsNum: WbsNumber;
117+
projectLeadId: number;
118+
projectManagerId: number;
119+
startDate: string;
120+
confirmDetails: boolean;
121+
type: string;
122+
}
123+
124+
export interface CreateStageGateChangeRequestPayload {
125+
submitterId: number;
126+
wbsNum: WbsNumber;
127+
confirmDone: boolean;
128+
type: string;
129+
}
130+
131+
export interface CreateProposeSolutionPayload {
132+
submitterId: number;
133+
crId: number;
134+
description: string;
135+
scopeImpact: string;
136+
timelineImpact: number;
137+
budgetImpact: number;
138+
}
139+
106140
/**
107141
* Custom React Hook to create an activation change request.
108142
*/
109143
export const useCreateActivationChangeRequest = () => {
110-
return useMutation<{ message: string }, Error, any>(['change requests', 'create', 'activation'], async (payload: any) => {
111-
const { data } = await createActivationChangeRequest(
112-
payload.submitterId,
113-
payload.wbsNum,
114-
payload.projectLeadId,
115-
payload.projectManagerId,
116-
payload.startDate,
117-
payload.confirmDetails
118-
);
119-
return data;
120-
});
144+
return useMutation<{ message: string }, Error, CreateActivationChangeRequestPayload>(
145+
['change requests', 'create', 'activation'],
146+
async (payload: CreateActivationChangeRequestPayload) => {
147+
const { data } = await createActivationChangeRequest(
148+
payload.submitterId,
149+
payload.wbsNum,
150+
payload.projectLeadId,
151+
payload.projectManagerId,
152+
payload.startDate,
153+
payload.confirmDetails
154+
);
155+
return data;
156+
}
157+
);
121158
};
122159

123160
/**
124161
* Custom React Hook to create a stage gate change request.
125162
*/
126163
export const useCreateStageGateChangeRequest = () => {
127-
return useMutation<{ message: string }, Error, any>(['change requests', 'create', 'stage gate'], async (payload: any) => {
128-
const { data } = await createStageGateChangeRequest(payload.submitterId, payload.wbsNum, payload.confirmDone);
129-
return data;
130-
});
164+
return useMutation<{ message: string }, Error, CreateStageGateChangeRequestPayload>(
165+
['change requests', 'create', 'stage gate'],
166+
async (payload: CreateStageGateChangeRequestPayload) => {
167+
const { data } = await createStageGateChangeRequest(payload.submitterId, payload.wbsNum, payload.confirmDone);
168+
return data;
169+
}
170+
);
131171
};
132172

133173
/**
134174
* Custom React Hook to create a proposed solution
135175
*/
136176
export const useCreateProposeSolution = () => {
137177
const queryClient = useQueryClient();
138-
return useMutation<{ message: string }, Error, any>(
178+
return useMutation<{ message: string }, Error, CreateProposeSolutionPayload>(
139179
['change requests', 'create', 'propose solution'],
140-
async (payload: any) => {
180+
async (payload: CreateProposeSolutionPayload) => {
141181
const { data } = await addProposedSolution(
142182
payload.submitterId,
143183
payload.crId,
@@ -156,14 +196,18 @@ export const useCreateProposeSolution = () => {
156196
);
157197
};
158198

199+
export interface CRReviewPayload {
200+
userIds: number[];
201+
}
202+
159203
/**
160204
* Custom React hook to request cr reviewers
161205
*/
162206
export const useRequestCRReview = (crId: string) => {
163207
const queryClient = useQueryClient();
164-
return useMutation<{ message: string }, Error, any>(
208+
return useMutation<{ message: string }, Error, CRReviewPayload>(
165209
['change requests', 'review'],
166-
async (crReviewPayload: { userIds: number[] }) => {
210+
async (crReviewPayload: CRReviewPayload) => {
167211
const { data } = await requestCRReview(crId, crReviewPayload);
168212
return data;
169213
},

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

Lines changed: 88 additions & 17 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, TeamType } from 'shared';
44
import { meetingStartTimePipe } from '../../../utils/pipes';
@@ -9,15 +9,16 @@ import TerminalIcon from '@mui/icons-material/Terminal';
99
import { useState } from 'react';
1010
import DRCSummaryModal from '../DesignReviewSummaryModal';
1111
import { DesignReviewCreateModal } from '../DesignReviewCreateModal';
12+
import DynamicTooltip from '../../../components/DynamicTooltip';
1213

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

2324
interface CalendarDayCardProps {
@@ -44,33 +45,103 @@ const CalendarDayCard: React.FC<CalendarDayCardProps> = ({ cardDate, events, tea
4445
</Grid>
4546
);
4647

47-
const EventCard = (event: DesignReview) => {
48+
const EventCard = ({ event }: { event: DesignReview }) => {
4849
const [isSummaryModalOpen, setIsSummaryModalOpen] = useState(false);
49-
const name = event.designReviewId;
50+
const name = event.wbsName;
5051
return (
5152
<>
5253
<DRCSummaryModal open={isSummaryModalOpen} onHide={() => setIsSummaryModalOpen(false)} designReview={event} />
5354
<Box marginLeft={0.5} marginBottom={0.5} onClick={() => setIsSummaryModalOpen(true)} sx={{ cursor: 'pointer' }}>
5455
<Card sx={{ backgroundColor: 'red', borderRadius: 1, minWidth: 140, maxWidth: 140, minHeight: 20, maxHeight: 20 }}>
5556
<Stack direction="row">
56-
{getTeamTypeIcon(event.teamType.teamTypeId)}
57-
<Typography marginLeft={0.5} marginBottom={0.3} fontSize={14}>
58-
{name + ' ' + meetingStartTimePipe(event.meetingTimes)}
59-
</Typography>
57+
{getTeamTypeIcon(event.teamType.name)}
58+
<DynamicTooltip
59+
title={name + (event.meetingTimes.length > 0 ? ' - ' + meetingStartTimePipe(event.meetingTimes) : '')}
60+
>
61+
<Typography marginLeft={0.5} marginBottom={0.3} fontSize={14} noWrap>
62+
{name + (event.meetingTimes.length > 0 ? ' ' + meetingStartTimePipe(event.meetingTimes) : '')}
63+
</Typography>
64+
</DynamicTooltip>
6065
</Stack>
6166
</Card>
6267
</Box>
6368
</>
6469
);
6570
};
6671

67-
const ExtraEventsCard = (extraEvents: number) => {
72+
const ExtraEventNote = ({ event }: { event: DesignReview }) => {
73+
const [isSummaryModalOpen, setIsSummaryModalOpen] = useState(false);
74+
75+
return (
76+
<>
77+
<DRCSummaryModal open={isSummaryModalOpen} onHide={() => setIsSummaryModalOpen(false)} designReview={event} />
78+
<Link
79+
style={{ cursor: 'pointer' }}
80+
fontSize={15}
81+
onClick={() => {
82+
setIsSummaryModalOpen(true);
83+
}}
84+
>
85+
{event.wbsName + (event.meetingTimes.length > 0 ? ' - ' + meetingStartTimePipe(event.meetingTimes) : '')}
86+
</Link>
87+
</>
88+
);
89+
};
90+
91+
const ExtraEventsCard = ({ extraEvents }: { extraEvents: DesignReview[] }) => {
92+
const [showTooltip, setShowTooltip] = useState(false);
6893
return (
6994
<Box marginLeft={0.5} marginBottom={0.2}>
70-
<Card sx={{ backgroundColor: 'grey', borderRadius: 1, minWidth: 140, maxWidth: 140, minHeight: 20, maxHeight: 20 }}>
71-
<Typography marginLeft={0.5} marginBottom={0.3} align="center">
72-
{'+' + extraEvents}
73-
</Typography>
95+
<Card
96+
sx={{
97+
backgroundColor: 'grey',
98+
borderRadius: 1,
99+
minWidth: 140,
100+
maxWidth: 140,
101+
minHeight: 20,
102+
maxHeight: 20
103+
}}
104+
>
105+
<Tooltip
106+
id="tooltip"
107+
open={showTooltip}
108+
disableHoverListener
109+
onClick={() => setShowTooltip(!showTooltip)}
110+
placement="right"
111+
sx={{ cursor: 'pointer' }}
112+
PopperProps={{
113+
popperOptions: {
114+
modifiers: [
115+
{
116+
name: 'flip',
117+
options: {
118+
fallbackPlacements: ['top', 'bottom'],
119+
padding: -1,
120+
rootBoundary: 'document'
121+
}
122+
},
123+
{
124+
name: 'offset',
125+
options: {
126+
offset: [0, -1]
127+
}
128+
}
129+
]
130+
}
131+
}}
132+
arrow
133+
title={
134+
<Stack direction="column">
135+
{extraEvents.map((event) => (
136+
<ExtraEventNote event={event} />
137+
))}
138+
</Stack>
139+
}
140+
>
141+
<Typography marginLeft={0.5} marginBottom={0.3} align="center">
142+
{'+' + extraEvents.length}
143+
</Typography>
144+
</Tooltip>
74145
</Card>
75146
</Box>
76147
);
@@ -88,11 +159,11 @@ const CalendarDayCard: React.FC<CalendarDayCardProps> = ({ cardDate, events, tea
88159
<CardContent sx={{ padding: 0 }}>
89160
<DayCardTitle />
90161
{events.length < 3 ? (
91-
events.map((event) => EventCard(event))
162+
events.map((event) => <EventCard event={event} />)
92163
) : (
93164
<>
94-
{EventCard(events[1])}
95-
{ExtraEventsCard(events.length - 1)}
165+
<EventCard event={events[0]} />
166+
<ExtraEventsCard extraEvents={events.slice(1)} />
96167
</>
97168
)}
98169
</CardContent>

0 commit comments

Comments
 (0)