From 0e1038da9d83741702a8ad516333d027ff91a67e Mon Sep 17 00:00:00 2001 From: Nils Pukropp Date: Tue, 17 Feb 2026 04:23:51 +0100 Subject: [PATCH] updated community tab and search bar --- backend/api/views.py | 6 ++-- frontend/src/App.tsx | 9 +++--- frontend/src/pages/CommunityFeed.tsx | 47 +++++++++++++++++++++++----- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/backend/api/views.py b/backend/api/views.py index 44aa835..8f18b17 100644 --- a/backend/api/views.py +++ b/backend/api/views.py @@ -223,7 +223,7 @@ class UserViewSet(viewsets.ModelViewSet): except User.DoesNotExist: return Response({'error': 'User not found'}, status=status.HTTP_404_NOT_FOUND) - ratings = user.ratings.select_related('flavor', 'flavor__category').exclude(flavor__category__slug='packs-and-other').order_by('-score') + ratings = user.ratings.select_related('flavor', 'flavor__category').order_by('-score') return Response({ 'id': user.id, @@ -426,12 +426,10 @@ class UserViewSet(viewsets.ModelViewSet): # Annotate with community average rating so it's available for sorting/display missing_flavors = Flavor.objects.exclude(id__in=rated_ids) \ - .exclude(category__slug='packs-and-other') \ .select_related('category') \ .annotate(average_rating=Avg('ratings__score')) - rated_flavors = user.ratings.select_related('flavor', 'flavor__category') \ - .exclude(flavor__category__slug='packs-and-other') + rated_flavors = user.ratings.select_related('flavor', 'flavor__category') return Response({ 'user': UserSerializer(user).data, diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 7277b25..39f442f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -70,13 +70,16 @@ const GlobalSearch = () => { try { // Fetch unified results: flavors, categories, and users const res = await api.get('flavors/search/'); - setOptions(res.data); + // Filter to only flavors + const results = (Array.isArray(res.data) ? res.data : (res.data.results || [])) + .filter((item: any) => item.type === 'flavor'); + setOptions(results); } catch (err) { console.error('Failed to fetch search options'); } }; fetchSearchOptions(); - }, []); // Only fetch once to avoid excessive API calls + }, []); useEffect(() => { const params = new URLSearchParams(location.search); @@ -108,8 +111,6 @@ const GlobalSearch = () => { onChange={(_, newValue) => { if (newValue && typeof newValue !== 'string') { if (newValue.type === 'flavor') navigate(`/flavor/${newValue.id}`); - if (newValue.type === 'category') navigate(`/category/${newValue.slug}`); - if (newValue.type === 'user') navigate(`/profile/${newValue.slug}`); } }} onKeyDown={(e) => { diff --git a/frontend/src/pages/CommunityFeed.tsx b/frontend/src/pages/CommunityFeed.tsx index c8ba117..0be2472 100644 --- a/frontend/src/pages/CommunityFeed.tsx +++ b/frontend/src/pages/CommunityFeed.tsx @@ -16,9 +16,11 @@ import { ListItemAvatar, ListItemText, ListItemButton, - Pagination + Pagination, + TextField, + InputAdornment } from '@mui/material'; -import StarIcon from '@mui/icons-material/Star'; +import SearchIcon from '@mui/icons-material/Search'; import { Link } from 'react-router-dom'; import api from '../api'; import { useTitle } from '../hooks/useTitle'; @@ -51,6 +53,11 @@ const CommunityFeed: React.FC = () => { const [loading, setLoading] = useState(true); const [page, setPage] = useState(1); const [totalPages, setTotalPages] = useState(1); + const [followingSearch, setFollowingSearch] = useState(''); + + const filteredFollowing = following.filter(user => + user.username.toLowerCase().includes(followingSearch.toLowerCase()) + ); const fetchFeedData = async (pageNum: number) => { setLoading(true); @@ -159,8 +166,7 @@ const CommunityFeed: React.FC = () => { {/* Compact rating for mobile, stars for desktop */} - - {rating.score}/10 + ⭐ {rating.score}/10 @@ -211,15 +217,37 @@ const CommunityFeed: React.FC = () => { - Following ({following.length}) + Following ({following.length}) + setFollowingSearch(e.target.value)} + InputProps={{ + startAdornment: ( + + + + ), + }} + sx={{ + bgcolor: 'background.paper', + borderRadius: 1, + '& .MuiOutlinedInput-root': { + '& fieldset': { border: 'none' }, + boxShadow: '0 1px 3px rgba(0,0,0,0.05)' + } + }} + /> {following.length === 0 ? ( You aren't following anyone yet. ) : ( - - {following.map((user) => ( + + {filteredFollowing.map((user) => ( @@ -237,6 +265,11 @@ const CommunityFeed: React.FC = () => { ))} + {filteredFollowing.length === 0 && followingSearch && ( + + No matching friends found. + + )} )}