1
0
Fork 0
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:
Sean Morley 2025-08-06 20:17:17 -04:00
parent 2da568dcc1
commit b7b7f9d26d
6 changed files with 107 additions and 65 deletions

View file

@ -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>

View file

@ -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>

View file

@ -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;
}}
>

View file

@ -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}

View file

@ -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}

View file

@ -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}