11import  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' ; 
316import  {  AuthGuard  }  from  '@ui/components/AuthGuard' ; 
417import  {  AppRoles  }  from  '@common/roles' ; 
518import  {  useApi  }  from  '@ui/util/api' ; 
619import  NewRoomRequest  from  './NewRoomRequest' ; 
7- import  {  RoomRequestGetResponse  }  from  '@common/types/roomRequest' ; 
20+ import  { 
21+   RoomRequestGetResponse , 
22+   RoomRequestStatus , 
23+   RoomRequestStatusUpdatePostBody , 
24+ }  from  '@common/types/roomRequest' ; 
825import  {  useParams  }  from  'react-router-dom' ; 
9- import  {  formatStatus ,  getStatusIcon  }  from  './roomRequestUtils' ; 
26+ import  {  formatStatus ,  getStatusColor ,   getStatusIcon  }  from  './roomRequestUtils' ; 
1027import  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
1232export  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 > 
0 commit comments