diff --git a/backend/server/adventures/views/location_view.py b/backend/server/adventures/views/location_view.py index e8c6fa67..85ca04b4 100644 --- a/backend/server/adventures/views/location_view.py +++ b/backend/server/adventures/views/location_view.py @@ -1,5 +1,4 @@ import logging -from urllib.parse import urlparse from django.utils import timezone from django.db import transaction from django.core.exceptions import PermissionDenied @@ -15,9 +14,22 @@ from django.contrib.contenttypes.models import ContentType from adventures.permissions import IsOwnerOrSharedWithFullAccess from adventures.serializers import LocationSerializer, MapPinSerializer, CalendarLocationSerializer from adventures.utils import pagination -from adventures.geocoding import get_place_details, reverse_geocode +from adventures.geocoding import reverse_geocode from worldtravel.models import City, Country, Region from .location_image_view import import_remote_images_for_object +from .quick_add_utils import ( + build_quick_add_description, + clean_url, + coerce_bool, + coerce_coordinate, + coerce_float, + coerce_int, + extract_google_place_details, + preferred_link, + resolve_quick_add_collection, + sanitize_photo_urls, + sanitize_tags, +) logger = logging.getLogger(__name__) @@ -172,8 +184,8 @@ class LocationViewSet(viewsets.ModelViewSet): if not name: return Response({"error": "name is required"}, status=status.HTTP_400_BAD_REQUEST) - latitude = self._coerce_coordinate(payload.get('latitude'), -90, 90) - longitude = self._coerce_coordinate(payload.get('longitude'), -180, 180) + latitude = coerce_coordinate(payload.get('latitude'), -90, 90) + longitude = coerce_coordinate(payload.get('longitude'), -180, 180) if latitude is None or longitude is None: return Response( {"error": "Valid latitude and longitude are required"}, @@ -184,9 +196,8 @@ class LocationViewSet(viewsets.ModelViewSet): if isinstance(collection, Response): return collection - place_id = str(payload.get('place_id') or '').strip() or None reverse_data = {} - details = {} + _, details = extract_google_place_details(payload, fallback_query=name) try: reverse_result = reverse_geocode(latitude, longitude, request.user) @@ -195,25 +206,15 @@ class LocationViewSet(viewsets.ModelViewSet): except Exception: reverse_data = {} - if place_id: - details_result = get_place_details(place_id, fallback_query=name) - if isinstance(details_result, dict): - if 'error' not in details_result or details_result.get('description'): - details = details_result - - rating = self._coerce_float(payload.get('rating')) + rating = coerce_float(payload.get('rating')) if rating is None: - rating = self._coerce_float(details.get('rating')) + rating = coerce_float(details.get('rating')) - review_count = self._coerce_int(payload.get('review_count')) + review_count = coerce_int(payload.get('review_count')) if review_count is None: - review_count = self._coerce_int(details.get('review_count')) + review_count = coerce_int(details.get('review_count')) - website = self._clean_url(details.get('website')) or self._clean_url(payload.get('website')) - maps_url = self._clean_url(details.get('google_maps_url')) or self._clean_url( - payload.get('google_maps_url') - ) - link = self._clean_url(payload.get('link')) or website or maps_url + link = preferred_link(payload, details) phone_number = str(details.get('phone_number') or payload.get('phone_number') or '').strip() or None @@ -224,7 +225,7 @@ class LocationViewSet(viewsets.ModelViewSet): or None ) - description = self._build_quick_add_description( + description = build_quick_add_description( base_description=payload.get('description'), detailed_description=details.get('description'), ) @@ -241,8 +242,8 @@ class LocationViewSet(viewsets.ModelViewSet): 'rating': rating, 'description': description, 'link': link, - 'tags': self._sanitize_tags(payload.get('types') or payload.get('tags')), - 'is_public': self._coerce_bool(payload.get('is_public'), default=False), + 'tags': sanitize_tags(payload.get('types') or payload.get('tags')), + 'is_public': coerce_bool(payload.get('is_public'), default=False), } if category_payload: @@ -258,7 +259,7 @@ class LocationViewSet(viewsets.ModelViewSet): location = serializer.instance self._apply_reverse_geocode_metadata(location, reverse_data, location_label) - photo_urls = self._sanitize_photo_urls(payload.get('photos')) + photo_urls = sanitize_photo_urls(payload.get('photos')) image_import_summary = None if photo_urls: image_import_summary = import_remote_images_for_object( @@ -581,108 +582,34 @@ class LocationViewSet(viewsets.ModelViewSet): ) def _resolve_quick_add_collection(self, collection_id): - if not collection_id: - return None - - try: - collection = Collection.objects.get(id=collection_id) - except Collection.DoesNotExist: - return Response( - {"error": "Collection not found."}, - status=status.HTTP_404_NOT_FOUND, - ) - - try: - self._validate_collection_permissions([collection]) - except PermissionDenied: - return Response( - {"error": "You do not have permission to add this location to the selected collection."}, - status=status.HTTP_403_FORBIDDEN, - ) - - return collection + return resolve_quick_add_collection( + collection_id, + validate_permissions=self._validate_collection_permissions, + permission_error_message=( + "You do not have permission to add this location to the selected collection." + ), + ) def _coerce_coordinate(self, value, min_value, max_value): - try: - number = round(float(value), 6) - except (TypeError, ValueError): - return None - - if number < min_value or number > max_value: - return None - - return number + return coerce_coordinate(value, min_value, max_value) def _coerce_float(self, value): - try: - return float(value) - except (TypeError, ValueError): - return None + return coerce_float(value) def _coerce_int(self, value): - try: - return int(value) - except (TypeError, ValueError): - return None + return coerce_int(value) def _coerce_bool(self, value, default=False): - if isinstance(value, bool): - return value - if isinstance(value, str): - normalized = value.strip().lower() - if normalized in {'true', '1', 'yes', 'on'}: - return True - if normalized in {'false', '0', 'no', 'off'}: - return False - return default + return coerce_bool(value, default=default) def _clean_url(self, value): - if not isinstance(value, str): - return None - - normalized = value.strip() - if not normalized: - return None - - parsed = urlparse(normalized) - if parsed.scheme in {'http', 'https'} and parsed.netloc: - return normalized - - return None + return clean_url(value) def _sanitize_tags(self, raw_tags): - if not isinstance(raw_tags, list): - return [] - - tags = [] - for item in raw_tags: - if not isinstance(item, str): - continue - - value = item.strip() - if not value or value in tags: - continue - - tags.append(value) - if len(tags) >= 8: - break - - return tags + return sanitize_tags(raw_tags) def _sanitize_photo_urls(self, raw_urls): - if not isinstance(raw_urls, list): - return [] - - cleaned = [] - for value in raw_urls: - url = self._clean_url(value) - if not url or url in cleaned: - continue - cleaned.append(url) - if len(cleaned) >= 5: - break - - return cleaned + return sanitize_photo_urls(raw_urls) def _normalize_quick_add_category(self, raw_category): if not raw_category: @@ -734,9 +661,7 @@ class LocationViewSet(viewsets.ModelViewSet): base_description, detailed_description, ): - description = str(detailed_description or '').strip() or str(base_description or '').strip() - - return description or None + return build_quick_add_description(base_description, detailed_description) def _apply_reverse_geocode_metadata(self, location, reverse_data, fallback_location): if not isinstance(reverse_data, dict): diff --git a/backend/server/adventures/views/lodging_view.py b/backend/server/adventures/views/lodging_view.py index 159c127a..c2ec8f36 100644 --- a/backend/server/adventures/views/lodging_view.py +++ b/backend/server/adventures/views/lodging_view.py @@ -1,12 +1,25 @@ from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response +from django.db import transaction from django.db.models import Q from adventures.models import Lodging from adventures.serializers import LodgingSerializer from rest_framework.exceptions import PermissionDenied from adventures.permissions import IsOwnerOrSharedWithFullAccess -from rest_framework.permissions import IsAuthenticated +from adventures.geocoding import reverse_geocode +from .location_image_view import import_remote_images_for_object +from .quick_add_utils import ( + build_quick_add_description, + coerce_bool, + coerce_coordinate, + coerce_float, + extract_google_place_details, + infer_lodging_type, + preferred_link, + resolve_quick_add_collection, + sanitize_photo_urls, +) class LodgingViewSet(viewsets.ModelViewSet): queryset = Lodging.objects.all() @@ -63,6 +76,103 @@ class LodgingViewSet(viewsets.ModelViewSet): def perform_update(self, serializer): serializer.save() + + @action(detail=False, methods=['post'], url_path='quick-add') + @transaction.atomic + def quick_add(self, request): + """Create a lodging from lightweight map/place input in one server-side call.""" + payload = request.data if isinstance(request.data, dict) else {} + + name = str(payload.get('name') or '').strip() + if not name: + return Response({"error": "name is required"}, status=status.HTTP_400_BAD_REQUEST) + + latitude = coerce_coordinate(payload.get('latitude'), -90, 90) + longitude = coerce_coordinate(payload.get('longitude'), -180, 180) + if latitude is None or longitude is None: + return Response( + {"error": "Valid latitude and longitude are required"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + collection = resolve_quick_add_collection( + payload.get('collection_id'), + validate_permissions=self._validate_collection_permissions, + permission_error_message=( + "You do not have permission to add this lodging to the selected collection." + ), + ) + if isinstance(collection, Response): + return collection + + reverse_data = {} + try: + reverse_result = reverse_geocode(latitude, longitude, request.user) + if isinstance(reverse_result, dict) and 'error' not in reverse_result: + reverse_data = reverse_result + except Exception: + reverse_data = {} + + _, details = extract_google_place_details(payload, fallback_query=name) + + rating = coerce_float(payload.get('rating')) + if rating is None: + rating = coerce_float(details.get('rating')) + + location_label = ( + str(payload.get('location') or '').strip() + or str(reverse_data.get('display_name') or '').strip() + or str(details.get('formatted_address') or '').strip() + or None + ) + + place_types = payload.get('types') + if not isinstance(place_types, list) or not place_types: + place_types = details.get('types') if isinstance(details.get('types'), list) else [] + + serializer_payload = { + 'name': name, + 'type': infer_lodging_type(payload.get('type'), place_types), + 'location': location_label, + 'latitude': latitude, + 'longitude': longitude, + 'rating': rating, + 'description': build_quick_add_description( + base_description=payload.get('description'), + detailed_description=details.get('description'), + ), + 'link': preferred_link(payload, details), + 'is_public': coerce_bool(payload.get('is_public'), default=False), + } + + if collection: + serializer_payload['collection'] = str(collection.id) + + serializer = self.get_serializer(data=serializer_payload) + serializer.is_valid(raise_exception=True) + self.perform_create(serializer) + + lodging = serializer.instance + + photo_urls = sanitize_photo_urls(payload.get('photos')) + image_import_summary = None + if photo_urls: + image_import_summary = import_remote_images_for_object( + lodging, + photo_urls, + owner=lodging.user, + max_workers=min(5, len(photo_urls)), + ) + + response_data = self.get_serializer(lodging).data + if image_import_summary and image_import_summary.get('failed'): + response_data['quick_add_image_import'] = { + 'created_count': image_import_summary['created_count'], + 'failed_count': image_import_summary['failed_count'], + 'failed': image_import_summary['failed'], + } + + return Response(response_data, status=status.HTTP_201_CREATED) # when creating an adventure, make sure the user is the owner of the collection or shared with the collection def perform_create(self, serializer): @@ -81,4 +191,13 @@ class LodgingViewSet(viewsets.ModelViewSet): return # Save the adventure with the current user as the owner - serializer.save(user=self.request.user) \ No newline at end of file + serializer.save(user=self.request.user) + + def _validate_collection_permissions(self, collections): + """Validate permissions for all collections (used by quick add).""" + for collection in collections: + if collection.user != self.request.user: + if not collection.shared_with.filter(id=self.request.user.id).exists(): + raise PermissionDenied( + f"You don't have permission to add lodging to collection '{collection.name}'" + ) \ No newline at end of file diff --git a/backend/server/adventures/views/quick_add_utils.py b/backend/server/adventures/views/quick_add_utils.py new file mode 100644 index 00000000..a7195704 --- /dev/null +++ b/backend/server/adventures/views/quick_add_utils.py @@ -0,0 +1,202 @@ +from urllib.parse import urlparse + +from django.core.exceptions import PermissionDenied as DjangoPermissionDenied +from rest_framework import status +from rest_framework.exceptions import PermissionDenied as DRFPermissionDenied +from rest_framework.response import Response + +from adventures.geocoding import get_place_details +from adventures.models import Collection + + +def coerce_coordinate(value, min_value, max_value): + try: + number = round(float(value), 6) + except (TypeError, ValueError): + return None + + if number < min_value or number > max_value: + return None + + return number + + +def coerce_float(value): + try: + return float(value) + except (TypeError, ValueError): + return None + + +def coerce_int(value): + try: + return int(value) + except (TypeError, ValueError): + return None + + +def coerce_bool(value, default=False): + if isinstance(value, bool): + return value + + if isinstance(value, str): + normalized = value.strip().lower() + if normalized in {"true", "1", "yes", "on"}: + return True + if normalized in {"false", "0", "no", "off"}: + return False + + return default + + +def clean_url(value): + if not isinstance(value, str): + return None + + normalized = value.strip() + if not normalized: + return None + + parsed = urlparse(normalized) + if parsed.scheme in {"http", "https"} and parsed.netloc: + return normalized + + return None + + +def sanitize_tags(raw_tags, max_tags=8): + if not isinstance(raw_tags, list): + return [] + + tags = [] + for item in raw_tags: + if not isinstance(item, str): + continue + + value = item.strip() + if not value or value in tags: + continue + + tags.append(value) + if len(tags) >= max_tags: + break + + return tags + + +def sanitize_photo_urls(raw_urls, max_urls=5): + if not isinstance(raw_urls, list): + return [] + + cleaned = [] + for value in raw_urls: + url = clean_url(value) + if not url or url in cleaned: + continue + + cleaned.append(url) + if len(cleaned) >= max_urls: + break + + return cleaned + + +def build_quick_add_description(base_description, detailed_description): + description = str(detailed_description or "").strip() or str(base_description or "").strip() + return description or None + + +def resolve_quick_add_collection(collection_id, validate_permissions, permission_error_message): + if not collection_id: + return None + + try: + collection = Collection.objects.get(id=collection_id) + except Collection.DoesNotExist: + return Response( + {"error": "Collection not found."}, + status=status.HTTP_404_NOT_FOUND, + ) + + try: + validate_permissions([collection]) + except (DjangoPermissionDenied, DRFPermissionDenied): + return Response( + {"error": permission_error_message}, + status=status.HTTP_403_FORBIDDEN, + ) + + return collection + + +def extract_google_place_details(payload, fallback_query=""): + place_id = str(payload.get("place_id") or "").strip() or None + details = {} + + if not place_id: + return place_id, details + + details_result = get_place_details(place_id, fallback_query=fallback_query) + if isinstance(details_result, dict): + if "error" not in details_result or details_result.get("description"): + details = details_result + + return place_id, details + + +def preferred_link(payload, details): + website = clean_url(details.get("website")) or clean_url(payload.get("website")) + maps_url = clean_url(details.get("google_maps_url")) or clean_url(payload.get("google_maps_url")) + return clean_url(payload.get("link")) or website or maps_url + + +def infer_lodging_type(primary_type, place_types): + valid_types = { + "hotel", + "hostel", + "resort", + "bnb", + "campground", + "cabin", + "apartment", + "house", + "villa", + "motel", + "other", + } + + if isinstance(primary_type, str): + normalized = primary_type.strip().lower() + if normalized in valid_types: + return normalized + + normalized_types = [ + str(type_name).strip().lower() + for type_name in (place_types or []) + if str(type_name).strip() + ] + + mapping = { + "hotel": "hotel", + "resort_hotel": "resort", + "motel": "motel", + "hostel": "hostel", + "bed_and_breakfast": "bnb", + "guest_house": "bnb", + "campground": "campground", + "rv_park": "campground", + "camping_cabin": "cabin", + "apartment_building": "apartment", + "lodging": "hotel", + "villa": "villa", + } + + for type_name in normalized_types: + if type_name in mapping: + return mapping[type_name] + + for type_name in normalized_types: + if type_name in valid_types: + return type_name + + return "other" diff --git a/frontend/package.json b/frontend/package.json index a54c7b95..537caf02 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,7 +20,7 @@ "@sveltejs/adapter-node": "^5.2.12", "@sveltejs/adapter-vercel": "^5.7.0", "@sveltejs/kit": "^2.49.5", - "@sveltejs/vite-plugin-svelte": "^3.1.2", + "@sveltejs/vite-plugin-svelte": "3.1.2", "@tailwindcss/typography": "^0.5.19", "@types/node": "^22.15.2", "@types/qrcode": "^1.5.5", @@ -30,7 +30,7 @@ "postcss": "^8.5.3", "prettier": "^3.5.3", "prettier-plugin-svelte": "^3.3.3", - "svelte": "^4.2.19", + "svelte": "4.2.19", "svelte-check": "^3.8.6", "tailwindcss": "^3.4.17", "tslib": "^2.8.1", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 2ba80d43..624a073d 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -11,8 +11,6 @@ overrides: brace-expansion@>=4.0.0 <5.0.5: '>=5.0.5' picomatch@<2.3.2: '>=2.3.2' picomatch@>=4.0.0 <4.0.4: '>=4.0.4' - svelte@<=5.51.4: '>=5.51.5' - svelte@<=5.53.4: '>=5.53.5' importers: @@ -20,7 +18,7 @@ importers: dependencies: '@lukulent/svelte-umami': specifier: ^0.0.3 - version: 0.0.3(svelte@5.55.1) + version: 0.0.3(svelte@4.2.19) dompurify: specifier: ^3.2.5 version: 3.3.3 @@ -44,13 +42,13 @@ importers: version: 1.5.4 svelte-dnd-action: specifier: ^0.9.68 - version: 0.9.69(svelte@5.55.1) + version: 0.9.69(svelte@4.2.19) svelte-i18n: specifier: ^4.0.1 - version: 4.0.1(svelte@5.55.1) + version: 4.0.1(svelte@4.2.19) svelte-maplibre: specifier: ^0.9.14 - version: 0.9.14(svelte@5.55.1) + version: 0.9.14(svelte@4.2.19) devDependencies: '@event-calendar/core': specifier: ^3.12.0 @@ -69,16 +67,16 @@ importers: version: 1.2.3 '@sveltejs/adapter-node': specifier: ^5.2.12 - version: 5.5.4(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)))(svelte@5.55.1)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15))) + version: 5.5.4(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)))(svelte@4.2.19)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15))) '@sveltejs/adapter-vercel': specifier: '>=6.3.2' - version: 6.3.3(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)))(svelte@5.55.1)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)))(rollup@4.59.0) + version: 6.3.3(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)))(svelte@4.2.19)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)))(rollup@4.59.0) '@sveltejs/kit': specifier: ^2.49.5 - version: 2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)))(svelte@5.55.1)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)) + version: 2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)))(svelte@4.2.19)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)) '@sveltejs/vite-plugin-svelte': - specifier: ^3.1.2 - version: 3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)) + specifier: 3.1.2 + version: 3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)) '@tailwindcss/typography': specifier: ^0.5.19 version: 0.5.19(tailwindcss@3.4.19) @@ -105,13 +103,13 @@ importers: version: 3.8.1 prettier-plugin-svelte: specifier: ^3.3.3 - version: 3.5.1(prettier@3.8.1)(svelte@5.55.1) + version: 3.5.1(prettier@3.8.1)(svelte@4.2.19) svelte: - specifier: '>=5.53.5' - version: 5.55.1 + specifier: 4.2.19 + version: 4.2.19 svelte-check: specifier: ^3.8.6 - version: 3.8.6(postcss@8.5.8)(svelte@5.55.1) + version: 3.8.6(postcss@8.5.8)(svelte@4.2.19) tailwindcss: specifier: ^3.4.17 version: 3.4.19 @@ -134,6 +132,10 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + '@antfu/install-pkg@0.4.1': resolution: {integrity: sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==} @@ -345,9 +347,6 @@ packages: '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -361,7 +360,7 @@ packages: '@lukulent/svelte-umami@0.0.3': resolution: {integrity: sha512-4pL0sJapfy14yDj6CyZgewbRDadRoBJtk/dLqCJh7/tQuX7HO4hviBzhrVa4Osxaq2kcGEKdpkhAKAoaNdlNSA==} peerDependencies: - svelte: '>=5.53.5' + svelte: ^4.0.0 '@mapbox/geojson-rewind@0.5.2': resolution: {integrity: sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==} @@ -611,7 +610,7 @@ packages: peerDependencies: '@opentelemetry/api': ^1.0.0 '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0 - svelte: '>=5.53.5' + svelte: ^4.0.0 || ^5.0.0-next.0 typescript: ^5.3.3 vite: ^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0 peerDependenciesMeta: @@ -625,14 +624,14 @@ packages: engines: {node: ^18.0.0 || >=20} peerDependencies: '@sveltejs/vite-plugin-svelte': ^3.0.0 - svelte: '>=5.53.5' + svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.0 '@sveltejs/vite-plugin-svelte@3.1.2': resolution: {integrity: sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==} engines: {node: ^18.0.0 || >=20} peerDependencies: - svelte: '>=5.53.5' + svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.0 '@tailwindcss/typography@0.5.19': @@ -682,10 +681,6 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@typescript-eslint/types@8.58.0': - resolution: {integrity: sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vercel/nft@1.5.0': resolution: {integrity: sha512-IWTDeIoWhQ7ZtRO/JRKH+jhmeQvZYhtGPmzw/QGDY+wDCQqfm25P9yIdoAFagu4fWsK4IwZXDFIjrmp5rRm/sA==} engines: {node: '>=20'} @@ -810,9 +805,8 @@ packages: cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} + code-red@1.0.4: + resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} @@ -848,6 +842,10 @@ packages: css-selector-tokenizer@0.8.0: resolution: {integrity: sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==} + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -965,12 +963,12 @@ packages: resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} engines: {node: '>=0.10'} - esrap@2.2.4: - resolution: {integrity: sha512-suICpxAmZ9A8bzJjEl/+rLJiDKC0X4gYWUxT6URAWBLvlXmtbZd5ySMu/N2ZGEtMCAmflUDPSehrP9BQcsGcSg==} - estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + event-emitter@0.3.5: resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} @@ -1218,6 +1216,9 @@ packages: engines: {node: '>= 18'} hasBin: true + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + memoizee@0.4.17: resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} engines: {node: '>=0.12'} @@ -1360,6 +1361,9 @@ packages: resolution: {integrity: sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==} hasBin: true + periscopic@3.1.0: + resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1450,7 +1454,7 @@ packages: resolution: {integrity: sha512-65+fr5+cgIKWKiqM1Doum4uX6bY8iFCdztvvp2RcF+AJoieaw9kJOFMNcJo/bkmKYsxFaM9OsVZK/gWauG/5mg==} peerDependencies: prettier: ^3.0.0 - svelte: '>=5.53.5' + svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 prettier@3.8.1: resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} @@ -1588,25 +1592,25 @@ packages: resolution: {integrity: sha512-ij0u4Lw/sOTREP13BdWZjiXD/BlHE6/e2e34XzmVmsp5IN4kVa3PWP65NM32JAgwjZlwBg/+JtiNV1MM8khu0Q==} hasBin: true peerDependencies: - svelte: '>=5.53.5' + svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 svelte-dnd-action@0.9.69: resolution: {integrity: sha512-NAmSOH7htJoYraTQvr+q5whlIuVoq88vEuHr4NcFgscDRUxfWPPxgie2OoxepBCQCikrXZV4pqV86aun60wVyw==} peerDependencies: - svelte: '>=5.53.5' + svelte: '>=3.23.0 || ^5.0.0-next.0' svelte-hmr@0.16.0: resolution: {integrity: sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==} engines: {node: ^12.20 || ^14.13.1 || >= 16} peerDependencies: - svelte: '>=5.53.5' + svelte: ^3.19.0 || ^4.0.0 svelte-i18n@4.0.1: resolution: {integrity: sha512-jaykGlGT5PUaaq04JWbJREvivlCnALtT+m87Kbm0fxyYHynkQaxQMnIKHLm2WeIuBRoljzwgyvz0Z6/CMwfdmQ==} engines: {node: '>= 16'} hasBin: true peerDependencies: - svelte: '>=5.53.5' + svelte: ^3 || ^4 || ^5 svelte-maplibre@0.9.14: resolution: {integrity: sha512-5HBvibzU/Uf3g8eEz4Hty5XAwoBhW9Tp7NQEvb80U/glR/M1IHyzUKss6XMq8Zbci2wtsASeoPc6dA5R4+0e0w==} @@ -1614,7 +1618,7 @@ packages: '@deck.gl/core': ^8.8.0 '@deck.gl/layers': ^8.8.0 '@deck.gl/mapbox': ^8.8.0 - svelte: '>=5.53.5' + svelte: ^3.54.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: '@deck.gl/core': optional: true @@ -1636,7 +1640,7 @@ packages: sass: ^1.26.8 stylus: ^0.55.0 sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0 - svelte: '>=5.53.5' + svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0' peerDependenciesMeta: '@babel/core': @@ -1660,9 +1664,9 @@ packages: typescript: optional: true - svelte@5.55.1: - resolution: {integrity: sha512-QjvU7EFemf6mRzdMGlAFttMWtAAVXrax61SZYHdkD6yoVGQ89VeyKfZD4H1JrV1WLmJBxWhFch9H6ig/87VGjw==} - engines: {node: '>=18'} + svelte@4.2.19: + resolution: {integrity: sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==} + engines: {node: '>=16'} tailwindcss@3.4.19: resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==} @@ -1846,13 +1850,15 @@ packages: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} engines: {node: '>=8'} - zimmerframe@1.1.4: - resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} - snapshots: '@alloc/quick-lru@5.2.0': {} + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@antfu/install-pkg@0.4.1': dependencies: package-manager-detector: 0.2.11 @@ -1947,22 +1953,22 @@ snapshots: '@event-calendar/core@3.12.0': dependencies: - svelte: 5.55.1 + svelte: 4.2.19 '@event-calendar/day-grid@3.12.0': dependencies: '@event-calendar/core': 3.12.0 - svelte: 5.55.1 + svelte: 4.2.19 '@event-calendar/interaction@3.12.0': dependencies: '@event-calendar/core': 3.12.0 - svelte: 5.55.1 + svelte: 4.2.19 '@event-calendar/time-grid@3.12.0': dependencies: '@event-calendar/core': 3.12.0 - svelte: 5.55.1 + svelte: 4.2.19 '@formatjs/ecma402-abstract@2.3.6': dependencies: @@ -2018,11 +2024,6 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} @@ -2032,9 +2033,9 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@lukulent/svelte-umami@0.0.3(svelte@5.55.1)': + '@lukulent/svelte-umami@0.0.3(svelte@4.2.19)': dependencies: - svelte: 5.55.1 + svelte: 4.2.19 '@mapbox/geojson-rewind@0.5.2': dependencies: @@ -2209,17 +2210,17 @@ snapshots: dependencies: acorn: 8.16.0 - '@sveltejs/adapter-node@5.5.4(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)))(svelte@5.55.1)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)))': + '@sveltejs/adapter-node@5.5.4(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)))(svelte@4.2.19)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)))': dependencies: '@rollup/plugin-commonjs': 29.0.2(rollup@4.59.0) '@rollup/plugin-json': 6.1.0(rollup@4.59.0) '@rollup/plugin-node-resolve': 16.0.3(rollup@4.59.0) - '@sveltejs/kit': 2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)))(svelte@5.55.1)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)) + '@sveltejs/kit': 2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)))(svelte@4.2.19)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)) rollup: 4.59.0 - '@sveltejs/adapter-vercel@6.3.3(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)))(svelte@5.55.1)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)))(rollup@4.59.0)': + '@sveltejs/adapter-vercel@6.3.3(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)))(svelte@4.2.19)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)))(rollup@4.59.0)': dependencies: - '@sveltejs/kit': 2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)))(svelte@5.55.1)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)) + '@sveltejs/kit': 2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)))(svelte@4.2.19)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15)) '@vercel/nft': 1.5.0(rollup@4.59.0) esbuild: 0.25.12 transitivePeerDependencies: @@ -2227,11 +2228,11 @@ snapshots: - rollup - supports-color - '@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)))(svelte@5.55.1)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15))': + '@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)))(svelte@4.2.19)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.15))': dependencies: '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)) '@types/cookie': 0.6.0 acorn: 8.16.0 cookie: 0.6.0 @@ -2242,29 +2243,29 @@ snapshots: mrmime: 2.0.1 set-cookie-parser: 3.0.1 sirv: 3.0.2 - svelte: 5.55.1 + svelte: 4.2.19 vite: 5.4.21(@types/node@22.19.15) optionalDependencies: typescript: 5.9.3 - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)))(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)))(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)) debug: 4.4.3 - svelte: 5.55.1 + svelte: 4.2.19 vite: 5.4.21(@types/node@22.19.15) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15))': + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)))(svelte@5.55.1)(vite@5.4.21(@types/node@22.19.15)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)))(svelte@4.2.19)(vite@5.4.21(@types/node@22.19.15)) debug: 4.4.3 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.21 - svelte: 5.55.1 - svelte-hmr: 0.16.0(svelte@5.55.1) + svelte: 4.2.19 + svelte-hmr: 0.16.0(svelte@4.2.19) vite: 5.4.21(@types/node@22.19.15) vitefu: 0.2.5(vite@5.4.21(@types/node@22.19.15)) transitivePeerDependencies: @@ -2315,9 +2316,8 @@ snapshots: dependencies: '@types/geojson': 7946.0.16 - '@types/trusted-types@2.0.7': {} - - '@typescript-eslint/types@8.58.0': {} + '@types/trusted-types@2.0.7': + optional: true '@vercel/nft@1.5.0(rollup@4.59.0)': dependencies: @@ -2447,7 +2447,13 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 6.2.0 - clsx@2.1.1: {} + code-red@1.0.4: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@types/estree': 1.0.8 + acorn: 8.16.0 + estree-walker: 3.0.3 + periscopic: 3.1.0 color-convert@2.0.1: dependencies: @@ -2474,6 +2480,11 @@ snapshots: cssesc: 3.0.0 fastparse: 1.1.2 + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.1 + cssesc@3.0.0: {} culori@3.3.0: {} @@ -2603,13 +2614,12 @@ snapshots: event-emitter: 0.3.5 type: 2.7.3 - esrap@2.2.4: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@typescript-eslint/types': 8.58.0 - estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + event-emitter@0.3.5: dependencies: d: 1.0.2 @@ -2851,6 +2861,8 @@ snapshots: marked@15.0.12: {} + mdn-data@2.0.30: {} + memoizee@0.4.17: dependencies: d: 1.0.2 @@ -2972,6 +2984,12 @@ snapshots: ieee754: 1.2.1 resolve-protobuf-schema: 2.1.0 + periscopic@3.1.0: + dependencies: + '@types/estree': 1.0.8 + estree-walker: 3.0.3 + is-reference: 3.0.3 + picocolors@1.1.1: {} picomatch@4.0.3: {} @@ -3045,10 +3063,10 @@ snapshots: potpack@2.1.0: {} - prettier-plugin-svelte@3.5.1(prettier@3.8.1)(svelte@5.55.1): + prettier-plugin-svelte@3.5.1(prettier@3.8.1)(svelte@4.2.19): dependencies: prettier: 3.8.1 - svelte: 5.55.1 + svelte: 4.2.19 prettier@3.8.1: {} @@ -3203,14 +3221,14 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.6(postcss@8.5.8)(svelte@5.55.1): + svelte-check@3.8.6(postcss@8.5.8)(svelte@4.2.19): dependencies: '@jridgewell/trace-mapping': 0.3.31 chokidar: 3.6.0 picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.55.1 - svelte-preprocess: 5.1.4(postcss@8.5.8)(svelte@5.55.1)(typescript@5.9.3) + svelte: 4.2.19 + svelte-preprocess: 5.1.4(postcss@8.5.8)(svelte@4.2.19)(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - '@babel/core' @@ -3223,15 +3241,15 @@ snapshots: - stylus - sugarss - svelte-dnd-action@0.9.69(svelte@5.55.1): + svelte-dnd-action@0.9.69(svelte@4.2.19): dependencies: - svelte: 5.55.1 + svelte: 4.2.19 - svelte-hmr@0.16.0(svelte@5.55.1): + svelte-hmr@0.16.0(svelte@4.2.19): dependencies: - svelte: 5.55.1 + svelte: 4.2.19 - svelte-i18n@4.0.1(svelte@5.55.1): + svelte-i18n@4.0.1(svelte@4.2.19): dependencies: cli-color: 2.0.4 deepmerge: 4.3.1 @@ -3239,10 +3257,10 @@ snapshots: estree-walker: 2.0.2 intl-messageformat: 10.7.18 sade: 1.8.1 - svelte: 5.55.1 + svelte: 4.2.19 tiny-glob: 0.2.9 - svelte-maplibre@0.9.14(svelte@5.55.1): + svelte-maplibre@0.9.14(svelte@4.2.19): dependencies: d3-geo: 3.1.1 dequal: 2.0.3 @@ -3250,38 +3268,36 @@ snapshots: just-flush: 2.3.0 maplibre-gl: 4.7.1 pmtiles: 3.2.1 - svelte: 5.55.1 + svelte: 4.2.19 - svelte-preprocess@5.1.4(postcss@8.5.8)(svelte@5.55.1)(typescript@5.9.3): + svelte-preprocess@5.1.4(postcss@8.5.8)(svelte@4.2.19)(typescript@5.9.3): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 magic-string: 0.30.21 sorcery: 0.11.1 strip-indent: 3.0.0 - svelte: 5.55.1 + svelte: 4.2.19 optionalDependencies: postcss: 8.5.8 typescript: 5.9.3 - svelte@5.55.1: + svelte@4.2.19: dependencies: - '@jridgewell/remapping': 2.3.5 + '@ampproject/remapping': 2.3.0 '@jridgewell/sourcemap-codec': 1.5.5 - '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) + '@jridgewell/trace-mapping': 0.3.31 '@types/estree': 1.0.8 - '@types/trusted-types': 2.0.7 acorn: 8.16.0 aria-query: 5.3.1 axobject-query: 4.1.0 - clsx: 2.1.1 - devalue: 5.6.4 - esm-env: 1.2.2 - esrap: 2.2.4 + code-red: 1.0.4 + css-tree: 2.3.1 + estree-walker: 3.0.3 is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.21 - zimmerframe: 1.1.4 + periscopic: 3.1.0 tailwindcss@3.4.19: dependencies: @@ -3457,5 +3473,3 @@ snapshots: which-module: 2.0.1 y18n: 4.0.3 yargs-parser: 18.1.3 - - zimmerframe@1.1.4: {} diff --git a/frontend/pnpm-workspace.yaml b/frontend/pnpm-workspace.yaml index d66e1150..c3322a78 100644 --- a/frontend/pnpm-workspace.yaml +++ b/frontend/pnpm-workspace.yaml @@ -5,5 +5,3 @@ overrides: brace-expansion@>=4.0.0 <5.0.5: '>=5.0.5' picomatch@<2.3.2: '>=2.3.2' picomatch@>=4.0.0 <4.0.4: '>=4.0.4' - svelte@<=5.51.4: '>=5.51.5' - svelte@<=5.53.4: '>=5.53.5' diff --git a/frontend/src/lib/components/locations/LocationQuickStart.svelte b/frontend/src/lib/components/locations/LocationQuickStart.svelte index cc54b4b4..60d34efc 100644 --- a/frontend/src/lib/components/locations/LocationQuickStart.svelte +++ b/frontend/src/lib/components/locations/LocationQuickStart.svelte @@ -1,800 +1,18 @@ -
{quickAddedLocation.name}
-- {$t('adventures.click_map') || 'Click on the map to select a location'} -
- {/if} - - {#if isReverseGeocoding} -{selectedLocation.name}
-{selectedLocation.location}
- {#if selectedLocation.rating} -- {selectedMarker.lat.toFixed(6)}, {selectedMarker.lng.toFixed(6)} -
- {#if selectedLocation.types && selectedLocation.types.length > 0} -- Optional. If not selected, backend defaults to General. -
-{quickAddedLocation.name}
++ {#if mode === 'lodging'} + Click on the map to select a lodging + {:else} + {$t('adventures.click_map') || 'Click on the map to select a location'} + {/if} +
+ {/if} + + {#if isReverseGeocoding} +{selectedLocation.name}
+{selectedLocation.location}
+ {#if selectedLocation.rating} ++ {selectedMarker.lat.toFixed(6)}, {selectedMarker.lng.toFixed(6)} +
+ {#if selectedLocation.types && selectedLocation.types.length > 0} ++ Optional. If not selected, backend defaults to General. +
+