diff --git a/src/firebase.js b/src/firebase.js index 5caec49..3cbf934 100644 --- a/src/firebase.js +++ b/src/firebase.js @@ -1,8 +1,5 @@ -// Import the functions you need from the SDKs you need -import { initializeApp } from "firebase/app"; -import { ref, child, get, set, getDatabase, onValue, push } from 'firebase/database'; -// TODO: Add SDKs for Firebase products that you want to use -// https://firebase.google.com/docs/web/setup#available-libraries +import { initializeApp, getApps, getApp } from 'firebase/app'; +import { getDatabase } from 'firebase/database'; // Your web app's Firebase configuration const firebaseConfig = { @@ -15,6 +12,8 @@ const firebaseConfig = { appId: import.meta.env.VITE_FIREBASE_APP_ID }; -// Initialize Firebase -const app = initializeApp(firebaseConfig); +// Initialize Firebase (with duplicate app prevention) +const app = getApps().length === 0 ? initializeApp(firebaseConfig) : getApp(); + +// Initialize Realtime Database and get a reference to the service export const db = getDatabase(app); \ No newline at end of file diff --git a/src/routes/viewimage/+page.svelte b/src/routes/viewimage/+page.svelte deleted file mode 100644 index fe6f146..0000000 --- a/src/routes/viewimage/+page.svelte +++ /dev/null @@ -1,124 +0,0 @@ - - -
-
- - \ No newline at end of file diff --git a/src/routes/viewimage/[tripId]/[memoryId]/+page.svelte b/src/routes/viewimage/[tripId]/[memoryId]/+page.svelte index 5dce965..299064d 100644 --- a/src/routes/viewimage/[tripId]/[memoryId]/+page.svelte +++ b/src/routes/viewimage/[tripId]/[memoryId]/+page.svelte @@ -8,13 +8,10 @@ import { db } from '../../../../firebase'; let memoryId = ''; - /** - * @type {{ location: any; startDate: any; endDate: any; images: any; } | null} - */ + let tripOptions = []; let memory = null; let tripId = ''; - // Subscribe to page store to get URL parameters $: { tripId = page.params.tripId; memoryId = page.params.memoryId; @@ -23,24 +20,52 @@ onMount(async () => { if (tripId && memoryId) { try { - const snapshot = await get(ref(db, `trips/${tripId}/memories/${memoryId}`)); - if (snapshot.exists()) { - memory = snapshot.val(); + const memorySnap = await get(ref(db, `trips/${tripId}/memories/${memoryId}`)); + const tripSnap = await get(ref(db, `trips/${tripId}`)); + + if (memorySnap.exists() && tripSnap.exists()) { + memory = memorySnap.val(); + const currentTrip = tripSnap.val(); + const { lat, lng } = currentTrip.destination.location; + + const allTripsSnap = await get(ref(db, 'trips')); + if (allTripsSnap.exists()) { + const allTrips = Object.entries(allTripsSnap.val()); + + tripOptions = allTrips + .filter(([id, trip]) => { + const loc = trip.destination?.location; + const hasMemories = trip.memories && Object.keys(trip.memories).length > 0; + const sameLocation = + loc && Math.abs(loc.lat - lat) < 0.0001 && Math.abs(loc.lng - lng) < 0.0001; + return sameLocation && hasMemories; + }) + .map(([id, trip]) => { + const memories = Object.values(trip.memories); + const latest = memories.sort((a, b) => new Date(b.startDate) - new Date(a.startDate))[0]; + return { + id, + label: `${latest.startDate} - ${latest.endDate}` + }; + }); + + const currentIndex = tripOptions.findIndex(t => t.id === tripId); + if (currentIndex > 0) { + const [current] = tripOptions.splice(currentIndex, 1); + tripOptions.unshift(current); + } + } } else { - console.error('No memory found'); + console.error('Trip or memory not found'); } } catch (error) { - console.error('Error fetching memory:', error); + console.error('Error fetching data:', error); } } }); let gradientColors = ['#e74c3c', '#f1c40f', '#2ecc71', '#3498db', '#9b59b6']; - $: gradientStyle = ` - conic-gradient( - ${gradientColors.map((c, i) => `${c} ${i * 72}deg ${(i + 1) * 72}deg`).join(',')} - ) - `; + $: gradientStyle = `conic-gradient(${gradientColors.map((c, i) => `${c} ${i * 72}deg ${(i + 1) * 72}deg`).join(',')})`;
@@ -50,22 +75,35 @@ {#if memory}

{memory.location}

-

{memory.startDate} - {memory.endDate}

+
+ +
+
+ {#each tripOptions as trip} + + {/each} +
-
- {#each memory.images as img} - - Memory image - {/each} +
+ {#if memory.images && memory.images.length > 0} +

Images

+
+ {#each memory.images as img} + memory image + {/each} +
+ {:else} +

No images uploaded.

+ {/if}
- {:else} -

Loading memory...

- {/if} + {/if}
@@ -80,14 +118,70 @@ .content { flex: 1; - padding: 2rem 1rem; - overflow-y: auto; + padding: 0 1rem 2rem 1rem; + position: relative; + display: flex; + flex-direction: column; } .header { - text-align: center; + padding-top: 2rem; + padding-left: 1rem; + background-color: var(--black); color: var(--white); - margin-bottom: 2rem; + } + + .header h1 { + font-size: 2rem; + font-weight: 600; + margin: 0; + } + + .trip-switcher { + width: 100%; + text-align: center; + overflow: hidden; + padding-top: 1.5rem; + } + + .trip-switcher-inner { + display: flex; + overflow-x: auto; + scroll-snap-type: x mandatory; + scroll-behavior: smooth; + -webkit-overflow-scrolling: touch; + gap: 1rem; + padding: 0.5rem; + } + + .trip-switcher-inner::-webkit-scrollbar { + width: 10px; + height: 4px; + } + + .trip-switcher-inner::-webkit-scrollbar-thumb { + background: var(--white); + border-radius: 2px; + } + + .trip-switcher-inner::-webkit-scrollbar-track { + background: transparent; + } + + .trip-switcher button { + flex: 0 0 auto; + background-color: white; + border: 1px solid var(--gray-200); + padding: 0.5rem 1rem; + border-radius: 8px; + font-size: 0.95rem; + cursor: pointer; + white-space: nowrap; + transition: color 0.3s ease; + } + + .trip-switcher button:hover { + background-color: var(--gray-100); } .gradient-wheel { @@ -103,23 +197,31 @@ justify-content: center; } - .image-list { - display: flex; - flex-direction: column; - align-items: center; + .image-preview { + padding: 1rem 2rem; + color: white; + } + + .image-preview h2 { + font-size: 1.25rem; + margin-bottom: 0.75rem; + } + + .image-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 1rem; - margin-top: 2rem; } - .image-list img { - width: 80%; - max-width: 500px; - border-radius: 12px; + .image-grid img { + width: 100%; + border-radius: 8px; + object-fit: cover; + aspect-ratio: 1 / 1; } - .empty { + .no-image { + font-size: 0.95rem; color: var(--gray-400); - text-align: center; - margin-top: 4rem; } - \ No newline at end of file + \ No newline at end of file