Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Want to Add Functionality To Seach blog by Author Name,Title ,Tag #1285 #1295

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/components/blogs/Blogs.css
Original file line number Diff line number Diff line change
Expand Up @@ -345,3 +345,53 @@ body {
white-space: nowrap;
text-overflow: ellipsis;
}
.search-modes{
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
}
.search-modes input{
margin-right: 5px;
}
#dark .search-modes{
color: white;
}
/* Modal styles */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(5px);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}

.modal {
background: white;
padding: 20px;
border-radius: 8px;
max-width: 500px;
width: 100%;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
text-align: center;
}

.modal h2 {
margin-bottom: 20px;
}

.modal .search-modes {
display: flex;

gap: 10px;
}

.modal button {
margin-top: 20px;
}
165 changes: 129 additions & 36 deletions src/components/blogs/Blogs.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import React, { useEffect, useState } from "react";
import "./Blogs.css"; // Import CSS file for styles
import './Blogs.css';
import Footer from "../Footer/Footer";
import { useNavigate } from "react-router-dom"; // Import Link and useNavigate from react-router-dom
import { getDatabase, ref, get } from "firebase/database";
import { useNavigate } from "react-router-dom";
import { getDatabase, ref, get } from 'firebase/database';
import DOMPurify from "dompurify";
import { marked } from "marked";
import Navbar from "../Navbar/Navbar";
import { toast, ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import BlogsSkeleton from "./BlogsSkeleton"; // Import Skeleton component
import { toast, ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import BlogsSkeleton from "./BlogsSkeleton";
import SearchIcon from '../../assets/search_icon.png';

const Blogs = () => {
const [isLoggedIn, setLogin] = useState(false);
const [ids, setIds] = useState({});
const [blogsData, setBlogsData] = useState([]);
const [loading, setLoading] = useState(true); // Loading state
const [filteredBlogs, setFilteredBlogs] = useState([]);
const [loading, setLoading] = useState(true);
const [searchTerm, setSearchTerm] = useState('');
const [searchMode, setSearchMode] = useState('all'); // Default to 'all' search mode
const [isModalOpen, setIsModalOpen] = useState(false);
const navigate = useNavigate();
const userId = localStorage.getItem("userUid");
const [user, setUser] = useState(null);
Expand All @@ -29,26 +33,13 @@ const Blogs = () => {
try {
const db = getDatabase();

// Fetch user data if logged in
if (userId) {
const userRef = ref(db, "users/" + userId);
const userSnap = await get(userRef);

if (userSnap.exists()) {
const userData = userSnap.val();
setUser(userData);

const articleCreated = userData.articleCreated;
if (articleCreated) {
const idArray = articleCreated.split(",");
const idObject = idArray.reduce((acc, id) => {
acc[id.trim()] = true;
return acc;
}, {});
setIds(idObject);
} else {
console.log("No articles created by the user.");
}
} else {
console.log("No user data available");
}
Expand All @@ -75,14 +66,15 @@ const Blogs = () => {
blogsArray.sort((a, b) => b.createdAt - a.createdAt);

setBlogsData(blogsArray);
setFilteredBlogs(blogsArray);
} else {
console.log("No data available");
}
} catch (error) {
console.error("Error fetching blogs:", error);
} finally {
setTimeout(() => {
setLoading(false); // Set loading to false after 2 seconds
setLoading(false);
}, 500);
}
};
Expand All @@ -106,6 +98,52 @@ const Blogs = () => {
}
}, []);

const handleSearchChange = (e) => {
const term = e.target.value.toLowerCase();
setSearchTerm(term);

switch (searchMode) {
case 'title':
searchByTitle(term);
break;
case 'author':
searchByAuthor(term);
break;
case 'tags':
searchByTags(term);
break;
default:
searchByAll(term);
}
};

const searchByTitle = (term) => {
const filtered = blogsData.filter(blog => blog.title.toLowerCase().includes(term));
setFilteredBlogs(filtered);
};

const searchByAuthor = (term) => {
const filtered = blogsData.filter(blog => blog.author.toLowerCase().includes(term));
setFilteredBlogs(filtered);
};

const searchByTags = (term) => {
const filtered = blogsData.filter(blog => blog.tags.some(tag => tag.toLowerCase().includes(term)));
setFilteredBlogs(filtered);
};

const searchByAll = (term) => {
const filtered = blogsData.filter(blog =>
blog.title.toLowerCase().includes(term) ||
blog.author.toLowerCase().includes(term) ||
blog.tags.some(tag => tag.toLowerCase().includes(term))
);
setFilteredBlogs(filtered);
};

const openModal = () => setIsModalOpen(true);
const closeModal = () => setIsModalOpen(false);

return (
<>
<Navbar />
Expand All @@ -114,25 +152,80 @@ const Blogs = () => {
<header className="blogs-header">
<h1>Our Latest Blogs</h1>
<p>Stay updated with our latest news and articles on counseling.</p>
{isLoggedIn && (
<button
onClick={() => navigate("/blogwrite")}
className="blogwrite"
>
Create Blog
</button>
{isLoggedIn && <button onClick={() => navigate('/blogwrite')} className="blogwrite">Create Blog</button>}

{/* Search Box */}
<div className="search">
<div className="s_bar_c">
<img src={SearchIcon} alt="Search" onClick={openModal} />
<div className="vl" />
<input
type="text"
placeholder={`Search by ${ searchMode === 'all' ? "Title , Author ,Tag" : searchMode}`}
value={searchTerm}
onChange={handleSearchChange}
style={{ outline: "1px solid black", fontSize: "20px" }}
/>
</div>
<div className="search_box">
<button>Search</button>
</div>
</div>

{/* Modal */}
{isModalOpen && (
<div className="modal-overlay">
<div className="modal">
<h2>Select Search Mode</h2>
<div className="search-modes">
<label>
<input
type="radio"
value="title"
checked={searchMode === 'title'}
onChange={() => setSearchMode('title')}
/>
Title
</label>
<label>
<input
type="radio"
value="author"
checked={searchMode === 'author'}
onChange={() => setSearchMode('author')}
/>
Author
</label>
<label>
<input
type="radio"
value="tags"
checked={searchMode === 'tags'}
onChange={() => setSearchMode('tags')}
/>
Tags
</label>
<label>
<input
type="radio"
value="all"
checked={searchMode === 'all'}
onChange={() => setSearchMode('all')}
/>
All
</label>
</div>
<button onClick={closeModal}>Close</button>
</div>
</div>
)}
</header>
<div className="blogs-list">
{loading ? (
<BlogsSkeleton count={blogsData.length} /> // Display skeleton while loading
<BlogsSkeleton count={blogsData.length} />
) : (
blogsData.map((blog, index) => (
<div
key={index}
className="blog-card"
onClick={() => navigate(blog.link)}
>
filteredBlogs.map((blog, index) => (
<div key={index} className="blog-card" onClick={() => navigate(blog.link)}>
<h2 className="clip-text">{blog.title}</h2>
<p className="blog-date">{blog.date}</p>
<p className="clip-text">{blog.summary}</p>
Expand Down
2 changes: 2 additions & 0 deletions src/components/blogs/BlogsSkeleton.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
.skeleton-container {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 20px;
padding: 20px;
width: 100%;
Expand Down
Loading