diff --git a/backend/server/adventures/views/global_search_view.py b/backend/server/adventures/views/global_search_view.py index 3780629..d2fa5d3 100644 --- a/backend/server/adventures/views/global_search_view.py +++ b/backend/server/adventures/views/global_search_view.py @@ -1,71 +1,73 @@ - from rest_framework import viewsets from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated +from django.db.models import Q +from django.contrib.postgres.search import SearchVector, SearchQuery from adventures.models import Adventure, Collection from adventures.serializers import AdventureSerializer, CollectionSerializer -from django.db.models import Q -from adventures.utils import pagination -from worldtravel.models import Country, Region, City -from worldtravel.serializers import CountrySerializer, RegionSerializer, CitySerializer +from worldtravel.models import Country, Region, City, VisitedCity, VisitedRegion +from worldtravel.serializers import CountrySerializer, RegionSerializer, CitySerializer, VisitedCitySerializer, VisitedRegionSerializer from users.models import CustomUser as User from users.serializers import CustomUserDetailsSerializer as UserSerializer class GlobalSearchView(viewsets.ViewSet): permission_classes = [IsAuthenticated] - pagination_class = pagination.StandardResultsSetPagination def list(self, request): - search_term = request.query_params.get('query', '') - # print(f"Searching for: {search_term}") # For debugging - + search_term = request.query_params.get('query', '').strip() if not search_term: return Response({"error": "Search query is required"}, status=400) - # Search for adventures - adventures = Adventure.objects.filter( - (Q(name__icontains=search_term) | Q(description__icontains=search_term) | Q(location__icontains=search_term)) & Q(user_id=request.user.id) - ) + # Initialize empty results + results = { + "adventures": [], + "collections": [], + "users": [], + "countries": [], + "regions": [], + "cities": [], + "visited_regions": [], + "visited_cities": [] + } - # Search for collections + # Adventures: Full-Text Search + adventures = Adventure.objects.annotate( + search=SearchVector('name', 'description', 'location') + ).filter(search=SearchQuery(search_term), user_id=request.user) + results["adventures"] = AdventureSerializer(adventures, many=True).data + + # Collections: Partial Match Search collections = Collection.objects.filter( - Q(name__icontains=search_term) & Q(user_id=request.user.id) + Q(name__icontains=search_term) & Q(user_id=request.user) ) + results["collections"] = CollectionSerializer(collections, many=True).data - # Search for users + # Users: Public Profiles Only users = User.objects.filter( - (Q(username__icontains=search_term) | Q(first_name__icontains=search_term) | Q(last_name__icontains=search_term)) & Q(public_profile=True) + (Q(username__icontains=search_term) | + Q(first_name__icontains=search_term) | + Q(last_name__icontains=search_term)) & Q(public_profile=True) ) + results["users"] = UserSerializer(users, many=True).data - # Search for countries - countries = Country.objects.filter( - Q(name__icontains=search_term) | Q(country_code__icontains=search_term) - ) + # Countries: Full-Text Search + countries = Country.objects.annotate( + search=SearchVector('name', 'country_code') + ).filter(search=SearchQuery(search_term)) + results["countries"] = CountrySerializer(countries, many=True).data - # Search for regions - regions = Region.objects.filter( - Q(name__icontains=search_term) | Q(country__name__icontains=search_term) - ) + # Regions and Cities: Partial Match Search + regions = Region.objects.filter(Q(name__icontains=search_term)) + results["regions"] = RegionSerializer(regions, many=True).data - # Search for cities - cities = City.objects.filter( - Q(name__icontains=search_term) | Q(region__name__icontains=search_term) | Q(region__country__name__icontains=search_term) - ) + cities = City.objects.filter(Q(name__icontains=search_term)) + results["cities"] = CitySerializer(cities, many=True).data - # Serialize the results - adventure_serializer = AdventureSerializer(adventures, many=True) - collection_serializer = CollectionSerializer(collections, many=True) - user_serializer = UserSerializer(users, many=True) - country_serializer = CountrySerializer(countries, many=True) - region_serializer = RegionSerializer(regions, many=True) - city_serializer = CitySerializer(cities, many=True) + # Visited Regions and Cities + visited_regions = VisitedRegion.objects.filter(user_id=request.user) + results["visited_regions"] = VisitedRegionSerializer(visited_regions, many=True).data - return Response({ - "adventures": adventure_serializer.data, - "collections": collection_serializer.data, - "users": user_serializer.data, - "countries": country_serializer.data, - "regions": region_serializer.data, - "cities": city_serializer.data - }) - \ No newline at end of file + visited_cities = VisitedCity.objects.filter(user_id=request.user) + results["visited_cities"] = VisitedCitySerializer(visited_cities, many=True).data + + return Response(results) diff --git a/frontend/src/lib/components/RegionCard.svelte b/frontend/src/lib/components/RegionCard.svelte index 5acd3a9..a5fc538 100644 --- a/frontend/src/lib/components/RegionCard.svelte +++ b/frontend/src/lib/components/RegionCard.svelte @@ -7,7 +7,7 @@ import { t } from 'svelte-i18n'; export let region: Region; - export let visited: boolean; + export let visited: boolean | undefined; function goToCity() { console.log(region); @@ -64,12 +64,12 @@
{result.type}
-{result.lat}, {result.lon}
-+ {$t('adventures.no_results')} +
+{/if} +