mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-07-24 07:19:36 +02:00
add transportation
This commit is contained in:
parent
61c3d23efa
commit
6155d531ab
5 changed files with 267 additions and 28 deletions
|
@ -30,7 +30,7 @@ class TransportationSerializer(serializers.ModelSerializer):
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'user_id', 'type', 'name', 'description', 'rating',
|
'id', 'user_id', 'type', 'name', 'description', 'rating',
|
||||||
'link', 'date', 'flight_number', 'from_location', 'to_location',
|
'link', 'date', 'flight_number', 'from_location', 'to_location',
|
||||||
'is_public', 'collection', 'collection_id', 'created_at', 'updated_at'
|
'is_public', 'collection', 'created_at', 'updated_at'
|
||||||
]
|
]
|
||||||
read_only_fields = ['id', 'created_at', 'updated_at']
|
read_only_fields = ['id', 'created_at', 'updated_at']
|
||||||
|
|
||||||
|
|
|
@ -11,18 +11,13 @@
|
||||||
|
|
||||||
let originalName = transportationToEdit.name;
|
let originalName = transportationToEdit.name;
|
||||||
|
|
||||||
let isPointModalOpen: boolean = false;
|
|
||||||
|
|
||||||
import MapMarker from '~icons/mdi/map-marker';
|
import MapMarker from '~icons/mdi/map-marker';
|
||||||
import Calendar from '~icons/mdi/calendar';
|
import Calendar from '~icons/mdi/calendar';
|
||||||
import Notebook from '~icons/mdi/notebook';
|
import Notebook from '~icons/mdi/notebook';
|
||||||
import ClipboardList from '~icons/mdi/clipboard-list';
|
|
||||||
import Image from '~icons/mdi/image';
|
|
||||||
import Star from '~icons/mdi/star';
|
import Star from '~icons/mdi/star';
|
||||||
import Attachment from '~icons/mdi/attachment';
|
import PlaneCar from '~icons/mdi/plane-car';
|
||||||
import PointSelectionModal from './PointSelectionModal.svelte';
|
import LinkVariant from '~icons/mdi/link-variant';
|
||||||
import Earth from '~icons/mdi/earth';
|
import Airplane from '~icons/mdi/airplane';
|
||||||
import TransportationCard from './TransportationCard.svelte';
|
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
modal = document.getElementById('my_modal_1') as HTMLDialogElement;
|
modal = document.getElementById('my_modal_1') as HTMLDialogElement;
|
||||||
|
@ -99,7 +94,7 @@
|
||||||
class="input input-bordered w-full max-w-xs mt-1"
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
/>
|
/>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label for="type">Type <Calendar class="inline-block mb-1 w-6 h-6" /></label><br />
|
<label for="type">Type <PlaneCar class="inline-block mb-1 w-6 h-6" /></label><br />
|
||||||
<select
|
<select
|
||||||
class="select select-bordered w-full max-w-xs"
|
class="select select-bordered w-full max-w-xs"
|
||||||
name="type"
|
name="type"
|
||||||
|
@ -164,7 +159,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label for="rating">Link <Star class="inline-block mb-1 w-6 h-6" /></label><br />
|
<label for="rating">Link <LinkVariant class="inline-block mb-1 w-6 h-6" /></label><br />
|
||||||
<input
|
<input
|
||||||
type="url"
|
type="url"
|
||||||
id="link"
|
id="link"
|
||||||
|
@ -173,22 +168,11 @@
|
||||||
class="input input-bordered w-full max-w-xs mt-1"
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2">
|
|
||||||
<label for="rating">Rating <Star class="inline-block mb-1 w-6 h-6" /></label><br />
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
max="5"
|
|
||||||
min="0"
|
|
||||||
id="rating"
|
|
||||||
name="rating"
|
|
||||||
bind:value={transportationToEdit.rating}
|
|
||||||
class="input input-bordered w-full max-w-xs mt-1"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{#if transportationToEdit.type == 'plane'}
|
{#if transportationToEdit.type == 'plane'}
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label for="flight_number"
|
<label for="flight_number"
|
||||||
>Flight Number <Star class="inline-block mb-1 w-6 h-6" /></label
|
>Flight Number <Airplane class="inline-block mb-1 w-6 h-6" /></label
|
||||||
><br />
|
><br />
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -200,8 +184,8 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label for="rating">From Location <Star class="inline-block mb-1 w-6 h-6" /></label><br
|
<label for="rating">From Location <MapMarker class="inline-block mb-1 w-6 h-6" /></label
|
||||||
/>
|
><br />
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="from_location"
|
id="from_location"
|
||||||
|
@ -211,7 +195,8 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label for="rating">To Location <Star class="inline-block mb-1 w-6 h-6" /></label><br />
|
<label for="rating">To Location <MapMarker class="inline-block mb-1 w-6 h-6" /></label
|
||||||
|
><br />
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="to_location"
|
id="to_location"
|
||||||
|
|
232
frontend/src/lib/components/NewTransportation.svelte
Normal file
232
frontend/src/lib/components/NewTransportation.svelte
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
<script lang="ts">
|
||||||
|
// let newTransportation: Transportation = {
|
||||||
|
// id:NaN,
|
||||||
|
// user_id: NaN,
|
||||||
|
// type: '',
|
||||||
|
// name: '',
|
||||||
|
// description: null,
|
||||||
|
// rating: NaN,
|
||||||
|
// link: null,
|
||||||
|
// date: null,
|
||||||
|
// flight_number: null,
|
||||||
|
// from_location: null,
|
||||||
|
// to_location: null,
|
||||||
|
// is_public: false,
|
||||||
|
// collection: null,
|
||||||
|
// created_at: '',
|
||||||
|
// updated_at: ''
|
||||||
|
// };
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
import type { Collection, Transportation } from '$lib/types';
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { addToast } from '$lib/toasts';
|
||||||
|
let modal: HTMLDialogElement;
|
||||||
|
|
||||||
|
export let collection: Collection;
|
||||||
|
|
||||||
|
import MapMarker from '~icons/mdi/map-marker';
|
||||||
|
import Calendar from '~icons/mdi/calendar';
|
||||||
|
import Notebook from '~icons/mdi/notebook';
|
||||||
|
import Star from '~icons/mdi/star';
|
||||||
|
import PlaneCar from '~icons/mdi/plane-car';
|
||||||
|
import LinkVariant from '~icons/mdi/link-variant';
|
||||||
|
import Airplane from '~icons/mdi/airplane';
|
||||||
|
|
||||||
|
let type: string = '';
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
modal = document.getElementById('my_modal_1') as HTMLDialogElement;
|
||||||
|
if (modal) {
|
||||||
|
modal.showModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// if (newTransportation.date) {
|
||||||
|
// newTransportation.date = newTransportation.date.slice(0, 19);
|
||||||
|
// }
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
dispatch('close');
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKeydown(event: KeyboardEvent) {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSubmit(event: Event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const form = event.target as HTMLFormElement;
|
||||||
|
const formData = new FormData(form);
|
||||||
|
|
||||||
|
const response = await fetch(`/api/transportations/`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
addToast('success', 'Transportation added successfully!');
|
||||||
|
dispatch('add', result);
|
||||||
|
close();
|
||||||
|
} else {
|
||||||
|
addToast('error', 'Error editing transportation');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<dialog id="my_modal_1" class="modal">
|
||||||
|
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||||
|
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||||
|
<div class="modal-box" role="dialog" on:keydown={handleKeydown} tabindex="0">
|
||||||
|
<h3 class="font-bold text-lg">New Transportation</h3>
|
||||||
|
<div
|
||||||
|
class="modal-action items-center"
|
||||||
|
style="display: flex; flex-direction: column; align-items: center; width: 100%;"
|
||||||
|
>
|
||||||
|
<form method="post" style="width: 100%;" on:submit={handleSubmit}>
|
||||||
|
<div class="mb-2">
|
||||||
|
<!-- <input
|
||||||
|
type="text"
|
||||||
|
id="id"
|
||||||
|
name="id"
|
||||||
|
hidden
|
||||||
|
readonly
|
||||||
|
bind:value={newTransportation.id}
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
|
/> -->
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="collection"
|
||||||
|
name="collection"
|
||||||
|
hidden
|
||||||
|
readonly
|
||||||
|
bind:value={collection.id}
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="is_public"
|
||||||
|
name="is_public"
|
||||||
|
hidden
|
||||||
|
readonly
|
||||||
|
bind:value={collection.is_public}
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
|
/>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="type">Type <PlaneCar class="inline-block mb-1 w-6 h-6" /></label><br />
|
||||||
|
<select
|
||||||
|
class="select select-bordered w-full max-w-xs"
|
||||||
|
name="type"
|
||||||
|
id="type"
|
||||||
|
bind:value={type}
|
||||||
|
>
|
||||||
|
<option disabled selected>Transport Type</option>
|
||||||
|
<option value="car">Car</option>
|
||||||
|
<option value="plane">Plane</option>
|
||||||
|
<option value="train">Train</option>
|
||||||
|
<option value="bus">Bus</option>
|
||||||
|
<option value="boat">Boat</option>
|
||||||
|
<option value="bike">Bike</option>
|
||||||
|
<option value="walking">Walking</option>
|
||||||
|
<option value="other">Other</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label for="name">Name</label><br />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
id="name"
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="date">Description <Notebook class="inline-block -mt-1 mb-1 w-6 h-6" /></label
|
||||||
|
><br />
|
||||||
|
<div class="flex">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="description"
|
||||||
|
name="description"
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1 mb-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="start_date"
|
||||||
|
>Date & Time <Calendar class="inline-block mb-1 w-6 h-6" /></label
|
||||||
|
><br />
|
||||||
|
<input
|
||||||
|
type="datetime-local"
|
||||||
|
id="date"
|
||||||
|
name="date"
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="rating">Rating <Star class="inline-block mb-1 w-6 h-6" /></label><br />
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
max="5"
|
||||||
|
min="0"
|
||||||
|
id="rating"
|
||||||
|
name="rating"
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="rating">Link <LinkVariant class="inline-block mb-1 w-6 h-6" /></label><br />
|
||||||
|
<input
|
||||||
|
type="url"
|
||||||
|
id="link"
|
||||||
|
name="link"
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if type == 'plane'}
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="flight_number"
|
||||||
|
>Flight Number <Airplane class="inline-block mb-1 w-6 h-6" /></label
|
||||||
|
><br />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="flight_number"
|
||||||
|
name="flight_number"
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="rating">From Location <MapMarker class="inline-block mb-1 w-6 h-6" /></label
|
||||||
|
><br />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="from_location"
|
||||||
|
name="from_location"
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="rating">To Location <MapMarker class="inline-block mb-1 w-6 h-6" /></label
|
||||||
|
><br />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="to_location"
|
||||||
|
name="to_location"
|
||||||
|
class="input input-bordered w-full max-w-xs mt-1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary mr-4 mt-4">Edit</button>
|
||||||
|
<!-- if there is a button in form, it will close the modal -->
|
||||||
|
<button class="btn mt-4" on:click={close}>Close</button>
|
||||||
|
</form>
|
||||||
|
<div class="flex items-center justify-center flex-wrap gap-4 mt-4"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
|
@ -88,7 +88,7 @@ export type OpenStreetMapPlace = {
|
||||||
|
|
||||||
export type Transportation = {
|
export type Transportation = {
|
||||||
id: number;
|
id: number;
|
||||||
user_id: User;
|
user_id: number;
|
||||||
type: string;
|
type: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string | null;
|
description: string | null;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
import { DefaultMarker, MapLibre, Popup } from 'svelte-maplibre';
|
import { DefaultMarker, MapLibre, Popup } from 'svelte-maplibre';
|
||||||
import TransportationCard from '$lib/components/TransportationCard.svelte';
|
import TransportationCard from '$lib/components/TransportationCard.svelte';
|
||||||
import EditTransportation from '$lib/components/EditTransportation.svelte';
|
import EditTransportation from '$lib/components/EditTransportation.svelte';
|
||||||
|
import NewTransportation from '$lib/components/NewTransportation.svelte';
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
let notFound: boolean = false;
|
let notFound: boolean = false;
|
||||||
let isShowingLinkModal: boolean = false;
|
let isShowingLinkModal: boolean = false;
|
||||||
let isShowingCreateModal: boolean = false;
|
let isShowingCreateModal: boolean = false;
|
||||||
|
let isShowingTransportationModal: boolean = false;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (data.props.adventure) {
|
if (data.props.adventure) {
|
||||||
|
@ -190,6 +192,17 @@
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if isShowingTransportationModal}
|
||||||
|
<NewTransportation
|
||||||
|
on:close={() => (isShowingTransportationModal = false)}
|
||||||
|
on:add={(event) => {
|
||||||
|
transportations = [event.detail, ...transportations];
|
||||||
|
isShowingTransportationModal = false;
|
||||||
|
}}
|
||||||
|
{collection}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if notFound}
|
{#if notFound}
|
||||||
<div
|
<div
|
||||||
class="flex min-h-[100dvh] flex-col items-center justify-center bg-background px-4 py-12 sm:px-6 lg:px-8 -mt-20"
|
class="flex min-h-[100dvh] flex-col items-center justify-center bg-background px-4 py-12 sm:px-6 lg:px-8 -mt-20"
|
||||||
|
@ -276,6 +289,15 @@
|
||||||
>
|
>
|
||||||
Dining</button
|
Dining</button
|
||||||
>
|
>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary"
|
||||||
|
on:click={() => {
|
||||||
|
isShowingTransportationModal = true;
|
||||||
|
newType = '';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Transportation</button
|
||||||
|
>
|
||||||
|
|
||||||
<!-- <button
|
<!-- <button
|
||||||
class="btn btn-primary"
|
class="btn btn-primary"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue