Hoping to get some help with an error I have been getting. I am working on a page dedicated on creating different social events. I have a data type which is:
export interface NewEventType {
eventDetails?: EventDetails;
eventType?: string;
location?: Location;
schedule?: Schedule;
eventSettings?: EventSettings;
_id?: string;
attendees?: Attendees;
createdBy?: string;
groupDetails?: GroupDetails;
isAttendee?: false;
isEventHost?: true;
isEventOwner?: true;
eventStatus?: string;
}
export interface EventResult {
docs?: NewEventType[];
next_key?: NextResult[];
}
export interface NextResult {
key?: string;
value?: string;
}
export interface EventDetails {
title?: string;
eventSummary?: string;
eventDetails?: string;
eventHosts?: {
docs: [
{
displayName: string;
firstName: string;
lastName: string;
photoURL: string;
userId: string;
_id: string;
}
];
};
images?: any[];
eventImageUrl?: string;
}
export interface EventSettings {
repeatEvent?: RepeatEvent;
askMembersQuestions?: AskMembersQuestion[];
attendeeLimit?: number;
eventFee?: EventFee;
refoundPolicy?: string;
}
export interface Attendees {
docs?: [
{
displayName: string;
firstName: string;
lastName: string;
photoURL: string;
status: string;
userId: string;
_id: string;
}
];
}
export interface AskMembersQuestion {
question?: string;
question2?: string;
}
export interface EventFee {
acceptedPayments?: string[];
eventFee?: string;
minPayment?: string;
currency?: string;
}
export interface RepeatEvent {
period?: string;
orWhichDays?: string;
}
export interface Location {
locationType?: string;
platform?: Platform;
address?: Address;
other?: null;
}
export interface Address {
city?: string;
address?: string;
postCode?: string;
state?: string;
country?: string;
}
export interface Platform {
name?: string;
url?: string;
}
export interface Schedule {
eventStartDateTime?: string;
eventEndDateTime?: string;
}
export interface GroupDetails {
groupDetails?: string;
groupId?: string;
groupImageUrl?: string;
groupName?: string;
groupSummary?: string;
}
I also have use Ant Design form where I take I am linking the form with the objects
const CreateEvent = (props: CreateEventProps) => {
const [attendeeLimit, setAttendeeLimit] = useState<number>(DEFAULT_ATTENDEE_LIMIT);
const [allowAttendeeLimit, setAllowAttendeeLimit] = useState<boolean>(true);
const [allowEventFee, setAllowEventFee] = useState<boolean>(true);
const [eventPhoto, setEventPhoto] = useState<File>();
const [eventStartDate, setEventStartDate] = useState<Moment>();
const [eventStartTime, setEventStartTime] = useState<Moment>();
const [eventEndDate, setEventEndDate] = useState<Moment>();
const [isLoading, setIsLoading] = useState<boolean>(false);
const onFinish = (formInput: any) => {
let startTime: Date, startDate: Date | undefined, endTime: Date, endDate: Date | undefined;
if (formInput.startTime && formInput.startDate) {
startTime = new Date(formInput.startTime);
startDate = new Date(formInput.startDate);
startDate.setHours(startTime.getHours());
startDate.setMinutes(startTime.getMinutes());
startDate.setMilliseconds(0);
} else {
startDate = new Date(Date.now());
}
if (formInput.endTime && formInput.endDate) {
endTime = new Date(formInput.endTime);
endDate = new Date(formInput.endDate);
endDate.setHours(endTime.getHours());
endDate.setMinutes(endTime.getMinutes());
endDate.setMilliseconds(0);
}
if (formInput.startDate > formInput.endDate) {
return MessageUtil.showErrorMessage('event end date cannot be earlier than start date');
}
const newEvent: NewEventType = {
eventType: formInput.category,
eventDetails: {
title: formInput.title,
eventDetails: formInput.description,
eventSummary: formInput.summary,
},
location: {
locationType: formInput.locationType,
platform: {
url: formInput.locationType === 'online' ? formInput.address : '',
},
address: formInput.address,
},
schedule: {
eventStartDateTime: startDate ? DateUtil.toIsoString(startDate) : DateUtil.toIsoString(new Date(Date.now())),
eventEndDateTime: endDate ? DateUtil.toIsoString(endDate) : DateUtil.toIsoString(new Date(Date.now())),
},
eventSettings: {
attendeeLimit: allowAttendeeLimit ? attendeeLimit : 0,
eventFee: allowEventFee
? {
acceptedPayments: formInput.payments,
eventFee: formInput.amount,
currency: formInput.currency,
}
: {},
},
};
setIsLoading(true);
props.groupId &&
createEvent(props.groupId, newEvent)
.then((res) => {
const { id: eventId } = res.data;
eventPhoto &&
props.groupId &&
uploadEventImage(eventId, props.groupId, eventPhoto)
.then((res) => {
setIsLoading(false);
appRouter.navigateToEventDetail(eventId);
})
.catch((err) => {
MessageUtil.showErrorMessage('Error uploading image');
setIsLoading(false);
});
})
.catch((err: AxiosError) => {
setIsLoading(false);
const { message } = err?.response?.data;
if (message === 'Event exists') {
return MessageUtil.showErrorMessage('This event is exist');
}
MessageUtil.showErrorMessage("Error creating event. Please try again.'");
});
};
const normFile = (e: any) => {
setEventPhoto(e.file.originFileObj);
if (Array.isArray(e)) {
return e;
}
return e?.fileList;
};
const handleStartDate = (value: any) => {
value && setEventStartDate(value as Moment);
};
const handleStartTime = (value: any) => {
value && setEventStartTime(value as Moment);
};
const handleEndDate = (value: any) => {
value && setEventEndDate(value as Moment);
};
const handleFormFailed = (errorInfo: ValidateErrorEntity) => {
const { values, errorFields, outOfDate } = errorInfo;
MessageUtil.showErrorMessage(errorFields[0].errors.toString());
};
const range = (start: number, end: number) => {
const result = [];
for (let i = start; i < end; i++) {
result.push(i);
}
return result;
};
return (
<div style={{ backgroundColor: 'white' }}>
<Row id='create-event-header' justify='center' align='middle'>
<Col span={16} xs={20} sm={16}>
<Row align='middle' justify='space-between'>
<Col>
<Typography.Title>Create event</Typography.Title>
<Typography.Text>Hosted by IT Events Trainings - Zero To Hero</Typography.Text>
</Col>
<Col>
<Button htmlType='submit' className='myprofile-follow-button' form='create-event-form'>
Publish
<div className='myprofile-follow-button-shadow'></div>
</Button>
</Col>
</Row>
</Col>
</Row>
<Row justify='center' style={{ marginBottom: '20px' }}>
<Col span={16} xs={20} sm={16}>
<Space direction='vertical'>
<Typography.Text style={{ fontSize: '30px', fontWeight: '500' }}>Basic Info</Typography.Text>
<Typography.Text>
Name your event and tell event-goers why they should come. Add details that highlight what makes it unique
</Typography.Text>
</Space>
</Col>
</Row>
<Form
id='create-event-form'
layout='vertical'
scrollToFirstError
name='create-event-form'
initialValues={{ locationType: 'venue', category: 'event', host: 'myself', remember: true }}
onFinish={onFinish}
onFinishFailed={handleFormFailed}
>
<Row align='middle' justify='center'>
<Col
xs={23}
sm={22}
md={20}
lg={16}
style={{
backgroundColor: '#F7F7FC',
borderRadius: '10px',
}}
>
<Col xs={23} sm={22} md={20} lg={16} style={{ margin: '80px auto' }}>
<Form.Item
label='Event Title'
name='title'
rules={[
{ required: true, message: 'Please input event name' },
{ min: 3, message: 'Event name must be min 3 char' },
]}
>
<Input placeholder='Event title' name='title' />
</Form.Item>
<Form.Item
label='Event Summary'
name='summary'
rules={[
{ required: true, message: 'Please input event summary' },
{ min: 3, message: 'Event name must be min 3 char' },
]}
>
<Input placeholder='Event summary' name='summary' />
</Form.Item>
<Form.Item
label='Description'
name='description'
rules={[
{ required: true, message: 'Please input description' },
{
min: 3,
message: 'Description must be min 3 char',
},
]}
>
<Form.Item>
<Typography.Text type='secondary'>
Let your attendees know what to expect, including the agenda, what they need to bring, and how to
find the group.
</Typography.Text>
<TextArea rows={10} placeholder='Description' name='description' />
</Form.Item>
</Form.Item>
<Form.Item label='Category' name='category'>
<Select
bordered={false}
placeholder='Select category'
style={{ backgroundColor: 'white', padding: '5px', border: '1px solid #999db6' }}
>
<Select.Option value='event'>EVENT</Select.Option>
<Select.Option value='training'>TRAINING</Select.Option>
<Select.Option value='bootcamp'>BOOTCAMP</Select.Option>
<Select.Option value='workshop'>WORKSHOP</Select.Option>
<Select.Option value='socialising-event'>SOCIALS EVENT</Select.Option>
<Select.Option value='volunteer-event'>VOLUNTEER EVENT</Select.Option>
</Select>
</Form.Item>
</Col>
</Col>
<Row justify='center' style={{ marginBottom: '30px', marginTop: '40px', width: '100%' }}>
<Col span={16} xs={20} sm={16}>
<Space direction='vertical'>
<Typography.Text style={{ fontSize: '30px', fontWeight: '500' }}>Location</Typography.Text>
<Typography.Text>
Help people in the area discover your event and let attendees know where to show up.
</Typography.Text>
</Space>
</Col>
</Row>
<Col
xs={23}
sm={22}
md={20}
lg={16}
style={{
backgroundColor: '#F7F7FC',
borderRadius: '10px',
}}
>
<Col span={16} style={{ margin: '80px auto' }}>
<Form.Item name='locationType'>
<Radio.Group buttonStyle='solid'>
<Space>
<Radio.Button value='venue'>Venue</Radio.Button>
<Radio.Button value='online'>Online Event</Radio.Button>
</Space>
</Radio.Group>
</Form.Item>
<Form.Item
style={{ marginTop: '35px' }}
name='address'
label='Event location'
rules={[{ required: true, message: 'Location is required' }]}
>
<Input placeholder='Search for adress' />
</Form.Item>
</Col>
</Col>
<Row justify='center' style={{ marginBottom: '30px', marginTop: '40px', width: '100%' }}>
<Col span={16} xs={20} sm={16}>
<Space direction='vertical'>
<Typography.Text style={{ fontSize: '30px', fontWeight: '500' }}>Date and time</Typography.Text>
<Typography.Text>
Tell event-goers when your event starts and ends so they can make plans to attend.
</Typography.Text>
</Space>
</Col>
</Row>
<Col
xs={23}
sm={22}
md={20}
lg={16}
style={{
backgroundColor: '#F7F7FC',
borderRadius: '10px',
}}
>
<Col span={16} style={{ margin: '80px auto' }}>
<Row justify='space-between' align='middle' gutter={20}>
<Col xs={24} lg={12}>
<Form.Item
label='Event start'
name='startDate'
rules={[{ required: true, message: 'Please choose event start date' }]}
>
<DatePicker
style={{ width: '100%' }}
onChange={handleStartDate}
disabledDate={(current) => current < moment().startOf('day')}
/>
</Form.Item>
</Col>
<Col xs={24} lg={12}>
<Form.Item label='Start time' name='startTime'>
<TimePicker
format='HH:mm'
onChange={handleStartTime}
onSelect={handleStartTime}
style={{ width: '100%' }}
disabledTime={(now: Moment) => {
if (now.date() === eventStartDate?.date()) {
return {
disabledHours: () => range(0, now.hour()),
disabledMinutes: () =>
now.hour() === eventStartTime?.hour() ? range(0, now.minute()) : [],
};
}
return {};
}}
/>
</Form.Item>
</Col>
</Row>
<Row justify='space-between' align='middle' gutter={20}>
<Col xs={24} lg={12}>
<Form.Item
label='Event end'
name='endDate'
rules={[{ required: true, message: 'Please choose event end date' }]}
>
<DatePicker
style={{ width: '100%' }}
onChange={handleEndDate}
disabledDate={(current: any) => {
return current && eventStartDate && current < eventStartDate?.startOf('day');
}}
/>
</Form.Item>
</Col>
<Col xs={24} lg={12}>
<Form.Item label='End time' name='endTime'>
<TimePicker
format='HH:mm'
style={{ width: '100%' }}
disabledTime={(now: Moment) => {
if (eventEndDate?.date() === eventStartDate?.date()) {
return {
disabledHours: () => range(0, ((eventStartTime?.hour() as number) + 1) as number),
};
}
return {};
}}
/>
</Form.Item>
</Col>
</Row>
</Col>
</Col>
<Row justify='center' style={{ marginBottom: '30px', marginTop: '40px', width: '100%' }}>
<Col span={16} xs={20} sm={16}>
<Space direction='vertical'>
<Typography.Text style={{ fontSize: '30px', fontWeight: '500' }}>Event</Typography.Text>
<Typography.Text>Lorem ipsum dolar sit amet ontordonto latinkomlor sit amed</Typography.Text>
</Space>
</Col>
</Row>
<Col
xs={23}
sm={22}
md={20}
lg={16}
style={{
backgroundColor: '#F7F7FC',
borderRadius: '10px',
}}
>
<Col span={16} style={{ margin: '80px auto' }}>
<Form.Item
rules={[{ required: true }]}
label='Featured photo'
name='photo'
valuePropName='fileList'
getValueFromEvent={normFile}
>
<Dragger
multiple={false}
name='files'
accept='.png,.jpeg,.jpg'
listType='picture'
style={{ backgroundColor: 'white', border: '1px dashed #A0A3BD' }}
>
<Space direction='vertical' size={60} style={{ margin: '45px 0' }}>
<Button type='primary'>
<FileImageOutlined />
Click or Drag
</Button>
<Typography.Text type='secondary'>1200 x 675</Typography.Text>
</Space>
</Dragger>
</Form.Item>
</Col>
</Col>
<Row justify='center' style={{ marginBottom: '30px', marginTop: '40px', width: '100%' }}>
<Col span={16} xs={20} sm={16}>
<Space direction='vertical'>
<Typography.Text style={{ fontSize: '30px', fontWeight: '500' }}>Optional Settings</Typography.Text>
<Typography.Text>Lorem ipsum dolar sit amet ontordonto latinkomlor sit amed</Typography.Text>
</Space>
</Col>
</Row>
<Col
xs={23}
sm={22}
md={20}
lg={16}
style={{
backgroundColor: '#F7F7FC',
borderRadius: '10px',
}}
>
<Col span={16} style={{ margin: '80px auto 50px auto' }}>
<Row justify='space-between'>
<Col>Attendee limit</Col>
<Col>
<Switch defaultChecked onChange={() => setAllowAttendeeLimit(!allowAttendeeLimit)} />
</Col>
</Row>
<Col span={7}>
<Row gutter={[15, 0]} align='middle' className='number-input'>
<Col>{allowAttendeeLimit ? attendeeLimit : '0'}</Col>
<Col>
<Button
type='default'
disabled={allowAttendeeLimit ? false : true}
onClick={() => setAttendeeLimit(attendeeLimit !== 0 ? attendeeLimit - 1 : 0)}
>
-
</Button>
</Col>
<Col>
<Button
type='default'
disabled={allowAttendeeLimit ? false : true}
onClick={() => setAttendeeLimit(attendeeLimit + 1)}
>
+
</Button>
</Col>
</Row>
</Col>
<Divider />
</Col>
<Col span={16} style={{ margin: '50px auto' }}>
<Row justify='space-between' style={{ marginBottom: '50px' }}>
<Col>Event fee</Col>
<Col>
<Switch defaultChecked onChange={() => setAllowEventFee(!allowEventFee)} />
</Col>
</Row>
<Form.Item label='Payment method' name='payment'>
<Select
bordered={false}
placeholder='Direct from member E.g. Cash...'
style={{ backgroundColor: 'white', padding: '5px', border: '1px solid #999db6' }}
disabled={allowEventFee ? false : true}
>
<Select.Option value='paypal'>PAYPAL</Select.Option>
<Select.Option value='credit card'>CREDIT CARD</Select.Option>
<Select.Option value='apple pay'>APPLE PAY</Select.Option>
<Select.Option value='google pay'>GOOGLE PAY</Select.Option>
</Select>
</Form.Item>
<Row justify='space-between' align='middle' gutter={20}>
<Col xs={24} lg={12}>
<Form.Item label='Currency' name='currency'>
<Select
bordered={false}
placeholder='Select'
style={{ backgroundColor: 'white', padding: '5px', border: '1px solid #999db6' }}
disabled={allowEventFee ? false : true}
>
<Select.Option value='GBP'>GBP</Select.Option>
<Select.Option value='EURO'>EURO</Select.Option>
<Select.Option value='DOLAR'>DOLAR</Select.Option>
</Select>
</Form.Item>
</Col>
<Col xs={24} lg={12}>
<Form.Item label='Amount' name='amount'>
<Input type='number' placeholder='0,00' disabled={allowEventFee ? false : true} />
</Form.Item>
</Col>
</Row>
<Row justify='end'>
<Button type='primary' form='create-event-form' htmlType='submit'>
Publish Event
</Button>
</Row>
</Col>
</Col>
</Row>
</Form>
<LoadingModal isShow={isLoading} message='Event being created' />
</div>
);
};
export default CreateEvent;
When I check the browser I get the following payload
{"eventType":"event","eventDetails":{"title":"Title example","eventDetails":"some group description","eventSummary":"summary example"},"location":{"locationType":"venue","platform":{"url":""},"address":"London"},"schedule":{"eventStartDateTime":"2022-10-13T12:00:00+01:00","eventEndDateTime":"2022-10-13T14:00:14+01:00"},"eventSettings":{"attendeeLimit":0,"eventFee":{}}}
I get the following response:
{
"statusCode": 400,
"message": [
"location.address.each value in nested property address must be either object or array"
],
}
I think I am making a mistake in the datatype in the Address object where I tried to pass it as an array but I keep hitting exactly the same error. What am I missing?