Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 4da7b143

Přidáno uživatelem Schwobik před téměř 2 roky(ů)

HomePage connected to new backend endpoint, SearchPage edited to take argument to display inventory content on open
re #10715

Zobrazit rozdíly:

src/api/homePageService.ts
1
import { axiosInstance } from "./api"
2

  
3
export const fetchHomeDataRequest = async () => {
4
    return await axiosInstance.get("/homePage")
5
}
src/components/listView/ListViewInventoryGroup.tsx
90 90
            <VStack mb={ 2 }>
91 91
                <Button
92 92
                    onPress={ () => setIsExpanded(!isExpanded) }
93
                    alignSelf={ "start" }
93
                    alignSelf={ "flex-start" }
94 94
                    variant="solid"
95 95
                    bg={ "primary.500" }
96 96
                    mb={ 2 }
97 97
                    p={ 1 }
98
                    key={ props.inventoryName }
98 99
                    size={ "md" }
99 100
                >
100 101
                    { props.inventoryLabel }
......
107 108
                        name={ parseArtists(item) }
108 109
                        image={ parseImage(item) }
109 110
                        itemId={ item.xml_id }
111
                        inventoryLabel={ props.inventoryLabel }
110 112
                        navigation={ props.navigation }
111 113
                    />
112 114
                )) }
src/components/search/SearchForm.tsx
1 1
import {
2 2
    Box,
3
    Button, ChevronDownIcon, ChevronUpIcon,
4
    CloseIcon, FormControl, HStack, Input,
5
    ScrollView, Text,
3
    Button,
4
    ChevronDownIcon,
5
    ChevronUpIcon,
6
    CloseIcon,
7
    HStack,
8
    Input,
9
    Text,
6 10
    VStack
7 11
} from "native-base"
8 12
import { useDispatch, useSelector } from "react-redux"
9
import { useEffect, useState } from "react"
13
import { useCallback, useEffect, useState } from "react"
10 14
import { AppDispatch, RootState } from "../../stores/store"
11 15
import { Inventory } from "../../types/searchFormTypes"
12 16
import { search } from "../../stores/actions/listViewThunks"
......
17 21
import { SearchParams } from "../../api/searchService"
18 22

  
19 23
interface SearchFormProps {
20
    isFilterOpen: boolean,
21
    setIsFilterOpen: (isFilterOpen: boolean) => void
24
    inventoryId: string | null
22 25
}
23 26

  
24 27

  
25 28
const SearchForm = (props: SearchFormProps) => {
29
    const [isFilterOpen, setIsFilterOpen] = useState<boolean>(true)
30

  
26 31
    const inventories: Inventory[] = useSelector((state: RootState) => state.searchForm.inventories)
27 32
    const nationalities = useSelector((state: RootState) => state.searchForm.nationalities)
28 33
    const artists = useSelector((state: RootState) => state.searchForm.artists)
......
72 77
        }
73 78
        dispatch(setFilterState(filterState))
74 79
        dispatch(search(filterState))
75
        props.setIsFilterOpen(false)
80
        setIsFilterOpen(false)
76 81
    }
77 82

  
78 83
    const clearForm = () => {
......
90 95
        setSearchQuery("")
91 96
    }
92 97

  
93
    const getSearchHeader = () => {
94
        if (inventories && inventories.length === 1) {
95
            return `Search: ${ inventories[0].name }`
96
        } else if (rooms && rooms.length === 1) {
97
            return `Search: ${ rooms[0].label }`
98
    const getSearchHeader = useCallback(() => {
99
        if (selectedInventories && selectedInventories.length === 1) {
100
            return `Search: ${ selectedInventories[0].label }`
101
        } else if (selectedRooms && selectedRooms.length === 1) {
102
            return `Search: ${ selectedRooms[0].label }`
98 103
        } else {
99 104
            return "Search:"
100 105
        }
101
    }
106
    }, [inventories, rooms])
107

  
108
    useEffect(() => {
109
        log.debug("SearchForm", "useEffect", "props.inventoryId", props.inventoryId)
110
        if (props.inventoryId) {
111
            clearForm()
112
            setIsFilterOpen(false)
113
            setSelectedInventories([{ label: props.inventoryId, value: props.inventoryId }])
114
            dispatch(setFilterState({ inventories: [props.inventoryId] }))
115
            dispatch(search({ inventories: [props.inventoryId] }))
116
        }
117
    }, [props.inventoryId])
102 118

  
103 119
    return (
104 120
        <>
......
118 134
            />
119 135
            <HStack justifyContent={"space-between"}>
120 136
                <Button
121
                    alignSelf={ "start" }
122
                    onPress={ () => props.setIsFilterOpen(!props.isFilterOpen) }
137
                    onPress={ () => setIsFilterOpen(!isFilterOpen) }
123 138
                    variant="outline"
124 139
                    endIcon={
125 140
                        <>
126
                            { props.isFilterOpen ?
141
                            { isFilterOpen ?
127 142
                                (<ChevronUpIcon size={ 4 } color={ "primary.500" }/>)
128 143
                                : (<ChevronDownIcon size={ 4 } color={ "primary.500" }/>) }
129 144
                        </>
......
137 152
                >
138 153
                    Filter
139 154
                </Button>
140
                { !props.isFilterOpen && (
155
                { !isFilterOpen && (
141 156
                    <Button
142 157
                        borderRadius={ 10 }
143 158
                        onPress={ () => searchSubmit() }
......
152 167
                    </Button>
153 168
                )}
154 169
            </HStack>
155
            { props.isFilterOpen && (
170
            { isFilterOpen && (
156 171
                <>
157 172
                    <MultiSelect
158 173
                        data={ inventories.map((inventory, index) => {
src/pages/HomePage.tsx
1
import { Center, Image, Text } from "native-base"
1
import { Center, Image, Pressable, ScrollView, Text } from "native-base"
2
import { useDispatch, useSelector } from "react-redux"
3
import { AppDispatch, RootState } from "../stores/store"
4
import { useEffect, useState } from "react"
5
import { fetchData } from "../stores/actions/homePageThunks"
6
import { ApplicationHeading } from "../components/reusables/ApplicationHeading"
7
import LoadingBox from "../components/loading/LoadingBox"
8
import { DrawerScreenProps } from "@react-navigation/drawer"
9
import { RootDrawerParamList } from "./Navigation"
10
import { log } from "../logging/logger"
11
// import { Image } from "react-native"
12

  
13
const HomePage = ({navigation}: DrawerScreenProps<RootDrawerParamList, 'Home'>) => {
14
    const data = useSelector((state: RootState) => state.homePage.data)
15
    const loading = useSelector((state: RootState) => state.homePage.loading)
16
    const error = useSelector((state: RootState) => state.homePage.lastError)
17
    const [aspectRatio, setAspectRatio] = useState(1.0)
18

  
19
    const dispatch = useDispatch<AppDispatch>()
20

  
21
    useEffect(() => {
22
        if (data === null || data.length === 0 && !loading) {
23
            dispatch(fetchData())
24
        }
25
        // Image.getSize("http:/147.228.173.159/static/home/Rudolf-Aachen-crop.png", (width, height) => {
26
        //     setAspectRatio(width / height)
27
        // })
28

  
29
    }, [])
2 30

  
3
const HomePage = () => {
4 31
    return (
5
        <Center>
6
            <Text>Home Page</Text>
7
            <Image
8
                source={{uri: "http:/147.228.173.159/static/home/Rudolf-Aachen-crop.png"}}
9
                w={"100%"}
10
                h={"50%"}
11
                alt={"Rudolf-Aachen"}
12
            />
32
        <Center m={2} mb={10}>
33
            { loading ? (
34
                <LoadingBox text={ "Loading..." }/>
35
            ) : (
36
                <>
37
                    <ApplicationHeading/>
38
                    <ScrollView >
39
                    <Image
40
                        source={ {uri: "http:/147.228.173.159/static/home/Rudolf-Aachen-crop.png"} }
41
                        w={"100%"} h={ 200 }
42
                        resizeMode={"contain"}
43
                        alignSelf={ "center" }
44
                        alt={ "Rudolf-Aachen" }
45
                    />
46
                    { data && data.length > 0 && (
47
                        <Text
48
                            mx={ 2 }
49
                            fontSize={ "sm" }
50
                            lineHeight={"sm"}
51
                            color={"gray.500"}
52
                            textAlign={"justify"}
53
                        >
54
                            {data[0]["general"].text}
55
                        </Text>
56
                    )}
57
                        <Text
58
                            mt={ 2 }
59
                            bold
60
                            fontSize={"xl"}
61
                            color={"primary.500"}
62
                        >
63
                            Inventories
64
                        </Text>
65
                    { data && data.length > 1 && data.slice(1).map((item) => (
66
                        <Pressable
67
                            onPress={() => navigation.navigate("Search", {inventoryId: Object.keys(item)[0]}) }
68
                            key={ Object.values(item)[0].label }
69
                            rounded={ "md" }
70
                            borderWidth={ 1 }
71
                            borderColor={ "gray.300" }
72
                            m = { 2 }
73
                            p={ 3 }
74
                        >
75
                            <Text
76
                                bold
77
                                fontSize={ "md" }
78
                                mb={1}
79
                            >
80
                                { Object.values(item)[0].label }
81
                            </Text>
82
                            <Text
83
                                fontSize={ "sm" }
84
                                lineHeight={"sm"}
85
                                color={"gray.500"}
86
                                textAlign={"justify"}
87
                            >
88
                                { Object.values(item)[0].text }
89
                            </Text>
90
                        </Pressable>
91
                    )) }
92

  
93
                    </ScrollView>
94
                </>
95
            ) }
13 96
        </Center>
14 97
    )
15 98
}
src/pages/ItemViewPage.tsx
10 10
import ItemTabBar from "../components/item/ItemTabBar"
11 11
import { log } from "../logging/logger"
12 12
import { DrawerScreenProps } from "@react-navigation/drawer"
13
import { RootDrawerParamList } from "../components/Navigation"
13
import { RootDrawerParamList } from "./Navigation"
14 14

  
15 15

  
16 16
const ItemViewPage = ({route, navigation}: DrawerScreenProps<RootDrawerParamList, 'Item'>) => {
src/pages/SearchPage.tsx
1 1
import {
2
    Button,
3 2
    Center,
4
    ChevronDownIcon,
5
    ChevronUpIcon, ScrollView,
3
    ScrollView,
6 4
    VStack
7 5
} from "native-base"
8 6
import ListView from "../components/listView/ListView"
9 7
import SearchForm from "../components/search/SearchForm"
10
import { useEffect, useState } from "react"
8
import { useEffect } from "react"
11 9
import {
12
    fetchArtists, fetchCities, fetchCountries, fetchInstitutions,
10
    fetchArtists,
11
    fetchCities,
12
    fetchCountries,
13
    fetchInstitutions,
13 14
    fetchInventories,
14 15
    fetchNationalities,
15 16
    fetchPlans,
16
    fetchSubjects, fetchTechniques
17
    fetchSubjects,
18
    fetchTechniques
17 19
} from "../stores/actions/searchFormThunks"
18 20
import { useDispatch } from "react-redux"
19 21
import { AppDispatch } from "../stores/store"
20 22
import { log } from "../logging/logger"
21 23
import { DrawerScreenProps } from "@react-navigation/drawer"
22
import { RootDrawerParamList } from "../components/Navigation"
24
import { RootDrawerParamList } from "./Navigation"
23 25

  
24
const SearchPage = ({navigation}: DrawerScreenProps<RootDrawerParamList, 'Search'>) => {
25
    const [isFilterOpen, setIsFilterOpen] = useState(true)
26 26

  
27
const SearchPage = ({route, navigation}: DrawerScreenProps<RootDrawerParamList, 'Search'>) => {
27 28
    const dispatch = useDispatch<AppDispatch>()
28 29

  
29 30
    useEffect(() => {
......
42 43
        log.debug("SearchPage", "useEffect", "fetchEverything", "done")
43 44
    }, [dispatch])
44 45

  
46

  
47
    useEffect(() => {
48
        log.debug("SearchPage", "props", route.params.inventoryId)
49
    }, [])
50

  
45 51
    return (
46 52
        <Center m={ 2 } mr={0} mb={6} flex={1}>
47 53

  
48 54
            <ScrollView flex={1} w={"100%"} >
49 55
                <VStack space={ 1 } mr={ 4 }>
50
                    <SearchForm isFilterOpen={ isFilterOpen } setIsFilterOpen={setIsFilterOpen}/>
56
                    <SearchForm inventoryId={route.params.inventoryId}/>
51 57
                    <ListView navigation={navigation}/>
52 58
                </VStack>
53 59
            </ScrollView>
src/stores/actions/homePageThunks.ts
1
import { createAsyncThunk } from "@reduxjs/toolkit"
2
import { fetchHomeDataRequest } from "../../api/homePageService"
3
import { HomePageData } from "../../types/homePageTypes"
4

  
5
export const fetchData = createAsyncThunk(
6
    "homePage/fetchData",
7
    async (_, thunkAPI) => {
8
        const response = await fetchHomeDataRequest()
9
        if (response.status !== 200) {
10
            return thunkAPI.rejectWithValue("Failed to fetch data")
11
        }
12
        return response.data as HomePageData
13
    }
14
)
src/stores/reducers/homePageSlice.ts
1
import { HomePageData } from "../../types/homePageTypes"
2
import { createSlice } from "@reduxjs/toolkit"
3
import { fetchData } from "../actions/homePageThunks"
4

  
5
export interface HomePageState {
6
    lastError?: string
7
    loading: boolean
8
    data: HomePageData
9
}
10

  
11
const initialState: HomePageState = {
12
    lastError: "",
13
    loading: false,
14
    data: []
15
}
16

  
17
export const homePageSlice = createSlice({
18
    name: "homePage",
19
    initialState: initialState,
20
    reducers: {
21
        resetHomePage: () => initialState,
22
    },
23
    extraReducers: (builder) => {
24
        builder.addCase(fetchData.pending, (state) => {
25
            state.loading = true
26
        })
27
        builder.addCase(fetchData.fulfilled, (state, action) => {
28
            state.loading = false
29
            state.data = action.payload
30
            state.lastError = ""
31
        })
32
        builder.addCase(fetchData.rejected, (state, action) => {
33
            state.loading = false
34
            state.lastError = action.error.message
35
        })
36
    }
37
})
38

  
39
export const { resetHomePage } = homePageSlice.actions
40
export default homePageSlice.reducer
src/stores/store.ts
3 3
import itemReducer from "./reducers/itemSlice"
4 4
import searchFormReducer from "./reducers/searchFormSlice"
5 5
import listViewReducer from "./reducers/listViewSlice"
6
import homePageReducer from "./reducers/homePageSlice"
6 7

  
7 8
const store = configureStore({
8 9
    reducer: {
......
10 11
        itemViewState: itemReducer,
11 12
        searchForm: searchFormReducer,
12 13
        listView: listViewReducer,
14
        homePage: homePageReducer,
13 15
    },
14 16
})
15 17

  
src/types/homePageTypes.ts
1
export type HomePageData = {
2
    [key: string]: {
3
        label?: string
4
        text: string
5
    }
6
}[]

Také k dispozici: Unified diff