Skip to content

Commit cac50af

Browse files
authored
Merge pull request #2215 from Northeastern-Electric-Racing/2136-design-review-calendar-design-review-edit-page
#2136 finalize design review modal
2 parents 61a3485 + 41cc3b6 commit cac50af

21 files changed

+665
-199
lines changed

src/backend/src/controllers/design-reviews.controllers.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export default class DesignReviewsController {
6969
try {
7070
const {
7171
dateScheduled,
72-
teamType,
72+
teamTypeId,
7373
requiredMembersIds,
7474
optionalMembersIds,
7575
isOnline,
@@ -91,7 +91,7 @@ export default class DesignReviewsController {
9191
user,
9292
designReviewId,
9393
dateScheduled,
94-
teamType.teamTypeId,
94+
teamTypeId,
9595
requiredMembersIds,
9696
optionalMembersIds,
9797
isOnline,

src/backend/src/prisma-query-args/design-reviews.query-args.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ const designReviewQueryArgs = Prisma.validator<Prisma.Design_ReviewArgs>()({
66
teamType: true,
77
requiredMembers: true,
88
optionalMembers: true,
9-
confirmedMembers: true,
9+
confirmedMembers: {
10+
include: {
11+
drScheduleSettings: true
12+
}
13+
},
1014
deniedMembers: true,
1115
attendees: true,
1216
userDeleted: true,

src/backend/src/services/users.services.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import {
1010
RoleEnum,
1111
isHead,
1212
UserSecureSettings,
13-
UserScheduleSettings
13+
UserScheduleSettings,
14+
UserWithScheduleSettings
1415
} from 'shared';
1516
import authUserQueryArgs from '../prisma-query-args/auth-user.query-args';
1617
import prisma from '../prisma/prisma';
@@ -23,17 +24,22 @@ import projectQueryArgs from '../prisma-query-args/projects.query-args';
2324
import userSecureSettingsTransformer from '../transformers/user-secure-settings.transformer';
2425
import { validateUserIsPartOfFinanceTeam } from '../utils/reimbursement-requests.utils';
2526
import userScheduleSettingsTransformer from '../transformers/user-schedule-settings.transformer';
27+
import userWithScheduleSettingsTransformer from '../transformers/designReviewUser.transformer';
2628

2729
export default class UsersService {
2830
/**
2931
* Gets all of the users from the database
3032
* @returns a list of all the users
3133
*/
32-
static async getAllUsers(): Promise<User[]> {
33-
const users = await prisma.user.findMany();
34+
static async getAllUsers(): Promise<UserWithScheduleSettings[]> {
35+
const users = await prisma.user.findMany({
36+
include: {
37+
drScheduleSettings: true
38+
}
39+
});
3440
users.sort((a, b) => a.firstName.localeCompare(b.firstName));
3541

36-
return users.map(userTransformer);
42+
return users.map(userWithScheduleSettingsTransformer);
3743
}
3844

3945
/**

src/backend/src/transformers/design-reviews.transformer.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Prisma } from '@prisma/client';
22
import { DesignReview, DesignReviewStatus } from 'shared';
33
import userTransformer from './user.transformer';
4+
import userWithScheduleSettingsTransformer from './designReviewUser.transformer';
45
import { wbsNumOf } from '../utils/utils';
56
import designReviewQueryArgs from '../prisma-query-args/design-reviews.query-args';
67

@@ -15,7 +16,7 @@ export const designReviewTransformer = (
1516
userCreated: userTransformer(designReview.userCreated),
1617
requiredMembers: designReview.requiredMembers.map(userTransformer),
1718
optionalMembers: designReview.optionalMembers.map(userTransformer),
18-
confirmedMembers: designReview.confirmedMembers.map(userTransformer),
19+
confirmedMembers: designReview.confirmedMembers.map(userWithScheduleSettingsTransformer),
1920
deniedMembers: designReview.deniedMembers.map(userTransformer),
2021
location: designReview.location ?? undefined,
2122
isOnline: designReview.isOnline,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Prisma } from '@prisma/client';
2+
import { UserWithScheduleSettings } from 'shared';
3+
import userScheduleSettingsTransformer from './user-schedule-settings.transformer';
4+
5+
const userWithScheduleSettingsTransformer = (
6+
user: Prisma.UserGetPayload<{ include: { drScheduleSettings: true } }>
7+
): UserWithScheduleSettings => {
8+
return {
9+
userId: user.userId,
10+
firstName: user.firstName,
11+
lastName: user.lastName,
12+
email: user.email,
13+
emailId: user.emailId,
14+
role: user.role,
15+
scheduleSettings: user.drScheduleSettings ? userScheduleSettingsTransformer(user.drScheduleSettings) : undefined
16+
};
17+
};
18+
19+
export default userWithScheduleSettingsTransformer;

src/backend/tests/test-data/design-reviews.test-data.ts

+81-7
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,18 @@ export const prismaDesignReview1: Prisma.Design_ReviewGetPayload<typeof designRe
6464
wbsElementId: 1,
6565
requiredMembers: [batman],
6666
optionalMembers: [],
67-
confirmedMembers: [batman],
67+
confirmedMembers: [
68+
{
69+
...batman,
70+
drScheduleSettings: {
71+
drScheduleSettingsId: '123',
72+
personalGmail: '[email protected]',
73+
personalZoomLink: 'https://zoom.us/j/123456789',
74+
availability: [1, 2, 3],
75+
userId: 1
76+
}
77+
}
78+
],
6879
deniedMembers: [],
6980
attendees: [batman],
7081
userDeleted: null,
@@ -90,7 +101,18 @@ export const prismaDesignReview2: Prisma.Design_ReviewGetPayload<typeof designRe
90101
userCreated: wonderwoman,
91102
requiredMembers: [wonderwoman],
92103
optionalMembers: [],
93-
confirmedMembers: [wonderwoman],
104+
confirmedMembers: [
105+
{
106+
...wonderwoman,
107+
drScheduleSettings: {
108+
drScheduleSettingsId: '123',
109+
personalGmail: '[email protected]',
110+
personalZoomLink: 'https://zoom.us/j/123456789',
111+
availability: [1, 2, 3],
112+
userId: 1
113+
}
114+
}
115+
],
94116
deniedMembers: [],
95117
attendees: [wonderwoman],
96118
userDeleted: null,
@@ -117,7 +139,18 @@ export const prismaDesignReview3: Prisma.Design_ReviewGetPayload<typeof designRe
117139
userCreated: batman,
118140
requiredMembers: [batman],
119141
optionalMembers: [],
120-
confirmedMembers: [batman],
142+
confirmedMembers: [
143+
{
144+
...batman,
145+
drScheduleSettings: {
146+
drScheduleSettingsId: '123',
147+
personalGmail: '[email protected]',
148+
personalZoomLink: 'https://zoom.us/j/123456789',
149+
availability: [1, 2, 3],
150+
userId: 1
151+
}
152+
}
153+
],
121154
deniedMembers: [],
122155
attendees: [batman],
123156
userDeleted: null,
@@ -145,7 +178,18 @@ export const prismaDesignReview5: Prisma.Design_ReviewGetPayload<typeof designRe
145178
wbsElementId: 1,
146179
requiredMembers: [batman],
147180
optionalMembers: [wonderwomanWithScheduleSettings],
148-
confirmedMembers: [batman],
181+
confirmedMembers: [
182+
{
183+
...batman,
184+
drScheduleSettings: {
185+
drScheduleSettingsId: 'bmschedule',
186+
personalGmail: '[email protected]',
187+
personalZoomLink: 'https://zoom.us/j/gotham',
188+
availability: [],
189+
userId: 69
190+
}
191+
}
192+
],
149193
deniedMembers: [],
150194
attendees: [wonderwoman],
151195
userDeleted: null,
@@ -169,7 +213,17 @@ export const designReview3: DesignReview = {
169213
wbsNum: { carNumber: 1, projectNumber: 2, workPackageNumber: 0 },
170214
requiredMembers: [sharedBatman],
171215
optionalMembers: [],
172-
confirmedMembers: [sharedBatman],
216+
confirmedMembers: [
217+
{
218+
...sharedBatman,
219+
scheduleSettings: {
220+
drScheduleSettingsId: '123',
221+
personalGmail: '[email protected]',
222+
personalZoomLink: 'https://zoom.us/j/123456789',
223+
availability: [1, 2, 3]
224+
}
225+
}
226+
],
173227
deniedMembers: [],
174228
attendees: [sharedBatman],
175229
userDeleted: undefined,
@@ -187,7 +241,17 @@ export const sharedDesignReview1: SharedDesignReview = {
187241
isInPerson: false,
188242
requiredMembers: [sharedBatman],
189243
optionalMembers: [],
190-
confirmedMembers: [sharedBatman],
244+
confirmedMembers: [
245+
{
246+
...sharedBatman,
247+
scheduleSettings: {
248+
drScheduleSettingsId: '123',
249+
personalGmail: '[email protected]',
250+
personalZoomLink: 'https://zoom.us/j/123456789',
251+
availability: [1, 2, 3]
252+
}
253+
}
254+
],
191255
deniedMembers: [],
192256
attendees: [sharedBatman],
193257
teamType: teamType1,
@@ -207,7 +271,17 @@ export const designReview5: DesignReview = {
207271
isInPerson: false,
208272
requiredMembers: [],
209273
optionalMembers: [wonderwomanMarkedWithScheduleSettings],
210-
confirmedMembers: [sharedBatman],
274+
confirmedMembers: [
275+
{
276+
...sharedBatman,
277+
scheduleSettings: {
278+
drScheduleSettingsId: 'bmschedule',
279+
personalGmail: '[email protected]',
280+
personalZoomLink: 'https://zoom.us/j/gotham',
281+
availability: []
282+
}
283+
}
284+
],
211285
deniedMembers: [],
212286
attendees: [wonderwoman],
213287
wbsName: 'car',

src/backend/tests/users.test.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ describe('Users', () => {
3838
expect(prisma.user.findMany).toHaveBeenCalledTimes(1);
3939
// note that batman was sorted to the front because his first name is before supermans alphabetically
4040
// and also that we don't return the google auth id for security reasons
41-
expect(res).toStrictEqual([restOfBatman, restOfSuperman]);
41+
expect(res).toStrictEqual([
42+
{ scheduleSettings: undefined, ...restOfBatman },
43+
{ scheduleSettings: undefined, ...restOfSuperman }
44+
]);
4245
});
4346

4447
test('getSingleUser', async () => {

src/frontend/src/apis/users.api.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import axios from '../utils/axios';
7-
import { Project, User, UserScheduleSettings, UserSecureSettings } from 'shared';
7+
import { Project, User, UserScheduleSettings, UserSecureSettings, UserWithScheduleSettings } from 'shared';
88
import { apiUrls } from '../utils/urls';
99
import { authUserTransformer, userTransformer } from './transformers/users.transformers';
1010
import { AuthenticatedUser, UserSettings } from 'shared';
@@ -14,7 +14,7 @@ import { projectTransformer } from './transformers/projects.transformers';
1414
* Fetches all users.
1515
*/
1616
export const getAllUsers = () => {
17-
return axios.get<User[]>(apiUrls.users(), {
17+
return axios.get<UserWithScheduleSettings[]>(apiUrls.users(), {
1818
transformResponse: (data) => JSON.parse(data).map(userTransformer)
1919
});
2020
};

src/frontend/src/components/TimeSlot.tsx

+4-24
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import { Box } from '@mui/system';
2-
import { ReactElement } from 'react';
3-
import WarningIcon from '@mui/icons-material/Warning';
4-
import BuildIcon from '@mui/icons-material/Build';
5-
import ComputerIcon from '@mui/icons-material/Computer';
6-
import ElectricalServicesIcon from '@mui/icons-material/ElectricalServices';
2+
import { Icon } from '@mui/material';
73

84
interface TimeSlotProps {
95
text?: string;
@@ -28,23 +24,6 @@ const TimeSlot: React.FC<TimeSlotProps> = ({
2824
onMouseUp,
2925
onMouseOver
3026
}) => {
31-
const getIcon = (icon: string, small: boolean): ReactElement | null => {
32-
const iconFont = small ? { fontSize: '1.4em' } : { fontSize: '2em' };
33-
34-
switch (icon) {
35-
case 'warning':
36-
return <WarningIcon sx={iconFont} />;
37-
case 'build':
38-
return <BuildIcon sx={iconFont} />;
39-
case 'computer':
40-
return <ComputerIcon sx={iconFont} />;
41-
case 'electrical':
42-
return <ElectricalServicesIcon sx={iconFont} />;
43-
default:
44-
return null;
45-
}
46-
};
47-
4827
return (
4928
<Box
5029
sx={{
@@ -61,14 +40,15 @@ const TimeSlot: React.FC<TimeSlotProps> = ({
6140
fontWeight: 'bold',
6241
display: 'flex',
6342
flexDirection: 'column',
64-
justifyContent: 'center'
43+
justifyContent: 'center',
44+
alignItems: 'center'
6545
}}
6646
onMouseDown={onMouseDown}
6747
onMouseEnter={onMouseEnter}
6848
onMouseUp={onMouseUp}
6949
onMouseOver={onMouseOver}
7050
>
71-
{icon && <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{getIcon(icon, small)}</Box>}
51+
{icon && <Icon>{icon}</Icon>}
7252
{text}
7353
</Box>
7454
);

src/frontend/src/hooks/design-reviews.hooks.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ export interface EditDesignReviewPayload {
5959
optionalMembersIds: number[];
6060
isOnline: boolean;
6161
isInPerson: boolean;
62-
zoomLink: string | null;
63-
location: string | null;
64-
docTemplateLink: string | null;
62+
zoomLink?: string;
63+
location?: string;
64+
docTemplateLink?: string;
6565
status: DesignReviewStatus;
6666
attendees: number[];
6767
meetingTimes: number[];

src/frontend/src/hooks/users.hooks.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ import {
2626
UpdateUserRolePayload,
2727
Project,
2828
UserSecureSettings,
29-
UserScheduleSettings
29+
UserScheduleSettings,
30+
UserWithScheduleSettings
3031
} from 'shared';
3132
import { useAuth } from './auth.hooks';
3233
import { useContext } from 'react';
@@ -45,7 +46,7 @@ export const useCurrentUser = (): AuthenticatedUser => {
4546
* Custom React Hook to supply all users.
4647
*/
4748
export const useAllUsers = () => {
48-
return useQuery<User[], Error>(['users'], async () => {
49+
return useQuery<UserWithScheduleSettings[], Error>(['users'], async () => {
4950
const { data } = await getAllUsers();
5051
return data;
5152
});

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { userToAutocompleteOption } from '../../utils/teams.utils';
2828
import { useQuery } from '../../hooks/utils.hooks';
2929
import NERAutocomplete from '../../components/NERAutocomplete';
3030
import { useAllWorkPackages } from '../../hooks/work-packages.hooks';
31+
import { HOURS } from '../../utils/design-review.utils';
3132

3233
const schema = yup.object().shape({
3334
date: yup.date().required('Date is required'),
@@ -63,7 +64,6 @@ export const DesignReviewCreateModal: React.FC<DesignReviewCreateModalProps> = (
6364
teamTypes,
6465
defaultDate
6566
}) => {
66-
const HOURS: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
6767
const query = useQuery();
6868

6969
const toast = useToast();
@@ -82,8 +82,9 @@ export const DesignReviewCreateModal: React.FC<DesignReviewCreateModalProps> = (
8282

8383
const onSubmit = async (data: CreateDesignReviewFormInput) => {
8484
const day = data.date.getDay();
85+
const adjustedDay = day === 0 ? 6 : day - 1;
8586
const times = [];
86-
for (let i = day * 12 + data.startTime; i <= day * 12 + data.endTime; i++) {
87+
for (let i = adjustedDay * 12 + data.startTime; i < adjustedDay * 12 + data.endTime; i++) {
8788
times.push(i);
8889
}
8990
try {

0 commit comments

Comments
 (0)