Skip to content

Commit 32eddda

Browse files
authored
Merge pull request #1283 from Northeastern-Electric-Racing/#1027-cr-dropdown
#1027 Create change request input component
2 parents b07b67b + a45b66f commit 32eddda

3 files changed

Lines changed: 95 additions & 4 deletions

File tree

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { Box, FormControl, FormLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material';
2+
import { isWithinInterval, subDays } from 'date-fns';
3+
import { Control, Controller } from 'react-hook-form';
4+
import { AuthenticatedUser, ChangeRequest, wbsPipe } from 'shared';
5+
import { useAllChangeRequests } from '../hooks/change-requests.hooks';
6+
import { useCurrentUser } from '../hooks/users.hooks';
7+
import LoadingIndicator from './LoadingIndicator';
8+
9+
// Filter and sort change requests to display in the dropdown
10+
const getFilteredChangeRequests = (changeRequests: ChangeRequest[], user: AuthenticatedUser): ChangeRequest[] => {
11+
const today = new Date();
12+
const fiveDaysAgo = subDays(today, 5);
13+
14+
const filteredRequests = changeRequests.filter(
15+
(cr) => cr.dateReviewed && cr.accepted && isWithinInterval(cr.dateReviewed, { start: fiveDaysAgo, end: today })
16+
);
17+
18+
// The current user's CRs should be at the top
19+
filteredRequests.sort((a, b) => {
20+
const isSubmitterAUser = a.submitter.userId === user.userId;
21+
const isSubmitterBUser = b.submitter.userId === user.userId;
22+
23+
if (isSubmitterAUser && isSubmitterBUser) return 0;
24+
if (isSubmitterAUser) return -1;
25+
if (isSubmitterBUser) return 1;
26+
27+
return a.crId - b.crId;
28+
});
29+
30+
return filteredRequests;
31+
};
32+
33+
interface ChangeRequestDropdownProps {
34+
control: Control<any, any>;
35+
name: string;
36+
}
37+
38+
const ChangeRequestDropdown = ({ control, name }: ChangeRequestDropdownProps) => {
39+
const user = useCurrentUser();
40+
const { isLoading, data: changeRequests } = useAllChangeRequests();
41+
if (isLoading || !changeRequests) return <LoadingIndicator />;
42+
43+
const filteredRequests = getFilteredChangeRequests(changeRequests, user);
44+
45+
const approvedChangeRequestOptions = filteredRequests.map((cr) => ({
46+
label: `${cr.crId} - ${wbsPipe(cr.wbsNum)} - ${cr.submitter.firstName} ${cr.submitter.lastName} - ${cr.type}`,
47+
value: cr.crId
48+
}));
49+
50+
return (
51+
<Box sx={{ display: 'flex', justifyContent: 'end' }}>
52+
<FormControl>
53+
<FormLabel sx={{ alignSelf: 'start' }}>Change Request ID</FormLabel>
54+
<Controller
55+
control={control}
56+
name={name}
57+
render={({ field: { onChange, value } }) => (
58+
<Select
59+
id="cr-autocomplete"
60+
displayEmpty
61+
renderValue={(value) => value}
62+
value={value}
63+
onChange={(event: SelectChangeEvent<number>) => onChange(event.target.value)}
64+
size={'small'}
65+
placeholder={'Change Request Id'}
66+
sx={{ width: 200, textAlign: 'left' }}
67+
MenuProps={{
68+
anchorOrigin: {
69+
vertical: 'bottom',
70+
horizontal: 'right'
71+
},
72+
transformOrigin: {
73+
vertical: 'top',
74+
horizontal: 'right'
75+
}
76+
}}
77+
>
78+
{approvedChangeRequestOptions.map((option) => (
79+
<MenuItem key={option.value} value={option.value}>
80+
{option.label}
81+
</MenuItem>
82+
))}
83+
</Select>
84+
)}
85+
/>
86+
</FormControl>
87+
</Box>
88+
);
89+
};
90+
91+
export default ChangeRequestDropdown;

src/frontend/src/pages/ProjectDetailPage/ProjectEdit/ProjectEditContainer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import NERFailButton from '../../../components/NERFailButton';
2626
import { useToast } from '../../../hooks/toasts.hooks';
2727
import { useState } from 'react';
2828
import PageLayout from '../../../components/PageLayout';
29+
import ChangeRequestDropdown from '../../../components/ChangeRequestDropdown';
2930

3031
/* TODO: slide deck changed to confluence in frontend - needs to be updated in the backend */
3132
const schema = yup.object().shape({
@@ -155,7 +156,7 @@ const ProjectEditContainer: React.FC<ProjectEditContainerProps> = ({ project, ex
155156
<PageLayout
156157
title={`${wbsPipe(project.wbsNum)} - ${project.name}`}
157158
previousPages={[{ name: 'Projects', route: routes.PROJECTS }]}
158-
headerRight={<ReactHookTextField name="crId" control={control} label="Change Request Id" type="number" size="small" />}
159+
headerRight={<ChangeRequestDropdown control={control} name="crId" />}
159160
>
160161
<form
161162
id="project-edit-form"

src/frontend/src/pages/WorkPackageDetailPage/WorkPackageEditContainer/WorkPackageEditContainer.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { Controller, useFieldArray, useForm } from 'react-hook-form';
1515
import { yupResolver } from '@hookform/resolvers/yup';
1616
import * as yup from 'yup';
1717
import { Box, TextField, Autocomplete, FormControl } from '@mui/material';
18-
import ReactHookTextField from '../../../components/ReactHookTextField';
1918
import ReactHookEditableList from '../../../components/ReactHookEditableList';
2019
import { useEditWorkPackage } from '../../../hooks/work-packages.hooks';
2120
import WorkPackageEditDetails from './WorkPackageEditDetails';
@@ -26,6 +25,7 @@ import { useToast } from '../../../hooks/toasts.hooks';
2625
import { useState } from 'react';
2726
import { useSingleProject } from '../../../hooks/projects.hooks';
2827
import PageLayout from '../../../components/PageLayout';
28+
import ChangeRequestDropdown from '../../../components/ChangeRequestDropdown';
2929

3030
const schema = yup.object().shape({
3131
name: yup.string().required('Name is required!'),
@@ -162,7 +162,6 @@ const WorkPackageEditContainer: React.FC<WorkPackageEditContainerProps> = ({ wor
162162
}
163163
}
164164
};
165-
166165
const projectWbsString: string = projectWbsPipe(workPackage.wbsNum);
167166

168167
return (
@@ -172,7 +171,7 @@ const WorkPackageEditContainer: React.FC<WorkPackageEditContainerProps> = ({ wor
172171
{ name: 'Projects', route: routes.PROJECTS },
173172
{ name: `${projectWbsString} - ${workPackage.projectName}`, route: `${routes.PROJECTS}/${projectWbsString}` }
174173
]}
175-
headerRight={<ReactHookTextField name="crId" control={control} label="Change Request Id" type="number" size="small" />}
174+
headerRight={<ChangeRequestDropdown control={control} name="crId" />}
176175
>
177176
<form
178177
id="work-package-edit-form"

0 commit comments

Comments
 (0)