Projekt

Obecné

Profil

Stáhnout (6.92 KB) Statistiky
| Větev: | Tag: | Revize:
1
import { Fragment, FunctionComponent, useEffect, useState } from "react"
2
import { useDispatch, useSelector } from "react-redux"
3
import { RootState } from "../redux/store"
4
import { PathVariant, MapPoint } from "./buildPathVariants"
5
import TextPath from "react-leaflet-textpath"
6
import { setPrimaryIdx, updateMapMarker } from "./trackingToolSlice"
7
import MapMarker from "./MapMarker"
8
import { LatLngTuple } from "leaflet"
9
import { Popup } from "react-leaflet"
10
import { Checkbox, FormControlLabel, Stack, Typography } from "@mui/material"
11
import { formatHtmlStringToReactDom } from "../../utils/formatting/HtmlUtils"
12
import { DialogCatalogItemDetail as CatalogItemDetailDialog } from "../Catalog/CatalogItemDetail"
13

    
14
export interface MapPathProps {
15
    idx: number // index of the path in the list
16
}
17

    
18
type EdgeElement = any
19

    
20
// Blue
21
export const primaryPathColor = "#346eeb"
22

    
23
// Grey
24
export const secondaryPathColor = "#878e9c"
25

    
26
const MapPath: FunctionComponent<MapPathProps> = ({ idx }) => {
27
    const dispatch = useDispatch()
28

    
29
    // Get list of all paths from the store
30
    // And extract path from them
31
    const paths = useSelector(
32
        (state: RootState) => state.trackingTool.pathVariants
33
    )
34
    const [path, setPath] = useState<PathVariant>([])
35
    useEffect(() => {
36
        // Either set the path if it exists or set it to an empty array
37
        setPath(paths && paths.length > idx ? paths[idx] : [])
38
    }, [idx, paths])
39

    
40
    // Primary path index to set the correct color
41
    const primaryPathIdx = useSelector(
42
        (state: RootState) => state.trackingTool.primaryPathIdx
43
    )
44

    
45
    // List of all active map points
46
    const [displayableMapPoints, setDisplayableMapPoints] = useState<
47
        MapPoint[]
48
    >([])
49
    useEffect(() => {
50
        // Set all displayable vertices
51
        setDisplayableMapPoints(path.filter((vertex) => vertex.displayable))
52
    }, [path])
53

    
54
    // List of all edges in the path
55
    const [edges, setEdges] = useState<EdgeElement[]>([])
56
    useEffect(() => {
57
        // Get all active map points
58
        const activeMapPoints = displayableMapPoints.filter(
59
            (item) => item.active
60
        )
61
        if (activeMapPoints.length < 2) {
62
            setEdges([])
63
            return
64
        }
65

    
66
        // Build edges
67
        const edges = []
68
        for (let i = 0; i < activeMapPoints.length - 1; i += 1) {
69
            const [start, end] = [
70
                activeMapPoints[i].catalogItem,
71
                activeMapPoints[i + 1].catalogItem,
72
            ]
73
            edges.push(
74
                <TextPath
75
                    // Somehow this refuses to work so let it rerender everything ...
76
                    key={`${start.id}-${end.id}:${start.latitude},${start.longitude}-${end.latitude},${end.longitude}`}
77
                    positions={[
78
                        [start.latitude, start.longitude],
79
                        [end.latitude, end.longitude],
80
                    ]}
81
                    text="►"
82
                    // text=" > > > > "
83
                    attributes={{
84
                        "font-size": 19,
85
                        // Set to primaryPathColor if primary index in the tracking tool is equal to this index
86
                        fill:
87
                            primaryPathIdx === idx
88
                                ? primaryPathColor
89
                                : secondaryPathColor,
90
                    }}
91
                    onClick={() => dispatch(setPrimaryIdx(idx))}
92
                    repeat
93
                    center
94
                    weight={0}
95
                />
96
            )
97
        }
98
        setEdges(edges)
99
    }, [dispatch, displayableMapPoints, idx, primaryPathIdx])
100

    
101
    // List of vertices to display
102
    const [vertices, setVertices] = useState<JSX.Element[]>([])
103
    useEffect(() => {
104
        // Iterate over all displayable map points and map them to MapMarker
105
        setVertices(
106
            displayableMapPoints.map((item) => (
107
                <MapMarker
108
                    key={`${item.catalogItem.latitude}${item.catalogItem.longitude}`}
109
                    position={[
110
                        item.catalogItem.latitude as number,
111
                        item.catalogItem.longitude as number,
112
                    ]}
113
                    updatePositionCallbackFn={(position: LatLngTuple) => {
114
                        dispatch(
115
                            updateMapMarker({
116
                                idx,
117
                                item: new MapPoint(item.idx, item.active, {
118
                                    ...item.catalogItem,
119
                                    latitude: position[0],
120
                                    longitude: position[1],
121
                                }),
122
                            })
123
                        )
124
                    }}
125
                >
126
                    <Popup>
127
                        <Fragment>
128
                            <Stack direction="column" sx={{ m: 0 }}>
129
                                <Typography
130
                                    variant="h6"
131
                                    fontWeight="bold"
132
                                    fontSize={16}
133
                                >
134
                                    {formatHtmlStringToReactDom(
135
                                        item.catalogItem.name as string
136
                                    )}
137
                                </Typography>
138
                                <FormControlLabel
139
                                    control={
140
                                        <Checkbox
141
                                            checked={item.active}
142
                                            onChange={() => {
143
                                                dispatch(
144
                                                    updateMapMarker({
145
                                                        idx,
146
                                                        item: new MapPoint(
147
                                                            item.idx,
148
                                                            !item.active,
149
                                                            item.catalogItem
150
                                                        ),
151
                                                    })
152
                                                )
153
                                            }}
154
                                        />
155
                                    }
156
                                    labelPlacement="end"
157
                                    label="Active"
158
                                />
159
                                <CatalogItemDetailDialog
160
                                    itemId={item.catalogItem.id ?? ""}
161
                                />
162
                            </Stack>
163
                        </Fragment>
164
                    </Popup>
165
                </MapMarker>
166
            ))
167
        )
168
    }, [dispatch, displayableMapPoints, idx])
169

    
170
    return (
171
        <Fragment>
172
            {vertices}
173
            {edges}
174
        </Fragment>
175
    )
176
}
177

    
178
export default MapPath
(3-3/9)