Projekt

Obecné

Profil

Stáhnout (7.3 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, isMapPointDisplayable } from './pathUtils'
5
import TextPath from 'react-leaflet-textpath'
6
import {
7
    setPrimaryIdx,
8
    updateMapMarker,
9
    updateMapMarkerWithId,
10
} from '../trackingToolSlice'
11
import MapMarker from './MapMarker'
12
import { LatLngTuple } from 'leaflet'
13
import { Popup, Tooltip } from 'react-leaflet'
14
import { Checkbox, FormControlLabel, Stack, Typography } from '@mui/material'
15
import { formatHtmlStringToReactDom } from '../../../utils/formatting/HtmlUtils'
16
import { DialogCatalogItemDetail as CatalogItemDetailDialog } from '../../Catalog/CatalogItemDetail'
17

    
18
export interface MapPathProps {
19
    idx: number // index of the path in the list
20
}
21

    
22
type EdgeElement = any
23

    
24
// Blue
25
export const primaryPathColor = '#346eeb'
26

    
27
// Grey
28
export const secondaryPathColor = '#878e9c'
29

    
30
const MapPath: FunctionComponent<MapPathProps> = ({ idx }) => {
31
    const dispatch = useDispatch()
32

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

    
44
    // Primary path index to set the correct color
45
    const primaryPathIdx = useSelector(
46
        (state: RootState) => state.trackingTool.primaryPathIdx
47
    )
48

    
49
    // List of all active map points
50
    const [displayableMapPoints, setDisplayableMapPoints] = useState<
51
        MapPoint[]
52
    >([])
53
    useEffect(() => {
54
        // Set all displayable vertices
55
        setDisplayableMapPoints(
56
            path.filter((mapPoint) => isMapPointDisplayable(mapPoint))
57
        )
58
    }, [path])
59

    
60
    // List of all edges in the path
61
    const [edges, setEdges] = useState<EdgeElement[]>([])
62
    useEffect(() => {
63
        // Get all active map points
64
        const activeMapPoints = displayableMapPoints.filter(
65
            (item) => item.addToPath && !item.hidden
66
        )
67
        if (activeMapPoints.length < 2) {
68
            setEdges([])
69
            return
70
        }
71

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

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

    
184
    return (
185
        <Fragment>
186
            {vertices}
187
            {edges}
188
        </Fragment>
189
    )
190
}
191

    
192
export default MapPath
(2-2/3)