1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
import React, { useState, useEffect } from "react"
import { Map, Marker, GeoJson, ZoomControl } from "pigeon-maps"
import useLocalState from "@phntms/use-local-state";
import moment from "moment";
import 'moment/min/locales';
export default () => {
moment.locale('ru');
const [point, setPoint] = useState({
"id": "",
"user_id": "",
"lat": 0,
"lon": 0,
"time": "2024-08-15T09:54:00.666Z",
"speed": 0,
"direction": 0,
"accuracy": 0,
});
const [selected, setSelected] = useState(null)
const [points, setPoints] = useState([])
const [loaded, setLoaded] = useState(false);
const [zoom, setZoom] = useLocalState("zoom", 5);
const [center, setCenter] = useState([])
const [page, setPage] = useState(0)
const updatePosition = () => {
fetch("/api/points/last").then(x => x.json()).then((p) => {
setPoint(p);
setCenter([point.lat, point.lon])
setLoaded(true);
})
fetch("/api/points").then(x => x.json()).then(p => {
setPoints(p.reverse())
})
}
useEffect(updatePosition, [])
if (!loaded) {
return <h1>Загрузка карты</h1>
}
const path = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "LineString",
coordinates: points.map((pp) => [pp.lon, pp.lat]),
},
properties: { prop0: "value0" },
},
],
};
return (
<div className="container">
<div className="column">
<Map height={'100vh'} center={center} defaultCenter={[point.lat, point.lon]} defaultZoom={zoom} onBoundsChanged={({ center, zoom, bounds, initial, }) => {setZoom(zoom); setCenter(center)}}>
<ZoomControl />
<GeoJson
data={path}
styleCallback={(feature, hover) => {
return { strokeWidth: "2", stroke: "red" };
}}
/>
<Marker
width={32}
anchor={[point.lat, point.lon]}
/>
{selected ? (<Marker
width={32}
anchor={[selected.lat, selected.lon]}
/>):null}
</Map>
</div>
<div className="column list">
<div>Дата последней точки: <b>{moment(point.time).format("LTS L")}</b></div>
<div>Точность: <b>{point.accuracy.toFixed(2)}м</b></div>
<div>
<button onClick={updatePosition}>Обновить</button>
<button onClick={() => setCenter([point.lat, point.lon])}>Перейти к последней позиции</button>
</div>
<div>История перемещения:</div>
<ul>
{points.slice(page*50, (page+1)*50).map(p => <li key={p.id}>
<a href="#" onClick={(ev) => {setSelected(p);setCenter([p.lat, p.lon]);ev.preventDefault(); }}>
{moment(p.time).format("LTS L")} —
{p.lat.toFixed(5)},
{p.lon.toFixed(5)}
(точность: {p.accuracy.toFixed(2)}м)
</a>
</li>)}
</ul>
<button onClick={() => setPage(Math.max(0, page-1))}>←</button>
<button onClick={() => setPage(Math.min(page+1, Math.floor(points.length / 50)))}>→</button>
</div>
</div >
)
}
|