Source

pages/PublicEvents/PublicEvents.jsx

import React, { useMemo } from "react";
import "./events.css";
import { NavLink } from "react-router-dom";
import { useState, useEffect } from "react";
import { Select } from "antd";
import { useGetEventsList } from "../../apis/Events";
import { AddToCalendarButton } from "add-to-calendar-button-react";
import LoadingAnimation from "../Dashboard/Loading/LoadingAnimation";
const companies = [
  {
    label: "All",
    value: "",
  },
  {
    label: "RKD Holdings Limited",
    value: "RKD Holdings Limited",
  },
  {
    label: "Tourism Investement Fund Limited",
    value: "Tourism Investement Fund Limited",
  },
  {
    label: "Bandipur Cable Car & Tourism Limited",
    value: "Bandipur Cable Car & Tourism Limited",
  },
  {
    label: "Panchase Cable Car and Tours Limited",
    value: "Panchase Cable Car and Tours Limited",
  },
  {
    label: "Bizbazar Limited",
    value: "Bizbazar Limited",
  },
];
const date_range = [
  {
    label: "All",
    value: "",
  },
  {
    label: "Upcoming Events",
    value: "UP",
  },
  {
    label: "Today",
    value: "TD",
  },
  {
    label: "This Month",
    value: "TM",
  },
  {
    label: "Past Events",
    value: "PE",
  },
];
/**
 * Represents the PublicEvents page for displaying public events.
 * @module PublicEvents
 * @returns {JSX.Element} The PublicEvents component.
 */
const PublicEvents = () => {
  const [gridView, setGridVied] = useState(true);
  const [sortBy, setSortBy] = useState("");
  const [filterDropdown, setFilterDropdown] = useState(false);
  const [searchInput, setSearchInput] = useState("");
  const [location, setLocation] = useState("");
  const [dateRange, setDateRange] = useState(date_range[0].value);
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [company, setCompany] = useState("RKD Holdings Limited");
  const [eventId, setEventId] = useState(null);
  const { data: event, isLoading: eventLoading } = useGetEventsList();
  /**
   * Gets the last day of the current month.
   * @function getLastDayOfMonth
   * @returns {number} The last day of the current month.
   */
  function getLastDayOfMonth() {
    const currentDate = new Date();
    const currentYear = currentDate.getFullYear();
    const currentMonth = currentDate.getMonth();

    // Months are zero-based, so adding 1 to get the next month and day 0 to get the last day of the current month
    const lastDayOfMonth = new Date(currentYear, currentMonth + 1, 0);

    return lastDayOfMonth.getDate();
  }
  /**
   * Filters events based on the selected date range.
   * @function getDataByRange
   * @param {Array} data - The list of events to filter.
   * @returns {Array} The filtered list of events.
   */
  const getDataByRange = (data = []) => {
    try {
      let date = new Date();
      let year = date.toLocaleDateString();
      const currentTimestampMillis = new Date(year);
      const currentTimestampSeconds = Math.floor(currentTimestampMillis / 1000);
      const today = new Date();
      const dayIndex = today.getDate();
      switch (dateRange) {
        case date_range[1].value:
          let filteredUpData = data.filter((item, i) => {
            const dateInMillis = new Date(item?.event_start_date);
            const dateInSeconds = dateInMillis / 1000;
            if (dateInSeconds > currentTimestampSeconds) {
              return true;
            }
            return false;
          });
          return filteredUpData;
        case date_range[2].value:
          let filteredTData = data.filter((item, i) => {
            const dateInMillis = new Date(item?.event_start_date);
            const dateInSeconds = dateInMillis / 1000;
            if (
              dateInSeconds >= currentTimestampSeconds &&
              dateInSeconds < parseInt(currentTimestampSeconds) + 86400
            ) {
              return true;
            }
            return false;
          });
          return filteredTData;
        case date_range[3].value:
          let filteredTMData = data.filter((item, i) => {
            const dateInMillis = new Date(item?.event_start_date);
            const dateInSeconds = dateInMillis / 1000;
            if (
              dateInSeconds <=
                currentTimestampSeconds +
                  (getLastDayOfMonth() - dayIndex) * 86400 &&
              dateInSeconds >=
                parseInt(currentTimestampSeconds) - 86400 * (dayIndex - 1)
            ) {
              return true;
            }
            return false;
          });
          return filteredTMData;
        case date_range[4].value:
          let filteredPEData = data.filter((item, i) => {
            const dateInMillis = new Date(item?.event_start_date);
            const dateInSeconds = dateInMillis / 1000;
            if (dateInSeconds < currentTimestampSeconds - 86400) {
              return true;
            }
            return false;
          });
          return filteredPEData;
      }
    } catch (err) {
      console.log(err.message);
    }
  };

  //Getting enents data
  const eventData = useMemo(() => {
    let temp = event?.data?.data?.results || [];
    temp = [...temp].reverse();
    // Search with name
    if (searchInput) {
      const filteredList = temp.filter((item) =>
        item.title.toLowerCase().includes(searchInput.toLowerCase())
      );
      temp = filteredList;
    }

    //handle company select
    if (company) {
      const filteredList = temp.filter((item) => {
        let companies = item?.company || [];
        let isCompanyExist = companies.some((el) => el.name === company);
        if (isCompanyExist) {
          return true;
        }
        return false;
      });
      temp = filteredList;
    }
    // handle location search
    if (location) {
      let filteredList = temp.filter((item) =>
        item.location.toLowerCase().includes(location.toLowerCase())
      );
      temp = filteredList;
    }
    if (dateRange) {
      let filteredList = getDataByRange(temp);
      temp = filteredList;
    }
    // Sorting reports
    switch (sortBy) {
      case "OLD":
        let revisedData = temp.map((el, i) => ({
          ...el,
          date: new Date(el?.event_start_date),
        }));
        temp = revisedData.slice().sort((a, b) => a.date - b.date);
        return temp;
      case "RECENT":
        let revisedRecentData = temp.map((el, i) => ({
          ...el,
          date: new Date(el?.event_start_date),
        }));
        temp = revisedRecentData.slice().sort((a, b) => b.date - a.date);
        return temp;
    }
    return temp;
  }, [event?.data, sortBy, company, searchInput, location, dateRange]);

  if (eventLoading) {
    return <LoadingAnimation />;
  }

  return (
    <div className="public_events_container">
      <>
        <div className="events_heading">
          <h2 className="main-title">Events</h2>
          <div className="events_filter_wrapper flex w-100 justify-between mt-3 gap-2 flex-wrap">
            <div className="report_selectors flex gap-2 flex-wrap justify-end">
              <div className="single_selector ">
                <div className="selector_label text-center">Company</div>
                <Select
                  style={{
                    width: 200,
                  }}
                  defaultValue="RKD Holdings Limited"
                  className="report_company_selector parent_select "
                  onChange={(value) => setCompany(value)}
                  options={companies}
                />
              </div>{" "}
              <div className="single_selector ">
                <div className="selector_label text-center">Date Range</div>
                <Select
                  name="date_range"
                  defaultValue={date_range[0].label}
                  className="report_company_selector parent_select "
                  style={{
                    width: 200,
                  }}
                  onChange={(value) => setDateRange(value)}
                  options={date_range}
                />
              </div>{" "}
            </div>

            <div className="events_search  flex flex-wrap justify-end gap-2">
              <div className="left_events_search">
                {/* <div className="left_events_search">
                <ion-icon name="search"></ion-icon>
              </div> */}
                <div className="search_input">
                  {/* <ion-icon name="search-outline"></ion-icon> */}
                  <input
                    type="text"
                    onChange={(e) => setLocation(e.target.value)}
                    placeholder="Search by location"
                  />
                </div>
              </div>
              <div className="left_events_search">
                <div className="left_events_search">
                  <ion-icon name="search"></ion-icon>
                </div>
                <div className="search_input">
                  {/* <ion-icon name="search-outline"></ion-icon> */}
                  <input
                    type="text"
                    onChange={(e) => setSearchInput(e.target.value)}
                    placeholder="Search"
                  />
                </div>
              </div>
              <div className="right_events_search">
                <div className="events_grid_list_view">
                  <ul>
                    {gridView ? (
                      <li
                        onClick={() => setGridVied(!gridView)}
                        style={{
                          background: "#53BF8A",
                          borderRadius: ".2rem",
                          color: "#ffffff",
                        }}
                      >
                        <ion-icon name="grid-outline"></ion-icon>
                      </li>
                    ) : (
                      <li onClick={() => setGridVied(!gridView)}>
                        <ion-icon name="grid-outline"></ion-icon>
                      </li>
                    )}
                    {gridView ? (
                      <li onClick={() => setGridVied(!gridView)}>
                        <ion-icon name="list-outline"></ion-icon>
                      </li>
                    ) : (
                      <li
                        onClick={() => setGridVied(!gridView)}
                        style={{
                          background: "#53BF8A",
                          borderRadius: ".2rem",
                          color: "#ffffff",
                        }}
                      >
                        <ion-icon name="list-outline"></ion-icon>
                      </li>
                    )}
                  </ul>
                </div>
                <div
                  className="events_filter_div"
                  onClick={() => {
                    setFilterDropdown(!filterDropdown);
                  }}
                >
                  <p>Sort by</p>
                  {filterDropdown ? (
                    <ion-icon name="chevron-up-outline"></ion-icon>
                  ) : (
                    <ion-icon name="chevron-down-outline"></ion-icon>
                  )}
                  {filterDropdown && (
                    <div className="events_filter_dropdown">
                      <p onClick={() => setSortBy("RECENT")}>Recent</p>
                      <p onClick={() => setSortBy("OLD")}>Oldest</p>
                    </div>
                  )}
                </div>
              </div>
            </div>
          </div>
        </div>
        <div className="navigation_for_mobile">
          <div className="left_mobile_navigation">
            <input
              type="text"
              onChange={(e) => setSearchInput(e.target.value)}
              placeholder="search"
            />
            <ion-icon name="search-outline"></ion-icon>
          </div>
          <div className="right_mobile_navigation">
            <ul>
              <li>
                <ion-icon name="options"></ion-icon>
              </li>
            </ul>
          </div>
        </div>
        <div className="events_body">
          {!eventData?.length ? (
            <div className="empty_event_container">
              <div className="event_logo">
                <ion-icon name="calendar-outline"></ion-icon>
                <h3>No events added yet</h3>
                <div className="add_new_event">
                  <p>Stay tuned for updates and secure your spot today.</p>
                </div>
              </div>
            </div>
          ) : (
            <div className="events_div">
              {gridView ? (
                <div className="documents_div_for_grid_view">
                  {eventData.map((dat, i) => {
                    const startDateObj = new Date(dat?.event_start_date);
                    const startMonth = startDateObj.toLocaleString("default", {
                      month: "short",
                    });
                    const startDay = startDateObj.getDate();
                    const formattedStartDate = `${startMonth} ${startDay}`;

                    const endDateObj = new Date(dat?.event_end_date);
                    const endMonth = endDateObj.toLocaleString("default", {
                      month: "short",
                    });
                    const endDay = endDateObj.getDate();
                    const formattedEndDate = `${endMonth} ${endDay}`;
                    return (
                      <div className="individual_events_card" key={i}>
                        <NavLink to={`../event/${dat.id}`}>
                          <div className="events_wrapper"></div>
                        </NavLink>
                        <img src={dat?.image} alt="" className="event_img" />

                        <div className="event_detail">
                          <h4>{dat?.title}</h4>
                          {/* <p className="event-content p-1 mb-2">
                            {String(dat?.content || "").substring(0, 100)}
                          </p> */}

                          <div className="location_container flex align-items-center mb-1">
                            <ion-icon
                              name="navigate-circle-outline"
                              className="location_icon"
                            ></ion-icon>
                            {dat?.location || ""}
                          </div>
                          <div className="event_start_end_div ">
                            <div className="start_date">
                              <p className="font-[600]">Start Date</p>
                              <h6 className="font-[600]">
                                {formattedStartDate}
                              </h6>
                            </div>
                            <div className="end_date">
                              <p className="font-[600]">End Date</p>
                              <h6 className="font-[600]">{formattedEndDate}</h6>
                            </div>
                          </div>
                          <div className="register_add_to_calander">
                            <div className="add_to_calendar">
                              <AddToCalendarButton
                                name={dat?.title || ""}
                                className="add-to-calendar-button"
                                options={["Apple", "Google", "Yahoo", "iCal"]}
                                location={dat?.location || ""}
                                startDate={dat?.event_start_date}
                                endDate={dat?.event_end_date}
                                description={dat?.content}
                                trigger="click"
                                size="3"
                              ></AddToCalendarButton>
                            </div>
                          </div>
                        </div>
                      </div>
                    );
                  })}
                </div>
              ) : (
                <>
                  <div className="list_container">
                    {eventData.map((dat, i) => {
                      const startDateObj = new Date(dat?.event_start_date);
                      const startMonth = startDateObj.toLocaleString(
                        "default",
                        {
                          month: "short",
                        }
                      );
                      const startDay = startDateObj.getDate();
                      const formattedStartDate = `${startMonth} ${startDay}`;

                      const endDateObj = new Date(dat?.event_end_date);
                      const endMonth = endDateObj.toLocaleString("default", {
                        month: "short",
                      });
                      const endDay = endDateObj.getDate();
                      const formattedEndDate = `${endMonth} ${endDay}`;
                      return (
                        <div className="event_card relative" key={i}>
                          <NavLink to={`../event/${dat.id}`}>
                            <div className="events_wrapper"></div>
                          </NavLink>
                          {/* Left side with thumbnail image */}
                          <div className="thumbnail">
                            <img src={dat?.image} alt="Event Thumbnail" />
                          </div>

                          {/* Right side with event details */}
                          <div className="event-details">
                            {/* Top div with event title and content */}
                            <div className="event-header">
                              <h3 className="event-title mb-1">{dat?.title}</h3>
                              <p className="event-content">
                                {String(dat?.content || "").substring(0, 150)}
                                ...
                              </p>
                            </div>
                            <div className="location_container flex align-items-center mb-1">
                              <div className="location_icon flex align-items-center mr-2">
                                <ion-icon name="navigate-circle-outline"></ion-icon>
                              </div>
                              {dat?.location || ""}
                            </div>
                            {/* Bottom div with date and buttons */}
                            <div className="event-footer font-semibold">
                              {/* Left div with date fields */}
                              <div className="event-dates">
                                <p className="event-date">
                                  Start Date: {formattedStartDate}
                                </p>
                                <p className="event-date">
                                  End Date: {formattedEndDate}
                                </p>
                              </div>

                              {/* Right div with buttons */}
                              <div className="event-buttons">
                                <button
                                  className="register-button"
                                  onClick={() => {
                                    setEventId(dat);
                                    setIsModalOpen(true);
                                  }}
                                >
                                  Register
                                </button>
                                <AddToCalendarButton
                                  name={dat?.title || ""}
                                  className="calander_btn"
                                  options={["Apple", "Google", "Yahoo", "iCal"]}
                                  location={dat?.location || ""}
                                  startDate={dat?.event_start_date}
                                  endDate={dat?.event_end_date}
                                  description={dat?.content}
                                  trigger="click"
                                  size="4"
                                ></AddToCalendarButton>
                              </div>
                            </div>
                          </div>
                        </div>
                      );
                    })}
                  </div>
                </>
              )}
            </div>
          )}
        </div>
      </>
    </div>
  );
};

export default PublicEvents;