merging
This commit is contained in:
commit
aa7c66ea70
|
@ -1,76 +1,30 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { fade } from 'svelte/transition';
|
export let destination = '';
|
||||||
import DeleteConfirmationPopup from './DeleteConfirmationPopup.svelte';
|
export let startDate = '';
|
||||||
import { ref, remove } from 'firebase/database';
|
export let endDate = '';
|
||||||
import { db } from '../../firebase';
|
export let image = '';
|
||||||
|
export let tid = '';
|
||||||
export let tripId: string;
|
export let memoryId = '';
|
||||||
export let memoryId: string;
|
|
||||||
export let destination: string;
|
|
||||||
export let startDate: string;
|
|
||||||
export let endDate: string;
|
|
||||||
export let image: string;
|
|
||||||
|
|
||||||
let showDelete = false;
|
|
||||||
let showDeleteConfirmation = false;
|
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
goto(`/viewimage/${tripId}/${memoryId}`);
|
goto(`/viewimage/${tid}/${memoryId}`);
|
||||||
}
|
|
||||||
|
|
||||||
function handleMouseEnter() {
|
|
||||||
showDelete = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleMouseLeave() {
|
|
||||||
showDelete = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDeleteClick(event: MouseEvent) {
|
|
||||||
event.stopPropagation();
|
|
||||||
showDeleteConfirmation = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleConfirmDelete() {
|
|
||||||
try {
|
|
||||||
const memoryRef = ref(db, `trips/${tripId}/memories/${memoryId}`);
|
|
||||||
await remove(memoryRef);
|
|
||||||
showDeleteConfirmation = false;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error deleting memory:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleCancelDelete() {
|
|
||||||
showDeleteConfirmation = false;
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
<div
|
<div
|
||||||
class="memory-card"
|
class="memory-card"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
on:mouseenter={handleMouseEnter}
|
onclick={handleClick}
|
||||||
on:mouseleave={handleMouseLeave}
|
|
||||||
on:click={handleClick}
|
|
||||||
>
|
>
|
||||||
<div class="image" style={`background-image: url("${image || ''}")`}>
|
<div class="image" style="background-image: url({image || ''})">
|
||||||
{#if !image}
|
{#if !image}
|
||||||
<div class="placeholder">
|
<div class="placeholder">
|
||||||
<i class="fa-solid fa-image" style="color: var(--gray-400)"></i>
|
<i class="fa-solid fa-image" style="color: var(--gray-400)"></i>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if showDelete}
|
|
||||||
<button
|
|
||||||
class="delete-btn"
|
|
||||||
on:click={handleDeleteClick}
|
|
||||||
transition:fade={{ duration: 100 }}
|
|
||||||
aria-label="Delete memory"
|
|
||||||
>
|
|
||||||
<i class="fa-solid fa-xmark"></i>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<h3>{destination}</h3>
|
<h3>{destination}</h3>
|
||||||
|
@ -78,40 +32,28 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DeleteConfirmationPopup
|
|
||||||
showPopup={showDeleteConfirmation}
|
|
||||||
{destination}
|
|
||||||
darkMode={true}
|
|
||||||
onConfirm={handleConfirmDelete}
|
|
||||||
onCancel={handleCancelDelete}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.memory-card {
|
.memory-card {
|
||||||
background: var(--black);
|
background: var(--gray-900);
|
||||||
color: var(--white);
|
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 2px 4px rgba(255, 255, 255, 0.05);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-family: 'Inter', sans-serif;
|
font-family: 'Inter', sans-serif;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.memory-card:hover {
|
.memory-card:hover {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: 0 4px 8px rgba(255, 255, 255, 0.1);
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
height: 160px;
|
height: 160px;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-color: var(--gray-900);
|
background-color: var(--gray-100);
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder {
|
.placeholder {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -119,42 +61,18 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info h3 {
|
.info h3 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
color: var(--white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
margin: 0.25rem 0 0 0;
|
margin: 0.25rem 0 0 0;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
color: var(--gray-400);
|
color: var(--gray-200);
|
||||||
}
|
|
||||||
|
|
||||||
.delete-btn {
|
|
||||||
position: absolute;
|
|
||||||
top: 0.75rem;
|
|
||||||
right: 0.75rem;
|
|
||||||
background: rgba(240, 240, 240, 0.8);
|
|
||||||
border: none;
|
|
||||||
width: 2rem;
|
|
||||||
height: 2rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
cursor: pointer;
|
|
||||||
color: var(--gray-600);
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete-btn:hover {
|
|
||||||
background-color: var(--memory-50);
|
|
||||||
color: var(--memory-600);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -233,6 +233,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
let isUploading = false;
|
let isUploading = false;
|
||||||
|
|
||||||
|
const isDark = document.documentElement.classList.contains('dark');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if showPopup}
|
{#if showPopup}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
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';
|
import { goto } from '$app/navigation';
|
||||||
|
import NewMemoryPopup from '$lib/components/NewMemoryPopup.svelte';
|
||||||
|
|
||||||
let mapContainer: HTMLDivElement;
|
let mapContainer: HTMLDivElement;
|
||||||
|
|
||||||
|
@ -65,6 +66,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
let cleanup: (() => void) | undefined;
|
let cleanup: (() => void) | undefined;
|
||||||
|
let showNewMemoryPopup = false;
|
||||||
|
let selectedTripIdForMemory = '';
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
let mounted = true;
|
let mounted = true;
|
||||||
|
@ -176,8 +179,32 @@
|
||||||
.attr('class', 'trip-marker')
|
.attr('class', 'trip-marker')
|
||||||
.attr('data-has-memory', trip.hasMemory ? 'true' : 'false')
|
.attr('data-has-memory', trip.hasMemory ? 'true' : 'false')
|
||||||
.style('cursor', 'pointer')
|
.style('cursor', 'pointer')
|
||||||
.on('click', function () {
|
.on('click', async function () {
|
||||||
|
// Use document.documentElement for dark mode detection
|
||||||
|
const isDark = document.documentElement.classList.contains('dark');
|
||||||
|
const hasMemory = trip.hasMemory;
|
||||||
|
|
||||||
|
if (isDark) {
|
||||||
|
if (hasMemory) {
|
||||||
|
// Fetch the topmost memoryId for this trip
|
||||||
|
const tripRef = ref(db, `trips/${trip.tid}/memories`);
|
||||||
|
const snapshot = await get(tripRef);
|
||||||
|
if (snapshot.exists()) {
|
||||||
|
const memoryIds = Object.keys(snapshot.val());
|
||||||
|
if (memoryIds.length > 0) {
|
||||||
|
const topMemoryId = memoryIds[0];
|
||||||
|
goto(`/viewimage/${trip.tid}/${topMemoryId}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Show NewMemoryPopup for this trip
|
||||||
|
selectedTripIdForMemory = trip.tid;
|
||||||
|
showNewMemoryPopup = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Default: go to itinerary
|
||||||
goto(`/itinerary/${trip.tid}`);
|
goto(`/itinerary/${trip.tid}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
markerGroup.append('text')
|
markerGroup.append('text')
|
||||||
|
@ -187,8 +214,32 @@
|
||||||
.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')
|
.style('cursor', 'pointer')
|
||||||
.on('click', function () {
|
.on('click', async function () {
|
||||||
|
// Use document.documentElement for dark mode detection
|
||||||
|
const isDark = document.documentElement.classList.contains('dark');
|
||||||
|
const hasMemory = trip.hasMemory;
|
||||||
|
|
||||||
|
if (isDark) {
|
||||||
|
if (hasMemory) {
|
||||||
|
// Fetch the topmost memoryId for this trip
|
||||||
|
const tripRef = ref(db, `trips/${trip.tid}/memories`);
|
||||||
|
const snapshot = await get(tripRef);
|
||||||
|
if (snapshot.exists()) {
|
||||||
|
const memoryIds = Object.keys(snapshot.val());
|
||||||
|
if (memoryIds.length > 0) {
|
||||||
|
const topMemoryId = memoryIds[0];
|
||||||
|
goto(`/viewimage/${trip.tid}/${topMemoryId}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Show NewMemoryPopup for this trip
|
||||||
|
selectedTripIdForMemory = trip.tid;
|
||||||
|
showNewMemoryPopup = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Default: go to itinerary
|
||||||
goto(`/itinerary/${trip.tid}`);
|
goto(`/itinerary/${trip.tid}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
markerGroup
|
markerGroup
|
||||||
|
@ -235,6 +286,10 @@
|
||||||
|
|
||||||
<div bind:this={mapContainer} class="map-wrapper"></div>
|
<div bind:this={mapContainer} class="map-wrapper"></div>
|
||||||
|
|
||||||
|
{#if showNewMemoryPopup}
|
||||||
|
<NewMemoryPopup bind:showPopup={showNewMemoryPopup} onCancel={() => showNewMemoryPopup = false} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.map-wrapper {
|
.map-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -10,6 +10,7 @@ export interface Trip {
|
||||||
lng: number;
|
lng: number;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
_cardImage?: string;
|
||||||
startDate: string;
|
startDate: string;
|
||||||
endDate: string;
|
endDate: string;
|
||||||
tripmates: string[];
|
tripmates: string[];
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
<<<<<<< HEAD
|
||||||
import '../../app.css';
|
import '../../app.css';
|
||||||
import MemoryCard from '$lib/components/MemoryCard.svelte';
|
import MemoryCard from '$lib/components/MemoryCard.svelte';
|
||||||
import Button from '$lib/components/Button.svelte';
|
import Button from '$lib/components/Button.svelte';
|
||||||
|
@ -48,6 +49,67 @@
|
||||||
function handleNewMemory() {
|
function handleNewMemory() {
|
||||||
showNewMemoryPopup = true;
|
showNewMemoryPopup = true;
|
||||||
}
|
}
|
||||||
|
=======
|
||||||
|
import '../../app.css';
|
||||||
|
import MemoryCard from '$lib/components/MemoryCard.svelte';
|
||||||
|
import Button from '$lib/components/Button.svelte';
|
||||||
|
import NewMemoryPopup from '$lib/components/NewMemoryPopup.svelte';
|
||||||
|
import Nav from '$lib/components/Nav.svelte';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { ref, onValue } from 'firebase/database';
|
||||||
|
import { db } from '../../firebase';
|
||||||
|
|
||||||
|
let showNewMemoryPopup = false;
|
||||||
|
let contentContainer: HTMLElement;
|
||||||
|
|
||||||
|
interface MemoryCardData {
|
||||||
|
tid: string;
|
||||||
|
memoryId: string;
|
||||||
|
destination: string;
|
||||||
|
startDate: string;
|
||||||
|
endDate: string;
|
||||||
|
image: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pastMemories: MemoryCardData[] = [];
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const tripsRef = ref(db, 'trips');
|
||||||
|
onValue(tripsRef, (snapshot) => {
|
||||||
|
const memories: MemoryCardData[] = [];
|
||||||
|
snapshot.forEach((childSnapshot) => {
|
||||||
|
const trip = childSnapshot.val();
|
||||||
|
const tid = childSnapshot.key;
|
||||||
|
if (trip.memories && typeof trip.memories === 'object') {
|
||||||
|
const memoryEntries = Object.entries(trip.memories);
|
||||||
|
if (memoryEntries.length > 0) {
|
||||||
|
const [memoryId, memory] = memoryEntries[0];
|
||||||
|
const mem = memory as { images: string[] };
|
||||||
|
if (mem.images && mem.images.length > 0) {
|
||||||
|
const format = (d: string) => {
|
||||||
|
const date = new Date(d);
|
||||||
|
return `${String(date.getDate()).padStart(2, '0')}/${String(date.getMonth() + 1).padStart(2, '0')}/${date.getFullYear()}`;
|
||||||
|
};
|
||||||
|
memories.push({
|
||||||
|
tid,
|
||||||
|
memoryId,
|
||||||
|
destination: trip.destination?.name || '',
|
||||||
|
startDate: format(trip.startDate),
|
||||||
|
endDate: format(trip.endDate),
|
||||||
|
image: mem.images[0]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pastMemories = memories;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleNewMemory() {
|
||||||
|
showNewMemoryPopup = true;
|
||||||
|
}
|
||||||
|
>>>>>>> 0570bcffe9996e925158c79503096d59ce341846
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
@ -61,7 +123,11 @@
|
||||||
<div class="memories-container">
|
<div class="memories-container">
|
||||||
{#if pastMemories.length === 0}
|
{#if pastMemories.length === 0}
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
|
<<<<<<< HEAD
|
||||||
<p>There is no memory</p>
|
<p>There is no memory</p>
|
||||||
|
=======
|
||||||
|
<p>There is no memory yet</p>
|
||||||
|
>>>>>>> 0570bcffe9996e925158c79503096d59ce341846
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="memories-grid">
|
<div class="memories-grid">
|
||||||
|
|
|
@ -21,13 +21,27 @@
|
||||||
const tripsRef = ref(db, 'trips');
|
const tripsRef = ref(db, 'trips');
|
||||||
|
|
||||||
// listen for changes in the trips data
|
// listen for changes in the trips data
|
||||||
onValue(tripsRef, (snapshot) => {
|
onValue(tripsRef, async (snapshot) => {
|
||||||
const trips: Trip[] = [];
|
const trips: Trip[] = [];
|
||||||
|
const tripImageMap: Record<string, string> = {};
|
||||||
|
const promises: Promise<void>[] = [];
|
||||||
snapshot.forEach((childSnapshot) => {
|
snapshot.forEach((childSnapshot) => {
|
||||||
trips.push({
|
const tripData = {
|
||||||
tid: childSnapshot.key,
|
tid: childSnapshot.key,
|
||||||
...childSnapshot.val()
|
...childSnapshot.val()
|
||||||
});
|
};
|
||||||
|
trips.push(tripData);
|
||||||
|
|
||||||
|
// Check for memories and get the first image if exists
|
||||||
|
if (tripData.memories && typeof tripData.memories === 'object') {
|
||||||
|
const memoryIds = Object.keys(tripData.memories);
|
||||||
|
if (memoryIds.length > 0) {
|
||||||
|
const firstMemory = tripData.memories[memoryIds[0]];
|
||||||
|
if (firstMemory.images && firstMemory.images.length > 0) {
|
||||||
|
tripImageMap[tripData.tid] = firstMemory.images[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// get today's date at midnight for comparison
|
// get today's date at midnight for comparison
|
||||||
|
@ -35,7 +49,6 @@
|
||||||
today.setHours(0, 0, 0, 0);
|
today.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
// filter trips based on end date
|
// filter trips based on end date
|
||||||
// end date > today = pastTrips
|
|
||||||
ongoingTrips = trips.filter(trip => {
|
ongoingTrips = trips.filter(trip => {
|
||||||
const endDate = new Date(trip.endDate);
|
const endDate = new Date(trip.endDate);
|
||||||
return endDate >= today;
|
return endDate >= today;
|
||||||
|
@ -45,6 +58,10 @@
|
||||||
const endDate = new Date(trip.endDate);
|
const endDate = new Date(trip.endDate);
|
||||||
return endDate < today;
|
return endDate < today;
|
||||||
}).sort((a, b) => new Date(b.endDate).getTime() - new Date(a.endDate).getTime()); // sort past trips by most recent first
|
}).sort((a, b) => new Date(b.endDate).getTime() - new Date(a.endDate).getTime()); // sort past trips by most recent first
|
||||||
|
|
||||||
|
// Attach the image override map to each trip for rendering
|
||||||
|
ongoingTrips = ongoingTrips.map(trip => ({ ...trip, _cardImage: tripImageMap[trip.tid] || trip.destination.photo }));
|
||||||
|
pastTrips = pastTrips.map(trip => ({ ...trip, _cardImage: tripImageMap[trip.tid] || trip.destination.photo }));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -95,7 +112,7 @@
|
||||||
destination={trip.destination.name}
|
destination={trip.destination.name}
|
||||||
startDate={new Date(trip.startDate).toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}
|
startDate={new Date(trip.startDate).toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}
|
||||||
endDate={new Date(trip.endDate).toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}
|
endDate={new Date(trip.endDate).toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}
|
||||||
image={trip.destination.photo}
|
image={trip._cardImage}
|
||||||
tid={trip.tid}
|
tid={trip.tid}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -113,7 +130,7 @@
|
||||||
destination={trip.destination.name}
|
destination={trip.destination.name}
|
||||||
startDate={new Date(trip.startDate).toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}
|
startDate={new Date(trip.startDate).toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}
|
||||||
endDate={new Date(trip.endDate).toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}
|
endDate={new Date(trip.endDate).toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}
|
||||||
image={trip.destination.photo}
|
image={trip._cardImage}
|
||||||
tid={trip.tid}
|
tid={trip.tid}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import '../../../../app.css';
|
import '../../../../app.css';
|
||||||
import Nav from '$lib/components/Nav.svelte';
|
import Nav from '$lib/components/Nav.svelte';
|
||||||
import Button from '$lib/components/Button.svelte';
|
import Button from '$lib/components/Button.svelte';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/state';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { ref, get } from 'firebase/database';
|
import { ref, get } from 'firebase/database';
|
||||||
import { db } from '../../../../firebase';
|
import { db } from '../../../../firebase';
|
||||||
|
|
||||||
let tripId, memoryId;
|
let tripId, memoryId;
|
||||||
let memory = null;
|
let memory: any = null;
|
||||||
let tripOptions = [];
|
let tripOptions: any[] = [];
|
||||||
let currentImageIndex = 0;
|
let currentImageIndex = 0;
|
||||||
let gradientLayers = [];
|
let gradientLayers: any[] = [];
|
||||||
let columnGroups = [];
|
let columnGroups: any[] = [];
|
||||||
let rotationAngle = 0;
|
let rotationAngle = 0;
|
||||||
|
|
||||||
let droppedTripId = null;
|
let droppedTripId: any = null;
|
||||||
let droppedMemory = null;
|
let droppedMemory: any = null;
|
||||||
let droppedImageIndex = 0;
|
let droppedImageIndex = 0;
|
||||||
let droppedColumnGroups = [];
|
let droppedColumnGroups: any[] = [];
|
||||||
let droppedGradientLayers = [];
|
let droppedGradientLayers: any[] = [];
|
||||||
let droppedWheelStyle = {};
|
let droppedWheelStyle = {};
|
||||||
let droppedCurrentImage = null;
|
let droppedCurrentImage: any = null;
|
||||||
let isDroppedVisible = true;
|
let isDroppedVisible = true;
|
||||||
|
|
||||||
$: tripId = $page.params.tripId;
|
$: tripId = page.params.tripId;
|
||||||
$: memoryId = $page.params.memoryId;
|
$: memoryId = page.params.memoryId;
|
||||||
$: currentImage = memory?.images?.[currentImageIndex];
|
$: currentImage = memory?.images?.[currentImageIndex];
|
||||||
|
|
||||||
$: if (tripId && memoryId) {
|
$: if (tripId && memoryId) {
|
||||||
loadMemoryAndTrip(tripId, memoryId);
|
loadMemoryAndTrip(tripId, memoryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadMemoryAndTrip(tripId, memoryId) {
|
async function loadMemoryAndTrip(tripId: string, memoryId: string) {
|
||||||
try {
|
try {
|
||||||
const memorySnap = await get(ref(db, `trips/${tripId}/memories/${memoryId}`));
|
const memorySnap = await get(ref(db, `trips/${tripId}/memories/${memoryId}`));
|
||||||
const tripSnap = await get(ref(db, `trips/${tripId}`));
|
const tripSnap = await get(ref(db, `trips/${tripId}`));
|
||||||
|
@ -79,8 +79,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
//get information from other trip in same region
|
//get information from other trip in same region
|
||||||
async function loadDroppedTrip(tripId, memoryId) {
|
async function loadDroppedTrip(tripId, memoryId) {
|
||||||
|
=======
|
||||||
|
async function loadDroppedTrip(tripId: any, memoryId: any) {
|
||||||
|
>>>>>>> 0570bcffe9996e925158c79503096d59ce341846
|
||||||
const memorySnap = await get(ref(db, `trips/${tripId}/memories/${memoryId}`));
|
const memorySnap = await get(ref(db, `trips/${tripId}/memories/${memoryId}`));
|
||||||
if (memorySnap.exists()) {
|
if (memorySnap.exists()) {
|
||||||
droppedTripId = tripId;
|
droppedTripId = tripId;
|
||||||
|
@ -105,7 +109,7 @@
|
||||||
transformOrigin: 'center center'
|
transformOrigin: 'center center'
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getImageData(url) {
|
async function getImageData(url: string) {
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.crossOrigin = 'Anonymous';
|
img.crossOrigin = 'Anonymous';
|
||||||
img.src = url;
|
img.src = url;
|
||||||
|
@ -143,8 +147,12 @@
|
||||||
return [h, s * 100, v * 255];
|
return [h, s * 100, v * 255];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// get most frequent color from each section
|
// get most frequent color from each section
|
||||||
function getColumnColors(imageData, columnCount = 5) {
|
function getColumnColors(imageData, columnCount = 5) {
|
||||||
|
=======
|
||||||
|
function getColumnColors(imageData: ImageData, columnCount = 5) {
|
||||||
|
>>>>>>> 0570bcffe9996e925158c79503096d59ce341846
|
||||||
const { data, width, height } = imageData;
|
const { data, width, height } = imageData;
|
||||||
const columnWidth = Math.floor(width / columnCount);
|
const columnWidth = Math.floor(width / columnCount);
|
||||||
const columns = Array.from({ length: columnCount }, () => []);
|
const columns = Array.from({ length: columnCount }, () => []);
|
||||||
|
@ -170,8 +178,12 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
//collect color by column
|
//collect color by column
|
||||||
async function extractColumnwiseColors(imageUrls, reverseColumns = true) {
|
async function extractColumnwiseColors(imageUrls, reverseColumns = true) {
|
||||||
|
=======
|
||||||
|
async function extractColumnwiseColors(imageUrls: any, reverseColumns = true) {
|
||||||
|
>>>>>>> 0570bcffe9996e925158c79503096d59ce341846
|
||||||
const columnColorGroups = [[], [], [], [], []];
|
const columnColorGroups = [[], [], [], [], []];
|
||||||
|
|
||||||
for (const url of imageUrls) {
|
for (const url of imageUrls) {
|
||||||
|
@ -237,7 +249,7 @@
|
||||||
gradients.push('radial-gradient(circle, var(--black) 100%)');
|
gradients.push('radial-gradient(circle, var(--black) 100%)');
|
||||||
}
|
}
|
||||||
|
|
||||||
droppedGradientLayers = gradients.map((bg, i) => {
|
droppedGradientLayers = gradients.map((bg: any, i: number) => {
|
||||||
const scale = 1 - i * 0.1;
|
const scale = 1 - i * 0.1;
|
||||||
return `background: ${bg};
|
return `background: ${bg};
|
||||||
width: ${scale * 100}%;
|
width: ${scale * 100}%;
|
||||||
|
@ -280,7 +292,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDrop(event) {
|
function handleDrop(event: { preventDefault: () => void; dataTransfer: { getData: (arg0: string) => any; }; }) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (droppedMemory && isDroppedVisible) return;
|
if (droppedMemory && isDroppedVisible) return;
|
||||||
|
|
||||||
|
@ -289,7 +301,7 @@
|
||||||
loadDroppedTrip(droppedTripId, droppedMemoryId);
|
loadDroppedTrip(droppedTripId, droppedMemoryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function allowDrop(event) {
|
function allowDrop(event: { preventDefault: () => void; }) {
|
||||||
if (!droppedMemory || !isDroppedVisible) {
|
if (!droppedMemory || !isDroppedVisible) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
@ -342,20 +354,28 @@
|
||||||
<img class="preview-img" src={currentImage} alt="Current Image" />
|
<img class="preview-img" src={currentImage} alt="Current Image" />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<!-- svelte-ignore a11y_consider_explicit_label -->
|
||||||
<div class="arrow-controls">
|
<div class="arrow-controls">
|
||||||
|
<!-- svelte-ignore a11y_consider_explicit_label -->
|
||||||
<button on:click={prevImage}>
|
<button on:click={prevImage}>
|
||||||
<img src="/lucide_chevron-up.png" alt="Up" width="24" height="24" />
|
<i class="fa-solid fa-chevron-up"></i>
|
||||||
</button>
|
</button>
|
||||||
<button on:click={nextImage}>
|
<button on:click={nextImage}>
|
||||||
<img src="/lucide_chevron-down.png" alt="Down" width="24" height="24" />
|
<i class="fa-solid fa-chevron-down"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- rightside dropped view -->
|
<!-- rightside dropped view -->
|
||||||
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<div class="wheel-section drop-zone" on:drop={handleDrop} on:dragover={allowDrop}>
|
<div class="wheel-section drop-zone" on:drop={handleDrop} on:dragover={allowDrop}>
|
||||||
{#if droppedMemory && isDroppedVisible}
|
{#if droppedMemory && isDroppedVisible}
|
||||||
<img src="/lucide_x.png" alt="Close" class="close-button" on:click={closeDroppedWheel} />
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
|
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
||||||
|
<!-- <img src="/lucide_x.png" alt="Close" class="close-button" on:click={closeDroppedWheel} /> -->
|
||||||
|
<button class="close-button" on:click={closeDroppedWheel} aria-label="Close">
|
||||||
|
<i class="fa-solid fa-xmark"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
<div class="dropped-mask">
|
<div class="dropped-mask">
|
||||||
<div class="dropped-wheel" style={droppedWheelStyle}>
|
<div class="dropped-wheel" style={droppedWheelStyle}>
|
||||||
|
@ -366,15 +386,18 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if droppedCurrentImage}
|
{#if droppedCurrentImage}
|
||||||
|
<!-- svelte-ignore a11y_img_redundant_alt -->
|
||||||
<img class="dropped-img" src={droppedCurrentImage} alt="Dropped Image" />
|
<img class="dropped-img" src={droppedCurrentImage} alt="Dropped Image" />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="dropped-controls">
|
<div class="dropped-controls">
|
||||||
|
<!-- svelte-ignore a11y_consider_explicit_label -->
|
||||||
<button on:click={prevDroppedImage}>
|
<button on:click={prevDroppedImage}>
|
||||||
<img src="/lucide_chevron-up.png" alt="Up" width="24" height="24" />
|
<i class="fa-solid fa-chevron-up"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<!-- svelte-ignore a11y_consider_explicit_label -->
|
||||||
<button on:click={nextDroppedImage}>
|
<button on:click={nextDroppedImage}>
|
||||||
<img src="/lucide_chevron-down.png" alt="Down" width="24" height="24" />
|
<i class="fa-solid fa-chevron-down"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -400,6 +423,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
@ -595,10 +619,13 @@
|
||||||
|
|
||||||
.close-button {
|
.close-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
color: white;
|
||||||
top: -48px;
|
top: -48px;
|
||||||
right: 2rem;
|
right: 2rem;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user