import { useState, useMemo } from "react";
import "./news.css";
import LoadingAnimation from "../Dashboard/Loading/LoadingAnimation";
import { NavLink } from "react-router-dom";
import { useGetNews } from "../../apis/News";
/**
* Represents the PublicNews page for displaying public news.
* @module PublicNews
* @returns {JSX.Element} The PublicNews component.
*/
const PublicNews = () => {
const [gridView, setGridVied] = useState(true);
const [filterDropdown, setFilterDropdown] = useState(false);
const [searchInput, setSearchInput] = useState("");
const [sortBy, setSortBy] = useState("");
const { data: news, isLoading: newsLoading } = useGetNews();
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]);
/**
* Removes HTML tags from an HTML string.
* @function stripHTML
* @param {string} htmlString - The HTML string to strip HTML tags from.
* @returns {string} The HTML string with tags stripped.
*/
function stripHTML(htmlString) {
const regex = /<[^>]*>/g; // Regular expression to match HTML tags
return htmlString.replace(regex, "");
}
/**
* Renders the selected view of news (grid or list).
* @function getSelectedView
* @param {boolean} view - The selected view (grid or list).
* @returns {JSX.Element} The rendered news view.
*/
const getSelectedView = (view) => {
if (view) {
return (
<div className="news_div">
<div className="documents_div_for_grid_view">
{getNewsData.map((dat, i) => {
return (
<div className="individual_news_card" key={i}>
<NavLink to={`../single/news/${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={`../single/news/${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="public_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>
{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="navigation_for_mobile">
<div className="left_mobile_navigation">
<input type="text" 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="news_body">{getSelectedView(gridView)}</div>
</>
)}
</div>
);
};
export default PublicNews;
Source