making pins clickable + adding the corresponding panels/buttons

This commit is contained in:
2026-06-06 15:41:51 +09:00
parent b8567ef513
commit bd9e4f652b
4 changed files with 213 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
<script>
import { mapStore } from '$lib/stores/mapStore.js';
let { message } = $props();
</script>
<!-- if message exists, sheet is visible -->
<div class="sheet" class:visible={!!message}>
{#if message}
<div class="handle"> </div>
<div class="content">
<p class="message-text">{message.text}</p>
<p class="meta">
left {message.lat.toFixed(4)}, {message.lng.toFixed(4)}
</p>
<div class="actions">
<button class="echo-button">Echo</button>
<button class="letgo-button" onclick={() => mapStore.set(
{ selectedMessage: null, composing: false })}>
let go
</button>
</div>
</div>
{/if}
</div>
<style>
.sheet {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
border-radius: 20px 20px 0 0;
padding: 1rem 1.5rem 2rem;
box-shadow: 0 -4px 20px rgba(0,0,0,0.15);
transform: translateY(100%);
transition: transform 0.35s cubic-bezier(0.32, 0.72, 0, 1);
z-index: 100;
}
.sheet.visible {
transform: translateY(0);
}
.handle {
width: 40px;
height: 4px;
background: #ddd;
border-radius: 2px;
margin: 0 auto 1rem;
}
.message-text {
font-size: 1rem;
line-height: 1.6;
margin-bottom: 0.5rem;
color: #111;
}
.meta {
font-size: 0.75rem;
color: #999;
margin-bottom: 1.2rem;
}
.actions {
display: flex;
gap: 0.75rem;
}
.echo-button {
flex: 1;
padding: 0.75rem;
background: #111;
color: white;
border: none;
border-radius: 10px;
font-size: 0.95rem;
cursor: pointer;
}
.letgo-button {
flex: 1;
padding: 0.75rem;
background: transparent;
color: #111;
border: 1.5px solid #ddd;
border-radius: 10px;
font-size: 0.95rem;
cursor: pointer;
}
</style>

View File

@@ -2,6 +2,7 @@
import { onMount } from 'svelte';
import { env } from '$env/dynamic/public';
import { messagesStore } from '$lib/stores/messagesStore.js'; // pass the messages store here
import { mapStore } from '$lib/stores/mapStore.js'; // use this to track interactions with da map
// export let latitude;
// export let longitude;
@@ -44,6 +45,11 @@
map: mapDiv,
title: message.text // firestore field for messages
});
marker.addListener('click', () => {
mapStore.set({ selectedMessage: message, composing: false}); //it updated the message object
});
markers.push(marker); // add the new pin to the array
});
}

View File

@@ -0,0 +1,92 @@
<script>
import { mapStore } from '$lib/stores/mapStore.js';
let { message } = $props();
</script>
<div class = "panel">
{#if message}
<div class="content">
<p class="message-text">{message.text}</p>
<p class="meta">
left {message.lat.toFixed(4)}, {message.lng.toFixed(4)}
</p>
<div class="actions">
<button class="echo-button">Echo</button>
<button class="letgo-button" onclick={() => mapStore.set(
{selectedMessage: null, composing: false})}>
Let go
</button>
</div>
</div>
{:else}
<div class="empty">
<p>Tap a pin to read a message</p>
</div>
{/if}
</div>
<style>
.panel {
position: fixed;
top: 0;
left: 0;
width: 320px;
height: 100vh;
background: white;
box-shadow: 2px 0 12px rgba(0,0,0,0.1);
padding: 2rem 1.5rem;
z-index: 100;
overflow-y: auto;
}
.message-text{
font-size: 1rem;
line-height: 1.6;
color: #111;
margin-bottom: 0.5rem;
}
.meta {
font-size: 1rem;
line-height: 1.6;
color: #111;
margin-bottom: 0.5rem;
}
.actions {
display: flex;
gap: 0.75rem;
}
.echo-button {
flex: 1;
padding: 0.75rem;
background: #111;
color: white;
border: none;
border-radius: 10px;
font-size: 0.95rem;
cursor: pointer;
}
.letgo-button {
flex: 1;
padding: 0..75rem;
background: transparent;
color: #111;
border: 1.5px solid #ddd;
border-radius: 10px;
font-size: 0.95rem;
cursor: pointer;
}
.empty {
color: #999;
font-size: 0.9rem;
margin-top: 2rem;
text-align: center;
}
</style>

View File

@@ -4,12 +4,19 @@
import { getNearbyMessages } from '$lib/firebase/messages.js';
import { messagesStore } from '$lib/stores/messagesStore.js';
import { mapStore } from '$lib/stores/mapStore.js';
import BottomSheet from '$lib/components/BottomSheet.svelte';
import SidePanel from '$lib/components/SidePanel.svelte';
let lat = $state();
let lng = $state();
let error = $state();
let windowWidth = $state(0);
let isMobile = $derived(windowWidth < 768);
onMount(() => {
if (!navigator.geolocation) {
error = "Your browser doesn't support geolocation :(";
@@ -37,6 +44,8 @@
</script>
<svelte:window bind:innerWidth={windowWidth} /> <!--this sends the windowWidth to our mobile checker -->
{#if error}
<p class="error">{error}</p>
{:else if lat && lng}
@@ -45,6 +54,18 @@
<p class="loading">Looking for you...</p>
{/if}
<!-- map must fill the whole screen-->
{#if lat && lng}
<MapView {lat} {lng} />
{/if}
<!-- show the right panel based on mobile or desktop-->
{#if windowWidth < 768}
<BottomSheet message={$mapStore.selectedMessage} />
{:else}
<SidePanel message={$mapStore.selectedMessage} />
{/if}
<style>
:global(body) {
margin: 0;