diff --git a/backend/server/adventures/models.py b/backend/server/adventures/models.py index c8cb90e..29ac2ce 100644 --- a/backend/server/adventures/models.py +++ b/backend/server/adventures/models.py @@ -9,8 +9,9 @@ from django.contrib.auth import get_user_model from django.contrib.postgres.fields import ArrayField from django.forms import ValidationError from django_resized import ResizedImageField -from worldtravel.models import City, Country, Region +from worldtravel.models import City, Country, Region, VisitedCity, VisitedRegion from adventures.geocoding import reverse_geocode +from django.utils import timezone def validate_file_extension(value): import os @@ -549,6 +550,17 @@ class Adventure(models.Model): # end_date = models.DateField(blank=True, null=True) # type = models.CharField(max_length=100, choices=ADVENTURE_TYPES, default='general') + def is_visited_status(self): + current_date = timezone.now().date() + for visit in self.visits.all(): + start_date = visit.start_date.date() if isinstance(visit.start_date, timezone.datetime) else visit.start_date + end_date = visit.end_date.date() if isinstance(visit.end_date, timezone.datetime) else visit.end_date + if start_date and end_date and (start_date <= current_date): + return True + elif start_date and not end_date and (start_date <= current_date): + return True + return False + def clean(self): if self.collection: if self.collection.is_public and not self.is_public: @@ -578,15 +590,26 @@ class Adventure(models.Model): self.category = category if self.latitude and self.longitude: + is_visited = self.is_visited_status() reverse_geocode_result = reverse_geocode(self.latitude, self.longitude, self.user_id) if 'region_id' in reverse_geocode_result: region = Region.objects.filter(id=reverse_geocode_result['region_id']).first() if region: self.region = region + if is_visited: + visited_region, created = VisitedRegion.objects.get_or_create( + user_id=self.user_id, + region=region + ) if 'city_id' in reverse_geocode_result: city = City.objects.filter(id=reverse_geocode_result['city_id']).first() if city: self.city = city + if is_visited: + visited_city, created = VisitedCity.objects.get_or_create( + user_id=self.user_id, + city=city + ) if 'country_id' in reverse_geocode_result: country = Country.objects.filter(country_code=reverse_geocode_result['country_id']).first() if country: diff --git a/backend/server/adventures/serializers.py b/backend/server/adventures/serializers.py index 3c2cd5f..0fe059e 100644 --- a/backend/server/adventures/serializers.py +++ b/backend/server/adventures/serializers.py @@ -138,15 +138,7 @@ class AdventureSerializer(CustomModelSerializer): return CustomUserDetailsSerializer(user).data def get_is_visited(self, obj): - current_date = timezone.now().date() - for visit in obj.visits.all(): - start_date = visit.start_date.date() if isinstance(visit.start_date, timezone.datetime) else visit.start_date - end_date = visit.end_date.date() if isinstance(visit.end_date, timezone.datetime) else visit.end_date - if start_date and end_date and (start_date <= current_date): - return True - elif start_date and not end_date and (start_date <= current_date): - return True - return False + return obj.is_visited_status() def create(self, validated_data): visits_data = validated_data.pop('visits', None) @@ -159,7 +151,8 @@ class AdventureSerializer(CustomModelSerializer): if category_data: category = self.get_or_create_category(category_data) adventure.category = category - adventure.save() + + adventure.save() return adventure @@ -196,6 +189,9 @@ class AdventureSerializer(CustomModelSerializer): visits_to_delete = current_visit_ids - updated_visit_ids instance.visits.filter(id__in=visits_to_delete).delete() + # call save on the adventure to update the updated_at field and trigger any geocoding + instance.save() + return instance class TransportationSerializer(CustomModelSerializer): diff --git a/frontend/src/lib/components/LocationDropdown.svelte b/frontend/src/lib/components/LocationDropdown.svelte index 1ca4b12..b39628f 100644 --- a/frontend/src/lib/components/LocationDropdown.svelte +++ b/frontend/src/lib/components/LocationDropdown.svelte @@ -55,7 +55,7 @@ } $: if (triggerMarkVisted && willBeMarkedVisited) { - markVisited(); + displaySuccessToast(); // since the server will trigger the geocode automatically, we just need to show the toast and let the server handle the rest. It's kinda a placebo effect... triggerMarkVisted = false; } @@ -102,6 +102,17 @@ } } + function displaySuccessToast() { + if (reverseGeocodePlace) { + if (reverseGeocodePlace.region) { + addToast('success', `Visit to ${reverseGeocodePlace.region} marked`); + } + if (reverseGeocodePlace.city) { + addToast('success', `Visit to ${reverseGeocodePlace.city} marked`); + } + } + } + async function markVisited() { console.log(reverseGeocodePlace); if (reverseGeocodePlace) { diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts index ab7f01c..f47d9ea 100644 --- a/frontend/src/lib/types.ts +++ b/frontend/src/lib/types.ts @@ -45,6 +45,9 @@ export type Adventure = { category: Category | null; attachments: Attachment[]; user?: User | null; + city?: string | null; + region?: string | null; + country?: string | null; }; export type AdditionalAdventure = Adventure & {