From f0efdaa933690a4f67f4b6f432a339517797f224 Mon Sep 17 00:00:00 2001 From: Sean Morley Date: Sat, 17 Aug 2024 22:40:27 -0400 Subject: [PATCH] new adventure modal --- ...Adventure.svelte => AdventureModal.svelte} | 199 +++--- .../src/lib/components/NewAdventure.svelte | 610 ------------------ frontend/src/lib/types.ts | 2 +- frontend/src/routes/adventures/+page.svelte | 66 +- .../src/routes/adventures/[id]/+page.svelte | 7 +- frontend/src/routes/collections/+page.svelte | 7 +- .../src/routes/collections/[id]/+page.svelte | 72 +-- .../routes/collections/archived/+page.svelte | 12 +- frontend/src/routes/map/+page.svelte | 9 +- frontend/src/routes/search/+page.svelte | 19 +- 10 files changed, 197 insertions(+), 806 deletions(-) rename frontend/src/lib/components/{EditAdventure.svelte => AdventureModal.svelte} (75%) delete mode 100644 frontend/src/lib/components/NewAdventure.svelte diff --git a/frontend/src/lib/components/EditAdventure.svelte b/frontend/src/lib/components/AdventureModal.svelte similarity index 75% rename from frontend/src/lib/components/EditAdventure.svelte rename to frontend/src/lib/components/AdventureModal.svelte index 985ef5b..64d94b9 100644 --- a/frontend/src/lib/components/EditAdventure.svelte +++ b/frontend/src/lib/components/AdventureModal.svelte @@ -8,6 +8,7 @@ export let longitude: number | null = null; export let latitude: number | null = null; + export let collection_id: string | null = null; import { DefaultMarker, MapEvents, MapLibre } from 'svelte-maplibre'; let markers: Point[] = []; @@ -24,38 +25,56 @@ let noPlaces: boolean = false; - export let adventureToEdit: Adventure; + export let adventureToEdit: Adventure | null = null; + + let adventure: Adventure = { + id: adventureToEdit?.id || '', + name: adventureToEdit?.name || '', + type: adventureToEdit?.type || 'visited', + date: adventureToEdit?.date || null, + link: adventureToEdit?.link || null, + description: adventureToEdit?.description || null, + activity_types: adventureToEdit?.activity_types || [], + rating: adventureToEdit?.rating || NaN, + is_public: adventureToEdit?.is_public || false, + latitude: adventureToEdit?.latitude || NaN, + longitude: adventureToEdit?.longitude || NaN, + location: adventureToEdit?.location || null, + images: adventureToEdit?.images || [], + user_id: adventureToEdit?.user_id || null, + collection: adventureToEdit?.collection || collection_id || null + }; let url: string = ''; let imageError: string = ''; let wikiImageError: string = ''; - images = adventureToEdit.images || []; + images = adventure.images || []; - if (adventureToEdit.longitude && adventureToEdit.latitude) { + if (adventure.longitude && adventure.latitude) { markers = [ { - lngLat: { lng: adventureToEdit.longitude, lat: adventureToEdit.latitude }, - location: adventureToEdit.location || '', - name: adventureToEdit.name, + lngLat: { lng: adventure.longitude, lat: adventure.latitude }, + location: adventure.location || '', + name: adventure.name, activity_type: '' } ]; } if (longitude && latitude) { - adventureToEdit.latitude = latitude; - adventureToEdit.longitude = longitude; + adventure.latitude = latitude; + adventure.longitude = longitude; reverseGeocode(); } $: { - if (!adventureToEdit.rating) { - adventureToEdit.rating = NaN; + if (!adventure.rating) { + adventure.rating = NaN; } } - let imageSearch: string = adventureToEdit.name || ''; + let imageSearch: string = adventure.name || ''; async function removeImage(id: string) { let res = await fetch(`/api/images/${id}/image_delete`, { @@ -63,7 +82,7 @@ }); if (res.status === 204) { images = images.filter((image) => image.id !== id); - adventureToEdit.images = images; + adventure.images = images; console.log(images); addToast('success', 'Image removed'); } else { @@ -74,18 +93,18 @@ let isDetails: boolean = true; function saveAndClose() { - dispatch('saveEdit', adventureToEdit); + dispatch('save', adventure); close(); } $: if (markers.length > 0) { - adventureToEdit.latitude = Math.round(markers[0].lngLat.lat * 1e6) / 1e6; - adventureToEdit.longitude = Math.round(markers[0].lngLat.lng * 1e6) / 1e6; - if (!adventureToEdit.location) { - adventureToEdit.location = markers[0].location; + adventure.latitude = Math.round(markers[0].lngLat.lat * 1e6) / 1e6; + adventure.longitude = Math.round(markers[0].lngLat.lng * 1e6) / 1e6; + if (!adventure.location) { + adventure.location = markers[0].location; } - if (!adventureToEdit.name) { - adventureToEdit.name = markers[0].name; + if (!adventure.name) { + adventure.name = markers[0].name; } } @@ -99,7 +118,7 @@ let file = new File([data], 'image.jpg', { type: 'image/jpeg' }); let formData = new FormData(); formData.append('image', file); - formData.append('adventure', adventureToEdit.id); + formData.append('adventure', adventure.id); let res2 = await fetch(`/adventures?/image`, { method: 'POST', body: formData @@ -108,7 +127,7 @@ console.log(data2); if (data2.type === 'success') { images = [...images, data2]; - adventureToEdit.images = images; + adventure.images = images; addToast('success', 'Image uploaded'); } else { addToast('error', 'Failed to upload image'); @@ -129,7 +148,7 @@ let file = new File([blob], `${imageSearch}.jpg`, { type: 'image/jpeg' }); let formData = new FormData(); formData.append('image', file); - formData.append('adventure', adventureToEdit.id); + formData.append('adventure', adventure.id); let res2 = await fetch(`/adventures?/image`, { method: 'POST', body: formData @@ -140,7 +159,7 @@ let newImage = { id: newData.data.id, image: newData.data.image }; console.log(newImage); images = [...images, newImage]; - adventureToEdit.images = images; + adventure.images = images; addToast('success', 'Image uploaded'); } else { addToast('error', 'Failed to upload image'); @@ -173,7 +192,7 @@ async function reverseGeocode() { let res = await fetch( - `https://nominatim.openstreetmap.org/search?q=${adventureToEdit.latitude},${adventureToEdit.longitude}&format=jsonv2`, + `https://nominatim.openstreetmap.org/search?q=${adventure.latitude},${adventure.longitude}&format=jsonv2`, { headers: { 'User-Agent': `AdventureLog / ${appVersion} ` @@ -182,9 +201,19 @@ ); let data = (await res.json()) as OpenStreetMapPlace[]; if (data.length > 0) { - adventureToEdit.name = data[0]?.name || ''; - adventureToEdit.activity_types?.push(data[0]?.type || ''); - adventureToEdit.location = data[0]?.display_name || ''; + adventure.name = data[0]?.name || ''; + adventure.activity_types?.push(data[0]?.type || ''); + adventure.location = data[0]?.display_name || ''; + if (longitude && latitude) { + markers = [ + { + lngLat: { lng: longitude, lat: latitude }, + location: data[0]?.display_name || '', + name: data[0]?.name || '', + activity_type: data[0]?.type || '' + } + ]; + } } console.log(data); } @@ -229,12 +258,12 @@ return async ({ result }: any) => { if (result.type === 'success') { if (result.data.id && result.data.image) { - adventureToEdit.images = [...adventureToEdit.images, result.data]; + adventure.images = [...adventure.images, result.data]; images = [...images, result.data]; addToast('success', 'Image uploaded'); fileInput.value = ''; - console.log(adventureToEdit); + console.log(adventure); } else { addToast('error', result.data.error || 'Failed to upload image'); } @@ -244,21 +273,39 @@ async function handleSubmit(event: Event) { event.preventDefault(); - console.log(adventureToEdit); - let res = await fetch(`/api/adventures/${adventureToEdit.id}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(adventureToEdit) - }); - let data = await res.json(); - if (data.id) { - adventureToEdit = data as Adventure; - isDetails = false; - addToast('success', 'Adventure updated'); + console.log(adventure); + if (adventure.id === '') { + let res = await fetch('/api/adventures', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(adventure) + }); + let data = await res.json(); + if (data.id) { + adventure = data as Adventure; + isDetails = false; + addToast('success', 'Adventure created'); + } else { + addToast('error', 'Failed to create adventure'); + } } else { - addToast('error', 'Failed to update adventure'); + let res = await fetch(`/api/adventures/${adventure.id}`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(adventure) + }); + let data = await res.json(); + if (data.id) { + adventure = data as Adventure; + isDetails = false; + addToast('success', 'Adventure updated'); + } else { + addToast('error', 'Failed to update adventure'); + } } } @@ -268,8 +315,8 @@ @@ -321,7 +368,7 @@ name="date" min={startDate || ''} max={endDate || ''} - bind:value={adventureToEdit.date} + bind:value={adventure.date} class="input input-bordered w-full" /> @@ -333,7 +380,7 @@ type="text" id="link" name="link" - bind:value={adventureToEdit.link} + bind:value={adventure.link} class="input input-bordered w-full" /> @@ -343,7 +390,7 @@ @@ -354,10 +401,10 @@ id="activity_types" name="activity_types" hidden - bind:value={adventureToEdit.activity_types} + bind:value={adventure.activity_types} class="input input-bordered w-full" /> - +
@@ -451,7 +498,7 @@ type="text" id="location" name="location" - bind:value={adventureToEdit.location} + bind:value={adventure.location} class="input input-bordered w-full" /> @@ -518,18 +565,18 @@ it would also work to just use on:click on the MapLibre component itself. --> - {#if adventureToEdit.is_public} + {#if adventure.is_public}

Share this Adventure!

- {window.location.origin}/adventures/{adventureToEdit.id} + {window.location.origin}/adventures/{adventure.id}

diff --git a/frontend/src/lib/components/NewAdventure.svelte b/frontend/src/lib/components/NewAdventure.svelte deleted file mode 100644 index b6b1d15..0000000 --- a/frontend/src/lib/components/NewAdventure.svelte +++ /dev/null @@ -1,610 +0,0 @@ - - - - - - - - diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts index 07c829e..2a299dd 100644 --- a/frontend/src/lib/types.ts +++ b/frontend/src/lib/types.ts @@ -11,7 +11,7 @@ export type User = { export type Adventure = { id: string; - user_id: number; + user_id: number | null; type: string; name: string; location?: string | null; diff --git a/frontend/src/routes/adventures/+page.svelte b/frontend/src/routes/adventures/+page.svelte index 5882cc5..7c92963 100644 --- a/frontend/src/routes/adventures/+page.svelte +++ b/frontend/src/routes/adventures/+page.svelte @@ -3,8 +3,7 @@ import { goto } from '$app/navigation'; import { page } from '$app/stores'; import AdventureCard from '$lib/components/AdventureCard.svelte'; - import EditAdventure from '$lib/components/EditAdventure.svelte'; - import NewAdventure from '$lib/components/NewAdventure.svelte'; + import AdventureModal from '$lib/components/AdventureModal.svelte'; import NotFound from '$lib/components/NotFound.svelte'; import type { Adventure } from '$lib/types'; @@ -95,31 +94,31 @@ } } - let adventureToEdit: Adventure; - let isEditModalOpen: boolean = false; + let adventureToEdit: Adventure | null = null; + let isAdventureModalOpen: boolean = false; function deleteAdventure(event: CustomEvent) { adventures = adventures.filter((adventure) => adventure.id !== event.detail); } - function createAdventure(event: CustomEvent) { - adventures = [event.detail, ...adventures]; - isShowingCreateModal = false; + // function that save changes to an existing adventure or creates a new one if it doesn't exist + function saveOrCreate(event: CustomEvent) { + if (adventures.find((adventure) => adventure.id === event.detail.id)) { + adventures = adventures.map((adventure) => { + if (adventure.id === event.detail.id) { + return event.detail; + } + return adventure; + }); + } else { + adventures = [event.detail, ...adventures]; + } + isAdventureModalOpen = false; } function editAdventure(event: CustomEvent) { adventureToEdit = event.detail; - isEditModalOpen = true; - } - - function saveEdit(event: CustomEvent) { - adventures = adventures.map((adventure) => { - if (adventure.id === event.detail.id) { - return event.detail; - } - return adventure; - }); - isEditModalOpen = false; + isAdventureModalOpen = true; } let sidebarOpen = false; @@ -129,19 +128,11 @@ } -{#if isShowingCreateModal} - (isShowingCreateModal = false)} - /> -{/if} - -{#if isEditModalOpen} - (isEditModalOpen = false)} - on:saveEdit={saveEdit} + on:close={() => (isAdventureModalOpen = false)} + on:save={saveOrCreate} /> {/if} @@ -160,21 +151,14 @@ - +