Skip to content

Commit 131749d

Browse files
authored
Merge pull request #52 from developmentseed/feature/url-params
add url params
2 parents 8201147 + 98d404a commit 131749d

File tree

1 file changed

+62
-10
lines changed

1 file changed

+62
-10
lines changed

packages/web/src/app/reducer/index.ts

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import tArea from "@turf/area";
77
import tBboxPolygon from "@turf/bbox-polygon";
88
import { getFgbData } from "../utils/get-fgb-data.ts";
99
import { Map } from "maplibre-gl";
10+
import { useEffect } from "preact/hooks";
11+
12+
// eslint-disable-next-line no-duplicate-imports
1013
import type { Dispatch, Reducer } from "preact/hooks";
1114

1215
const availableTimestamps = [
@@ -33,6 +36,15 @@ export enum AppActionTypes {
3336
UPDATE_VIEW_ERROR = "UPDATE_VIEW_ERROR",
3437
}
3538

39+
// Utility function to update URL params
40+
const updateURLParams = (params: Record<string, string | number | boolean>) => {
41+
const url = new URL(window.location.href);
42+
Object.keys(params).forEach((key) =>
43+
url.searchParams.set(key, String(params[key])),
44+
);
45+
window.history.pushState({}, "", url.href);
46+
};
47+
3648
export type AppReducer<State, Action> = (state: State, action: Action) => State;
3749
/* eslint-enable no-unused-vars */
3850

@@ -44,17 +56,35 @@ export interface AppState {
4456
timestamps: string[];
4557
}
4658

47-
const appInitialState: AppState = {
48-
map: undefined,
49-
mapStatus: MapStatus.IDLE,
50-
mapData: {
51-
type: "FeatureCollection",
52-
features: [],
53-
},
54-
currentTimestamp: new Date(availableTimestamps[2]),
55-
timestamps: [...availableTimestamps],
59+
const getInitialStateFromURL = () => {
60+
const urlParams = new URLSearchParams(window.location.search);
61+
62+
const lng = urlParams.get("lng");
63+
const lat = urlParams.get("lat");
64+
const zoom = urlParams.get("zoom");
65+
const timestamp = urlParams.get("timestamp");
66+
67+
return {
68+
map: undefined,
69+
mapStatus: MapStatus.IDLE,
70+
mapData: {
71+
type: "FeatureCollection" as const,
72+
features: [],
73+
},
74+
currentTimestamp: timestamp
75+
? new Date(timestamp)
76+
: new Date(availableTimestamps[2]),
77+
timestamps: [...availableTimestamps],
78+
initialView: {
79+
lng: lng ? parseFloat(lng) : undefined,
80+
lat: lat ? parseFloat(lat) : undefined,
81+
zoom: zoom ? parseFloat(zoom) : undefined,
82+
},
83+
};
5684
};
5785

86+
const appInitialState: AppState = getInitialStateFromURL();
87+
5888
export type AppAction =
5989
| {
6090
type: AppActionTypes.SET_MAP_REF;
@@ -110,6 +140,16 @@ function appReducer(state: AppState, action: AppAction) {
110140
const area = tArea(poly);
111141
const formattedArea = new Intl.NumberFormat().format(area / 1e6);
112142

143+
// Update URL params
144+
const center = state.map.getCenter();
145+
const zoom = state.map.getZoom();
146+
updateURLParams({
147+
lng: center.lng,
148+
lat: center.lat,
149+
zoom,
150+
timestamp: currentTimestamp.toISOString(),
151+
});
152+
113153
return {
114154
...state,
115155
formattedArea,
@@ -188,9 +228,21 @@ const asyncActionHandlers: AsyncActionHandlers<
188228
};
189229

190230
export const useAppReducer = () => {
191-
return useReducerAsync(
231+
const [state, dispatch] = useReducerAsync(
192232
logReducer(appReducer),
193233
appInitialState,
194234
asyncActionHandlers,
195235
);
236+
237+
useEffect(() => {
238+
if (state.map && state.initialView) {
239+
const { lng, lat, zoom } = state.initialView;
240+
if (lng !== undefined && lat !== undefined && zoom !== undefined) {
241+
state.map.setCenter([lng, lat]);
242+
state.map.setZoom(zoom);
243+
}
244+
}
245+
}, [state.initialView, state.map]);
246+
247+
return [state, dispatch];
196248
};

0 commit comments

Comments
 (0)