Basic node information mostly done

This commit is contained in:
toqvist 2024-04-05 18:41:53 +02:00
parent ed420d5ff1
commit 0645bbd877
5 changed files with 158 additions and 17 deletions

View File

@ -0,0 +1,25 @@
import React from 'react'
type Props = {
name: string | undefined;
email?: string | undefined;
phoneNumber?: string | undefined;
role: 'maker' | 'retailer' | 'courier'
}
const roleLabels = {
maker: "Maker",
retailer: "Retailer",
courier: "Courier",
}
export default function Contacts(props: Props) {
return (
<div className='flex flex-col'>
{props.name && <p className='text-sm font-light'>{roleLabels[props.role]}:</p>}
{props.name && <h2 className='text-xl font-bold underline-offset-2 underline py-2'>{props.name}</h2>}
{props.phoneNumber && <p>Phone Number: <span className='font-semibold'>{props.phoneNumber}</span></p>}
{props.email && <p>Email: <span className='font-semibold'>{props.email}</span></p>}
</div>
)
}

View File

@ -5,6 +5,7 @@ import L, { LatLngBounds } from 'leaflet';
import { useQuery, useMutation, useQueryClient, queryOptions } from "@tanstack/react-query";
import axios from "axios";
import Contacts from './Contacts';
//Todo: Move types to own file
interface User {
@ -60,8 +61,8 @@ interface Dispatch {
createdAt: string;
updatedAt: string;
maker?: Maker;
retailer?: Retailer;
maker: Maker;
retailer: Retailer;
products: Product[];
courier?: User;
@ -173,19 +174,45 @@ const dashOpacities: Record<DispatchStatus, number> = {
archived: 0.5
}
interface NodeSelection {
id: string,
type: "maker" | "retailer" | "dispatch" | "none"
}
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 [selectedNode, setSelectedNode] = useState<NodeSelection>({ id: "", type: "none" })
const handleSelectNode = (nodeId: string) => {
setSelectedNodeId(nodeId)
let selectedMaker: Maker | undefined = undefined;
let selectedRetailer: Retailer | undefined = undefined;
let selectedDispatch: Dispatch | undefined = undefined;
if (selectedNode.type === "maker" && makers) {
selectedMaker = makers.find(maker => maker.id === selectedNode.id && selectedNode.type === "maker");
}
if (selectedNode.type === "retailer" && retailers) {
selectedRetailer = retailers.find(retailer => retailer.id === selectedNode.id && selectedNode.type === "retailer");
}
if (selectedNode.type === "dispatch" && dispatches) {
selectedDispatch = dispatches.find(dispatch => dispatch.id === selectedNode.id && selectedNode.type === "dispatch");
}
const handleSelectNode = (nodeId: string, typeParam: "maker" | "retailer" | "dispatch" | "none") => {
setSelectedNode({ id: nodeId, type: typeParam })
console.log("set id:", nodeId)
}
const handleAcceptRoute = () => {
}
const blackDotIcon = L.divIcon({
className: 'bg-gray-950 rounded-full',
iconSize: [20, 20],
@ -207,9 +234,71 @@ export const KiosMap = () => {
return (
<div className='w-full flex justify-center align-middle'>
<div className=''>
<div></div>
</div>
{
selectedNode.type !== 'none' && (
<div className='absolute bg-white border-gray-950 border-2 z-[999] left-10 top-1/4 p-4'>
<div className='flex gap-8 flex-col'>
{selectedMaker !== undefined && (
<Contacts
name={selectedMaker.name}
email={selectedMaker.email}
phoneNumber={selectedMaker.phoneNumber}
role={'maker'}
/>
)}
{selectedRetailer !== undefined && (
<Contacts
name={selectedRetailer.name}
email={selectedRetailer.email}
phoneNumber={selectedRetailer.phoneNumber}
role={'retailer'}
/>
)}
{selectedDispatch !== undefined && (
<div className='flex flex-col gap-4'>
<Contacts
name={selectedDispatch.maker.name}
email={selectedDispatch.maker.email}
phoneNumber={selectedDispatch.maker.phoneNumber}
role={'maker'}
/>
<Contacts
name={selectedDispatch.retailer.name}
email={selectedDispatch.retailer.email}
phoneNumber={selectedDispatch.retailer.phoneNumber}
role={'retailer'}
/>
{selectedDispatch.courier !== undefined ? (
<Contacts
name={selectedDispatch.courier.name}
email={selectedDispatch.courier.email}
phoneNumber={selectedDispatch.courier.phoneNumber}
role={'courier'}
/>
) :
<div>
<h2 className='text-xl font-bold underline-offset-2 underline py-2'>No courier!</h2>
<button
className="border-2 border-gray-950 py-2 px-4 w-full hover:bg-gray-950 transition-all hover:text-white hover:font-bold"
onClick={() => handleAcceptRoute()}
>
Accept route as courier
</button>
</div>
}
</div>
)}
</div>
</div>
)
}
<MapContainer
id="map"
center={[-6.1815, 106.8228]}
@ -220,6 +309,9 @@ export const KiosMap = () => {
>
<TileLayer url="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
maxZoom={19}
eventHandlers={{
click: () => handleSelectNode("", "none")
}}
attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
/>
@ -227,12 +319,12 @@ export const KiosMap = () => {
<LayerGroup>
{makers.map((maker: any, index: number) => (
<Marker
eventHandlers={{
click: () => handleSelectNode(maker.id)
}}
key={maker.id}
eventHandlers={{
click: () => handleSelectNode(maker.id, "maker")
}}
key={maker.id}
position={[locationSwitcharoo(maker.location)[0], locationSwitcharoo(maker.location)[1]]}
icon={selectedNodeId === maker.id ? selectedDotIcon : blackDotIcon}
icon={selectedNode.id === maker.id ? selectedDotIcon : blackDotIcon}
>
{/* <Popup>{maker.name}</Popup> */}
</Marker>
@ -245,11 +337,11 @@ export const KiosMap = () => {
{retailers.map((retailer: any, index: number) => (
<Marker
eventHandlers={{
click: () => handleSelectNode(retailer.id)
click: () => handleSelectNode(retailer.id, "retailer")
}}
key={retailer.id}
position={[locationSwitcharoo(retailer.location)[0], locationSwitcharoo(retailer.location)[1]]}
icon={selectedNodeId === retailer.id ? selectedDotIcon : blackDotIcon}
icon={selectedNode.id === retailer.id ? selectedDotIcon : blackDotIcon}
>
{/* <Popup>{retailer.name}</Popup> */}
</Marker>
@ -282,11 +374,11 @@ export const KiosMap = () => {
return (
<Polyline
eventHandlers={{
click: () => handleSelectNode(dispatch.id)
click: () => handleSelectNode(dispatch.id, "dispatch")
}}
key={dispatch.id}
positions={[[start[0], start[1]], [end[0], end[1]]]}
pathOptions={{color: selectedNodeId === dispatch.id ? dashColorSelected : dashColor}}
pathOptions={{ color: selectedNode.id === dispatch.id ? dashColorSelected : dashColor }}
opacity={dashOpacity}
dashArray={dashArray} />
);

View File

@ -72,6 +72,8 @@ export interface Product {
export interface Maker {
id: string;
name: string;
phoneNumber?: string;
email?: string;
/**
* @minItems 2
* @maxItems 2
@ -84,6 +86,8 @@ export interface Maker {
export interface Retailer {
id: string;
name: string;
phoneNumber?: string;
email?: string;
/**
* @minItems 2
* @maxItems 2

View File

@ -14,6 +14,16 @@ const Makers: CollectionConfig = {
type: 'text',
required: true,
},
{
name: 'phoneNumber',
type: 'text',
required: false
},
{
name: 'email',
type: 'email',
required: false
},
{
name: 'location',
type: 'point',

View File

@ -15,6 +15,16 @@ const Retailers: CollectionConfig = {
type: 'text',
required: true,
},
{
name: 'phoneNumber',
type: 'text',
required: false
},
{
name: 'email',
type: 'email',
required: false
},
{
name: 'location',
type: 'point',