Skip to content

Commit

Permalink
Merge pull request #25 from AkshatBujethiya/main
Browse files Browse the repository at this point in the history
Add filter option in posts
  • Loading branch information
Ultimateutkarsh11 authored May 29, 2024
2 parents 01c6e7e + 574342a commit 6b2ac1d
Showing 1 changed file with 94 additions and 2 deletions.
96 changes: 94 additions & 2 deletions frontend/src/pages/Posts.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useState, useRef } from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom';
import { PostData } from '../types';
Expand All @@ -8,6 +8,10 @@ const Posts = () => {
const [posts, setPosts] = useState<PostData[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [showFilterDialog, setShowFilterDialog] = useState(false);
const [tagInput, setTagInput] = useState('');
const [filterTags, setFilterTags] = useState<string[]>([]);
const filterRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const fetchPosts = async () => {
Expand All @@ -24,6 +28,45 @@ const Posts = () => {
fetchPosts();
}, []);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (filterRef.current && !filterRef.current.contains(event.target as Node)) {
setShowFilterDialog(false);
}
};

document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);

const toggleFilterDialog = () => {
setShowFilterDialog(!showFilterDialog);
};

const addTag = () => {
if (tagInput && !filterTags.includes(tagInput.toLowerCase())) {
setFilterTags([...filterTags, tagInput.toLowerCase()]);
setTagInput('');
}
};

const removeTag = (tagToRemove: string) => {
setFilterTags(filterTags.filter(tag => tag !== tagToRemove));
};

const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter') {
event.preventDefault();
addTag();
}
};

const filteredPosts = posts.filter(post =>
filterTags.every(tag => post.tags.map(t => t.toLowerCase()).includes(tag))
);

if (loading) {
return <Loader/>;
}
Expand All @@ -35,8 +78,57 @@ const Posts = () => {
return (
<div className='max-w-screen-xl flex flex-col items-center justify-center mx-auto p-4'>
<h1 className="text-2xl font-semibold mb-4 text-white">Posts</h1>
<div className="w-full flex justify-between mb-4 relative">
<button
onClick={toggleFilterDialog}
className="flex items-center text-white hover:text-gray-400"
>
Filter
<svg className="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
{showFilterDialog && (
<div
ref={filterRef}
className="absolute top-full mt-2 bg-gray-800 p-4 rounded shadow-lg w-full max-w-md"
>
<div className="mb-2">
<input
type="text"
value={tagInput}
onChange={(e) => setTagInput(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Add tag"
className="p-2 w-full rounded bg-gray-700 text-white focus:outline-none focus:ring-2 focus:ring-gray-500"
/>
</div>
<button
onClick={addTag}
className="px-4 py-2 text-white border border-gray-600 rounded hover:bg-gray-700"
>
Add Tag
</button>
<div className="mt-2 flex flex-wrap">
{filterTags.map((tag, index) => (
<div key={index} className="flex items-center bg-gray-700 text-white px-2 py-1 rounded mr-2 mb-2">
<span>{tag}</span>
<button
onClick={() => removeTag(tag)}
className="ml-2 focus:outline-none"
>
<svg className="w-4 h-4 fill-current text-red-500" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M10 0c-5.523 0-10 4.477-10 10s4.477 10 10 10 10-4.477 10-10-4.477-10-10-10zm5 13.586-1.414 1.414-3.586-3.586-3.586 3.586-1.414-1.414 3.586-3.586-3.586-3.586 1.414-1.414 3.586 3.586 3.586-3.586 1.414 1.414-3.586 3.586 3.586 3.586z" />
</svg>
</button>
</div>
))}
</div>
</div>
)}
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 w-full">
{posts.map((post) => (
{filteredPosts.map((post) => (
<div key={post.id} className="bg-gray-800 border border-gray-600 p-4 rounded">
<h2 className="text-lg font-semibold mb-2 text-white">{post.title}</h2>
<p className="text-gray-400 mb-2">{post.description.length > 100 ? `${post.description.slice(0, 100)}...` : post.description}</p>
Expand Down

0 comments on commit 6b2ac1d

Please sign in to comment.