Projekt

Obecné

Profil

Stáhnout (4.68 KB) Statistiky
| Větev: | Tag: | Revize:
1
import { createSlice } from "@reduxjs/toolkit"
2
import { LatLngTuple } from "leaflet"
3
import { persistReducer } from "redux-persist"
4
import mapConfig from "../../config/mapConfig"
5
import { PathDto } from "../../swagger/data-contracts"
6
import buildPathVariants, { MapPoint, PathVariant } from "./buildPathVariants"
7
import { sendTextForProcessing } from "./trackingToolThunks"
8
import storage from "redux-persist/lib/storage"
9

    
10
export interface TrackingToolState {
11
    isLoading: boolean // whether the data is being loaded
12
    pathDto?: PathDto // the data
13
    pathVariants?: PathVariant[] // undefined signals that no path variants were yet fetched from the API
14
    lastError?: string // consumable for errors during thunks
15
    mapCenter: LatLngTuple // pair of latitude and longitude
16
    primaryPathIdx: number // index of the primary path
17
    // trigger to close the dialog when API call is finished
18
    dialogApiCallSuccess: boolean
19
    pathsPerPage: number // max number of paths to show on the map at once
20
    currentPage: number // current page of paths - starts from 0
21
}
22

    
23
const defaultPathsPerPage = 5
24

    
25
const initialState: TrackingToolState = {
26
    isLoading: false,
27
    mapCenter: [mapConfig.defaultCoordinates[0], mapConfig.defaultCoordinates[1]],
28
    primaryPathIdx: 0,
29
    dialogApiCallSuccess: true,
30
    pathsPerPage: defaultPathsPerPage,
31
    currentPage: 0,
32
}
33

    
34
const calculateMapCenter = (pathVariant: PathVariant): LatLngTuple | undefined => {
35
    const displayableItems = pathVariant.filter((item) => item.displayable)
36
    if (displayableItems.length === 0) {
37
        return undefined
38
    }
39

    
40
    return [
41
        displayableItems
42
            .map((item) => item.catalogItem.latitude ?? 0)
43
            .reduce((a, b) => a + b, 0) / displayableItems.length,
44
        displayableItems
45
            .map((item) => item.catalogItem.longitude ?? 0)
46
            .reduce((a, b) => a + b, 0) / displayableItems.length,
47
    ]
48
}
49

    
50
const persistConfig = {
51
    key: "auth",
52
    storage, // localStorage for browsers
53
}
54

    
55
export const trackingToolSlice = createSlice({
56
    name: "trackingTool",
57
    initialState,
58
    reducers: {
59
        consumeErr: (state: TrackingToolState) => ({
60
            ...state,
61
            lastErr: undefined,
62
        }),
63
        setPrimaryIdx: (state: TrackingToolState, action: any) => ({
64
            ...state,
65
            primaryPathIdx: action.payload,
66
        }),
67
        resetDialogApiCallSuccess: (state: TrackingToolState) => ({
68
            ...state,
69
            dialogApiCallSuccess: false,
70
        }),
71
        setPage: (state: TrackingToolState, action: { payload: number }) => ({
72
            ...state,
73
            currentPage: action.payload,
74
        }),
75
        updateMapMarker: (state: TrackingToolState, action: { payload: { idx: number, item: MapPoint } }) => {
76
            const { idx, item } = action.payload
77
            if (!state.pathVariants || state.pathVariants.length <= idx) {
78
                return state
79
            }
80

    
81
            return {
82
                ...state,
83
                pathVariants: state.pathVariants.map((pathVariant, i) => {
84
                    if (i !== idx) {
85
                        return [...pathVariant]
86
                    }
87

    
88
                    return [
89
                        ...pathVariant.slice(0, item.idx),
90
                        item,
91
                        ...pathVariant.slice(item.idx + 1),
92
                    ]
93
                })
94
            }
95
        },
96
        clear: () => ({ ...initialState }),
97
    },
98
    extraReducers: (builder) => {
99
        builder.addCase(sendTextForProcessing.fulfilled, (state, action) => {
100
            const pathDto: PathDto = action.payload
101
            const pathVariants = buildPathVariants(pathDto)
102

    
103
            const mapCenter = calculateMapCenter(pathVariants[state.primaryPathIdx])
104
            return {
105
                ...state,
106
                pathVariants,
107
                pathDto,
108
                mapCenter: mapCenter ?? state.mapCenter,
109
                isLoading: false,
110
                dialogApiCallSuccess: true,
111
                currentPage: 0,
112
            }
113
        })
114
        builder.addCase(sendTextForProcessing.rejected, (_, action) => ({
115
            ...initialState,
116
            lastError: action.error.message,
117
            isLoading: false,
118
            dialogApiCallSuccess: false,
119
            currentPage: 0,
120
        }))
121
        builder.addCase(sendTextForProcessing.pending, (state) => {
122
            return {
123
                ...state,
124
                isLoading: true,
125
                dialogApiCallSuccess: false,
126
            }
127
        })
128
    },
129
})
130

    
131
export const { consumeErr, setPrimaryIdx, resetDialogApiCallSuccess, clear, updateMapMarker } =
132
    trackingToolSlice.actions
133
const trackingToolReducer = trackingToolSlice.reducer
134
export default trackingToolReducer
(8-8/9)