mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-07-19 12:59:36 +02:00
Enhance Adventure model and serializers with visited status logic and toast notifications for marking visits
This commit is contained in:
parent
84cd136401
commit
a1062e72cf
4 changed files with 45 additions and 12 deletions
|
@ -9,8 +9,9 @@ from django.contrib.auth import get_user_model
|
||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
from django.forms import ValidationError
|
from django.forms import ValidationError
|
||||||
from django_resized import ResizedImageField
|
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 adventures.geocoding import reverse_geocode
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
def validate_file_extension(value):
|
def validate_file_extension(value):
|
||||||
import os
|
import os
|
||||||
|
@ -549,6 +550,17 @@ class Adventure(models.Model):
|
||||||
# end_date = models.DateField(blank=True, null=True)
|
# end_date = models.DateField(blank=True, null=True)
|
||||||
# type = models.CharField(max_length=100, choices=ADVENTURE_TYPES, default='general')
|
# 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):
|
def clean(self):
|
||||||
if self.collection:
|
if self.collection:
|
||||||
if self.collection.is_public and not self.is_public:
|
if self.collection.is_public and not self.is_public:
|
||||||
|
@ -578,15 +590,26 @@ class Adventure(models.Model):
|
||||||
self.category = category
|
self.category = category
|
||||||
|
|
||||||
if self.latitude and self.longitude:
|
if self.latitude and self.longitude:
|
||||||
|
is_visited = self.is_visited_status()
|
||||||
reverse_geocode_result = reverse_geocode(self.latitude, self.longitude, self.user_id)
|
reverse_geocode_result = reverse_geocode(self.latitude, self.longitude, self.user_id)
|
||||||
if 'region_id' in reverse_geocode_result:
|
if 'region_id' in reverse_geocode_result:
|
||||||
region = Region.objects.filter(id=reverse_geocode_result['region_id']).first()
|
region = Region.objects.filter(id=reverse_geocode_result['region_id']).first()
|
||||||
if region:
|
if region:
|
||||||
self.region = 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:
|
if 'city_id' in reverse_geocode_result:
|
||||||
city = City.objects.filter(id=reverse_geocode_result['city_id']).first()
|
city = City.objects.filter(id=reverse_geocode_result['city_id']).first()
|
||||||
if city:
|
if city:
|
||||||
self.city = 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:
|
if 'country_id' in reverse_geocode_result:
|
||||||
country = Country.objects.filter(country_code=reverse_geocode_result['country_id']).first()
|
country = Country.objects.filter(country_code=reverse_geocode_result['country_id']).first()
|
||||||
if country:
|
if country:
|
||||||
|
|
|
@ -138,15 +138,7 @@ class AdventureSerializer(CustomModelSerializer):
|
||||||
return CustomUserDetailsSerializer(user).data
|
return CustomUserDetailsSerializer(user).data
|
||||||
|
|
||||||
def get_is_visited(self, obj):
|
def get_is_visited(self, obj):
|
||||||
current_date = timezone.now().date()
|
return obj.is_visited_status()
|
||||||
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
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
visits_data = validated_data.pop('visits', None)
|
visits_data = validated_data.pop('visits', None)
|
||||||
|
@ -159,7 +151,8 @@ class AdventureSerializer(CustomModelSerializer):
|
||||||
if category_data:
|
if category_data:
|
||||||
category = self.get_or_create_category(category_data)
|
category = self.get_or_create_category(category_data)
|
||||||
adventure.category = category
|
adventure.category = category
|
||||||
adventure.save()
|
|
||||||
|
adventure.save()
|
||||||
|
|
||||||
return adventure
|
return adventure
|
||||||
|
|
||||||
|
@ -196,6 +189,9 @@ class AdventureSerializer(CustomModelSerializer):
|
||||||
visits_to_delete = current_visit_ids - updated_visit_ids
|
visits_to_delete = current_visit_ids - updated_visit_ids
|
||||||
instance.visits.filter(id__in=visits_to_delete).delete()
|
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
|
return instance
|
||||||
|
|
||||||
class TransportationSerializer(CustomModelSerializer):
|
class TransportationSerializer(CustomModelSerializer):
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$: if (triggerMarkVisted && willBeMarkedVisited) {
|
$: 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;
|
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() {
|
async function markVisited() {
|
||||||
console.log(reverseGeocodePlace);
|
console.log(reverseGeocodePlace);
|
||||||
if (reverseGeocodePlace) {
|
if (reverseGeocodePlace) {
|
||||||
|
|
|
@ -45,6 +45,9 @@ export type Adventure = {
|
||||||
category: Category | null;
|
category: Category | null;
|
||||||
attachments: Attachment[];
|
attachments: Attachment[];
|
||||||
user?: User | null;
|
user?: User | null;
|
||||||
|
city?: string | null;
|
||||||
|
region?: string | null;
|
||||||
|
country?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AdditionalAdventure = Adventure & {
|
export type AdditionalAdventure = Adventure & {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue