why
This commit is contained in:
commit
8e6126c26f
|
@ -1,7 +1,7 @@
|
||||||
import { initializeApp, getApps, getApp } from 'firebase/app';
|
import { initializeApp, getApps, getApp } from 'firebase/app';
|
||||||
import { getDatabase } from 'firebase/database';
|
import { getDatabase } from 'firebase/database';
|
||||||
|
|
||||||
// Your web app's Firebase configuration
|
// Firebase configuration
|
||||||
const firebaseConfig = {
|
const firebaseConfig = {
|
||||||
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
|
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
|
||||||
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
|
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { Loader } from '@googlemaps/js-api-loader';
|
import { Loader } from '@googlemaps/js-api-loader';
|
||||||
|
import { fetchUnsplashPhoto } from '../../services/unsplash';
|
||||||
|
|
||||||
// Extend the PlaceResult type to include our custom photoUrl
|
// Extend the PlaceResult type to include our custom photoUrl
|
||||||
interface ExtendedPlaceResult extends google.maps.places.PlaceResult {
|
interface ExtendedPlaceResult extends google.maps.places.PlaceResult {
|
||||||
|
@ -58,25 +59,12 @@
|
||||||
const autocomplete = new google.maps.places.Autocomplete(input, autocompleteOptions);
|
const autocomplete = new google.maps.places.Autocomplete(input, autocompleteOptions);
|
||||||
autocomplete.setFields(['name', 'formatted_address', 'photos', 'place_id', 'geometry']);
|
autocomplete.setFields(['name', 'formatted_address', 'photos', 'place_id', 'geometry']);
|
||||||
|
|
||||||
autocomplete.addListener('place_changed', () => {
|
autocomplete.addListener('place_changed', async () => {
|
||||||
const place = autocomplete.getPlace() as ExtendedPlaceResult;
|
const place = autocomplete.getPlace() as ExtendedPlaceResult;
|
||||||
if (place && place.name) {
|
if (place && place.name) {
|
||||||
// If the place has photos, get the URL for the first photo
|
// Use Unsplash for the photo
|
||||||
if (place.photos && place.photos.length > 0) {
|
const unsplashUrl = await fetchUnsplashPhoto(place.name);
|
||||||
try {
|
place.photoUrl = unsplashUrl || '/placeholder.jpeg';
|
||||||
const photoOptions = {
|
|
||||||
maxWidth: 400,
|
|
||||||
maxHeight: 300
|
|
||||||
};
|
|
||||||
place.photoUrl = place.photos[0].getUrl(photoOptions);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error getting photo URL:', error);
|
|
||||||
place.photoUrl = '/placeholder.jpeg';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
place.photoUrl = '/placeholder.jpeg';
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedPlace = place;
|
selectedPlace = place;
|
||||||
lastSelectedPlaceName = input.value.trim();
|
lastSelectedPlaceName = input.value.trim();
|
||||||
|
|
|
@ -145,6 +145,28 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UNSPLASH_ACCESS_KEY = import.meta.env.VITE_UNSPLASH_ACCESS_KEY;
|
||||||
|
|
||||||
|
async function fetchUnsplashPhoto(query: string): Promise<string | null> {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.unsplash.com/search/photos?query=${encodeURIComponent(query)}&client_id=${UNSPLASH_ACCESS_KEY}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("Failed to fetch Unsplash photo");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
const firstPhoto = data.results?.[0];
|
||||||
|
return firstPhoto?.urls?.regular || null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching Unsplash photo:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function handleStart() {
|
async function handleStart() {
|
||||||
destinationError = !destination;
|
destinationError = !destination;
|
||||||
startDateError = !startDate;
|
startDateError = !startDate;
|
||||||
|
@ -174,7 +196,7 @@
|
||||||
const placeDetails = {
|
const placeDetails = {
|
||||||
name: selectedPlace.name,
|
name: selectedPlace.name,
|
||||||
formatted_address: selectedPlace.formatted_address,
|
formatted_address: selectedPlace.formatted_address,
|
||||||
photo: selectedPlace.photos?.[0]?.getUrl(),
|
photo: await fetchUnsplashPhoto(destination) || '/placeholder.jpeg',
|
||||||
location: {
|
location: {
|
||||||
lat: selectedPlace.geometry.location.lat(),
|
lat: selectedPlace.geometry.location.lat(),
|
||||||
lng: selectedPlace.geometry.location.lng()
|
lng: selectedPlace.geometry.location.lng()
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
import '../../app.css';
|
import '../../app.css';
|
||||||
import { ref, get } from 'firebase/database';
|
import { ref, get } from 'firebase/database';
|
||||||
import { db } from '../../firebase';
|
import { db } from '../../firebase';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
let mapContainer: HTMLDivElement;
|
let mapContainer: HTMLDivElement;
|
||||||
|
|
||||||
interface TripLocation {
|
interface TripLocation {
|
||||||
|
tid: string;
|
||||||
name: string;
|
name: string;
|
||||||
location: {
|
location: {
|
||||||
lat: number;
|
lat: number;
|
||||||
|
@ -17,6 +19,7 @@
|
||||||
};
|
};
|
||||||
startDate: string;
|
startDate: string;
|
||||||
endDate: string;
|
endDate: string;
|
||||||
|
hasMemory: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDate(dateStr: string): string {
|
function formatDate(dateStr: string): string {
|
||||||
|
@ -37,16 +40,19 @@
|
||||||
|
|
||||||
const locationMap: Record<string, TripLocation[]> = {};
|
const locationMap: Record<string, TripLocation[]> = {};
|
||||||
|
|
||||||
Object.values(snapshot.val()).forEach((trip: any) => {
|
Object.entries(snapshot.val()).forEach(([tid, trip]: [string, any]) => {
|
||||||
const endDate = new Date(trip.endDate);
|
const endDate = new Date(trip.endDate);
|
||||||
if (endDate < today && trip.destination?.location) {
|
if (endDate < today && trip.destination?.location) {
|
||||||
const key = `${trip.destination.location.lat},${trip.destination.location.lng}`;
|
const key = `${trip.destination.location.lat},${trip.destination.location.lng}`;
|
||||||
if (!locationMap[key]) locationMap[key] = [];
|
if (!locationMap[key]) locationMap[key] = [];
|
||||||
|
const hasMemory = trip.memories && Object.keys(trip.memories).length > 0;
|
||||||
locationMap[key].push({
|
locationMap[key].push({
|
||||||
|
tid,
|
||||||
name: trip.destination.name,
|
name: trip.destination.name,
|
||||||
location: trip.destination.location,
|
location: trip.destination.location,
|
||||||
startDate: trip.startDate,
|
startDate: trip.startDate,
|
||||||
endDate: trip.endDate
|
endDate: trip.endDate,
|
||||||
|
hasMemory
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -167,14 +173,23 @@
|
||||||
.attr('cy', baseY - offsetY)
|
.attr('cy', baseY - offsetY)
|
||||||
.attr('r', 5)
|
.attr('r', 5)
|
||||||
.attr('fill', Colors.planner.med400)
|
.attr('fill', Colors.planner.med400)
|
||||||
.attr('class', 'trip-marker');
|
.attr('class', 'trip-marker')
|
||||||
|
.attr('data-has-memory', trip.hasMemory ? 'true' : 'false')
|
||||||
|
.style('cursor', 'pointer')
|
||||||
|
.on('click', function () {
|
||||||
|
goto(`/itinerary/${trip.tid}`);
|
||||||
|
});
|
||||||
|
|
||||||
markerGroup.append('text')
|
markerGroup.append('text')
|
||||||
.attr('x', baseX + 10)
|
.attr('x', baseX + 10)
|
||||||
.attr('y', baseY - offsetY + 4)
|
.attr('y', baseY - offsetY + 4)
|
||||||
.attr('font-size', '12px')
|
.attr('font-size', '12px')
|
||||||
.attr('class', 'trip-label')
|
.attr('class', 'trip-label')
|
||||||
.text(`${formatDate(trip.startDate)} - ${formatDate(trip.endDate)}`);
|
.text(`${formatDate(trip.startDate)} - ${formatDate(trip.endDate)}`)
|
||||||
|
.style('cursor', 'pointer')
|
||||||
|
.on('click', function () {
|
||||||
|
goto(`/itinerary/${trip.tid}`);
|
||||||
|
});
|
||||||
|
|
||||||
markerGroup
|
markerGroup
|
||||||
.style('opacity', 0)
|
.style('opacity', 0)
|
||||||
|
@ -271,10 +286,14 @@
|
||||||
fill: var(--memory-500);
|
fill: var(--memory-500);
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark .trip-marker) {
|
:global(.dark .trip-marker[data-has-memory="true"]) {
|
||||||
fill: var(--memory-500);
|
fill: var(--memory-500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark .trip-marker[data-has-memory="false"]) {
|
||||||
|
fill: var(--planner-400);
|
||||||
|
}
|
||||||
|
|
||||||
:global(.dark .trip-line) {
|
:global(.dark .trip-line) {
|
||||||
stroke: var(--memory-500);
|
stroke: var(--memory-500);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
import RecommendationPopup from '$lib/components/RecommendationPopup.svelte';
|
import RecommendationPopup from '$lib/components/RecommendationPopup.svelte';
|
||||||
import LoadingOverlay from '$lib/components/LoadingOverlay.svelte';
|
import LoadingOverlay from '$lib/components/LoadingOverlay.svelte';
|
||||||
import TurnIntoItineraryPopup from '$lib/components/TurnIntoItineraryPopup.svelte';
|
import TurnIntoItineraryPopup from '$lib/components/TurnIntoItineraryPopup.svelte';
|
||||||
|
import { fetchUnsplashPhoto } from '../../../services/unsplash';
|
||||||
import type { Place } from '$lib/constants/Interfaces';
|
import type { Place } from '$lib/constants/Interfaces';
|
||||||
|
|
||||||
let tripData: any = null;
|
let tripData: any = null;
|
||||||
|
@ -288,12 +289,6 @@
|
||||||
itinerary: true
|
itinerary: true
|
||||||
};
|
};
|
||||||
|
|
||||||
let recommendedPlaces = [
|
|
||||||
{ name: "Place name" },
|
|
||||||
{ name: "Place name" },
|
|
||||||
{ name: "Place name" }
|
|
||||||
];
|
|
||||||
|
|
||||||
let placesToVisit: any[] = [];
|
let placesToVisit: any[] = [];
|
||||||
|
|
||||||
async function handleDeletePlace(index: number) {
|
async function handleDeletePlace(index: number) {
|
||||||
|
@ -419,12 +414,13 @@
|
||||||
|
|
||||||
if (results.length > 0) {
|
if (results.length > 0) {
|
||||||
const place = results[0];
|
const place = results[0];
|
||||||
const photoUrl = place.photos?.[0]?.getUrl();
|
// Use Unsplash for the photo
|
||||||
|
const unsplashUrl = await fetchUnsplashPhoto(place.name || rec.name);
|
||||||
|
|
||||||
const newPlace = {
|
const newPlace = {
|
||||||
name: place.name || rec.name,
|
name: place.name || rec.name,
|
||||||
desc: place.formatted_address || '',
|
desc: place.formatted_address || '',
|
||||||
image: photoUrl || '/placeholder.jpeg',
|
image: unsplashUrl || '/placeholder.jpeg',
|
||||||
geometry: place.geometry?.location ? {
|
geometry: place.geometry?.location ? {
|
||||||
lat: place.geometry.location.lat(),
|
lat: place.geometry.location.lat(),
|
||||||
lng: place.geometry.location.lng()
|
lng: place.geometry.location.lng()
|
||||||
|
|
21
src/services/unsplash.ts
Normal file
21
src/services/unsplash.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
const UNSPLASH_ACCESS_KEY = import.meta.env.VITE_UNSPLASH_ACCESS_KEY;
|
||||||
|
|
||||||
|
export async function fetchUnsplashPhoto(query: string): Promise<string | null> {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.unsplash.com/search/photos?query=${encodeURIComponent(query)}&client_id=${UNSPLASH_ACCESS_KEY}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("Failed to fetch Unsplash photo");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
const firstPhoto = data.results?.[0];
|
||||||
|
return firstPhoto?.urls?.regular || null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching Unsplash photo:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user