Skip to main content

Routing

Fetch and display a route between two points using the barikoiClient.routeOverview() method. This combines the Shapes pattern with a real API call.

Example

import { Camera, LineLayer, MapView, MarkerView, ShapeSource } from '@maplibre/maplibre-react-native';
import type { FeatureCollection } from 'geojson';
import React, { useCallback, useEffect, useState } from 'react';
import { ActivityIndicator, Pressable, StyleSheet, Text, View } from 'react-native';
import { barikoiClient, BARIKOI_COLORS, MAP_STYLES, useBarikoiMapStyle } from '../utils/mapUtils';

const ORIGIN: [number, number] = [90.364159, 23.823724]; // Barikoi Head Office
const DESTINATION: [number, number] = [90.415482, 23.793059]; // Gulshan

type RouteInfo = {
distanceKm: number;
durationMin: number;
geometry: FeatureCollection;
};

export default function RoutingScreen() {
const { styleJson, loading: mapLoading, error: mapError } = useBarikoiMapStyle();
const [route, setRoute] = useState<RouteInfo | null>(null);
const [loadingRoute, setLoadingRoute] = useState(false);
const [error, setError] = useState<string | null>(null);

const fetchRoute = useCallback(async () => {
try {
setLoadingRoute(true);
setError(null);
const coordinates = `${ORIGIN[0]},${ORIGIN[1]};${DESTINATION[0]},${DESTINATION[1]}`;
const result = await barikoiClient.routeOverview({
coordinates,
geometries: 'geojson',
profile: 'car',
});

const routes = result.data?.routes;
if (routes && routes.length > 0) {
const r = routes[0];
const routeGeoJSON: FeatureCollection = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: {},
geometry: r.geometry as any, // GeoJSON LineString
}],
};
setRoute({
distanceKm: (r.distance ?? 0) / 1000,
durationMin: (r.duration ?? 0) / 60,
geometry: routeGeoJSON,
});
} else {
setError('No route found');
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to fetch route');
} finally {
setLoadingRoute(false);
}
}, []);

useEffect(() => { fetchRoute(); }, [fetchRoute]);

if (mapLoading) return <View style={styles.centered}><ActivityIndicator size="large" color={BARIKOI_COLORS.primary} /></View>;
if (mapError) return <View style={styles.centered}><Text>{mapError}</Text></View>;

const midPoint: [number, number] = [
(ORIGIN[0] + DESTINATION[0]) / 2,
(ORIGIN[1] + DESTINATION[1]) / 2,
];

return (
<View style={styles.container}>
<MapView style={styles.map} attributionEnabled={false} zoomEnabled compassEnabled mapStyle={styleJson}>
<Camera centerCoordinate={midPoint} zoomLevel={12} animationMode="linearTo" />

{/* Route line */}
{route && (
<ShapeSource id="routeSource" shape={route.geometry}>
<LineLayer id="routeLine" style={{ ...MAP_STYLES.line, lineWidth: 4, lineColor: '#2e8555' }} />
</ShapeSource>
)}

{/* Origin marker */}
<MarkerView coordinate={ORIGIN} anchor={{ x: 0.5, y: 1.0 }}>
<View style={styles.originMarker}>
<Text style={styles.markerLabel}>A</Text>
</View>
</MarkerView>

{/* Destination marker */}
<MarkerView coordinate={DESTINATION} anchor={{ x: 0.5, y: 1.0 }}>
<View style={styles.destMarker}>
<Text style={styles.markerLabel}>B</Text>
</View>
</MarkerView>
</MapView>

{/* Route info panel */}
<View style={styles.infoPanel}>
{loadingRoute && (
<View style={styles.loadingRow}>
<ActivityIndicator size="small" color={BARIKOI_COLORS.primary} />
<Text style={styles.loadingText}>Fetching route...</Text>
</View>
)}
{error && (
<View>
<Text style={styles.errorText}>{error}</Text>
<Pressable style={styles.retryBtn} onPress={fetchRoute}>
<Text style={styles.retryText}>Retry</Text>
</Pressable>
</View>
)}
{route && !loadingRoute && (
<View style={styles.routeInfo}>
<View style={styles.routeStat}>
<Text style={styles.statValue}>{route.distanceKm.toFixed(1)} km</Text>
<Text style={styles.statLabel}>Distance</Text>
</View>
<View style={styles.statDivider} />
<View style={styles.routeStat}>
<Text style={styles.statValue}>{Math.round(route.durationMin)} min</Text>
<Text style={styles.statLabel}>Duration</Text>
</View>
</View>
)}
</View>
</View>
);
}

const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: 'white' },
map: { flex: 1 },
centered: { flex: 1, justifyContent: 'center', alignItems: 'center' },
originMarker: { width: 28, height: 28, borderRadius: 14, backgroundColor: BARIKOI_COLORS.primary, justifyContent: 'center', alignItems: 'center', borderWidth: 2, borderColor: 'white' },
destMarker: { width: 28, height: 28, borderRadius: 14, backgroundColor: BARIKOI_COLORS.secondary, justifyContent: 'center', alignItems: 'center', borderWidth: 2, borderColor: 'white' },
markerLabel: { color: 'white', fontSize: 13, fontWeight: 'bold' },
infoPanel: { position: 'absolute', bottom: 24, left: 16, right: 16, backgroundColor: 'white', borderRadius: 16, padding: 16, elevation: 10, shadowColor: '#000', shadowOpacity: 0.1, shadowOffset: { width: 0, height: 10 }, shadowRadius: 20 },
loadingRow: { flexDirection: 'row', alignItems: 'center', gap: 10 },
loadingText: { fontSize: 15, color: BARIKOI_COLORS.text, marginLeft: 10 },
errorText: { fontSize: 14, color: BARIKOI_COLORS.secondary, marginBottom: 8 },
retryBtn: { backgroundColor: BARIKOI_COLORS.primary, borderRadius: 8, paddingVertical: 8, alignItems: 'center' },
retryText: { color: 'white', fontWeight: '600' },
routeInfo: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center' },
routeStat: { flex: 1, alignItems: 'center' },
statValue: { fontSize: 20, fontWeight: 'bold', color: BARIKOI_COLORS.text },
statLabel: { fontSize: 12, color: BARIKOI_COLORS.text, opacity: 0.6, marginTop: 2 },
statDivider: { width: 1, height: 30, backgroundColor: '#e0e0e0' },
});

Key points

  • The coordinates parameter is a string: lng,lat;lng,lat (semicolon-separated, GeoJSON order)
  • Use geometries: 'geojson' to get a GeoJSON LineString you can pass directly to ShapeSource
  • distance is in meters, duration is in seconds — convert for display
  • The response can include multiple routes; use routes[0] for the recommended one

routeOverview parameters

ParameterTypeDescription
coordinatesstringlng,lat;lng,lat (semicolon-separated)
geometries"geojson" | "polyline" | "polyline6"Geometry format
profile"car" | "foot"Routing profile (default: car)