Skip to content

Commit

Permalink
Merge pull request #6133 from realCity/debug-ui-place-id-planning
Browse files Browse the repository at this point in the history
debug client: support stop ids in from / to inputs
  • Loading branch information
leonardehrenfried authored Nov 22, 2024
2 parents 0a8e872 + bc1bca0 commit 9aed1e3
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 27 deletions.
16 changes: 10 additions & 6 deletions client/src/components/MapView/NavigationMarkers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { TripQueryVariables } from '../../gql/graphql.ts';
import { Marker } from 'react-map-gl';
import markerFlagStart from '../../static/img/marker-flag-start-shadowed.png';
import markerFlagEnd from '../../static/img/marker-flag-end-shadowed.png';
import { useCoordinateResolver } from './useCoordinateResolver.ts';

export function NavigationMarkers({
setCursor,
Expand All @@ -14,13 +15,16 @@ export function NavigationMarkers({
setTripQueryVariables: (variables: TripQueryVariables) => void;
loading: boolean;
}) {
const fromCoordinates = useCoordinateResolver(tripQueryVariables.from);
const toCoordinates = useCoordinateResolver(tripQueryVariables.to);

return (
<>
{tripQueryVariables.from.coordinates && (
{fromCoordinates && (
<Marker
draggable
latitude={tripQueryVariables.from.coordinates?.latitude}
longitude={tripQueryVariables.from.coordinates?.longitude}
latitude={fromCoordinates.latitude}
longitude={fromCoordinates.longitude}
onDragStart={() => setCursor('grabbing')}
onDragEnd={(e) => {
setCursor('auto');
Expand All @@ -36,11 +40,11 @@ export function NavigationMarkers({
<img alt="" src={markerFlagStart} height={48} width={49} />
</Marker>
)}
{tripQueryVariables.to.coordinates && (
{toCoordinates && (
<Marker
draggable
latitude={tripQueryVariables.to.coordinates?.latitude}
longitude={tripQueryVariables.to.coordinates?.longitude}
latitude={toCoordinates.latitude}
longitude={toCoordinates.longitude}
onDragStart={() => setCursor('grabbing')}
onDragEnd={(e) => {
setCursor('auto');
Expand Down
30 changes: 30 additions & 0 deletions client/src/components/MapView/useCoordinateResolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Location } from '../../gql/graphql.ts';
import { useQuayCoordinateQuery } from '../../hooks/useQuayCoordinateQuery.ts';

interface Coordinates {
latitude: number;
longitude: number;
}

export function useCoordinateResolver(location: Location): Coordinates | undefined {
const quay = useQuayCoordinateQuery(location);

if (quay) {
const { latitude, longitude } = quay;

if (latitude && longitude) {
return {
latitude,
longitude,
};
}
}

if (location.coordinates) {
return {
...location.coordinates,
};
}

return undefined;
}
52 changes: 39 additions & 13 deletions client/src/components/SearchBar/LocationInputField.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,37 @@
import { Form } from 'react-bootstrap';
import { COORDINATE_PRECISION } from './constants.ts';
import { Location } from '../../gql/graphql.ts';
import { toString, parseLocation } from '../../util/locationConverter.ts';
import { Location, TripQueryVariables } from '../../gql/graphql.ts';
import { useCallback, useEffect, useState } from 'react';

interface Props {
id: string;
label: string;
tripQueryVariables: TripQueryVariables;
setTripQueryVariables: (tripQueryVariables: TripQueryVariables) => void;
locationFieldKey: 'from' | 'to';
}

export function LocationInputField({ id, label, tripQueryVariables, setTripQueryVariables, locationFieldKey }: Props) {
const [value, setValue] = useState('');

useEffect(() => {
const initialLocation: Location = tripQueryVariables[locationFieldKey];

setValue(toString(initialLocation) || '');
}, [tripQueryVariables, locationFieldKey]);

const onLocationChange = useCallback(
(value: string) => {
const newLocation = parseLocation(value) || {};

setTripQueryVariables({
...tripQueryVariables,
[locationFieldKey]: newLocation,
});
},
[tripQueryVariables, setTripQueryVariables, locationFieldKey],
);

export function LocationInputField({ location, id, label }: { location: Location; id: string; label: string }) {
return (
<Form.Group>
<Form.Label column="sm" htmlFor={id}>
Expand All @@ -14,16 +43,13 @@ export function LocationInputField({ location, id, label }: { location: Location
size="sm"
placeholder="[Click in map]"
className="input-medium"
// Intentionally empty for now, but needed because of
// https://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable
onChange={() => {}}
value={
location.coordinates
? `${location.coordinates?.latitude.toPrecision(
COORDINATE_PRECISION,
)} ${location.coordinates?.longitude.toPrecision(COORDINATE_PRECISION)}`
: ''
}
onChange={(e) => {
setValue(e.target.value);
}}
onBlur={(event) => {
onLocationChange(event.target.value);
}}
value={value}
/>
</Form.Group>
);
Expand Down
16 changes: 14 additions & 2 deletions client/src/components/SearchBar/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,21 @@ export function SearchBar({ onRoute, tripQueryVariables, setTripQueryVariables,
{showServerInfo && <ServerInfoTooltip serverInfo={serverInfo} target={target} />}
</div>
</Navbar.Brand>
<LocationInputField location={tripQueryVariables.from} label="From" id="fromInputField" />
<LocationInputField
label="From"
id="fromInputField"
locationFieldKey="from"
tripQueryVariables={tripQueryVariables}
setTripQueryVariables={setTripQueryVariables}
/>
<SwapLocationsButton tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
<LocationInputField location={tripQueryVariables.to} label="To" id="toInputField" />
<LocationInputField
label="To"
id="toInputField"
locationFieldKey="to"
tripQueryVariables={tripQueryVariables}
setTripQueryVariables={setTripQueryVariables}
/>
<DepartureArrivalSelect tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
<DateTimeInputField tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
<NumTripPatternsInput tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
Expand Down
36 changes: 36 additions & 0 deletions client/src/hooks/useQuayCoordinateQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useEffect, useState } from 'react';
import { request } from 'graphql-request';
import { Location, QueryType } from '../gql/graphql.ts';
import { getApiUrl } from '../util/getApiUrl.ts';
import { graphql } from '../gql';

const query = graphql(`
query quayCoordinate($id: String!) {
quay(id: $id) {
latitude
longitude
}
}
`);

export const useQuayCoordinateQuery = (location: Location) => {
const [data, setData] = useState<QueryType | null>(null);

useEffect(() => {
const fetchData = async () => {
if (location.place) {
const variables = { id: location.place };
try {
setData((await request(getApiUrl(), query, variables)) as QueryType);
} catch (e) {
console.error('Error at useQuayCoordinateQuery', e);
}
} else {
setData(null);
}
};
fetchData();
}, [location]);

return data?.quay;
};
20 changes: 14 additions & 6 deletions client/src/hooks/useTripQuery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback, useEffect, useState } from 'react';
import { request } from 'graphql-request';
import { QueryType, TripQueryVariables } from '../gql/graphql.ts';
import { Location, QueryType, TripQueryVariables } from '../gql/graphql.ts';
import { getApiUrl } from '../util/getApiUrl.ts';
import { query } from '../static/query/tripQuery.tsx';

Expand All @@ -22,10 +22,14 @@ export const useTripQuery: TripQueryHook = (variables) => {
} else {
if (variables) {
setLoading(true);
if (pageCursor) {
setData((await request(getApiUrl(), query, { ...variables, pageCursor })) as QueryType);
} else {
setData((await request(getApiUrl(), query, variables)) as QueryType);
try {
if (pageCursor) {
setData((await request(getApiUrl(), query, { ...variables, pageCursor })) as QueryType);
} else {
setData((await request(getApiUrl(), query, variables)) as QueryType);
}
} catch (e) {
console.error('Error at useTripQuery', e);
}
setLoading(false);
} else {
Expand All @@ -37,10 +41,14 @@ export const useTripQuery: TripQueryHook = (variables) => {
);

useEffect(() => {
if (variables?.from.coordinates && variables?.to.coordinates) {
if (validLocation(variables?.from) && validLocation(variables?.to)) {
callback();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [variables?.from, variables?.to]);
return [data, loading, callback];
};

function validLocation(location: Location | undefined) {
return location && (location.coordinates || location.place);
}
37 changes: 37 additions & 0 deletions client/src/util/locationConverter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { COORDINATE_PRECISION } from '../components/SearchBar/constants.ts';
import { Location } from '../gql/graphql.ts';

const DOUBLE_PATTERN = '-{0,1}\\d+(\\.\\d+){0,1}';

const LAT_LON_PATTERN = '(' + DOUBLE_PATTERN + ')(\\s+)(' + DOUBLE_PATTERN + ')';

export function parseLocation(value: string): Location | null {
const latLonMatch = value.match(LAT_LON_PATTERN);

if (latLonMatch) {
return {
coordinates: {
latitude: +latLonMatch[1],
longitude: +latLonMatch[4],
},
};
}

return {
place: value,
};
}

export function toString(location: Location): string | null {
if (location.coordinates) {
return `${location.coordinates?.latitude.toPrecision(
COORDINATE_PRECISION,
)} ${location.coordinates?.longitude.toPrecision(COORDINATE_PRECISION)}`;
}

if (location.place) {
return location.place;
}

return null;
}

0 comments on commit 9aed1e3

Please sign in to comment.