mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-08-07 22:25:19 +02:00
feat: integrate NewLocationModal across various components; update location handling and state management
This commit is contained in:
parent
2da568dcc1
commit
b7b7f9d26d
6 changed files with 107 additions and 65 deletions
|
@ -1,13 +1,16 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import type { Location, User } from '$lib/types';
|
||||
import type { Collection, Location, User } from '$lib/types';
|
||||
import { addToast } from '$lib/toasts';
|
||||
import { t } from 'svelte-i18n';
|
||||
import LocationQuickStart from './locations/LocationQuickStart.svelte';
|
||||
import LocationDetails from './locations/LocationDetails.svelte';
|
||||
import LocationMedia from './locations/LocationMedia.svelte';
|
||||
import LocationVisits from './locations/LocationVisits.svelte';
|
||||
|
||||
export let user: User | null = null;
|
||||
export let collection: Collection | null = null;
|
||||
export let initialLatLng: { lat: number; lng: number } | null = null; // Used to pass the location from the map selection to the modal
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
|
@ -96,6 +99,12 @@
|
|||
steps[0].selected = false;
|
||||
steps[1].selected = true;
|
||||
}
|
||||
if (initialLatLng) {
|
||||
location.latitude = initialLatLng.lat;
|
||||
location.longitude = initialLatLng.lng;
|
||||
steps[1].selected = true;
|
||||
steps[0].selected = false;
|
||||
}
|
||||
});
|
||||
|
||||
function close() {
|
||||
|
@ -296,6 +305,7 @@
|
|||
}}
|
||||
on:close={() => close()}
|
||||
measurementSystem={user?.measurement_system || 'metric'}
|
||||
{collection}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { MapLibre, Marker, MapEvents } from 'svelte-maplibre';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { number, t } from 'svelte-i18n';
|
||||
import { getBasemapUrl } from '$lib';
|
||||
import CategoryDropdown from '../CategoryDropdown.svelte';
|
||||
import type { Collection, Location } from '$lib/types';
|
||||
|
@ -210,6 +210,7 @@
|
|||
|
||||
async function performDetailedReverseGeocode(lat: number, lng: number) {
|
||||
try {
|
||||
console.log('Performing detailed reverse geocoding for:', lat, lng);
|
||||
const response = await fetch(
|
||||
`/api/reverse-geocode/reverse_geocode/?lat=${lat}&lon=${lng}&format=json`
|
||||
);
|
||||
|
@ -349,6 +350,33 @@
|
|||
dispatch('back');
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
if (initialLocation.latitude && initialLocation.longitude) {
|
||||
selectedMarker = {
|
||||
lng: initialLocation.longitude,
|
||||
lat: initialLocation.latitude
|
||||
};
|
||||
location.latitude = initialLocation.latitude;
|
||||
location.longitude = initialLocation.longitude;
|
||||
mapCenter = [initialLocation.longitude, initialLocation.latitude];
|
||||
mapZoom = 14;
|
||||
selectedLocation = {
|
||||
name: initialLocation.name || '',
|
||||
lat: initialLocation.latitude,
|
||||
lng: initialLocation.longitude,
|
||||
location: initialLocation.location || '',
|
||||
type: 'point',
|
||||
category: initialLocation.category || null
|
||||
};
|
||||
selectedMarker = {
|
||||
lng: Number(initialLocation.longitude),
|
||||
lat: Number(initialLocation.latitude)
|
||||
};
|
||||
// trigger reverse geocoding to populate location data
|
||||
await performDetailedReverseGeocode(initialLocation.latitude, initialLocation.longitude);
|
||||
}
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
if (initialLocation && typeof initialLocation === 'object') {
|
||||
// Only update location properties if they don't already have values
|
||||
|
@ -366,17 +394,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
if (initialLocation.latitude && initialLocation.longitude) {
|
||||
selectedMarker = {
|
||||
lng: initialLocation.longitude,
|
||||
lat: initialLocation.latitude
|
||||
};
|
||||
location.latitude = initialLocation.latitude;
|
||||
location.longitude = initialLocation.longitude;
|
||||
mapCenter = [initialLocation.longitude, initialLocation.latitude];
|
||||
mapZoom = 14;
|
||||
}
|
||||
|
||||
if (initialLocation.tags && Array.isArray(initialLocation.tags)) {
|
||||
location.tags = initialLocation.tags;
|
||||
}
|
||||
|
@ -397,7 +414,7 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<div class="min-h-screen bg-gradient-to-br from-base-200/30 via-base-100 to-primary/5 pl-6 pr-6">
|
||||
<div class="min-h-screen bg-gradient-to-br from-base-200/30 via-base-100 to-primary/5 p-6">
|
||||
<div class="max-w-full mx-auto space-y-6">
|
||||
<!-- Basic Information Section -->
|
||||
<div class="card bg-base-100 border border-base-300 shadow-lg">
|
||||
|
@ -454,7 +471,7 @@
|
|||
|
||||
<!-- Rating Field -->
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<label class="label" for="rating">
|
||||
<span class="label-text font-medium">Rating</span>
|
||||
</label>
|
||||
<div
|
||||
|
@ -464,6 +481,7 @@
|
|||
<input
|
||||
type="radio"
|
||||
name="rating"
|
||||
id="rating"
|
||||
class="rating-hidden"
|
||||
checked={Number.isNaN(location.rating)}
|
||||
/>
|
||||
|
@ -615,7 +633,7 @@
|
|||
|
||||
<!-- Search Input -->
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<label class="label" for="search-location">
|
||||
<span class="label-text font-medium">Search Location</span>
|
||||
</label>
|
||||
<div class="relative">
|
||||
|
@ -624,6 +642,7 @@
|
|||
</div>
|
||||
<input
|
||||
type="text"
|
||||
id="search-location"
|
||||
bind:value={searchQuery}
|
||||
on:input={handleSearchInput}
|
||||
placeholder="Enter city, location, or landmark..."
|
||||
|
@ -649,9 +668,9 @@
|
|||
</div>
|
||||
{:else if searchResults.length > 0}
|
||||
<div class="space-y-2">
|
||||
<label class="label">
|
||||
<div class="label">
|
||||
<span class="label-text text-sm font-medium">Search Results</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="max-h-48 overflow-y-auto space-y-1">
|
||||
{#each searchResults as result}
|
||||
<button
|
||||
|
@ -732,9 +751,9 @@
|
|||
<!-- Map -->
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="label">
|
||||
<div class="label">
|
||||
<span class="label-text font-medium">Interactive Map</span>
|
||||
</label>
|
||||
</div>
|
||||
{#if isReverseGeocoding}
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="loading loading-spinner loading-sm"></span>
|
||||
|
|
|
@ -39,13 +39,13 @@
|
|||
|
||||
import ChecklistCard from '$lib/components/ChecklistCard.svelte';
|
||||
import ChecklistModal from '$lib/components/ChecklistModal.svelte';
|
||||
import LocationModal from '$lib/components/LocationModal.svelte';
|
||||
import TransportationModal from '$lib/components/TransportationModal.svelte';
|
||||
import CardCarousel from '$lib/components/CardCarousel.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import LodgingModal from '$lib/components/LodgingModal.svelte';
|
||||
import LodgingCard from '$lib/components/LodgingCard.svelte';
|
||||
import CollectionAllView from '$lib/components/CollectionAllView.svelte';
|
||||
import NewLocationModal from '$lib/components/NewLocationModal.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
console.log(data);
|
||||
|
@ -530,7 +530,24 @@
|
|||
let noteToEdit: Note | null;
|
||||
let checklistToEdit: Checklist | null;
|
||||
|
||||
let newType: string;
|
||||
let locationBeingUpdated: Location | undefined = undefined;
|
||||
|
||||
// Sync the locationBeingUpdated with the adventures array
|
||||
$: {
|
||||
if (locationBeingUpdated && locationBeingUpdated.id) {
|
||||
const index = adventures.findIndex((adventure) => adventure.id === locationBeingUpdated?.id);
|
||||
|
||||
if (index !== -1) {
|
||||
adventures[index] = { ...locationBeingUpdated };
|
||||
adventures = adventures; // Trigger reactivity
|
||||
} else {
|
||||
adventures = [{ ...locationBeingUpdated }, ...adventures];
|
||||
if (data.props.adventure) {
|
||||
data.props.adventure.locations = adventures; // Update data.props.adventure.locations as well
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function editAdventure(event: CustomEvent<Location>) {
|
||||
adventureToEdit = event.detail;
|
||||
|
@ -690,12 +707,13 @@
|
|||
{/if}
|
||||
|
||||
{#if isLocationModalOpen}
|
||||
<LocationModal
|
||||
locationToEdit={adventureToEdit}
|
||||
<NewLocationModal
|
||||
on:close={() => (isLocationModalOpen = false)}
|
||||
on:save={saveOrCreateAdventure}
|
||||
{collection}
|
||||
user={data.user}
|
||||
locationToEdit={adventureToEdit}
|
||||
bind:location={locationBeingUpdated}
|
||||
{collection}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
@ -790,7 +808,6 @@
|
|||
// Reset the transportation object for creating a new one
|
||||
transportationToEdit = null;
|
||||
isShowingTransportationModal = true;
|
||||
newType = '';
|
||||
}}
|
||||
>
|
||||
{$t('adventures.transportation')}</button
|
||||
|
@ -799,7 +816,7 @@
|
|||
class="btn btn-primary"
|
||||
on:click={() => {
|
||||
isNoteModalOpen = true;
|
||||
newType = '';
|
||||
|
||||
noteToEdit = null;
|
||||
}}
|
||||
>
|
||||
|
@ -809,7 +826,7 @@
|
|||
class="btn btn-primary"
|
||||
on:click={() => {
|
||||
isShowingChecklistModal = true;
|
||||
newType = '';
|
||||
|
||||
checklistToEdit = null;
|
||||
}}
|
||||
>
|
||||
|
@ -819,7 +836,7 @@
|
|||
class="btn btn-primary"
|
||||
on:click={() => {
|
||||
isShowingLodgingModal = true;
|
||||
newType = '';
|
||||
|
||||
lodgingToEdit = null;
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
<script lang="ts">
|
||||
import { enhance, deserialize } from '$app/forms';
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import LocationCard from '$lib/components/LocationCard.svelte';
|
||||
import LocationModal from '$lib/components/LocationModal.svelte';
|
||||
import CategoryFilterDropdown from '$lib/components/CategoryFilterDropdown.svelte';
|
||||
import CategoryModal from '$lib/components/CategoryModal.svelte';
|
||||
import NotFound from '$lib/components/NotFound.svelte';
|
||||
import type { Location, Category } from '$lib/types';
|
||||
import type { Location } from '$lib/types';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
import Plus from '~icons/mdi/plus';
|
||||
|
@ -15,9 +12,7 @@
|
|||
import Sort from '~icons/mdi/sort';
|
||||
import MapMarker from '~icons/mdi/map-marker';
|
||||
import Eye from '~icons/mdi/eye';
|
||||
import EyeOff from '~icons/mdi/eye-off';
|
||||
import Calendar from '~icons/mdi/calendar';
|
||||
import Star from '~icons/mdi/star';
|
||||
import Tag from '~icons/mdi/tag';
|
||||
import Compass from '~icons/mdi/compass';
|
||||
import NewLocationModal from '$lib/components/NewLocationModal.svelte';
|
||||
|
@ -40,10 +35,14 @@
|
|||
// Sync the locationBeingUpdated with the adventures array
|
||||
$: {
|
||||
if (locationBeingUpdated && locationBeingUpdated.id) {
|
||||
const index = adventures.findIndex((adventure) => adventure.id === locationBeingUpdated!.id);
|
||||
const index = adventures.findIndex((adventure) => adventure.id === locationBeingUpdated?.id);
|
||||
|
||||
if (index !== -1) {
|
||||
adventures[index] = { ...locationBeingUpdated };
|
||||
adventures = adventures; // Trigger reactivity
|
||||
} else {
|
||||
adventures = [{ ...locationBeingUpdated }, ...adventures];
|
||||
data.props.adventures = adventures; // Update data.props.adventures as well
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,19 +143,6 @@
|
|||
adventures = adventures.filter((adventure) => adventure.id !== event.detail);
|
||||
}
|
||||
|
||||
function saveOrCreate(event: CustomEvent<Location>) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
function editAdventure(event: CustomEvent<Location>) {
|
||||
adventureToEdit = event.detail;
|
||||
isLocationModalOpen = true;
|
||||
|
@ -181,15 +167,8 @@
|
|||
</svelte:head>
|
||||
|
||||
{#if isLocationModalOpen}
|
||||
<!-- <LocationModal
|
||||
locationToEdit={adventureToEdit}
|
||||
on:close={() => (isLocationModalOpen = false)}
|
||||
on:save={saveOrCreate}
|
||||
user={data.user}
|
||||
/> -->
|
||||
<NewLocationModal
|
||||
on:close={() => (isLocationModalOpen = false)}
|
||||
on:save={saveOrCreate}
|
||||
user={data.user}
|
||||
locationToEdit={adventureToEdit}
|
||||
bind:location={locationBeingUpdated}
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
import LightbulbOn from '~icons/mdi/lightbulb-on';
|
||||
import WeatherSunset from '~icons/mdi/weather-sunset';
|
||||
import ClipboardList from '~icons/mdi/clipboard-list';
|
||||
import LocationModal from '$lib/components/LocationModal.svelte';
|
||||
import ImageDisplayModal from '$lib/components/ImageDisplayModal.svelte';
|
||||
import AttachmentCard from '$lib/components/AttachmentCard.svelte';
|
||||
import { getBasemapUrl, isAllDay } from '$lib';
|
||||
import ActivityCard from '$lib/components/ActivityCard.svelte';
|
||||
import TrailCard from '$lib/components/TrailCard.svelte';
|
||||
import NewLocationModal from '$lib/components/NewLocationModal.svelte';
|
||||
|
||||
let geojson: any;
|
||||
|
||||
|
@ -241,11 +241,11 @@
|
|||
{/if}
|
||||
|
||||
{#if isEditModalOpen}
|
||||
<LocationModal
|
||||
locationToEdit={adventure}
|
||||
<NewLocationModal
|
||||
on:close={() => (isEditModalOpen = false)}
|
||||
on:save={saveEdit}
|
||||
user={data.user}
|
||||
locationToEdit={adventure}
|
||||
bind:location={adventure}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script lang="ts">
|
||||
import LocationModal from '$lib/components/LocationModal.svelte';
|
||||
import { DefaultMarker, MapEvents, MapLibre, Popup, Marker } from 'svelte-maplibre';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { Location, VisitedRegion } from '$lib/types.js';
|
||||
|
@ -13,11 +12,10 @@
|
|||
import Plus from '~icons/mdi/plus';
|
||||
import Clear from '~icons/mdi/close';
|
||||
import Eye from '~icons/mdi/eye';
|
||||
import EyeOff from '~icons/mdi/eye-off';
|
||||
import Pin from '~icons/mdi/map-marker';
|
||||
import Calendar from '~icons/mdi/calendar';
|
||||
import Category from '~icons/mdi/shape';
|
||||
import LocationIcon from '~icons/mdi/crosshairs-gps';
|
||||
import NewLocationModal from '$lib/components/NewLocationModal.svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
|
@ -39,7 +37,6 @@
|
|||
let newLongitude: number | null = null;
|
||||
let newLatitude: number | null = null;
|
||||
|
||||
let openPopupId: string | null = null;
|
||||
let isPopupOpen = false;
|
||||
|
||||
// Statistics
|
||||
|
@ -68,6 +65,25 @@
|
|||
}
|
||||
}
|
||||
|
||||
let locationBeingUpdated: Location | undefined = undefined;
|
||||
|
||||
// Sync the locationBeingUpdated with the adventures array
|
||||
$: {
|
||||
if (locationBeingUpdated && locationBeingUpdated.id) {
|
||||
const index = adventures.findIndex((adventure) => adventure.id === locationBeingUpdated?.id);
|
||||
|
||||
if (index !== -1) {
|
||||
adventures[index] = { ...locationBeingUpdated };
|
||||
adventures = adventures; // Trigger reactivity
|
||||
} else {
|
||||
adventures = [{ ...locationBeingUpdated }, ...adventures];
|
||||
if (data.props.adventures) {
|
||||
data.props.adventures = adventures; // Update data.props.adventure.locations as well
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addMarker(e: { detail: { lngLat: { lng: any; lat: any } } }) {
|
||||
newMarker = null;
|
||||
newMarker = { lngLat: e.detail.lngLat };
|
||||
|
@ -461,11 +477,12 @@
|
|||
</div>
|
||||
|
||||
{#if createModalOpen}
|
||||
<LocationModal
|
||||
<NewLocationModal
|
||||
on:close={() => (createModalOpen = false)}
|
||||
on:save={createNewAdventure}
|
||||
{initialLatLng}
|
||||
user={data.user}
|
||||
bind:location={locationBeingUpdated}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue