Source

pages/Dashboard/News/News.jsx

import { useState, useMemo } from "react";
import "../News/news.css";
import LoadingAnimation from "../Loading/LoadingAnimation";
import { NavLink } from "react-router-dom";
import { useGetNews } from "../../../apis/News";

/**
 * Represents the News page component
 * @module News
 * @returns {JSX.Element}
 */
const News = () => {
  /**
   * React state that stores the view type of the news page
   * @name gridView
   * @type {Array}
   * @default useState(true)
   * @memberof module:News
   */
  const [gridView, setGridVied] = useState(true);
  /**
   * React state that stores the filter dropdown state
   * @name filterDropdown
   * @type {Array}
   * @default useState(false)
   * @memberof module:News
   */
  const [filterDropdown, setFilterDropdown] = useState(false);
  /**
   * React state that stores the search input value
   * @name searchInput
   * @type {Array}
   * @default useState("")
   * @memberof module:News
   */
  const [searchInput, setSearchInput] = useState("");
  /**
   * React state that stores the sort by value
   * @name sortBy
   * @type {Array}
   * @default useState("")
   * @memberof module:News
   */
  const [sortBy, setSortBy] = useState("");
  /**
   * React query hook that fetches the news data
   * @name useGetNews
   * @type {Function}
   * @memberof module:News
   */
  const { data: news, isLoading: newsLoading } = useGetNews();
  /**
   * React hook that memoizes the news data
   * @name getNewsData
   * @memberof module:News
   * @type {Array}
   */
  const getNewsData = useMemo(() => {
    const temp = news?.data?.data?.results || [];
    if (searchInput) {
      const filteredList = temp.filter((contract) =>
        contract.title.toLowerCase().includes(searchInput.toLowerCase())
      );
      return filteredList.reverse();
    }
    switch (sortBy) {
      case "AZ":
        return [...temp].sort((a, b) => a.title.localeCompare(b.title));
      case "ZA":
        return [...temp]
          .sort((a, b) => a.title.localeCompare(b.title))
          .reverse();
      case "OLD":
        return [...temp].reverse();
      case "RECENT":
        return temp;
    }
    return temp;
  }, [news?.data, searchInput, sortBy]);

  /**
   * Function to strip HTML tags from a string
   * @function stripHTML
   * @param htmlString {String} The string to strip HTML tags from
   * @returns {*}
   */
  function stripHTML(htmlString) {
    const regex = /<[^>]*>/g; // Regular expression to match HTML tags
    return htmlString.replace(regex, "");
  }

  /**
   * Function to get the selected view
   * @function getSelectedView
   * @param view {String} The view type
   * @returns {JSX.Element}
   */
  const getSelectedView = (view) => {
    if (view) {
      return (
        <div className="news_div">
          <div className="documents_divfor_grid_view">
            {getNewsData.map((dat, i) => {
              return (
                <div className="individual_news_card" key={i}>
                  <NavLink to={`/dashboard/news/newspage/${dat.id}`}>
                    <div className="news_wrapper"></div>
                  </NavLink>
                  <div className="news_card_body">
                    <div className="news_thumbnail">
                      <img src={dat?.image} alt="" />
                    </div>
                  </div>

                  <div className="news_card_footer">
                    <div className="news_card_footer_content">
                      <div className="news_start_end_div">
                        <div className="start_date">
                          {/* <small>Published at: </small> */}
                          <small>{dat?.created_at}</small>
                        </div>
                      </div>
                      <h4>{dat?.title}</h4>
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      );
    }
    return (
      <div className="news_div">
        <div className="documents_div_for_list_view">
          {/* no css rules for the above div class */}
          {getNewsData.map((dat, i) => {
            return (
              <div className="individual_list_news_card" key={i}>
                <NavLink to={`/dashboard/news/newspage/${dat.id}`}>
                  <div className="news_list_card_body">
                    <div className="news_list_thumbnail">
                      <img src={dat?.image} alt="" />
                    </div>
                    <div className="news_list_card_footer">
                      <div className="news_list_card_footer_content">
                        <div className="news_start_end_div">
                          <div className="start_date">
                            <p>Published at : {dat?.created_at}</p>
                          </div>
                        </div>
                        <div>
                          <b>{dat?.title}</b>
                          <p className="mt-2 content">
                            {stripHTML(dat?.content.substring(0, 100))}...
                          </p>
                        </div>
                      </div>
                    </div>
                  </div>
                </NavLink>
              </div>
            );
          })}
        </div>
      </div>
    );
  };
  if (newsLoading) {
    return <LoadingAnimation />;
  }
  return (
    <div className="news_container">
      <div className="news_heading flex justify-between mb-2">
        <h2 className="main-title">News</h2>
        <div className="news_search">
          <div className="left_news_search">
            <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="left_news_search ">
            <ion-icon name="search"></ion-icon>
          </div>
          <div className="right_news_search">
            <div className="right_news_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="right_news_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="news_filter_dropdown">
                  <p onClick={() => setSortBy("AZ")}>A - Z</p>
                  <p onClick={() => setSortBy("ZA")}>Z - A</p>
                  <p onClick={() => setSortBy("RECENT")}>Recent</p>
                  <p onClick={() => setSortBy("OLD")}>Oldest</p>
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
      <div className="navigation_for_mobile">
        <div className="left_mobile_navigation">
          <input
            type="text"
            placeholder="search"
            onChange={(e) => setSearchInput(e.target.value)}
          />
          <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>
      {getNewsData?.length === 0 ? (
        <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="news_body">{getSelectedView(gridView)}</div>
      )}
    </div>
  );
};
export default News;