Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 100 additions & 39 deletions tavla/app/(admin)/utils/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import type { NormalizedDropdownItemType } from '@entur/dropdown'
import { uniq } from 'lodash'
import { CLIENT_NAME, COUNTY_ENDPOINT, GEOCODER_ENDPOINT } from 'src/assets/env'
import {
CLIENT_NAME,
COUNTY_ENDPOINT,
GEOCODER_ENDPOINT,
GRAPHQL_ENDPOINTS,
} from 'src/assets/env'
import { StopPlacesHaveDeparturesQuery } from 'src/graphql'
import type { LocationDB } from 'src/types/db-types/boards'
import { getIcons, type TCategory } from '../tavler/[id]/utils'

Expand Down Expand Up @@ -68,6 +74,36 @@ export async function fetchCounties(): Promise<NormalizedDropdownItemType[]> {
})
}

async function fetchStopPlaceIdsWithDepartures(
ids: string[],
): Promise<Set<string>> {
if (ids.length === 0) return new Set()

const response = await fetch(GRAPHQL_ENDPOINTS['journey-planner'], {
headers: {
'Content-Type': 'application/json',
'ET-Client-Name': CLIENT_NAME,
},
body: JSON.stringify({
query: StopPlacesHaveDeparturesQuery.toString(),
variables: { ids },
}),
method: 'POST',
})

const json = await response.json()
const stopPlaces = json.data?.stopPlaces ?? []

return new Set(
stopPlaces
.filter(
(sp: { id: string; estimatedCalls: unknown[] } | null) =>
sp && sp.estimatedCalls.length > 0,
)
.map((sp: { id: string }) => sp.id),
)
}

export async function fetchStopPlaces(
text: string,
countyIds?: string[],
Expand All @@ -76,64 +112,89 @@ export async function fetchStopPlaces(

const searchParams = new URLSearchParams({
lang: 'no',
size: '5',
size: '10',
layers: 'venue,address',
text,
})

if (countyIds && countyIds.length > 0)
searchParams.append('boundary.county_ids', countyIds.join(','))

return fetch(`${GEOCODER_ENDPOINT}/autocomplete?${searchParams}`, {
headers: {
'ET-Client-Name': CLIENT_NAME,
const data: TPartialGeoResponse = await fetch(
`${GEOCODER_ENDPOINT}/autocomplete?${searchParams}`,
{
headers: {
'ET-Client-Name': CLIENT_NAME,
},
},
})
.then((res) => res.json())
.then((data: TPartialGeoResponse) => {
return data.features.map(({ properties, geometry }) => ({
value: {
id: properties.id ?? '',
county: properties.county,
category: properties.category,
coordinates: toGeoCoordinate(geometry.coordinates),
layer: properties.layer,
},
label: properties.label || '',
icons: uniq(getIcons(properties.layer, properties.category)),
county: properties.county,
itemKey: properties.id ?? properties.label ?? '',
}))
})
).then((res) => res.json())

const items = data.features.map(({ properties, geometry }) => ({
value: {
id: properties.id ?? '',
county: properties.county,
category: properties.category,
coordinates: toGeoCoordinate(geometry.coordinates),
layer: properties.layer,
},
label: properties.label || '',
icons: uniq(getIcons(properties.layer, properties.category)),
county: properties.county,
itemKey: properties.id ?? properties.label ?? '',
}))

const venueIds = items
.filter((item) => item.value.layer === 'venue' && item.value.id)
.map((item) => item.value.id)

const idsWithDepartures = await fetchStopPlaceIdsWithDepartures(venueIds)

return items
.filter(
(item) =>
item.value.layer !== 'venue' ||
idsWithDepartures.has(item.value.id),
)
.slice(0, 5)
}

export async function fetchClosestStopPlaces(
coordinates: GeoCoordinate,
numberOfStopPlaces: number,
areaRadiusInKm: number = 1,
): Promise<NormalizedDropdownItemType<StopPlace>[]> {
return fetch(
`${GEOCODER_ENDPOINT}/reverse?point.lat=${coordinates.lat}&point.lon=${coordinates.lon}&boundary.circle.radius=${areaRadiusInKm}&layers=venue&size=${numberOfStopPlaces}`,
const requestSize = numberOfStopPlaces * 2

const data: TPartialGeoResponse = await fetch(
`${GEOCODER_ENDPOINT}/reverse?point.lat=${coordinates.lat}&point.lon=${coordinates.lon}&boundary.circle.radius=${areaRadiusInKm}&layers=venue&size=${requestSize}`,
{
headers: {
'ET-Client-Name': CLIENT_NAME,
},
},
)
.then((res) => res.json())
.then((data: TPartialGeoResponse) => {
return data.features.map(({ properties, geometry }) => ({
value: {
id: properties.id ?? '',
county: properties.county,
coordinates: toGeoCoordinate(geometry.coordinates),
name: properties.name ?? '',
},
label: properties.label || '',
icons: uniq(getIcons(properties.layer, properties.category)),
county: properties.county,
}))
})
).then((res) => res.json())

const items = data.features.map(({ properties, geometry }) => ({
value: {
id: properties.id ?? '',
county: properties.county,
coordinates: toGeoCoordinate(geometry.coordinates),
name: properties.name ?? '',
},
label: properties.label || '',
icons: uniq(getIcons(properties.layer, properties.category)),
county: properties.county,
}))

const venueIds = items
.filter((item) => item.value.id)
.map((item) => item.value.id)

const idsWithDepartures = await fetchStopPlaceIdsWithDepartures(venueIds)

return items
.filter((item) => idsWithDepartures.has(item.value.id))
.slice(0, numberOfStopPlaces)
}

export async function fetchPoints(
Expand Down
13 changes: 13 additions & 0 deletions tavla/src/graphql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,19 @@ export const StopPlaceNameQuery = new TypedDocumentString(`
Types.TStopPlaceNameQuery,
Types.TStopPlaceNameQueryVariables
>
export const StopPlacesHaveDeparturesQuery = new TypedDocumentString(`
query StopPlacesHaveDepartures($ids: [String]) {
stopPlaces(ids: $ids) {
id
estimatedCalls(numberOfDepartures: 1, timeRange: 86400) {
expectedDepartureTime
}
}
}
`) as unknown as TypedDocumentString<
Types.TStopPlacesHaveDeparturesQuery,
Types.TStopPlacesHaveDeparturesQueryVariables
>
export const WalkDistanceQuery = new TypedDocumentString(`
query walkDistance($from: InputCoordinates!, $to: InputCoordinates!) {
trip(
Expand Down
8 changes: 8 additions & 0 deletions tavla/src/graphql/queries/stopPlacesDepartures.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
query StopPlacesHaveDepartures($ids: [String]) {
stopPlaces(ids: $ids) {
id
estimatedCalls(numberOfDepartures: 1, timeRange: 86400) {
expectedDepartureTime
}
}
}
19 changes: 19 additions & 0 deletions tavla/src/types/graphql-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2605,6 +2605,25 @@ export type TStopPlaceNameQuery = {
stopPlace: { __typename?: 'StopPlace'; name: string; id: string } | null
}

export type TStopPlacesHaveDeparturesQueryVariables = Exact<{
ids?: InputMaybe<
| Array<InputMaybe<Scalars['String']['input']>>
| InputMaybe<Scalars['String']['input']>
>
}>

export type TStopPlacesHaveDeparturesQuery = {
__typename?: 'QueryType'
stopPlaces: Array<{
__typename?: 'StopPlace'
id: string
estimatedCalls: Array<{
__typename?: 'EstimatedCall'
expectedDepartureTime: DateTime
}>
} | null>
}

export type TWalkDistanceQueryVariables = Exact<{
from: TInputCoordinates
to: TInputCoordinates
Expand Down
Loading