diff --git a/frontend/src/pages/Posts.tsx b/frontend/src/pages/Posts.tsx index 1b371dd8..a2ea6335 100644 --- a/frontend/src/pages/Posts.tsx +++ b/frontend/src/pages/Posts.tsx @@ -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'; @@ -8,6 +8,10 @@ const Posts = () => { const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); + const [showFilterDialog, setShowFilterDialog] = useState(false); + const [tagInput, setTagInput] = useState(''); + const [filterTags, setFilterTags] = useState([]); + const filterRef = useRef(null); useEffect(() => { const fetchPosts = async () => { @@ -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) => { + 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 ; } @@ -35,8 +78,57 @@ const Posts = () => { return (

Posts

+
+ + {showFilterDialog && ( +
+
+ 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" + /> +
+ +
+ {filterTags.map((tag, index) => ( +
+ {tag} + +
+ ))} +
+
+ )} +
- {posts.map((post) => ( + {filteredPosts.map((post) => (

{post.title}

{post.description.length > 100 ? `${post.description.slice(0, 100)}...` : post.description}