@@ -25,14 +25,21 @@ import { useApi } from "@ui/util/api";
25
25
import { AllOrganizationList as orgList } from "@acm-uiuc/js-shared" ;
26
26
import { AppRoles } from "@common/roles" ;
27
27
import { EVENT_CACHED_DURATION } from "@common/config" ;
28
- import { IconInfoCircle , IconPlus , IconTrash } from "@tabler/icons-react" ;
28
+ import {
29
+ IconAlertCircle ,
30
+ IconInfoCircle ,
31
+ IconPlus ,
32
+ IconTrash ,
33
+ } from "@tabler/icons-react" ;
29
34
import {
30
35
MAX_METADATA_KEYS ,
31
36
MAX_KEY_LENGTH ,
32
37
MAX_VALUE_LENGTH ,
33
38
metadataSchema ,
34
39
} from "@common/types/events" ;
35
40
import { zod4Resolver as zodResolver } from "mantine-form-zod-resolver" ;
41
+ import FullScreenLoader from "@ui/components/AuthContext/LoadingScreen" ;
42
+ import { X } from "vitest/dist/chunks/reporters.d.BFLkQcL6" ;
36
43
37
44
export function capitalizeFirstLetter ( string : string ) {
38
45
return string . charAt ( 0 ) . toUpperCase ( ) + string . slice ( 1 ) ;
@@ -75,9 +82,11 @@ const baseBodySchema = z.object({
75
82
76
83
const requestBodySchema = baseBodySchema
77
84
. extend ( {
85
+ start : z . coerce . date ( ) ,
86
+ end : z . coerce . date ( ) ,
78
87
repeats : z . optional ( z . enum ( repeatOptions ) ) . nullable ( ) ,
79
88
repeatEnds : z . date ( ) . optional ( ) ,
80
- repeatExcludes : z . array ( z . date ( ) ) . max ( 100 ) . optional ( ) ,
89
+ repeatExcludes : z . array ( z . coerce . date ( ) ) . max ( 100 ) . optional ( ) ,
81
90
} )
82
91
. refine ( ( data ) => ( data . repeatEnds ? data . repeats !== undefined : true ) , {
83
92
message : "Repeat frequency is required when Repeat End is specified." ,
@@ -95,6 +104,7 @@ type EventPostRequest = z.infer<typeof requestBodySchema>;
95
104
96
105
export const ManageEventPage : React . FC = ( ) => {
97
106
const [ isSubmitting , setIsSubmitting ] = useState < boolean > ( false ) ;
107
+ const [ isLoading , setIsLoading ] = useState < boolean > ( true ) ;
98
108
const navigate = useNavigate ( ) ;
99
109
const api = useApi ( "core" ) ;
100
110
@@ -104,6 +114,7 @@ export const ManageEventPage: React.FC = () => {
104
114
105
115
useEffect ( ( ) => {
106
116
if ( ! isEditing ) {
117
+ setIsLoading ( false ) ;
107
118
return ;
108
119
}
109
120
const getEvent = async ( ) => {
@@ -136,10 +147,14 @@ export const ManageEventPage: React.FC = () => {
136
147
metadata : eventData . metadata || { } ,
137
148
} ;
138
149
form . setValues ( formValues ) ;
150
+ setIsLoading ( false ) ;
139
151
} catch ( error ) {
140
152
console . error ( "Error fetching event data:" , error ) ;
141
153
notifications . show ( {
142
- message : "Failed to fetch event data, please try again." ,
154
+ title : "Failed to fetch event data" ,
155
+ message : "Please try again or contact support." ,
156
+ color : "red" ,
157
+ icon : < IconAlertCircle size = { 16 } /> ,
143
158
} ) ;
144
159
}
145
160
} ;
@@ -176,12 +191,21 @@ export const ManageEventPage: React.FC = () => {
176
191
if ( form . values . locationLink === "" ) {
177
192
form . setFieldValue ( "locationLink" , undefined ) ;
178
193
}
179
- if ( form . values . repeatExcludes ?. length === 0 ) {
180
- form . setFieldValue ( "repeatExcludes" , undefined ) ;
181
- }
182
- } , [ form . values . locationLink , form . values . repeatExcludes ] ) ;
194
+ } , [ form . values . locationLink ] ) ;
183
195
184
- const handleSubmit = async ( values : EventPostRequest ) => {
196
+ const handleSubmit = async ( ) => {
197
+ const result = form . validate ( ) ;
198
+ if ( result . hasErrors ) {
199
+ console . warn ( result . errors ) ;
200
+ notifications . show ( {
201
+ title : "Validation failed" ,
202
+ message : "Please review the errors and try again." ,
203
+ color : "red" ,
204
+ icon : < IconAlertCircle size = { 16 } /> ,
205
+ } ) ;
206
+ return ;
207
+ }
208
+ const values = form . values ;
185
209
try {
186
210
setIsSubmitting ( true ) ;
187
211
@@ -195,9 +219,10 @@ export const ManageEventPage: React.FC = () => {
195
219
values . repeatEnds && values . repeats
196
220
? dayjs ( values . repeatEnds ) . format ( "YYYY-MM-DD[T]HH:mm:00" )
197
221
: undefined ,
198
- repeatExcludes : values . repeatExcludes
199
- ? values . repeatExcludes . map ( ( x ) => dayjs ( x ) . format ( "YYYY-MM-DD" ) )
200
- : undefined ,
222
+ repeatExcludes :
223
+ values . repeatExcludes && values . repeatExcludes . length > 0
224
+ ? values . repeatExcludes . map ( ( x ) => dayjs ( x ) . format ( "YYYY-MM-DD" ) )
225
+ : [ ] ,
201
226
repeats : values . repeats ? values . repeats : undefined ,
202
227
metadata :
203
228
Object . keys ( values . metadata || { } ) . length > 0
@@ -301,7 +326,9 @@ export const ManageEventPage: React.FC = () => {
301
326
302
327
setMetadataKeys ( newMetadataKeys ) ;
303
328
} , [ Object . keys ( form . values . metadata || { } ) . length ] ) ;
304
-
329
+ if ( isLoading ) {
330
+ return < FullScreenLoader /> ;
331
+ }
305
332
return (
306
333
< AuthGuard
307
334
resourceDef = { { service : "core" , validRoles : [ AppRoles . EVENTS_MANAGER ] } }
@@ -328,7 +355,7 @@ export const ManageEventPage: React.FC = () => {
328
355
</ Alert >
329
356
) }
330
357
331
- < form onSubmit = { form . onSubmit ( handleSubmit ) } >
358
+ < form >
332
359
< TextInput
333
360
label = "Event Title"
334
361
withAsterisk
@@ -501,7 +528,12 @@ export const ManageEventPage: React.FC = () => {
501
528
) }
502
529
</ Box >
503
530
504
- < Button type = "submit" mt = "md" >
531
+ < Button
532
+ mt = "md"
533
+ onClick = { ( ) => {
534
+ handleSubmit ( ) ;
535
+ } }
536
+ >
505
537
{ isSubmitting ? (
506
538
< >
507
539
< Loader size = { 16 } color = "white" />
0 commit comments