Revize 4da7b143
Přidáno uživatelem Schwobik před téměř 2 roky(ů)
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
HomePage connected to new backend endpoint, SearchPage edited to take argument to display inventory content on open
re #10715