Make map nodes selectable and stylish
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
toqvist 2024-04-05 15:03:18 +02:00
parent 12c43e9a00
commit ed420d5ff1
3 changed files with 121 additions and 95 deletions

View File

@ -1,4 +1,4 @@
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { MapContainer, TileLayer, Marker, CircleMarker, Popup, Polyline, LayerGroup, GeoJSON, } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import L, { LatLngBounds } from 'leaflet';
@ -7,30 +7,33 @@ import { useQuery, useMutation, useQueryClient, queryOptions } from "@tanstack/r
import axios from "axios";
//Todo: Move types to own file
type User = {
interface User {
name: string;
id: string;
email: string;
phoneNumber: string;
}
type Product = {
interface Node {
name: string;
id: string;
title: string;
}
interface Product extends Node {
id: string;
name: string;
weight?: number;
picture: string;
createdAt: string;
updatedAt: string;
};
// type Location = {
// interface Location = {
// latitude: number;
// longitude: number;
// }
type Maker = {
id: string;
name: string;
interface Maker extends Node {
email: string;
phoneNumber?: string;
location: [number, number];
@ -39,9 +42,7 @@ type Maker = {
updatedAt: string;
};
type Retailer = {
id: string;
name: string;
interface Retailer extends Node {
email: string;
phoneNumber?: string;
location: [number, number];
@ -53,7 +54,7 @@ type Retailer = {
const DISPATCH_STATUS = ['requested', 'accepted', 'archived'] as const;
type DispatchStatus = typeof DISPATCH_STATUS[number];
type Dispatch = {
interface Dispatch {
id: string;
dispatchesCode?: string; //Human readable id
createdAt: string;
@ -164,25 +165,40 @@ const dashColors: Record<DispatchStatus, string> = {
archived: '#000',
}
const dashColorSelected: string = '#f87171' //same as tw red 400
const dashOpacities: Record<DispatchStatus, number> = {
requested: 0.7,
accepted: 0.7,
archived: 0.5
}
export const KiosMap = () => {
const { data: makers, isLoading: isLoadingMakers } = useGetMakers();
const { data: retailers, isLoading: isLoadingRetailers } = useGetRetailers();
const { data: dispatches, isLoading: isLoadingDispatches } = useGetDispatches();
const [selectedNodeId, setSelectedNodeId] = useState<string>('')
const handleSelectNode = (nodeId: string) => {
setSelectedNodeId(nodeId)
console.log("set id:", nodeId)
}
const blackDotIcon = L.divIcon({
className: 'bg-gray-950 rounded-full',
iconSize: [20, 20],
iconAnchor: [10, 10]
});
const selectedDotIcon = L.divIcon({
className: 'bg-red-400 rounded-full ring-offset-2 ring-4 ring-red-400 ring-dashed',
iconSize: [20, 20],
iconAnchor: [10, 10]
});
const bounds = new LatLngBounds(
[-90, -180], // Southwest corner
@ -191,7 +207,9 @@ export const KiosMap = () => {
return (
<div className='w-full flex justify-center align-middle'>
<div className=''>
<div></div>
</div>
<MapContainer
id="map"
center={[-6.1815, 106.8228]}
@ -209,11 +227,14 @@ export const KiosMap = () => {
<LayerGroup>
{makers.map((maker: any, index: number) => (
<Marker
key={index}
eventHandlers={{
click: () => handleSelectNode(maker.id)
}}
key={maker.id}
position={[locationSwitcharoo(maker.location)[0], locationSwitcharoo(maker.location)[1]]}
icon={blackDotIcon}
icon={selectedNodeId === maker.id ? selectedDotIcon : blackDotIcon}
>
<Popup>{maker.name}</Popup>
{/* <Popup>{maker.name}</Popup> */}
</Marker>
))}
</LayerGroup>
@ -223,11 +244,14 @@ export const KiosMap = () => {
<LayerGroup>
{retailers.map((retailer: any, index: number) => (
<Marker
key={index}
eventHandlers={{
click: () => handleSelectNode(retailer.id)
}}
key={retailer.id}
position={[locationSwitcharoo(retailer.location)[0], locationSwitcharoo(retailer.location)[1]]}
icon={blackDotIcon}
icon={selectedNodeId === retailer.id ? selectedDotIcon : blackDotIcon}
>
<Popup>{retailer.name}</Popup>
{/* <Popup>{retailer.name}</Popup> */}
</Marker>
))}
</LayerGroup>
@ -256,13 +280,15 @@ export const KiosMap = () => {
const dashOpacity: number = dashOpacities[status]
return (
<div key={index}>
<Polyline
eventHandlers={{
click: () => handleSelectNode(dispatch.id)
}}
key={dispatch.id}
positions={[[start[0], start[1]], [end[0], end[1]]]}
color={dashColor}
pathOptions={{color: selectedNodeId === dispatch.id ? dashColorSelected : dashColor}}
opacity={dashOpacity}
dashArray={dashArray} />
</div>
);
}
})}

View File

@ -63,7 +63,7 @@ export interface Dispatch {
}
export interface Product {
id: string;
title: string;
name: string;
picture: string | Media;
weight?: number;
updatedAt: string;

View File

@ -3,14 +3,14 @@ import { CollectionConfig } from 'payload/types';
const Products: CollectionConfig = {
slug: 'products',
admin: {
useAsTitle: 'title',
useAsTitle: 'name',
},
access: {
read: () => true,
},
fields: [
{
name: 'title',
name: 'name',
type: 'text',
required: true,
},