show marker in WorldMap
This commit is contained in:
parent
422c39e3e1
commit
c7c4153220
|
@ -83,9 +83,9 @@
|
||||||
{#if fullPlace.desc}
|
{#if fullPlace.desc}
|
||||||
<p class="place-desc">{fullPlace.desc}</p>
|
<p class="place-desc">{fullPlace.desc}</p>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="plan-time">
|
<!-- <div class="plan-time">
|
||||||
<button class="edit-time">{fullPlace.time}</button>
|
<button class="edit-time">{fullPlace.time}</button>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -236,7 +236,7 @@
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-time {
|
/* .edit-time {
|
||||||
background-color: var(--gray-200);
|
background-color: var(--gray-200);
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
|
@ -249,5 +249,5 @@
|
||||||
|
|
||||||
.edit-time:hover {
|
.edit-time:hover {
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
}
|
} */
|
||||||
</style>
|
</style>
|
|
@ -4,10 +4,62 @@
|
||||||
import { feature } from 'topojson-client';
|
import { feature } from 'topojson-client';
|
||||||
import { Colors } from '../constants/Colors';
|
import { Colors } from '../constants/Colors';
|
||||||
import '../../app.css';
|
import '../../app.css';
|
||||||
|
import { ref, get } from 'firebase/database';
|
||||||
|
import { db } from '../../firebase';
|
||||||
|
|
||||||
let mapContainer: HTMLDivElement;
|
let mapContainer: HTMLDivElement;
|
||||||
|
|
||||||
|
interface TripLocation {
|
||||||
|
name: string;
|
||||||
|
location: {
|
||||||
|
lat: number;
|
||||||
|
lng: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPastTripLocations(): Promise<TripLocation[]> {
|
||||||
|
try {
|
||||||
|
const tripsRef = ref(db, 'trips');
|
||||||
|
const snapshot = await get(tripsRef);
|
||||||
|
|
||||||
|
if (!snapshot.exists()) return [];
|
||||||
|
|
||||||
|
// Get today's date at midnight for comparison
|
||||||
|
const today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
// Create a Set to store unique locations
|
||||||
|
const uniqueLocations = new Map<string, TripLocation>();
|
||||||
|
|
||||||
|
// Filter past trips and extract unique destinations
|
||||||
|
Object.values(snapshot.val()).forEach((trip: any) => {
|
||||||
|
const endDate = new Date(trip.endDate);
|
||||||
|
if (endDate < today && trip.destination?.location) {
|
||||||
|
const locationKey = `${trip.destination.location.lat},${trip.destination.location.lng}`;
|
||||||
|
if (!uniqueLocations.has(locationKey)) {
|
||||||
|
uniqueLocations.set(locationKey, {
|
||||||
|
name: trip.destination.name,
|
||||||
|
location: trip.destination.location
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Array.from(uniqueLocations.values());
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching past trips:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let cleanup: (() => void) | undefined;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
let mounted = true;
|
||||||
|
|
||||||
|
async function initMap() {
|
||||||
|
if (!mounted) return;
|
||||||
|
|
||||||
const width = mapContainer.clientWidth;
|
const width = mapContainer.clientWidth;
|
||||||
const height = mapContainer.clientHeight;
|
const height = mapContainer.clientHeight;
|
||||||
|
|
||||||
|
@ -16,8 +68,8 @@
|
||||||
.append('svg')
|
.append('svg')
|
||||||
.attr('width', '100%')
|
.attr('width', '100%')
|
||||||
.attr('height', '100%')
|
.attr('height', '100%')
|
||||||
.attr('viewBox', `0 0 ${width} ${height}`) // make a coordinate from (0, 0) to (width, height)
|
.attr('viewBox', `0 0 ${width} ${height}`)
|
||||||
.attr('preserveAspectRatio', 'xMidYMid meet') as d3.Selection<SVGSVGElement, unknown, null, undefined>; // center the map
|
.attr('preserveAspectRatio', 'xMidYMid meet') as d3.Selection<SVGSVGElement, unknown, null, undefined>;
|
||||||
|
|
||||||
// Add a group for all map elements that will be transformed
|
// Add a group for all map elements that will be transformed
|
||||||
const g = svg.append('g');
|
const g = svg.append('g');
|
||||||
|
@ -29,13 +81,14 @@
|
||||||
|
|
||||||
const path = d3.geoPath().projection(projection);
|
const path = d3.geoPath().projection(projection);
|
||||||
|
|
||||||
// Tokyo coordinates [longitude, latitude]
|
|
||||||
const tokyo: [number, number] = [139.6917, 35.6895];
|
|
||||||
|
|
||||||
const initMap = async () => {
|
|
||||||
try {
|
try {
|
||||||
|
// Get past trip locations
|
||||||
|
const pastLocations = await getPastTripLocations();
|
||||||
|
if (!mounted) return;
|
||||||
|
|
||||||
// Load world map data
|
// Load world map data
|
||||||
const response = await fetch('https://unpkg.com/world-atlas@2/countries-110m.json');
|
const response = await fetch('https://unpkg.com/world-atlas@2/countries-110m.json');
|
||||||
|
if (!mounted) return;
|
||||||
const world = await response.json();
|
const world = await response.json();
|
||||||
|
|
||||||
// Convert TopoJSON to GeoJSON
|
// Convert TopoJSON to GeoJSON
|
||||||
|
@ -53,13 +106,16 @@
|
||||||
.attr('stroke', Colors.gray.light50)
|
.attr('stroke', Colors.gray.light50)
|
||||||
.attr('stroke-width', '0.5');
|
.attr('stroke-width', '0.5');
|
||||||
|
|
||||||
// Add Tokyo marker
|
// Add markers for past trip locations
|
||||||
g.append('circle')
|
g.selectAll('circle')
|
||||||
.attr('cx', projection(tokyo)![0])
|
.data(pastLocations)
|
||||||
.attr('cy', projection(tokyo)![1])
|
.enter()
|
||||||
|
.append('circle')
|
||||||
|
.attr('cx', d => projection([d.location.lng, d.location.lat])![0])
|
||||||
|
.attr('cy', d => projection([d.location.lng, d.location.lat])![1])
|
||||||
.attr('r', 5)
|
.attr('r', 5)
|
||||||
.attr('class', 'marker')
|
.attr('class', 'marker')
|
||||||
.attr('fill', Colors.planner.med400);
|
.attr('fill', Colors.planner.med400)
|
||||||
|
|
||||||
// Add zoom behavior
|
// Add zoom behavior
|
||||||
const zoom = d3.zoom<SVGSVGElement, unknown>()
|
const zoom = d3.zoom<SVGSVGElement, unknown>()
|
||||||
|
@ -70,16 +126,20 @@
|
||||||
|
|
||||||
svg.call(zoom)
|
svg.call(zoom)
|
||||||
.call(zoom.transform, d3.zoomIdentity);
|
.call(zoom.transform, d3.zoomIdentity);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading map:', error);
|
console.error('Error initializing map:', error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
initMap();
|
initMap();
|
||||||
|
|
||||||
return () => {
|
cleanup = () => {
|
||||||
|
mounted = false;
|
||||||
d3.select(mapContainer).selectAll('*').remove();
|
d3.select(mapContainer).selectAll('*').remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return cleanup;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -259,7 +259,7 @@
|
||||||
tripDates = dates;
|
tripDates = dates;
|
||||||
|
|
||||||
// initialize expanded states for dates
|
// initialize expanded states for dates
|
||||||
expandedDates = Object.fromEntries(dates.map(date => [date, false]));
|
expandedDates = Object.fromEntries(dates.map(date => [date, true]));
|
||||||
|
|
||||||
// initialize placesToVisit from database or empty array
|
// initialize placesToVisit from database or empty array
|
||||||
placesToVisit = tripData.placesToVisit || [];
|
placesToVisit = tripData.placesToVisit || [];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user