Projekt

Obecné

Profil

Stáhnout (7.35 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 { setPrimaryIdx, updateMapMarker } from '../trackingToolSlice'
7
import MapMarker from './MapMarker'
8
import { LatLngTuple } from 'leaflet'
9
import { Popup, Tooltip } 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(
52
            path.filter((mapPoint) => isMapPointDisplayable(mapPoint))
53
        )
54
    }, [path])
55

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

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

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

    
179
    return (
180
        <Fragment>
181
            {vertices}
182
            {edges}
183
        </Fragment>
184
    )
185
}
186

    
187
export default MapPath
(2-2/3)