Skip to content

Commit

Permalink
Directions: Move from/to to array of points
Browse files Browse the repository at this point in the history
  • Loading branch information
jvaclavik committed Dec 9, 2024
1 parent 111e441 commit f3e1680
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 74 deletions.
39 changes: 17 additions & 22 deletions src/components/Directions/DirectionsAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ import { AlphabeticalMarker } from './TextMarker';
import MyLocationIcon from '@mui/icons-material/MyLocation';
import { DotLoader, useIsClient } from '../helpers';
import { useSnackbar } from '../utils/SnackbarContext';
import { useGetOnSubmitFactory } from './useGetOnSubmit';
import { useGetOnSubmitFactory, useUpdatePoint } from './useGetOnSubmit';
import { useDirectionsContext } from './DirectionsContext';
import { removeElementOnIndex } from '../FeaturePanel/Climbing/utils/array';
const DotLoaderContainer = styled.div`
font-size: 16px;
right: 6px;
Expand Down Expand Up @@ -171,15 +172,16 @@ const Row = styled.div`
`;

const useInputMapClickOverride = (
setValue: (value: Option) => void,
pointIndex: number,
setInputValue: (value: string) => void,
selectedOptionInputValue: React.MutableRefObject<string | null>,
) => {
const { mapClickOverrideRef } = useMapStateContext();
const previousBehaviourRef = useRef<MapClickOverride>();
const updatePoint = useUpdatePoint();

const mapClickCallback = (coords: LonLat, label: string) => {
setValue(getCoordsOption(coords, label));
updatePoint(pointIndex, getCoordsOption(coords, label));
setInputValue(label);
selectedOptionInputValue.current = label;

Expand All @@ -203,23 +205,18 @@ const useInputMapClickOverride = (
type Props = {
label: string;
value: Option;
setValue: (value: Option) => void;
pointIndex: number;
};

export const DirectionsAutocomplete = ({
label,
value,
setValue,
pointIndex,
}: Props) => {
export const DirectionsAutocomplete = ({ label, value, pointIndex }: Props) => {
const autocompleteRef = useRef();
const { inputValue, setInputValue } = useInputValueState();
const selectedOptionInputValue = useRef<string | null>(null);
const mapCenter = useMapCenter();
const { currentTheme } = useUserThemeContext();
const { userSettings } = useUserSettingsContext();
const { isImperial } = userSettings;
const updatePoint = useUpdatePoint();

const ALPHABETICAL_MARKER = useMemo(() => {
let svgElement;
Expand All @@ -239,7 +236,9 @@ export const DirectionsAutocomplete = ({
}, [pointIndex]);

const markerRef = useRef<maplibregl.Marker>();
const { from, to, mode, setResult, setLoading } = useDirectionsContext();
const { points, mode, setResult, setLoading, setPoints } =
useDirectionsContext();
const submitFactory = useGetOnSubmitFactory(setResult, setLoading);

useEffect(() => {
const map = getGlobalMap();
Expand All @@ -254,20 +253,15 @@ export const DirectionsAutocomplete = ({
}, [ALPHABETICAL_MARKER, value]);

const handleUpdate = (coordsOption: Option) => {
if (pointIndex === 0) {
submitFactory(coordsOption, to, mode);
}
if (pointIndex === 1) {
submitFactory(from, coordsOption, mode);
}
const newPoints = updatePoint(pointIndex, coordsOption);
submitFactory(newPoints, mode);
};

const submitFactory = useGetOnSubmitFactory(setResult, setLoading);
const onDragEnd = () => {
const lngLat = markerRef.current?.getLngLat();
if (lngLat) {
const coordsOption = getCoordsOption([lngLat.lng, lngLat.lat]);
setValue(coordsOption);
updatePoint(pointIndex, coordsOption);
handleUpdate(coordsOption);
}
};
Expand All @@ -279,13 +273,14 @@ export const DirectionsAutocomplete = ({
const onChange = (_: unknown, option: Option) => {
console.log('selected', option); // eslint-disable-line no-console
setInputValue(getOptionLabel(option));
setValue(option);
updatePoint(pointIndex, option);

selectedOptionInputValue.current = getOptionLabel(option);
handleUpdate(option);
};

const { onInputFocus, onInputBlur } = useInputMapClickOverride(
setValue,
pointIndex,
setInputValue,
selectedOptionInputValue,
);
Expand All @@ -297,7 +292,7 @@ export const DirectionsAutocomplete = ({
if (options.length > 0 && inputValue) {
onChange(null, options[0]);
} else {
setValue(null);
setPoints(removeElementOnIndex(points, pointIndex));
}
}
};
Expand Down
17 changes: 5 additions & 12 deletions src/components/Directions/DirectionsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,15 @@ import React, { createContext, useContext, useState } from 'react';
import { Profile, RoutingResult } from './routing/types';
import { Option } from '../SearchBox/types';

type CragViewLayout = 'vertical' | 'horizontal' | 'auto';

type DirectionsContextType = {
loading: boolean;
setLoading: (loading: boolean) => void;
mode: Profile;
setMode: (mode: Profile) => void;
from: Option;
setFrom: (from: Option) => void;
to: Option;
setTo: (to: Option) => void;
result: RoutingResult;
setResult: (result: RoutingResult) => void;
points: Array<Option>;
setPoints: (points: Array<Option>) => void;
};

export const DirectionsContext =
Expand All @@ -23,21 +19,18 @@ export const DirectionsContext =
export const DirectionsProvider: React.FC = ({ children }) => {
const [loading, setLoading] = useState(false);
const [mode, setMode] = useState<Profile>('car');
const [from, setFrom] = useState<Option>();
const [to, setTo] = useState<Option>();
const [result, setResult] = useState<RoutingResult>(null);
const [points, setPoints] = useState<Array<Option>>([]);

const value: DirectionsContextType = {
loading,
setLoading,
mode,
setMode,
from,
setFrom,
to,
setTo,
result,
setResult,
points,
setPoints,
};
return (
<DirectionsContext.Provider value={value}>
Expand Down
138 changes: 108 additions & 30 deletions src/components/Directions/DirectionsForm.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Option } from '../SearchBox/types';
import { RoutingResult } from './routing/types';
import { CloseButton } from './helpers';
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { StyledPaper } from './Result';
import { Stack } from '@mui/material';
import { Box, Stack } from '@mui/material';
import { ModeToggler } from './ModeToggler';
import { DirectionsAutocomplete } from './DirectionsAutocomplete';
import { t } from '../../services/intl';
Expand All @@ -12,46 +12,99 @@ import SearchIcon from '@mui/icons-material/Search';
import { getCoordsOption } from '../SearchBox/options/coords';
import { useMapStateContext } from '../utils/MapStateContext';
import { useDirectionsContext } from './DirectionsContext';
import { useGetOnSubmitFactory, useReactToUrl } from './useGetOnSubmit';
import {
useGetOnSubmitFactory,
useReactToUrl,
useUpdatePoint,
} from './useGetOnSubmit';

type Props = {
setResult: (result: RoutingResult) => void;
hideForm: boolean;
};

const useGlobalMapClickOverride = (
from: Option,
setFrom: (value: Option) => void,
setTo: (value: Option) => void,
points: Array<Option>,
setPoints: (points: Array<Option>) => void,
) => {
const { setResult, setLoading, to, mode } = useDirectionsContext();
const { setResult, setLoading, mode } = useDirectionsContext();
const submitFactory = useGetOnSubmitFactory(setResult, setLoading);
const updatePoint = useUpdatePoint();

const { mapClickOverrideRef } = useMapStateContext();
useEffect(() => {
mapClickOverrideRef.current = (coords, label) => {
const coordinates = getCoordsOption(coords, label);
if (!from) {
submitFactory(coordinates, to, mode);
setFrom(coordinates);
if (!points[0]) {
const newPoints = updatePoint(0, coordinates);
submitFactory(newPoints, mode);
} else {
submitFactory(from, coordinates, mode);
setTo(coordinates);
const newPoints = updatePoint(1, coordinates);
submitFactory(newPoints, mode);
}
};

return () => {
mapClickOverrideRef.current = undefined;
};
}, [from, mapClickOverrideRef, mode, setFrom, setTo, submitFactory, to]);
}, [
mapClickOverrideRef,
mode,
points,
setPoints,
submitFactory,
updatePoint,
]);
};

type InputItem = {
value: Option;
pointIndex: number;
label: string;
};

const defaultFrom = {
value: null,
pointIndex: 0,
label: t('directions.form.start_or_click'),
};

const defaultTo = {
value: null,
pointIndex: 1,
label: t('directions.form.destination'),
};

export const DirectionsForm = ({ setResult, hideForm }: Props) => {
const { loading, setLoading, mode, setMode, from, setFrom, to, setTo } =
const { loading, setLoading, mode, setMode, points, setPoints } =
useDirectionsContext();

useGlobalMapClickOverride(from, setFrom, setTo);
useReactToUrl(setMode, setFrom, setTo, setResult);
const [inputs, setInputs] = useState<Array<InputItem>>([
defaultFrom,
defaultTo,
]);

useEffect(() => {
const newPoints = points.map((point, index) => ({
value: point,
pointIndex: index,
label: t(
index === 0
? 'directions.form.start_or_click'
: 'directions.form.destination',
),
}));

if (points?.length === 1) {
setInputs([...newPoints, defaultTo]);
}
if (points?.length >= 2) {
setInputs(newPoints);
}
}, [points]);

useGlobalMapClickOverride(points, setPoints);
useReactToUrl(setMode, setPoints, setResult);

const onSubmitFactory = useGetOnSubmitFactory(setResult, setLoading);

Expand All @@ -65,7 +118,7 @@ export const DirectionsForm = ({ setResult, hideForm }: Props) => {
<ModeToggler
value={mode}
setMode={setMode}
onChange={(newMode) => onSubmitFactory(from, to, newMode)}
onChange={(newMode) => onSubmitFactory(points, newMode)}
/>
<div style={{ flex: 1 }} />
<div>
Expand All @@ -74,18 +127,43 @@ export const DirectionsForm = ({ setResult, hideForm }: Props) => {
</Stack>

<Stack spacing={1} mb={3}>
<DirectionsAutocomplete
value={from}
setValue={setFrom}
label={t('directions.form.start_or_click')}
pointIndex={0}
/>
<DirectionsAutocomplete
value={to}
setValue={setTo}
label={t('directions.form.destination')}
pointIndex={1}
/>
{inputs.map((item, index) => {
const { value, label, pointIndex } = item;
return (
<Box sx={{ position: 'relative' }} key={`input-${pointIndex}`}>
<Stack direction="row" alignItems="center">
{/* <DragHandler */}
{/* onDragStart={(e) => { */}
{/* handleDragStart(e, { */}
{/* id: index, */}
{/* content: item, */}
{/* }); */}
{/* }} */}
{/* onDragOver={(e) => { */}
{/* handleDragOver(e, index); */}
{/* }} */}
{/* onDragEnd={(e) => { */}
{/* handleDragEnd(e); */}

{/* const newArray = moveElementToIndex( */}
{/* inputs, */}
{/* draggedItem.id, */}
{/* draggedOverIndex, */}
{/* ); */}

{/* setInputs(newArray); */}
{/* }} */}
{/* /> */}
<DirectionsAutocomplete
value={value}
label={label}
pointIndex={index}
/>
</Stack>
{/* <HighlightedDropzone index={index} /> */}
</Box>
);
})}
</Stack>

<LoadingButton
Expand All @@ -94,7 +172,7 @@ export const DirectionsForm = ({ setResult, hideForm }: Props) => {
variant="contained"
fullWidth
startIcon={<SearchIcon />}
onClick={() => onSubmitFactory(from, to, mode)}
onClick={() => onSubmitFactory(points, mode)}
>
{t('directions.get_directions')}
</LoadingButton>
Expand Down
Loading

0 comments on commit f3e1680

Please sign in to comment.