diff --git a/packages/ui/index.html b/packages/ui/index.html
index c179981..d2d7370 100644
--- a/packages/ui/index.html
+++ b/packages/ui/index.html
@@ -2,10 +2,10 @@
- Busmap
+ Busmap - Stop and vehicle locations of popular transit agencies.
+ content="Maps providing real-time arrival and departure times of vehicles for bus stops along routes in San Francisco Muni CIS, Toronto Transit Commission, OmniTrans and other transit agencies across North and South America." />
diff --git a/packages/ui/src/components/busSelector.tsx b/packages/ui/src/components/busSelector.tsx
index 4ee013a..b607682 100644
--- a/packages/ui/src/components/busSelector.tsx
+++ b/packages/ui/src/components/busSelector.tsx
@@ -13,6 +13,7 @@ import { SelectorError } from './error/selector.js'
import { useGlobals } from '../globals.js'
import { useMap } from '../contexts/map.js'
+import { useDocMeta } from '../hooks/useDocMeta.js'
import { useHomeStop } from '../hooks/useHomeStop.js'
import { useVehiclesDispatch } from '../contexts/vehicles.js'
import { getAll as getAllRoutes, get as getRoute } from '../api/rb/route.js'
@@ -157,6 +158,11 @@ const BusSelector = memo(function BusSelector({ agencies }: BusSelectorProps) {
const error = getFirstDataError([routesError, routeError])
const isLoading = isRoutesLoading || isRouteLoading
+ /**
+ * Update page title and description.
+ */
+ useDocMeta()
+
useEffect(() => {
if (routes) {
if (bookmark.current.route) {
diff --git a/packages/ui/src/components/busmap.tsx b/packages/ui/src/components/busmap.tsx
index 149fd1f..8d8e8b6 100644
--- a/packages/ui/src/components/busmap.tsx
+++ b/packages/ui/src/components/busmap.tsx
@@ -5,6 +5,11 @@ import type { FC } from 'react'
const BusmapPage: FC = () => {
return (
+
+ Busmap provides real-time arrival and departure times for vehicles servicing bus
+ stops along routes in San Francisco Muni CIS, Toronto Transit Commission,
+ OmniTrans, and other transit agencies across North and South America.
+
Busmap is a public, open source project{' '}
@@ -21,9 +26,7 @@ const BusmapPage: FC = () => {
restbus
- .
-
-
+ .{' '}
- predictions?: Prediction[]
+ predictions: Prediction[]
}
const Predictions = createContext({
dispatch: () => {},
- predictions: undefined
+ predictions: []
})
-const reducer = (state: Prediction[] | undefined, action: PredictionsAction) => {
+const reducer = (state: Prediction[], action: PredictionsAction) => {
switch (action.type) {
case 'predictions':
return action.value
case 'direction':
case 'stop':
- return undefined
+ return []
default:
return state
}
diff --git a/packages/ui/src/hooks/useDocMeta.ts b/packages/ui/src/hooks/useDocMeta.ts
new file mode 100644
index 0000000..ff2c80a
--- /dev/null
+++ b/packages/ui/src/hooks/useDocMeta.ts
@@ -0,0 +1,58 @@
+import { useEffect, useRef } from 'react'
+
+import { useGlobals } from '../globals.js'
+import { usePredictions } from '../contexts/predictions'
+
+const useDocMeta = () => {
+ const metaDesc = useRef()
+ const { agency, stop } = useGlobals()
+ const { predictions } = usePredictions()
+
+ useEffect(() => {
+ const meta = document.querySelector('meta[name="description"]')
+
+ if (meta) {
+ metaDesc.current = meta
+ }
+ }, [])
+
+ useEffect(() => {
+ if (metaDesc.current) {
+ if (agency && stop) {
+ let event = 'arrival'
+ let title = `${stop.title}`
+
+ if (predictions.length) {
+ const [one, two] = predictions[0].values
+
+ if (one.isDeparture) {
+ event = 'departure'
+ }
+
+ title += `: ${one.minutes || 'Now'}`
+
+ if (two) {
+ title += ` & ${two.minutes || 'Now'}`
+ }
+
+ title += ' min'
+ }
+
+ document.title = title
+ metaDesc.current.setAttribute(
+ 'content',
+ `Maps providing real-time ${event} times of vehicles for ${agency.title} stop ${stop.title}.`
+ )
+ } else {
+ document.title =
+ 'Busmap - Stop and vehicle locations of popular transit agencies.'
+ metaDesc.current.setAttribute(
+ 'content',
+ 'Maps providing real-time arrival and departure times of vehicles for bus stops along routes in San Francisco Muni CIS, Toronto Transit Commission, OmniTrans and other transit agencies across North and South America.'
+ )
+ }
+ }
+ }, [agency, stop, predictions])
+}
+
+export { useDocMeta }
diff --git a/packages/ui/src/hooks/useVehiclesLayer.ts b/packages/ui/src/hooks/useVehiclesLayer.ts
index 27647ff..843416d 100644
--- a/packages/ui/src/hooks/useVehiclesLayer.ts
+++ b/packages/ui/src/hooks/useVehiclesLayer.ts
@@ -183,14 +183,14 @@ const useVehiclesLayer = ({ vehiclesLayer }: UseVehiclesLayer) => {
useVehicleSettings()
const iconDimensions = useRef(null)
- const preds = useRef(predictions?.length ? predictions[0].values.slice(0, 3) : [])
+ const preds = useRef(predictions.length ? predictions[0].values.slice(0, 3) : [])
useEffect(() => {
iconDimensions.current = null
}, [route])
useEffect(() => {
- const nextPreds = predictions?.length ? predictions[0].values.slice(0, 3) : []
+ const nextPreds = predictions.length ? predictions[0].values.slice(0, 3) : []
preds.current = nextPreds
}, [predictions])