Skip to content

Commit e4957b3

Browse files
committed
Replace slider with navigator
1 parent d173937 commit e4957b3

File tree

7 files changed

+119
-109
lines changed

7 files changed

+119
-109
lines changed

packages/web/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@
1313
"dependencies": {
1414
"@turf/area": "^6.5.0",
1515
"@turf/bbox-polygon": "^6.5.0",
16-
"@types/react-slider": "^1.3.1",
16+
"date-fns": "^3.6.0",
1717
"flatgeobuf": "^3.26.2",
1818
"lodash.get": "^4.4.2",
1919
"maplibre-gl": "^3.3.1",
2020
"preact": "^10.16.0",
21-
"react-slider": "^2.0.6",
2221
"use-reducer-async": "^2.1.1"
2322
},
2423
"devDependencies": {

packages/web/src/app/cartoslider.tsx

Lines changed: 0 additions & 54 deletions
This file was deleted.

packages/web/src/app/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Map } from "./map";
55
import { Panel } from "./panel";
66
import { MapStatus, useAppReducer } from "./reducer";
77
import { Stats } from "./stats";
8-
import { CartoSlider } from "./cartoslider";
8+
import TimeNavigator from "./time-navigator";
99

1010
export function App() {
1111
const [appState, dispatchAppState] = useAppReducer();
@@ -27,7 +27,7 @@ export function App() {
2727
</Panel>
2828
<main class="carto">
2929
<Map appState={appState} dispatchAppState={dispatchAppState} />
30-
<CartoSlider
30+
<TimeNavigator
3131
currentTimestamp={currentTimestamp}
3232
isLoading={isLoading}
3333
timestamps={timestamps}

packages/web/src/app/map/index.tsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,5 @@ export function Map(props: MapProps) {
210210
});
211211
}, [appState?.map]);
212212

213-
useEffect(() => {
214-
if (appState && appState.map && appState.currentTimestampGeojson) {
215-
appState.map.getSource("data").setData(appState.currentTimestampGeojson);
216-
}
217-
}, [appState?.map, appState?.currentTimestampGeojson]);
218-
219213
return <div id="map" />;
220214
}

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

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import tArea from "@turf/area";
55
import tBboxPolygon from "@turf/bbox-polygon";
66
import { getFgbData } from "../utils/get-fgb-data.ts";
77
import { Map } from "maplibre-gl";
8-
import { Reducer } from "preact/hooks";
8+
import { Dispatch, Reducer } from "preact/hooks";
99

1010
const availableTimestamps = [
1111
`2024-05-19T05:00:00Z`,
@@ -73,8 +73,12 @@ export type AppAction =
7373
type: AppActionTypes.UPDATE_VIEW_SUCCESS;
7474
data: {
7575
mapData: GeoJSON.FeatureCollection;
76+
currentTimestamp: Date;
7677
};
77-
};
78+
}
79+
| AsyncAction;
80+
81+
export type AppDispatch = Dispatch<AppAction>;
7882

7983
function appReducer(state: AppState, action: AppAction) {
8084
switch (action.type) {
@@ -94,8 +98,7 @@ function appReducer(state: AppState, action: AppAction) {
9498
return { ...state };
9599
}
96100

97-
const { mapData } = action.data;
98-
const { currentTimestamp } = state;
101+
const { mapData, currentTimestamp } = action.data;
99102

100103
const stats = calculateStats(mapData);
101104

@@ -135,6 +138,9 @@ function appReducer(state: AppState, action: AppAction) {
135138

136139
type AsyncAction = {
137140
type: AppActionTypes.UPDATE_VIEW;
141+
data: {
142+
currentTimestamp: Date;
143+
};
138144
};
139145

140146
const asyncActionHandlers: AsyncActionHandlers<
@@ -143,9 +149,14 @@ const asyncActionHandlers: AsyncActionHandlers<
143149
> = {
144150
[AppActionTypes.UPDATE_VIEW]:
145151
({ dispatch, getState }) =>
146-
async () => {
152+
async (action) => {
147153
try {
148-
const { map, mapStatus, currentTimestamp } = getState();
154+
const state = getState();
155+
156+
const { map, mapStatus } = state;
157+
158+
const currentTimestamp =
159+
action?.data?.currentTimestamp || state.currentTimestamp;
149160

150161
if (!map || mapStatus !== MapStatus.READY) {
151162
return;
@@ -164,7 +175,7 @@ const asyncActionHandlers: AsyncActionHandlers<
164175

165176
dispatch({
166177
type: AppActionTypes.UPDATE_VIEW_SUCCESS,
167-
data: { mapData },
178+
data: { mapData, currentTimestamp },
168179
});
169180
} catch (error) {
170181
// eslint-disable-next-line no-console
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { addHours, addDays, subDays, subHours } from "date-fns";
2+
import { AppActionTypes, AppDispatch, AppState } from "./reducer";
3+
import { ComponentChild } from "preact";
4+
5+
function LoadingSkeleton() {
6+
return (
7+
<div class="carto__slider--loading">
8+
<p>Loading...</p>
9+
</div>
10+
);
11+
}
12+
13+
const TimeChangeButton = ({
14+
dispatchAppState,
15+
nextTimestamp,
16+
children,
17+
}: {
18+
dispatchAppState: AppDispatch;
19+
nextTimestamp: Date;
20+
children: ComponentChild;
21+
}) => (
22+
<button
23+
onClick={(e) => {
24+
e.preventDefault();
25+
dispatchAppState({
26+
type: AppActionTypes.UPDATE_VIEW,
27+
data: {
28+
currentTimestamp: nextTimestamp,
29+
},
30+
});
31+
}}
32+
class="carto__slider--button"
33+
>
34+
{children}
35+
</button>
36+
);
37+
38+
function TimeNavigator({
39+
currentTimestamp,
40+
isLoading,
41+
dispatchAppState,
42+
}: {
43+
currentTimestamp: Date;
44+
isLoading: boolean;
45+
timestamps: string[];
46+
dispatchAppState: AppDispatch;
47+
appState: AppState;
48+
}) {
49+
return (
50+
<section class="carto__slider--wrapper">
51+
<div class="carto__slider--heading">
52+
<h4>Change Timeline</h4>
53+
</div>
54+
<div class="carto__slider">
55+
<div class="carto__slider--tools">
56+
<p>
57+
{!isLoading && currentTimestamp ? (
58+
new Date(currentTimestamp).toUTCString()
59+
) : (
60+
<LoadingSkeleton />
61+
)}
62+
</p>
63+
<TimeChangeButton
64+
dispatchAppState={dispatchAppState}
65+
nextTimestamp={subDays(currentTimestamp, -1)}
66+
>
67+
← Day
68+
</TimeChangeButton>
69+
<TimeChangeButton
70+
dispatchAppState={dispatchAppState}
71+
nextTimestamp={subHours(currentTimestamp, -1)}
72+
>
73+
← Hour
74+
</TimeChangeButton>
75+
<TimeChangeButton
76+
dispatchAppState={dispatchAppState}
77+
nextTimestamp={addHours(currentTimestamp, 1)}
78+
>
79+
Hour →
80+
</TimeChangeButton>
81+
<TimeChangeButton
82+
dispatchAppState={dispatchAppState}
83+
nextTimestamp={addDays(currentTimestamp, 1)}
84+
>
85+
Day →
86+
</TimeChangeButton>
87+
</div>
88+
</div>
89+
</section>
90+
);
91+
}
92+
93+
export default TimeNavigator;

packages/web/yarn.lock

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -751,32 +751,6 @@
751751
resolved "https://registry.yarnpkg.com/@types/pbf/-/pbf-3.0.2.tgz#8d291ad68b4b8c533e96c174a2e3e6399a59ed61"
752752
integrity sha512-EDrLIPaPXOZqDjrkzxxbX7UlJSeQVgah3i0aA4pOSzmK9zq3BIh7/MZIQxED7slJByvKM4Gc6Hypyu2lJzh3SQ==
753753

754-
"@types/prop-types@*":
755-
version "15.7.5"
756-
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
757-
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
758-
759-
"@types/react-slider@^1.3.1":
760-
version "1.3.1"
761-
resolved "https://registry.yarnpkg.com/@types/react-slider/-/react-slider-1.3.1.tgz#a3816989eb4fc172e7df316930f242fec90690fc"
762-
integrity sha512-4X2yK7RyCIy643YCFL+bc6XNmcnBtt8n88uuyihvcn5G7Lut23eNQU3q3KmwF7MWIfKfsW5NxCjw0SeDZRtgaA==
763-
dependencies:
764-
"@types/react" "*"
765-
766-
"@types/react@*":
767-
version "18.2.21"
768-
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.21.tgz#774c37fd01b522d0b91aed04811b58e4e0514ed9"
769-
integrity sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==
770-
dependencies:
771-
"@types/prop-types" "*"
772-
"@types/scheduler" "*"
773-
csstype "^3.0.2"
774-
775-
"@types/scheduler@*":
776-
version "0.16.3"
777-
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5"
778-
integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==
779-
780754
"@types/semver@^7.3.12", "@types/semver@^7.5.0":
781755
version "7.5.2"
782756
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.2.tgz#31f6eec1ed7ec23f4f05608d3a2d381df041f564"
@@ -1355,11 +1329,6 @@ csscolorparser@~1.0.2:
13551329
resolved "https://registry.yarnpkg.com/csscolorparser/-/csscolorparser-1.0.3.tgz#b34f391eea4da8f3e98231e2ccd8df9c041f171b"
13561330
integrity sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==
13571331

1358-
csstype@^3.0.2:
1359-
version "3.1.2"
1360-
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
1361-
integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==
1362-
13631332
damerau-levenshtein@^1.0.8:
13641333
version "1.0.8"
13651334
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
@@ -1372,6 +1341,11 @@ dashdash@^1.12.0:
13721341
dependencies:
13731342
assert-plus "^1.0.0"
13741343

1344+
date-fns@^3.6.0:
1345+
version "3.6.0"
1346+
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-3.6.0.tgz#f20ca4fe94f8b754951b24240676e8618c0206bf"
1347+
integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==
1348+
13751349
debug@^3.2.7:
13761350
version "3.2.7"
13771351
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
@@ -3164,13 +3138,6 @@ react-is@^16.13.1:
31643138
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
31653139
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
31663140

3167-
react-slider@^2.0.6:
3168-
version "2.0.6"
3169-
resolved "https://registry.yarnpkg.com/react-slider/-/react-slider-2.0.6.tgz#8c7ff0301211f7c3ff32aa0163b33bdab6258559"
3170-
integrity sha512-gJxG1HwmuMTJ+oWIRCmVWvgwotNCbByTwRkFZC6U4MBsHqJBmxwbYRJUmxy4Tke1ef8r9jfXjgkmY/uHOCEvbA==
3171-
dependencies:
3172-
prop-types "^15.8.1"
3173-
31743141
31753142
version "1.0.5"
31763143
resolved "https://registry.yarnpkg.com/read/-/read-1.0.5.tgz#007a3d169478aa710a491727e453effb92e76203"

0 commit comments

Comments
 (0)