1

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?

royalTiger
  • 11
  • 2

0 Answers0