jquense / react-big-calendar

gcal/outlook like calendar component
http://jquense.github.io/react-big-calendar/examples/index.html
MIT License
7.9k stars 2.24k forks source link

Issue Displaying the Calendar within vite react app #2522

Open nourbenamor2001 opened 8 months ago

nourbenamor2001 commented 8 months ago

Check that this is really a bug

Reproduction link

n/a

Bug description

image image image image

I have requested to display some event data (dummy data, not actual backend api calls) to my react big calendar monthly and agenda cells. But the monthly calendar and the agenda do not show as seen in the images. This might be due to a responsiveness issue, but I doubt it because the Day and Week cells display quite properly. I think it might be in my code, please help me if you have any idea :

import React, { useState, useMemo } from 'react';
import { Calendar, momentLocalizer } from 'react-big-calendar';
import 'react-big-calendar/lib/css/react-big-calendar.css';
import moment from 'moment';
import { bookings } from '../../../data/dummy'; // Import bookings data from dummy.js
import HomeP from '../Home/Home';

const localizer = momentLocalizer(moment);

export default function Schedule() {
  const [showModal, setShowModal] = useState(false);
  const [selectedEvent, setSelectedEvent] = useState(null);

  const events = bookings.map(booking => {
    const start = moment(booking.eventStartDate).toDate();
    const end = moment(booking.eventEndDate).toDate();

    return {
      id: booking.id, // Adding a unique ID for each event
      start,
      end,
      title: booking.eventType,
      data: {
        booking: {
          id: booking.id,
          status: booking.bookingStatus,
          resource: booking.customerName,
          address: booking.eventLocation, // Changed to eventLocation
          packageOrders: booking.packageOrders,
          packageQuantity: booking.packageQuantity,
          discount: booking.discount,
          total: booking.total,
          delivery_needed: booking.delivery_needed // Corrected to delivery_needed
        }
      }
    };
  });

  const handleSelectEvent = (event) => {
    setShowModal(true);
    setSelectedEvent(event);
  };

  const deleteEvent = () => {
    // Implement logic to delete the selected event from your data source
    console.log("Event deleted:", selectedEvent);
    setShowModal(false);
  };

  const confirmEvent = () => {
    // Implement logic to change the status of the selected event to 'Confirmed'
    console.log("Event confirmed:", selectedEvent);
    setShowModal(false);
  };

  const closeModal = () => {
    setShowModal(false);
  };

  const bookingData = selectedEvent?.data?.booking; // Defensive access

  const components = useMemo(
    () => ({
      event: ({event}) => {
        const eventStatus = event?.data?.booking?.status;
        switch (eventStatus) {
          case 'Confirmed':
            return <div style={{ background: '#94A684', height: '100%' }}>{event.title}</div>;
          case 'Pending':
            return <div style={{ background: '#FFC090', height: '100%' }}>{event.title}</div>;
          default:
            return <div></div>;
        }
      },
      agenda: {
        event: ({ event }) => (
          <div>
            <h3>Event Details:</h3>
            <p><strong>Title:</strong> {event.title}</p>
            <p><strong>Customer:</strong>{event.data.booking.resource}</p>
            <p><strong>Status:</strong> {event.data.booking.status}</p>
            <p><strong>Address:</strong> {event.data.booking.address}</p>
            <p><strong>Delivery:</strong> {event.data.booking.delivery_needed ? 'Yes' : 'No'}</p>
            <p><strong>Package Orders:</strong></p>
            <ul>
              {event.data.booking.packageOrders.map((order, index) => (
                <li key={index}>
                  {order} - Quantity: {event.data.booking.packageQuantity[index]}
                </li>
              ))}
            </ul>
            <p><strong>Discount:</strong> {event.data.booking.discount}</p>
            <p><strong>Total:</strong> {event.data.booking.total}</p>
          </div>
        )
      }
    }),
    []
  );

  return (
    <>
    <div style={{ height: '100%', width: '100%',  backgroundColor: "#f8f9fa" }}>
    {console.log(events)}
      <Calendar
        localizer={localizer}
        events={events}
        components={components}
        style={{ margin: '50px' }}
        selectable={true}

        onSelectEvent={handleSelectEvent}
      />
      {showModal && (
        <div className="modal" style={{ display: 'block', backgroundColor: "rgba(0,0,0,0.15)", position: 'fixed', top: 0, bottom: 0, left: 0, right: 0 }}>
          <div className="modal-dialog">
            <div className="modal-content">
              <div className="modal-header">
                <h5 className="modal-title">Event Title : {selectedEvent.title}</h5>
                <button type="button" className="btn-close" onClick={closeModal}></button>
              </div>
              <div className="modal-body">
                <p><strong>Status :</strong> {bookingData.status}</p>
                <p><strong>Customer :</strong> {bookingData.resource}</p>
                <p><strong>Location :</strong> {bookingData.address}</p>
                <p><strong>Delivery:</strong> {bookingData.delivery_needed ? 'Yes' : 'No'}</p>
                <p><strong>Package Orders:</strong></p>
                <ul>
                  {bookingData.packageOrders.map((order, index) => (
                    <li key={index}>
                      {order} : {bookingData.packageQuantity[index]}
                    </li>
                  ))}
                </ul>
                <p><strong>Discount:</strong> {bookingData.discount}</p>
                <p><strong>Total :</strong> {bookingData.total}</p>
              </div>
              <div className="modal-footer">
                <button type="button" className="btn btn-danger" onClick={deleteEvent}>Refuse</button>
                {/* Refuse deletes the event */}
                <button type="button" className="btn btn-success" onClick={confirmEvent}>Confirm</button>
                {/* Confirm changes event status to green */}
                <button type="button" className="btn btn-warning" onClick={closeModal}>Cancel</button> 
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
    </>
  );
}

Expected Behavior

I expected the Monthly and Agenda cells to display properly in the frontend, but only the week and day cells properly show. This might be due to me sending data for the agenda and monthly calendar to display.

this is the data :

export const bookings =[
    {
      id:1,
      eventType:"Wedding",
      eventStartDate:"2024/02/24 12:00:00",
      eventEndDate:"2024/02/24 16:00:00",
      eventLocation:"address, City, Country",
      customerName:'Marwa Bouselmi',
      packageOrders:[services[0].packages[0].title,services[1].packages[2].title],
      packageQuantity:[3, 4],
      discount:0.2,
      total:249.80,
      delivery_needed:true,
      bookingStatus:"Pending",
    },
    {
      id:2,
      eventType:"Wedding",
      eventStartDate:"2024/02/23 12:00:00",
      eventEndDate:"2024/02/23 16:00:00",
      eventLocation:"address, City, Country",
      customerName:'Marwa Bouselmi',
      packageOrders:[services[0].packages[1].title, services[1].packages[0].title],
      packageQuantity:[3, 4],
      discount:0.2,
      total:249.80,
      delivery_needed:true,
      bookingStatus:"Confirmed",
    },
    {
      id:3,
      eventType:"Wedding",
      eventStartDate:"2024/03/24 12:00:00",
      eventEndDate:"2024/03/24 16:00:00",
      eventLocation:"address, City, Country",
      customerName:'Marwa Bouselmi',
      packageOrders:[services[0].packages[2].title, services[1].packages[1].title],
      packageQuantity:[3, 4],
      discount:0.2,
      total:249.80,
      delivery_needed:true,
      bookingStatus:"Pending",
    },
];`

Actual Behavior

I tried to console.log the events, and they render properly : image

I get one warning : image

react-big-calendar version

1.9.1

React version

18.2.0

Platform/Target and Browser Versions

Windows 10

Validations

Would you like to open a PR for this bug?

nourbenamor2001 commented 8 months ago

I tried fixing the issue by adding a useEffect and parse the date strings using moment.

import React, { useState, useEffect, useMemo } from 'react';
import { Calendar, momentLocalizer } from 'react-big-calendar';
import 'react-big-calendar/lib/css/react-big-calendar.css';
import moment from 'moment';
import { bookings } from '../../../data/dummy'; // Import bookings data from dummy.js

const localizer = momentLocalizer(moment);

export default function Schedule() {
  const [showModal, setShowModal] = useState(false);
  const [selectedEvent, setSelectedEvent] = useState(null);
  const [events, setEvents] = useState([]);

  useEffect(() => {
    const transformedEvents = bookings.map(booking => ({
      id: booking.id,
      start: moment(booking.eventStartDate, "YYYY/MM/DD HH:mm:ss").toDate(),
      end: moment(booking.eventEndDate, "YYYY/MM/DD HH:mm:ss").toDate(),
      title: booking.eventType,
      data: {
        booking: {
          id: booking.id,
          status: booking.bookingStatus,
          resource: booking.customerName,
          address: booking.eventLocation,
          packageOrders: booking.packageOrders,
          packageQuantity: booking.packageQuantity,
          discount: booking.discount,
          total: booking.total,
          delivery_needed: booking.delivery_needed
        }
      }
    }));
    setEvents(transformedEvents);
  }, []); // Empty dependency array ensures this effect runs only once, similar to componentDidMount

  const handleSelectEvent = (event) => {
    setShowModal(true);
    setSelectedEvent(event);
  };

  const deleteEvent = () => {
    // Implement logic to delete the selected event from your data source
    console.log("Event deleted:", selectedEvent);
    setShowModal(false);
  };

  const confirmEvent = () => {
    // Implement logic to change the status of the selected event to 'Confirmed'
    console.log("Event confirmed:", selectedEvent);
    setShowModal(false);
  };

  const closeModal = () => {
    setShowModal(false);
  };

  const bookingData = selectedEvent?.data?.booking; // Defensive access

  const components = useMemo(
    () => ({
      event: ({ event }) => {
        const eventStatus = event?.data?.booking?.status;
        switch (eventStatus) {
          case 'Confirmed':
            return <div style={{ background: '#94A684', height: '100%' }}>{event.title}</div>;
          case 'Pending':
            return <div style={{ background: '#FFC090', height: '100%' }}>{event.title}</div>;
          default:
            return <div></div>;
        }
      },
      agenda: {
        event: ({ event }) => (
          <div>
            <h3>Event Details:</h3>
            <p><strong>Title:</strong> {event.title}</p>
            <p><strong>Customer:</strong>{event.data.booking.resource}</p>
            <p><strong>Status:</strong> {event.data.booking.status}</p>
            <p><strong>Address:</strong> {event.data.booking.address}</p>
            <p><strong>Delivery:</strong> {event.data.booking.delivery_needed ? 'Yes' : 'No'}</p>
            <p><strong>Package Orders:</strong></p>
            <ul>
              {event.data.booking.packageOrders.map((order, index) => (
                <li key={index}>
                  {order} - Quantity: {event.data.booking.packageQuantity[index]}
                </li>
              ))}
            </ul>
            <p><strong>Discount:</strong> {event.data.booking.discount}</p>
            <p><strong>Total:</strong> {event.data.booking.total}</p>
          </div>
        )
      }
    }),
    []
  );

  return (
    <>
      <div style={{ height: '100%', width: '100%', backgroundColor: "#f8f9fa" }}>
        <Calendar
          localizer={localizer}
          events={events}
          components={components}
          style={{ margin: '50px' }}
          selectable={true}
          onSelectEvent={handleSelectEvent}
        />
        {showModal && (
          <div className="modal" style={{ display: 'block', backgroundColor: "rgba(0,0,0,0.15)", position: 'fixed', top: 0, bottom: 0, left: 0, right: 0 }}>
            <div className="modal-dialog">
              <div className="modal-content">
                <div className="modal-header">
                  <h5 className="modal-title">Event Title : {selectedEvent.title}</h5>
                  <button type="button" className="btn-close" onClick={closeModal}></button>
                </div>
                <div className="modal-body">
                  <p><strong>Status :</strong> {bookingData.status}</p>
                  <p><strong>Customer :</strong> {bookingData.resource}</p>
                  <p><strong>Location :</strong> {bookingData.address}</p>
                  <p><strong>Delivery:</strong> {bookingData.delivery_needed ? 'Yes' : 'No'}</p>
                  <p><strong>Package Orders:</strong></p>
                  <ul>
                    {bookingData.packageOrders.map((order, index) => (
                      <li key={index}>
                        {order} : {bookingData.packageQuantity[index]}
                      </li>
                    ))}
                  </ul>
                  <p><strong>Discount:</strong> {bookingData.discount}</p>
                  <p><strong>Total :</strong> {bookingData.total}</p>
                </div>
                <div className="modal-footer">
                  <button type="button" className="btn btn-danger" onClick={deleteEvent}>Refuse</button>
                  {/* Refuse deletes the event */}
                  <button type="button" className="btn btn-success" onClick={confirmEvent}>Confirm</button>
                  {/* Confirm changes event status to green */}
                  <button type="button" className="btn btn-warning" onClick={closeModal}>Cancel</button>
                </div>
              </div>
            </div>
          </div>
        )}
      </div>
    </>
  );
}

But it displays another warning : image

cutterbl commented 8 months ago

@nourbenamor2001 Questions like this are best served from our Slack group or StackOverflow.

I see you figured out your date parsing issue (I always suggest that, when using string date values from your datasource, use UTC date/time format YYYY-MM-DDTHH:mm:ssZ. It's fully compliant, and conversion to JS Date is straight forward).

The React warning you received at the end is, as it says, a warning. It does not effect code execution in any way. It's a note from the React team that support will eventually be removed. We have an update for this in the works.

Your standard event replacement object would render an empty div if it did not have certain status. Also, you're doing this when you likely just want to use an eventPropGetter to apply a specific backgroundColor to your event display.

As far as overriding your Agenda Event, we'd really need to see some running code in a CodeSandbox.