Skip to content

Commit e780a9c

Browse files
committed
ability to update status in the UI
1 parent 17c249f commit e780a9c

File tree

4 files changed

+161
-25
lines changed

4 files changed

+161
-25
lines changed

src/api/routes/roomRequests.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ const roomRequestRoutes: FastifyPluginAsync = async (fastify, _options) => {
7777
message: "Could not save status update.",
7878
});
7979
}
80-
return reply.status(201);
80+
return reply.status(201).send();
8181
},
8282
);
8383
fastify.get<{

src/ui/pages/roomRequest/ExistingRoomRequests.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React, { useEffect, useState } from 'react';
22
import { RoomRequestGetAllResponse } from '@common/types/roomRequest';
3-
import { Loader, Table } from '@mantine/core';
3+
import { Badge, Loader, Table } from '@mantine/core';
44
import { useNavigate } from 'react-router-dom';
5-
import { formatStatus } from './roomRequestUtils';
5+
import { formatStatus, getStatusColor } from './roomRequestUtils';
66

77
interface ExistingRoomRequestsProps {
88
getRoomRequests: (semester: string) => Promise<RoomRequestGetAllResponse>;
@@ -43,7 +43,9 @@ const ExistingRoomRequests: React.FC<ExistingRoomRequestsProps> = ({
4343
{item.title}
4444
</Table.Td>
4545
<Table.Td>{item.host}</Table.Td>
46-
<Table.Td>{formatStatus(item.status)}</Table.Td>
46+
<Table.Td>
47+
<Badge color={getStatusColor(item.status)}>{formatStatus(item.status)}</Badge>
48+
</Table.Td>
4749
</Table.Tr>
4850
);
4951
})}

src/ui/pages/roomRequest/ViewRoomRequest.page.tsx

Lines changed: 135 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,89 @@
11
import React, { useEffect, useState } from 'react';
2-
import { Container, Title, Grid, Timeline, Text, Tooltip } from '@mantine/core';
2+
import {
3+
Container,
4+
Title,
5+
Grid,
6+
Timeline,
7+
Text,
8+
Tooltip,
9+
Paper,
10+
Select,
11+
Textarea,
12+
Badge,
13+
Button,
14+
Loader,
15+
} from '@mantine/core';
316
import { AuthGuard } from '@ui/components/AuthGuard';
417
import { AppRoles } from '@common/roles';
518
import { useApi } from '@ui/util/api';
619
import NewRoomRequest from './NewRoomRequest';
7-
import { RoomRequestGetResponse } from '@common/types/roomRequest';
20+
import {
21+
RoomRequestGetResponse,
22+
RoomRequestStatus,
23+
RoomRequestStatusUpdatePostBody,
24+
} from '@common/types/roomRequest';
825
import { useParams } from 'react-router-dom';
9-
import { formatStatus, getStatusIcon } from './roomRequestUtils';
26+
import { formatStatus, getStatusColor, getStatusIcon } from './roomRequestUtils';
1027
import moment from 'moment-timezone';
28+
import { useForm } from '@mantine/form';
29+
import { notifications } from '@mantine/notifications';
30+
import FullScreenLoader from '@ui/components/AuthContext/LoadingScreen';
1131

1232
export const ViewRoomRequest: React.FC = () => {
1333
const { semesterId, requestId } = useParams();
1434
const [data, setData] = useState<RoomRequestGetResponse | null>(null);
35+
const [isSubmitting, setIsSubmitting] = useState(false);
36+
const newStatusForm = useForm<{ status: RoomRequestStatus | null; notes?: string }>({
37+
initialValues: { status: null },
38+
validate: {
39+
status: (value) =>
40+
value && Object.keys(RoomRequestStatus).includes(value) ? null : 'Please select a status.',
41+
notes: (value) =>
42+
value && value.length <= 1000 ? null : 'Please limit your response to 1000 characters.',
43+
},
44+
});
45+
const handleStatusChange = async (payload: RoomRequestStatusUpdatePostBody) => {
46+
await api.post(`/api/v1/roomRequests/${semesterId}/${requestId}/status`, payload);
47+
};
48+
const updateData = async () => {
49+
const response = await api.get(`/api/v1/roomRequests/${semesterId}/${requestId}`);
50+
setData(response.data);
51+
};
52+
const submitStatusChange = async () => {
53+
try {
54+
setIsSubmitting(true);
55+
await handleStatusChange(newStatusForm.values as RoomRequestStatusUpdatePostBody);
56+
notifications.show({
57+
title: 'Status update submitted!',
58+
message: 'The requestor has been notified.',
59+
});
60+
updateData();
61+
setIsSubmitting(false);
62+
newStatusForm.reset();
63+
} catch (e) {
64+
notifications.show({
65+
color: 'red',
66+
title: 'Failed to submit update',
67+
message: 'Please try again or contact support.',
68+
});
69+
setIsSubmitting(false);
70+
throw e;
71+
}
72+
};
1573
const api = useApi('core');
74+
const getStatusOptions = (currentStatus: RoomRequestStatus) => {
75+
if (!data?.updates) return [];
76+
if (currentStatus === RoomRequestStatus.APPROVED) return [];
77+
return Object.values(RoomRequestStatus)
78+
.filter((status) => status !== data.updates[data.updates.length - 1].status)
79+
.filter((status) => status !== RoomRequestStatus.CREATED)
80+
.map((status) => ({
81+
value: status,
82+
label: formatStatus(status),
83+
}));
84+
};
1685
useEffect(() => {
17-
const thing = async () => {
18-
const response = await api.get(`/api/v1/roomRequests/${semesterId}/${requestId}`);
19-
setData(response.data);
20-
};
21-
thing();
86+
updateData();
2287
}, []);
2388
return (
2489
<AuthGuard
@@ -28,12 +93,71 @@ export const ViewRoomRequest: React.FC = () => {
2893
}}
2994
showSidebar={true}
3095
>
31-
<Container mb="xl" ml="xl">
32-
<Title>View Room Request</Title>
33-
</Container>
96+
{data && (
97+
<Container mb="xl" ml="xl">
98+
<Title>{data.data.title}</Title>
99+
<Badge color={getStatusColor(data.updates[data.updates.length - 1].status)}>
100+
{formatStatus(data.updates[data.updates.length - 1].status)}
101+
</Badge>
102+
</Container>
103+
)}
104+
{!data && <FullScreenLoader />}
34105
<Grid ml={'xl'}>
35106
<Grid.Col span={8}>
36107
{data && <NewRoomRequest viewOnly initialValues={data?.data} />}
108+
<AuthGuard
109+
resourceDef={{
110+
service: 'core',
111+
validRoles: [AppRoles.ROOM_REQUEST_UPDATE],
112+
}}
113+
showSidebar={true}
114+
isAppShell={false}
115+
>
116+
{data && data.data && (
117+
<>
118+
<Text mb="md" size="xl">
119+
Update Status
120+
</Text>
121+
{getStatusOptions(data.updates[data.updates.length - 1].status).length > 0 ? (
122+
<>
123+
<Select
124+
label="New Status"
125+
placeholder="Select new status"
126+
data={getStatusOptions(data.updates[data.updates.length - 1].status)}
127+
allowDeselect={false}
128+
key={newStatusForm.key('status')}
129+
mb="md"
130+
{...newStatusForm.getInputProps('status')}
131+
/>
132+
{newStatusForm.values.status && (
133+
<>
134+
<Textarea
135+
label="Event Description"
136+
description="Max 1000 characters."
137+
placeholder="Provide any requisite details needed to use the room."
138+
{...newStatusForm.getInputProps('notes')}
139+
/>
140+
<Button onClick={submitStatusChange} color="green">
141+
{isSubmitting ? (
142+
<>
143+
<Loader size={16} color="white" />
144+
Submitting...
145+
</>
146+
) : (
147+
'Submit'
148+
)}
149+
</Button>
150+
</>
151+
)}
152+
</>
153+
) : (
154+
<>
155+
<Text size="sm">No status updates can be made at this time.</Text>
156+
</>
157+
)}
158+
</>
159+
)}
160+
</AuthGuard>
37161
</Grid.Col>
38162
<Grid.Col span={3} ml={'lg'}>
39163
{data && (
@@ -68,15 +192,6 @@ export const ViewRoomRequest: React.FC = () => {
68192
</Text>
69193
</>
70194
)}
71-
<AuthGuard
72-
resourceDef={{
73-
service: 'core',
74-
validRoles: [AppRoles.ROOM_REQUEST_UPDATE],
75-
}}
76-
showSidebar={true}
77-
>
78-
Status update ability coming soon! {/** TODO */}
79-
</AuthGuard>
80195
</Grid.Col>
81196
</Grid>
82197
</AuthGuard>

src/ui/pages/roomRequest/roomRequestUtils.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,24 @@ export const formatStatus = (status: RoomRequestStatus) => {
2929
if (status === RoomRequestStatus.SUBMITTED) {
3030
return 'Submitted to UIUC';
3131
}
32-
return capitalizeFirstLetter(status).replaceAll('_', ' ').replaceAll('uiuc', 'UIUC');
32+
return capitalizeFirstLetter(status)
33+
.replaceAll('_', ' ')
34+
.replaceAll('uiuc', 'UIUC')
35+
.replaceAll('acm', 'ACM');
36+
};
37+
38+
export const getStatusColor = (status: RoomRequestStatus) => {
39+
switch (status) {
40+
case RoomRequestStatus.APPROVED:
41+
return 'green';
42+
case RoomRequestStatus.REJECTED_BY_UIUC:
43+
case RoomRequestStatus.REJECTED_BY_ACM:
44+
return 'red';
45+
case RoomRequestStatus.SUBMITTED:
46+
return 'orange';
47+
case RoomRequestStatus.MORE_INFORMATION_NEEDED:
48+
return 'yellow';
49+
default:
50+
return 'black';
51+
}
3352
};

0 commit comments

Comments
 (0)