Skip to content

Commit 0bdc90e

Browse files
committed
Merge branch 'develop' of https://github.com/Northeastern-Electric-Racing/FinishLine into #2142-misc-tab-page-blocks
2 parents 784d06b + e3ebe9e commit 0bdc90e

26 files changed

Lines changed: 329 additions & 135 deletions

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,11 @@ export default class DesignReviewsService {
162162
for (const memberUserSetting of memberUserSettings) {
163163
if (memberUserSetting.slackId) {
164164
try {
165-
await sendSlackDesignReviewNotification(memberUserSetting.slackId, designReview.designReviewId);
165+
await sendSlackDesignReviewNotification(
166+
memberUserSetting.slackId,
167+
designReview.designReviewId,
168+
designReview.wbsElement.name
169+
);
166170
} catch (err: unknown) {
167171
if (err instanceof Error) {
168172
throw new HttpException(500, `Failed to send slack notification: ${err.message}`);
@@ -321,19 +325,22 @@ export default class DesignReviewsService {
321325
if (!isUserOnDesignReview(submitter, designReviewTransformer(designReview)))
322326
throw new HttpException(400, 'Current user is not in the list of this design reviews members');
323327

324-
// Update user schedule settings
325-
const validAvailability = validateMeetingTimes(availability);
328+
availability.forEach((time) => {
329+
if (time < 0 || time > 83) {
330+
throw new HttpException(400, 'Availability times have to be in range 0-83');
331+
}
332+
});
326333

327334
await prisma.schedule_Settings.upsert({
328335
where: { userId: submitter.userId },
329336
update: {
330-
availability: validAvailability
337+
availability
331338
},
332339
create: {
333340
userId: submitter.userId,
334341
personalGmail: '',
335342
personalZoomLink: '',
336-
availability: validAvailability
343+
availability
337344
}
338345
});
339346

@@ -353,7 +360,7 @@ export default class DesignReviewsService {
353360

354361
// If all requested attendees have confirmed their schedule, mark design review as confirmed
355362
if (
356-
designReview.confirmedMembers.length ===
363+
updatedDesignReview.confirmedMembers.length ===
357364
designReview.requiredMembers.length + designReview.optionalMembers.length
358365
) {
359366
await prisma.design_Review.update({

src/backend/src/utils/slack.utils.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,15 @@ export const sendReimbursementRequestDeniedNotification = async (slackId: string
9191
}
9292
};
9393

94-
export const sendSlackDesignReviewNotification = async (slackId: string, designReviewId: string) => {
94+
export const sendSlackDesignReviewNotification = async (
95+
slackId: string,
96+
designReviewId: string,
97+
designReviewName: string
98+
) => {
9599
if (process.env.NODE_ENV !== 'production') return; // don't send msgs unless in prod
96-
const msg = `You have been invited to a Design Review!`;
97-
const fullLink = `https://finishlinebyner.com/design-reviews/${designReviewId}`;
98-
const linkButtonText = 'RSVP for the Design Review';
100+
const msg = `You have been invited to the ${designReviewName} Design Review!`;
101+
const fullLink = `https://finishlinebyner.com/settings/preferences?drId=${designReviewId}`;
102+
const linkButtonText = 'Confirm Availability';
99103

100104
try {
101105
await sendMessage(slackId, msg, fullLink, linkButtonText);

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -535,14 +535,7 @@ describe('Design Reviews', () => {
535535
vi.spyOn(prisma.design_Review, 'findUnique').mockResolvedValue(prismaDesignReview5);
536536
await expect(() =>
537537
DesignReviewsService.markUserConfirmed(prismaDesignReview5.designReviewId, [0, 85], batman)
538-
).rejects.toThrow(new HttpException(400, 'Meeting times have to be in range 0-83'));
539-
});
540-
541-
test('Availabilities were invalid - non-consecutive', async () => {
542-
vi.spyOn(prisma.design_Review, 'findUnique').mockResolvedValue(prismaDesignReview5);
543-
await expect(() =>
544-
DesignReviewsService.markUserConfirmed(prismaDesignReview5.designReviewId, [1, 3], batman)
545-
).rejects.toThrow(new HttpException(400, 'Meeting times have to be consecutive'));
538+
).rejects.toThrow(new HttpException(400, 'Availability times have to be in range 0-83'));
546539
});
547540
});
548541
});

src/frontend/src/apis/design-reviews.api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,7 @@ export const getSingleDesignReview = async (id: string) => {
5757
transformResponse: (data) => designReviewTransformer(JSON.parse(data))
5858
});
5959
};
60+
61+
export const markUserConfirmed = async (id: string, payload: { availability: number[] }) => {
62+
return axios.post<DesignReview>(apiUrls.designReviewMarkUserConfirmed(id), payload);
63+
};

src/frontend/src/components/Tabs.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ interface TabProps {
1313
baseUrl: string; //the URL that all the tab URLs extend
1414
defaultTab: string; //tab that the tabs component defaults to
1515
id: string;
16+
noUnderline?: boolean;
1617
}
1718

18-
const NERTabs = ({ setTab, tabsLabels, baseUrl, defaultTab, id }: TabProps) => {
19+
const NERTabs = ({ setTab, tabsLabels, baseUrl, defaultTab, id, noUnderline = false }: TabProps) => {
1920
const tabUrlValues = tabsLabels.map((tab) => tab.tabUrlValue);
2021
const match = useRouteMatch<{ tabValueString: string }>(`${baseUrl}/:tabValueString`);
2122
const tabValueString = match?.params?.tabValueString;
@@ -39,7 +40,7 @@ const NERTabs = ({ setTab, tabsLabels, baseUrl, defaultTab, id }: TabProps) => {
3940
<Tabs value={tabValue} onChange={handleTabChange} aria-label={`${id}-tabs`}>
4041
{tabsLabels.map((tab, idx) => (
4142
<Tab
42-
sx={{ borderBottom: 1, borderColor: 'divider' }}
43+
sx={noUnderline ? {} : { borderBottom: 1, borderColor: 'divider' }}
4344
label={tab.tabName}
4445
aria-label={tab.tabUrlValue}
4546
value={idx}

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

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import {
99
createDesignReviews,
1010
getAllDesignReviews,
1111
getAllTeamTypes,
12-
getSingleDesignReview
12+
getSingleDesignReview,
13+
markUserConfirmed
1314
} from '../apis/design-reviews.api';
15+
import { useCurrentUser } from './users.hooks';
1416

1517
export interface CreateDesignReviewsPayload {
1618
dateScheduled: Date;
@@ -101,9 +103,31 @@ export const useAllTeamTypes = () => {
101103
*
102104
* @returns a single design review
103105
*/
104-
export const useSingleDesignReview = (id: string) => {
105-
return useQuery<DesignReview, Error>(['design-reviews', id], async () => {
106-
const { data } = await getSingleDesignReview(id);
107-
return data;
108-
});
106+
export const useSingleDesignReview = (id?: string) => {
107+
return useQuery<DesignReview, Error>(
108+
['design-reviews', id],
109+
async () => {
110+
const { data } = await getSingleDesignReview(id!);
111+
return data;
112+
},
113+
{ enabled: !!id }
114+
);
115+
};
116+
117+
export const useMarkUserConfirmed = (id: string) => {
118+
const user = useCurrentUser();
119+
const queryClient = useQueryClient();
120+
return useMutation<DesignReview, Error, { availability: number[] }>(
121+
['design-reviews', 'mark-confirmed'],
122+
async (designReviewPayload: { availability: number[] }) => {
123+
const { data } = await markUserConfirmed(id, designReviewPayload);
124+
return data;
125+
},
126+
{
127+
onSuccess: () => {
128+
queryClient.invalidateQueries(['design-reviews']);
129+
queryClient.invalidateQueries(['users', user.userId, 'schedule-settings']);
130+
}
131+
}
132+
);
109133
};

src/frontend/src/pages/AdminToolsPage/AdminToolsBOMConfig.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
import { Grid } from '@mui/material';
2-
import PageBlock from '../../layouts/PageBlock';
1+
import { Grid, Typography } from '@mui/material';
32
import ManufacturerTable from './BOMConfig/ManufacturerTable';
43
import MaterialTypeTable from './BOMConfig/MaterialTypeTable';
54
import UnitTable from './BOMConfig/UnitTable';
5+
import { Box } from '@mui/system';
66

77
const AdminToolsBOMConfig: React.FC = () => {
88
return (
9-
<PageBlock title="Bill of Material Config">
9+
<Box>
10+
<Typography variant="h5" gutterBottom borderBottom={1} color="red" borderColor={'white'}>
11+
Bill of Materials Config
12+
</Typography>
1013
<Grid container spacing="3%">
1114
<Grid item direction="column" xs={12} md={6}>
1215
<ManufacturerTable />
@@ -18,7 +21,7 @@ const AdminToolsBOMConfig: React.FC = () => {
1821
<UnitTable />
1922
</Grid>
2023
</Grid>
21-
</PageBlock>
24+
</Box>
2225
);
2326
};
2427

src/frontend/src/pages/AdminToolsPage/AdminToolsFinanceConfig.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import AccountCodesTable from './FinanceConfig/AccountCodesTable';
55
const AdminToolsFinanceConfig: React.FC = () => {
66
return (
77
<Box padding="5px">
8-
<Typography marginBottom="15px" variant="h5">
8+
<Typography variant="h5" gutterBottom borderBottom={1} color="red" borderColor={'white'}>
99
Finance Config
1010
</Typography>
1111
<Grid container spacing="3%">

src/frontend/src/pages/AdminToolsPage/AdminToolsPage.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ const AdminToolsPage: React.FC = () => {
4343

4444
const UserManagementTab = () => {
4545
return isUserAdmin ? (
46-
<>
47-
<AdminToolsUserManagement />
46+
<Box>
47+
<Box mb={2}>
48+
<AdminToolsUserManagement />
49+
</Box>
4850
<TeamsTools />
49-
</>
51+
</Box>
5052
) : (
5153
<AdminToolsUserManagement />
5254
);
@@ -67,13 +69,16 @@ const AdminToolsPage: React.FC = () => {
6769
<PageLayout
6870
title="Admin Tools"
6971
tabs={
70-
<NERTabs
71-
setTab={setTabIndex}
72-
tabsLabels={tabs}
73-
baseUrl={routes.ADMIN_TOOLS}
74-
defaultTab={defaultTab}
75-
id="admin-tools-tabs"
76-
/>
72+
<Box borderBottom={1} borderColor={'divider'} width={'100%'}>
73+
<NERTabs
74+
noUnderline
75+
setTab={setTabIndex}
76+
tabsLabels={tabs}
77+
baseUrl={routes.ADMIN_TOOLS}
78+
defaultTab={defaultTab}
79+
id="admin-tools-tabs"
80+
/>
81+
</Box>
7782
}
7883
>
7984
{tabIndex === 0 ? (

src/frontend/src/pages/AdminToolsPage/AdminToolsProjectsConfig.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
import PageBlock from '../../layouts/PageBlock';
1+
import { Box } from '@mui/system';
22
import LinkTypeTable from './ProjectsConfig/LinkTypeTable';
3+
import { Typography } from '@mui/material';
34

45
const AdminToolsProjectsConfig: React.FC = () => {
56
return (
6-
<PageBlock title="Projects Config">
7+
<Box>
8+
<Typography variant="h5" gutterBottom borderBottom={1} color="red" borderColor={'white'}>
9+
Links Config
10+
</Typography>
711
<LinkTypeTable />
8-
</PageBlock>
12+
</Box>
913
);
1014
};
1115

0 commit comments

Comments
 (0)