Projekt

Obecné

Profil

Stáhnout (6.45 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, updateMapMarkerPosition } 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
    }, [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
            return
63
        }
64

    
65
        // Build edges
66
        const edges = []
67
        for (let i = 0; i < activeMapPoints.length - 1; i += 1) {
68
            const [start, end] = [
69
                activeMapPoints[i].catalogItem,
70
                activeMapPoints[i + 1].catalogItem,
71
            ]
72
            edges.push(
73
                <TextPath
74
                    // Somehow this refuses to work so let it rerender everything ...
75
                    // key={`${start.latitude},${start.longitude}-${end.latitude},${end.longitude}`}
76
                    // key={`${start.id}-${end.id}`}
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.latitude}`}
109
                    position={[
110
                        item.catalogItem.latitude as number,
111
                        item.catalogItem.longitude as number,
112
                    ]}
113
                    updatePositionCallbackFn={(position: LatLngTuple) => {
114
                        // Update the position of the map point
115
                        dispatch(
116
                            updateMapMarkerPosition({
117
                                idx,
118
                                mapPointIdx: item.idx,
119
                                position,
120
                            })
121
                        )
122
                    }}
123
                >
124
                    <Popup>
125
                        <Fragment>
126
                            <Stack direction="column" sx={{ m: 0 }}>
127
                                <Typography
128
                                    variant="h6"
129
                                    fontWeight="bold"
130
                                    fontSize={16}
131
                                >
132
                                    {formatHtmlStringToReactDom(
133
                                        item.catalogItem.name as string
134
                                    )}
135
                                </Typography>
136
                                <FormControlLabel
137
                                    control={
138
                                        <Checkbox
139
                                            checked={item.active}
140
                                            onChange={() => {
141
                                                item.active = !item.active
142
                                                setDisplayableMapPoints([
143
                                                    ...displayableMapPoints,
144
                                                ])
145
                                            }}
146
                                        />
147
                                    }
148
                                    labelPlacement="end"
149
                                    label="Active"
150
                                />
151
                                <CatalogItemDetailDialog
152
                                    itemId={item.catalogItem.id ?? ""}
153
                                />
154
                            </Stack>
155
                        </Fragment>
156
                    </Popup>
157
                </MapMarker>
158
            ))
159
        )
160
    }, [dispatch, displayableMapPoints, idx])
161

    
162
    return (
163
        <Fragment>
164
            {vertices}
165
            {edges}
166
        </Fragment>
167
    )
168
}
169

    
170
export default MapPath
(3-3/9)