import React = require('react'); import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IReactionDisposer, ObservableMap, action, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, NumListCast, Opt } from '../../../../fields/Doc'; import { returnFalse, setupMoveUpEvents, unimplementedFunction } from '../../../../Utils'; import { SelectionManager } from '../../../util/SelectionManager'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; // import { GPTPopup, GPTPopupMode } from './../../GPTPopup/GPTPopup'; import { Button, IconButton } from 'browndash-components'; import { SettingsManager } from '../../../util/SettingsManager'; import './MapAnchorMenu.scss'; import { NumCast, StrCast } from '../../../../fields/Types'; import { IconLookup, faDiamondTurnRight, faCalendarDays, faEdit, faAdd, faRoute, faArrowLeft, faLocationDot, faArrowDown, faCar, faBicycle, faPersonWalking, faUpload, faArrowsRotate, } from '@fortawesome/free-solid-svg-icons'; import { DirectionsAnchorMenu } from './DirectionsAnchorMenu'; import { Autocomplete, Checkbox, FormControlLabel, TextField } from '@mui/material'; import { MapboxApiUtility, TransportationType } from './MapboxApiUtility'; import { MapBox } from './MapBox'; import { List } from '../../../../fields/List'; import { MarkerIcons } from './MarkerIcons'; import { CirclePicker, ColorState } from 'react-color'; import { Position } from 'geojson'; type MapAnchorMenuType = 'standard' | 'routeCreation' | 'calendar' | 'customize' | 'route'; @observer export class MapAnchorMenu extends AntimodeMenu { static Instance: MapAnchorMenu; private _disposer: IReactionDisposer | undefined; private _commentRef = React.createRef(); private _fileInputRef = React.createRef(); public onMakeAnchor: () => Opt = () => undefined; // Method to get anchor from text search public Center: () => void = unimplementedFunction; public OnClick: (e: PointerEvent) => void = unimplementedFunction; // public OnAudio: (e: PointerEvent) => void = unimplementedFunction; public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public Highlight: (color: string, isTargetToggler: boolean, savedAnnotations?: ObservableMap, addAsAnnotation?: boolean) => Opt = (color: string, isTargetToggler: boolean) => undefined; public GetAnchor: (savedAnnotations: Opt>, addAsAnnotation: boolean) => Opt = (savedAnnotations: Opt>, addAsAnnotation: boolean) => undefined; public Delete: () => void = unimplementedFunction; // public MakeTargetToggle: () => void = unimplementedFunction; // public ShowTargetTrail: () => void = unimplementedFunction; public IsTargetToggler: () => boolean = returnFalse; public DisplayRoute: (routeInfoMap: Record | undefined, type: TransportationType) => void = unimplementedFunction; public HideRoute: () => void = unimplementedFunction; public AddNewRouteToMap: (coordinates: Position[], origin: string, destination: any, createPinForDestination: boolean) => void = unimplementedFunction; public CreatePin: (feature: any) => void = unimplementedFunction; public UpdateMarkerColor: (color: string) => void = unimplementedFunction; public UpdateMarkerIcon: (iconKey: string) => void = unimplementedFunction; public OpenAnimationPanel: (routeDoc: Doc | undefined) => void = unimplementedFunction; @observable menuType: MapAnchorMenuType = 'standard'; @action public setMenuType = (menuType: MapAnchorMenuType) => { this.menuType = menuType; } private allMapPinDocs: Doc[] = []; private pinDoc: Doc | undefined = undefined; private routeDoc: Doc | undefined = undefined; private title: string | undefined = undefined; public setPinDoc(pinDoc: Doc){ this.pinDoc = pinDoc; this.title = StrCast(pinDoc.title ? pinDoc.title : `${NumCast(pinDoc.longitude)}, ${NumCast(pinDoc.latitude)}`) ; } public setRouteDoc(routeDoc: Doc){ this.routeDoc = routeDoc; this.title = StrCast(routeDoc.title ?? 'Map route') } public setAllMapboxPins(pinDocs: Doc[]) { this.allMapPinDocs = pinDocs; pinDocs.forEach((p, idx) => { console.log(`Pin ${idx}: ${p.title}`); }) } public get Active() { return this._left > 0; } constructor(props: Readonly<{}>) { super(props); MapAnchorMenu.Instance = this; MapAnchorMenu.Instance._canFade = false; } componentWillUnmount() { this.destinationFeatures = []; this.destinationSelected = false; this.selectedDestinationFeature = undefined; this.currentRouteInfoMap = undefined; this._disposer?.(); } componentDidMount() { this._disposer = reaction( () => SelectionManager.Views().slice(), sel => MapAnchorMenu.Instance.fadeOut(true) ); } // audioDown = (e: React.PointerEvent) => { // setupMoveUpEvents(this, e, returnFalse, returnFalse, e => this.OnAudio?.(e)); // }; // cropDown = (e: React.PointerEvent) => { // setupMoveUpEvents( // this, // e, // (e: PointerEvent) => { // this.StartCropDrag(e, this._commentCont.current!); // return true; // }, // returnFalse, // e => this.OnCrop?.(e) // ); // }; notePointerDown = (e: React.PointerEvent) => { setupMoveUpEvents( this, e, (e: PointerEvent) => { this.StartDrag(e, this._commentRef.current!); return true; }, returnFalse, e => this.OnClick(e) ); }; static top = React.createRef(); // public get Top(){ // return this.top // } @action DirectionsClick = () => { this.menuType = 'routeCreation'; } @action CustomizeClick = () => { this.currentRouteInfoMap = undefined; this.menuType = 'customize'; } @action BackClick = () => { this.currentRouteInfoMap = undefined; this.menuType = 'standard'; } @action TriggerFileInputClick = () => { if (this._fileInputRef) { this._fileInputRef.current?.click(); // Trigger the file input click event } } @action onMarkerColorChange = (color: ColorState) => { if (this.pinDoc){ this.pinDoc.markerColor = color.hex; } } revertToOriginalMarker = () => { if (this.pinDoc) { this.pinDoc.markerType = "MAP_PIN"; this.pinDoc.markerColor = "#ff5722"; } } onMarkerIconChange = (iconKey: string) => { if (this.pinDoc) { this.pinDoc.markerType = iconKey; } } @observable destinationFeatures: any[] = [] @observable destinationSelected: boolean = false; @observable selectedDestinationFeature: any = undefined; @observable createPinForDestination: boolean = true; @observable currentRouteInfoMap: Record | undefined = undefined; @observable selectedTransportationType: TransportationType = 'driving'; @action handleTransportationTypeChange = (newType: TransportationType) => { if (newType !== this.selectedTransportationType){ this.selectedTransportationType = newType; this.DisplayRoute(this.currentRouteInfoMap, newType); } } @action handleSelectedDestinationFeature = (destinationFeature: any) => { this.selectedDestinationFeature = destinationFeature; } @action toggleCreatePinForDestinationCheckbox = () => { this.createPinForDestination = !this.createPinForDestination; } @action handleDestinationSearchChange = async (searchText: string) => { if (this.selectedDestinationFeature !== undefined) this.selectedDestinationFeature = undefined; const features = await MapboxApiUtility.forwardGeocodeForFeatures(searchText); if (features){ runInAction(() => { this.destinationFeatures = features; }) } } getRoutes = async (destinationFeature: any) => { const currentPinLong: number = NumCast(this.pinDoc?.longitude); const currentPinLat: number = NumCast(this.pinDoc?.latitude); if (currentPinLong && currentPinLat && destinationFeature.center){ const routeInfoMap = await MapboxApiUtility.getDirections([currentPinLong, currentPinLat], destinationFeature.center); if (routeInfoMap) { runInAction(() => { this.currentRouteInfoMap = routeInfoMap; }) this.DisplayRoute(routeInfoMap, 'driving'); } } // get route menu, set it equal to here // create a temporary route // create pin if createPinForDestination was clicked } HandleAddRouteClick = () => { if (this.currentRouteInfoMap && this.selectedTransportationType && this.selectedDestinationFeature){ const coordinates = this.currentRouteInfoMap[this.selectedTransportationType].coordinates; console.log(coordinates); console.log(this.selectedDestinationFeature); this.AddNewRouteToMap(coordinates, this.title ?? "", this.selectedDestinationFeature, this.createPinForDestination); this.HideRoute(); } } getMarkerIcon = (): JSX.Element | undefined => { if (this.pinDoc){ const markerType = StrCast(this.pinDoc.markerType); const markerColor = StrCast(this.pinDoc.markerColor); return MarkerIcons.getFontAwesomeIcon(markerType, '2x', markerColor); } return undefined; } render() { const buttons = (
{this.menuType === 'standard' && <> } color={SettingsManager.userColor} /> } color={SettingsManager.userColor} /> } color={SettingsManager.userColor} />
} color={SettingsManager.userColor} />
} color={SettingsManager.userColor} /> } color={SettingsManager.userColor} /> } {this.menuType === 'routeCreation' && <> } color={SettingsManager.userColor} /> } color={SettingsManager.userColor} /> } {this.menuType === 'route' && <> } color={SettingsManager.userColor} /> this.OpenAnimationPanel(this.routeDoc)} /**TODO: fix */ icon={} color={SettingsManager.userColor} />
} color={SettingsManager.userColor} />
} color={SettingsManager.userColor} /> } {this.menuType === 'customize' && <> } color={SettingsManager.userColor} /> this.revertToOriginalMarker()} icon={} color={SettingsManager.userColor} /> } {/* {this.IsTargetToggler !== returnFalse && ( } color={SettingsManager.userColor} /> )} */}
); // return ( //
// HELLO THIS IS ANCHOR MENU // {this.getElement(buttons)} //
// ) return this.getElement(
{this.menuType === 'standard' &&
{this.title}
} {this.menuType === 'routeCreation' &&
this.handleDestinationSearchChange(searchText)} onChange={(e, feature, reason) => { if (reason === 'clear'){ this.handleSelectedDestinationFeature(undefined); } else if (reason === 'selectOption'){ this.handleSelectedDestinationFeature(feature); } }} options={this.destinationFeatures .filter(feature => feature.place_name) .map(feature => feature)} getOptionLabel={(feature) => feature.place_name} renderInput={(params) => ( )} /> {this.selectedDestinationFeature && <> {!this.allMapPinDocs.some(pinDoc => pinDoc.title === this.selectedDestinationFeature.place_name) &&
} />
} } {/* */}
} {this.currentRouteInfoMap &&
this.handleTransportationTypeChange('driving')} icon={} color={this.selectedTransportationType === 'driving' ? 'lightblue': 'grey'} /> this.handleTransportationTypeChange('cycling')} icon={} color={this.selectedTransportationType === 'cycling' ? 'lightblue': 'grey'} /> this.handleTransportationTypeChange('walking')} icon={} color={this.selectedTransportationType === 'walking' ? 'lightblue': 'grey'} />
Duration: {this.currentRouteInfoMap[this.selectedTransportationType].duration}
Distance: {this.currentRouteInfoMap[this.selectedTransportationType].distance}
} {this.menuType === 'customize' &&
Current Marker:
{this.getMarkerIcon()}
this.onMarkerColorChange(color)} />
{Object.keys(MarkerIcons.FAMarkerIconsMap).map((iconKey) => (
this.onMarkerIconChange(iconKey)} icon={MarkerIcons.getFontAwesomeIcon(iconKey, '1x', 'white')} />
))}
} {this.menuType === 'route' && this.routeDoc &&
{StrCast(this.routeDoc.title)}
} {buttons}
, true); } }