1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-07-23 06:49:37 +02:00

feat: Add Transportation and Lodging models to AdventureViewSet; update Avatar and TransportationModal components for improved user experience

This commit is contained in:
Sean Morley 2025-02-22 10:37:22 -05:00
parent 232e01bf8f
commit ea36b104b6
5 changed files with 57 additions and 7 deletions

View file

@ -6,9 +6,9 @@ from django.db.models.functions import Lower
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from adventures.models import Adventure, Category from adventures.models import Adventure, Category, Transportation, Lodging
from adventures.permissions import IsOwnerOrSharedWithFullAccess from adventures.permissions import IsOwnerOrSharedWithFullAccess
from adventures.serializers import AdventureSerializer from adventures.serializers import AdventureSerializer, TransportationSerializer, LodgingSerializer
from adventures.utils import pagination from adventures.utils import pagination
class AdventureViewSet(viewsets.ModelViewSet): class AdventureViewSet(viewsets.ModelViewSet):
@ -198,3 +198,49 @@ class AdventureViewSet(viewsets.ModelViewSet):
serializer = self.get_serializer(queryset, many=True) serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data) return Response(serializer.data)
# @action(detail=True, methods=['post'])
# def convert(self, request, pk=None):
# """
# Convert an Adventure instance into a Transportation or Lodging instance.
# Expects a JSON body with "target_type": "transportation" or "lodging".
# """
# adventure = self.get_object()
# target_type = request.data.get("target_type", "").lower()
# if target_type not in ["transportation", "lodging"]:
# return Response(
# {"error": "Invalid target type. Must be 'transportation' or 'lodging'."},
# status=400
# )
# if not adventure.collection:
# return Response(
# {"error": "Adventure must be part of a collection to be converted."},
# status=400
# )
# # Define the overlapping fields that both the Adventure and target models share.
# overlapping_fields = ["name", "description", "is_public", 'collection']
# # Gather the overlapping data from the adventure instance.
# conversion_data = {}
# for field in overlapping_fields:
# if hasattr(adventure, field):
# conversion_data[field] = getattr(adventure, field)
# # Make sure to include the user reference
# conversion_data["user_id"] = adventure.user_id
# # Convert the adventure instance within an atomic transaction.
# with transaction.atomic():
# if target_type == "transportation":
# new_instance = Transportation.objects.create(**conversion_data)
# serializer = TransportationSerializer(new_instance)
# else: # target_type == "lodging"
# new_instance = Lodging.objects.create(**conversion_data)
# serializer = LodgingSerializer(new_instance)
# # Optionally, delete the original adventure to avoid duplicates.
# adventure.delete()
# return Response(serializer.data)

View file

@ -39,10 +39,10 @@
</li> </li>
<li><button on:click={() => goto('/adventures')}>{$t('navbar.my_adventures')}</button></li> <li><button on:click={() => goto('/adventures')}>{$t('navbar.my_adventures')}</button></li>
<li><button on:click={() => goto('/shared')}>{$t('navbar.shared_with_me')}</button></li> <li><button on:click={() => goto('/shared')}>{$t('navbar.shared_with_me')}</button></li>
<li><button on:click={() => goto('/settings')}>{$t('navbar.settings')}</button></li>
{#if user.is_staff} {#if user.is_staff}
<li><button on:click={() => goto('/admin')}>{$t('navbar.admin_panel')}</button></li> <li><button on:click={() => goto('/admin')}>{$t('navbar.admin_panel')}</button></li>
{/if} {/if}
<li><button on:click={() => goto('/settings')}>{$t('navbar.settings')}</button></li>
<form method="post"> <form method="post">
<li><button formaction="/?/logout">{$t('navbar.logout')}</button></li> <li><button formaction="/?/logout">{$t('navbar.logout')}</button></li>
</form> </form>

View file

@ -94,6 +94,7 @@
'User-Agent': `AdventureLog / ${appVersion} ` 'User-Agent': `AdventureLog / ${appVersion} `
} }
}); });
console.log(query);
let data = await res.json(); let data = await res.json();
return data; return data;
}; };
@ -464,7 +465,7 @@
bind:value={starting_airport} bind:value={starting_airport}
name="starting_airport" name="starting_airport"
class="input input-bordered w-full" class="input input-bordered w-full"
placeholder="Enter starting airport code (e.g., JFK)" placeholder={$t('transportation.starting_airport_desc')}
/> />
<label for="ending_airport" class="label"> <label for="ending_airport" class="label">
<span class="label-text">{$t('adventures.ending_airport')}</span> <span class="label-text">{$t('adventures.ending_airport')}</span>
@ -475,10 +476,10 @@
bind:value={ending_airport} bind:value={ending_airport}
name="ending_airport" name="ending_airport"
class="input input-bordered w-full" class="input input-bordered w-full"
placeholder="Enter ending airport code (e.g., LAX)" placeholder={$t('transportation.ending_airport_desc')}
/> />
<button type="button" class="btn btn-primary mt-2" on:click={geocode}> <button type="button" class="btn btn-primary mt-2" on:click={geocode}>
Fetch Location Information {$t('transportation.fetch_location_information')}
</button> </button>
</div> </div>
{/if} {/if}

View file

@ -484,6 +484,9 @@
"flight_number": "Flight Number", "flight_number": "Flight Number",
"from_location": "From Location", "from_location": "From Location",
"to_location": "To Location", "to_location": "To Location",
"fetch_location_information": "Fetch Location Information",
"starting_airport_desc": "Enter starting airport code (e.g., JFK)",
"ending_airport_desc": "Enter ending airport code (e.g., LAX)",
"edit": "Edit", "edit": "Edit",
"modes": { "modes": {
"car": "Car", "car": "Car",

View file

@ -203,7 +203,7 @@
</MapLibre> </MapLibre>
<svelte:head> <svelte:head>
<title>Travel Map</title> <title>Adventure Map</title>
<meta name="description" content="View your travels on a map." /> <meta name="description" content="View your travels on a map." />
</svelte:head> </svelte:head>