diff --git a/backend/server/adventures/views.py b/backend/server/adventures/views.py index 5c0c593..1ce81f5 100644 --- a/backend/server/adventures/views.py +++ b/backend/server/adventures/views.py @@ -8,7 +8,7 @@ from django.db.models.functions import Lower from rest_framework.response import Response from .models import Adventure, Checklist, Collection, Transportation, Note, AdventureImage, Category from django.core.exceptions import PermissionDenied -from worldtravel.models import VisitedRegion, Region, Country +from worldtravel.models import VisitedCity, VisitedRegion, Region, Country, City from .serializers import AdventureImageSerializer, AdventureSerializer, CategorySerializer, CollectionSerializer, NoteSerializer, TransportationSerializer, ChecklistSerializer from rest_framework.permissions import IsAuthenticated from django.db.models import Q @@ -1159,41 +1159,48 @@ class ReverseGeocodeViewSet(viewsets.ViewSet): Returns a dictionary containing the region name, country name, and ISO code if found. """ iso_code = None - town = None - city = None - county = None + town_city_or_county = None display_name = None country_code = None + city = None + + # town = None + # city = None + # county = None + if 'address' in data.keys(): keys = data['address'].keys() for key in keys: if key.find("ISO") != -1: iso_code = data['address'][key] if 'town' in keys: - town = data['address']['town'] + town_city_or_county = data['address']['town'] if 'county' in keys: - county = data['address']['county'] + town_city_or_county = data['address']['county'] if 'city' in keys: - city = data['address']['city'] + town_city_or_county = data['address']['city'] if not iso_code: return {"error": "No region found"} + region = Region.objects.filter(id=iso_code).first() visited_region = VisitedRegion.objects.filter(region=region, user_id=self.request.user).first() - is_visited = False + + region_visited = False + city_visited = False country_code = iso_code[:2] if region: - if city: - display_name = f"{city}, {region.name}, {country_code}" - elif town: - display_name = f"{town}, {region.name}, {country_code}" - elif county: - display_name = f"{county}, {region.name}, {country_code}" + if town_city_or_county: + display_name = f"{town_city_or_county}, {region.name}, {country_code}" + city = City.objects.filter(name__contains=town_city_or_county, region=region).first() + visited_city = VisitedCity.objects.filter(city=city, user_id=self.request.user).first() if visited_region: - is_visited = True + region_visited = True + if visited_city: + city_visited = True if region: - return {"id": iso_code, "region": region.name, "country": region.country.name, "is_visited": is_visited, "display_name": display_name} + return {"region_id": iso_code, "region": region.name, "country": region.country.name, "region_visited": region_visited, "display_name": display_name, "city": city.name if city else None, "city_id": city.id if city else None, "city_visited": city_visited} return {"error": "No region found"} @action(detail=False, methods=['get']) diff --git a/backend/server/worldtravel/views.py b/backend/server/worldtravel/views.py index 6cb2575..c77309d 100644 --- a/backend/server/worldtravel/views.py +++ b/backend/server/worldtravel/views.py @@ -137,6 +137,10 @@ class VisitedCityViewSet(viewsets.ModelViewSet): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) + # if the region is not visited, visit it + region = serializer.validated_data['city'].region + if not VisitedRegion.objects.filter(user_id=request.user.id, region=region).exists(): + VisitedRegion.objects.create(user_id=request.user, region=region) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) diff --git a/frontend/src/lib/components/AdventureModal.svelte b/frontend/src/lib/components/AdventureModal.svelte index eda9df6..9e014e8 100644 --- a/frontend/src/lib/components/AdventureModal.svelte +++ b/frontend/src/lib/components/AdventureModal.svelte @@ -365,15 +365,31 @@ async function markVisited() { console.log(reverseGeocodePlace); if (reverseGeocodePlace) { - let res = await fetch(`/worldtravel?/markVisited`, { - method: 'POST', - body: JSON.stringify({ regionId: reverseGeocodePlace.id }) - }); - if (res.ok) { - reverseGeocodePlace.is_visited = true; - addToast('success', `Visit to ${reverseGeocodePlace.region} marked`); - } else { - addToast('error', `Failed to mark visit to ${reverseGeocodePlace.region}`); + if (!reverseGeocodePlace.region_visited && reverseGeocodePlace.region_id) { + let region_res = await fetch(`/api/visitedregion`, { + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + body: JSON.stringify({ region: reverseGeocodePlace.region_id }) + }); + if (region_res.ok) { + reverseGeocodePlace.region_visited = true; + addToast('success', `Visit to ${reverseGeocodePlace.region} marked`); + } else { + addToast('error', `Failed to mark visit to ${reverseGeocodePlace.region}`); + } + } + if (!reverseGeocodePlace.city_visited && reverseGeocodePlace.city_id != null) { + let city_res = await fetch(`/api/visitedcity`, { + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + body: JSON.stringify({ city: reverseGeocodePlace.city_id }) + }); + if (city_res.ok) { + reverseGeocodePlace.city_visited = true; + addToast('success', `Visit to ${reverseGeocodePlace.city} marked`); + } else { + addToast('error', `Failed to mark visit to ${reverseGeocodePlace.city}`); + } } } } @@ -542,7 +558,10 @@ addToast('error', $t('adventures.adventure_update_error')); } } - if (adventure.is_visited && !reverseGeocodePlace?.is_visited) { + if ( + (adventure.is_visited && !reverseGeocodePlace?.region_visited) || + !reverseGeocodePlace?.city_visited + ) { markVisited(); } imageSearch = adventure.name; @@ -785,19 +804,33 @@ it would also work to just use on:click on the MapLibre component itself. --> {#if reverseGeocodePlace}
-

{reverseGeocodePlace.region}, {reverseGeocodePlace.country}

- {reverseGeocodePlace.is_visited + {reverseGeocodePlace.city + ? reverseGeocodePlace.city + ', ' + : ''}{reverseGeocodePlace.region}, + {reverseGeocodePlace.country} +

+

+ {reverseGeocodePlace.region}: + {reverseGeocodePlace.region_visited ? $t('adventures.visited') : $t('adventures.not_visited')}

+ {#if reverseGeocodePlace.city} +

+ {reverseGeocodePlace.city}: + {reverseGeocodePlace.city_visited + ? $t('adventures.visited') + : $t('adventures.not_visited')} +

+ {/if}
- {#if !reverseGeocodePlace.is_visited && !willBeMarkedVisited} + {#if !reverseGeocodePlace.region_visited || (!reverseGeocodePlace.city_visited && !willBeMarkedVisited)} {/if} - {#if !reverseGeocodePlace.is_visited && willBeMarkedVisited} + {#if !reverseGeocodePlace.region_visited || (!reverseGeocodePlace.city_visited && willBeMarkedVisited)}