Added marker highlighting when hovering table.

main
Eloi Zalczer 2024-06-18 18:04:21 +02:00
parent fa49ed91a8
commit 0dae1684d1
4 changed files with 81 additions and 9 deletions

View File

@ -7,36 +7,66 @@ import LatLng from "../models/map";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { useRestaurantsStore } from "../stores/restaurants"; import { useRestaurantsStore } from "../stores/restaurants";
const initialMap = ref<L.Map | null>(null); const map = ref<L.Map | null>(null);
const { restaurants } = storeToRefs(useRestaurantsStore()); const { restaurants } = storeToRefs(useRestaurantsStore());
const props = defineProps({
highlighted: { type: String },
});
const emit = defineEmits({ const emit = defineEmits({
clicked: (latlng: LatLng) => true, clicked: (latlng: LatLng) => true,
}); });
const markers = ref<Map<string, L.Marker>>(new Map());
onMounted(() => { onMounted(() => {
initialMap.value = L.map("map").setView([48.8363012, 2.240709935], 14); map.value = L.map("map").setView([48.8363012, 2.240709935], 14);
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 19, maxZoom: 19,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>', attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
}).addTo(initialMap.value); }).addTo(map.value);
initialMap.value!.on("click", function (e) { map.value!.on("click", function (e) {
emit("clicked", e.latlng); emit("clicked", e.latlng);
}); });
watch( watch(
() => restaurants.value, () => restaurants.value,
async (newval, oldval) => { async (newval, oldval) => {
markers.value.forEach((marker) => marker.remove());
markers.value.clear();
restaurants.value?.forEach((restaurant) => { restaurants.value?.forEach((restaurant) => {
const marker = L.marker({ lat: restaurant.latitude, lng: restaurant.longitude }); const marker = L.marker({ lat: restaurant.latitude, lng: restaurant.longitude });
marker.bindPopup(`<p>${restaurant.name}</p>`); marker.bindPopup(`<p>${restaurant.name}</p>`);
marker.addTo(initialMap.value); marker.addTo(map.value);
markers.value.set(restaurant.id, marker);
}); });
}, },
{ immediate: true } { immediate: true }
); );
watch(
() => props.highlighted,
(newval, oldval) => {
console.log(markers.value);
if (oldval != null) {
var old = markers.value.get(oldval);
console.log("old", old, oldval);
if (old.isPopupOpen()) {
old.closePopup();
}
}
if (newval != null) {
var marker = markers.value.get(newval);
console.log("new", marker, newval);
if (!marker.isPopupOpen()) {
marker.openPopup();
}
}
}
);
}); });
</script> </script>

View File

@ -6,11 +6,12 @@ import DataTablesCore from "datatables.net";
import "datatables.net-select"; import "datatables.net-select";
import { PropType, ref } from "vue"; import { PropType, ref } from "vue";
import RatingField from "./RatingField.vue"; import RatingField from "./RatingField.vue";
import Restaurant from "../models/restaurant";
DataTable.use(DataTablesCore); DataTable.use(DataTablesCore);
const props = defineProps({ const props = defineProps({
data: { type: Array as PropType<Object[]> }, data: { type: Array as PropType<Restaurant[]> },
}); });
const columns = [ const columns = [
@ -31,7 +32,35 @@ function deselectAll() {
table.value?.dt.rows({ selected: true }).deselect(); table.value?.dt.rows({ selected: true }).deselect();
} }
const emit = defineEmits(["restaurantSelected"]); const emit = defineEmits({
restaurantSelected: (restaurant: Object) => true,
restaurantHovered: (restaurant: Object | null) => true,
});
const hovered = ref<Restaurant | null>();
function onMouseOver(e) {
const row = e.target?._DT_CellIndex?.row;
console.log("row", row);
if (row !== undefined && props.data !== undefined) {
if (hovered.value != props.data[row]) {
emit("restaurantHovered", props.data[row].id);
}
hovered.value = props.data[row];
} else {
if (hovered.value !== null) {
emit("restaurantHovered", null);
console.log("hovered");
}
hovered.value = null;
}
}
function onMouseLeave() {
emit("restaurantHovered", null);
hovered.value = null;
}
defineExpose({ deselectAll }); defineExpose({ deselectAll });
</script> </script>
@ -40,6 +69,8 @@ defineExpose({ deselectAll });
<DataTable <DataTable
class="table" class="table"
ref="table" ref="table"
@mouseover="onMouseOver"
@mouseleave="onMouseLeave"
:columns="columns" :columns="columns"
:data="props.data" :data="props.data"
:options="{ :options="{

View File

@ -1,4 +1,5 @@
export default interface Restaurant { export default interface Restaurant {
id: string;
name: string; name: string;
tags: string[]; tags: string[];
price: string; price: string;

View File

@ -14,6 +14,7 @@ const drawer = ref<typeof ReviewsDrawer>();
const table = ref<typeof RestaurantsTable>(); const table = ref<typeof RestaurantsTable>();
const selectedRestaurant = ref<Object>(); const selectedRestaurant = ref<Object>();
const highlightedRestaurant = ref<string>();
const { restaurants } = storeToRefs(useRestaurantsStore()); const { restaurants } = storeToRefs(useRestaurantsStore());
@ -22,6 +23,10 @@ function onRestaurantSelected(restaurant: Object) {
drawer.value?.open(); drawer.value?.open();
} }
function onRestaurantHovered(id: string) {
highlightedRestaurant.value = id;
}
function onDrawerClosed() { function onDrawerClosed() {
console.log("closed"); console.log("closed");
table.value?.deselectAll(); table.value?.deselectAll();
@ -31,10 +36,15 @@ function onDrawerClosed() {
<template> <template>
<div class="flex flex-col-reverse sm:flex-row"> <div class="flex flex-col-reverse sm:flex-row">
<div class="w-full flex-1"> <div class="w-full flex-1">
<RestaurantsTable ref="table" @restaurant-selected="onRestaurantSelected" :data="restaurants" /> <RestaurantsTable
ref="table"
@restaurant-selected="onRestaurantSelected"
@restaurant-hovered="onRestaurantHovered"
:data="restaurants"
/>
</div> </div>
<div class="flex-1 h-3/6 lg:h-full"> <div class="flex-1 h-3/6 lg:h-full">
<RestaurantsMap /> <RestaurantsMap :highlighted="highlightedRestaurant" />
</div> </div>
</div> </div>