Projekt

Obecné

Profil

Stáhnout (5.9 KB) Statistiky
| Větev: | Tag: | Revize:
1
import { createSlice } from '@reduxjs/toolkit'
2
import mapConfig from '../../config/mapConfig'
3
import { PathDto } from '../../swagger/data-contracts'
4
import buildPathVariants from './Map/mapUtils'
5
import TrackingToolState from './trackingToolState'
6
import { sendTextForProcessing } from './trackingToolThunks'
7
import { calculateMapCenter, MapPoint, PathVariant } from './trackingToolUtils'
8

    
9
const initialState: TrackingToolState = {
10
    isLoading: false,
11
    mapCenter: [mapConfig.defaultCoordinates[0], mapConfig.defaultCoordinates[1]],
12
    displayedPathIdx: 0,
13
    dialogApiCallSuccess: true,
14
}
15

    
16
export const trackingToolSlice = createSlice({
17
    name: 'trackingTool',
18
    initialState,
19
    reducers: {
20
        consumeErr: (state: TrackingToolState) => ({ ...state, lastErr: undefined, }),
21
        setSelectedPathIdx: (state: TrackingToolState, action: { payload: number }) => ({ ...state, selectedPathIdx: action.payload, }),
22
        resetDialogApiCallSuccess: (state: TrackingToolState) => ({ ...state, dialogApiCallSuccess: false, }),
23
        // Updates currently displayed path
24
        updateDisplayedPath: (state: TrackingToolState, action: { payload: PathVariant }) => ({ ...state, displayedPath: action.payload, }),
25
        // Updates map marker
26
        updateMapMarker: (state: TrackingToolState, action: { payload: MapPoint }) => {
27
            const newPath = [...state.displayedPath ?? []]
28
            if (newPath.length <= action.payload.idx) {
29
                return state // do nothing if there is no path
30
            }
31

    
32
            newPath[action.payload.idx] = action.payload
33
            return {
34
                ...state,
35
                displayedPath: newPath,
36
            }
37
        },
38
        // Removes map marker from currently used path
39
        removeMapMarker: (state: TrackingToolState, action: { payload: { id: string, idx: number } }) => {
40
            const newPath = [...state.displayedPath ?? []]
41
            if (newPath.length <= action.payload.idx) {
42
                return state // do nothing if there is no path
43
            }
44

    
45
            return {
46
                ...state,
47
                displayedPath: [...newPath.slice(0, action.payload.idx), ...newPath.slice(action.payload.idx + 1)],
48
            }
49
        },
50
        // Moves map marker in the path array
51
        moveMarkerToDestination: (state: TrackingToolState, action: { payload: { destination: number, source: number } }) => {
52
            const { destination, source } = action.payload
53
            const newPath = [...state.displayedPath ?? []]
54
            if (newPath.length <= source
55
                || newPath.length <= destination
56
                || source === destination) {
57
                return state // do nothing if there is no path
58
            }
59

    
60
            // JS array dark magic
61
            const [removed] = newPath.splice(action.payload.source, 1)
62
            newPath.splice(destination, 0, removed)
63
            return {
64
                ...state,
65
                displayedPath: newPath.map((item, idx) => ({ ...item, idx })),
66
            }
67
        },
68
        clear: () => ({ ...initialState }),
69
        mergeWithCurrentPath: (state: TrackingToolState, action: { payload: PathVariant }) => {
70
            const { payload: jsonPath } = action
71
            if (!jsonPath) {
72
                return state
73
            }
74

    
75
            const newPath = [...state.displayedPath ?? []]
76
            const existingIds = new Set(newPath.map(item => item.id ?? ''))
77

    
78
            const newItems: MapPoint[] = []
79
            jsonPath.forEach(item => {
80
                if (!existingIds.has(item.id ?? '')) {
81
                    newItems.push(item)
82
                }
83
            })
84

    
85
            newItems.forEach(item => {
86
                item.addToPath = !state.pathVariants || state.pathVariants.length === 0
87
                item.idx = newPath.length
88
                newPath.push(item)
89
            })
90

    
91
            return {
92
                ...state,
93
                displayedPath: newPath,
94
            }
95
        },
96
    },
97
    extraReducers: (builder) => {
98
        builder.addCase(sendTextForProcessing.fulfilled, (state, action) => {
99
            const pathDto: PathDto = action.payload
100
            const pathVariants = buildPathVariants(pathDto)
101
            const selectedPath = pathVariants.length > 0 ? pathVariants[0] : undefined
102
            if (!selectedPath) {
103
                return {
104
                    ...state,
105
                    pathDto,
106
                    pathVariants,
107
                    displayedPath: undefined,
108
                    displayedPathIdx: 0,
109
                    dialogApiCallSuccess: true,
110
                    isLoading: false,
111
                }
112
            }
113

    
114
            const mapCenter = calculateMapCenter(selectedPath)
115
            return {
116
                ...state,
117
                pathVariants,
118
                pathDto,
119
                mapCenter: mapCenter ?? state.mapCenter,
120
                isLoading: false,
121
                dialogApiCallSuccess: true,
122
                currentPage: 0,
123
                displayedPath: selectedPath,
124
                displayedPathIdx: 0,
125
            }
126
        })
127
        builder.addCase(sendTextForProcessing.rejected, (_, action) => ({
128
            ...initialState,
129
            lastError: action.error.message,
130
            isLoading: false,
131
            dialogApiCallSuccess: false,
132
            currentPage: 0,
133
            displayedPath: undefined,
134
            displayedPathIdx: 0,
135
            pathDto: undefined,
136
            pathVariants: undefined,
137
        }))
138
        builder.addCase(sendTextForProcessing.pending, (state) => ({
139
            ...state,
140
            isLoading: true,
141
            dialogApiCallSuccess: false,
142
        }))
143
    }
144
})
145

    
146
export const {
147
    consumeErr,
148
    setSelectedPathIdx,
149
    resetDialogApiCallSuccess,
150
    updateDisplayedPath,
151
    updateMapMarker,
152
    removeMapMarker,
153
    moveMarkerToDestination,
154
    clear,
155
    mergeWithCurrentPath,
156
} = trackingToolSlice.actions
157

    
158
const trackingToolReducer = trackingToolSlice.reducer
159
export default trackingToolReducer
(3-3/5)