commit e49b1f44ec5d6dc2fb278d349162b558d78ddfd3
Author: Schwobik <michal.schwob@seznam.cz>
Date:   Tue May 2 12:06:05 2023 +0200

    Implementation of multiselect component, search page finished with listview
    re #10478

diff --git a/package.json b/package.json
index 14784b1..710143f 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
     "react-native": "0.71.6",
     "react-native-deck-swiper": "^2.0.13",
     "react-native-gesture-handler": "~2.9.0",
+    "react-native-logs": "^5.0.1",
     "react-native-multiple-select": "^0.5.12",
     "react-native-reanimated": "~2.14.4",
     "react-native-safe-area-context": "4.5.0",
diff --git a/src/api/searchService.ts b/src/api/searchService.ts
index b57884a..1aba8fe 100644
--- a/src/api/searchService.ts
+++ b/src/api/searchService.ts
@@ -1,10 +1,44 @@
 import { axiosInstance } from "./api"
+import { log } from "../logging/logger"
 
 export interface SearchParams {
-    inventory?: string
+    inventories?: string[]
+    rooms?: string[]
+    artists?: string[]
+    nationalities?: string[]
+    subjects?: string[]
+    techniques?: string[]
+    isSchoolOfPrague?: boolean
+    isOriginal?: boolean
+    isCopy?: boolean
+    isLowQuality?: boolean
+    isHighQuality?: boolean
+    isIdentified?: boolean
+    institutions?: string[]
+    cities?: string[]
+    countries?: string[]
+    searchQuery?: string
     //TODO: add other search params
 }
 
+const composeSearchParams = (array: string[] | undefined, identifier: string) => {
+    log.debug("composeSearchParams", array, identifier)
+
+    if (array && array.length > 0) {
+        return array.map((item) => `&${identifier}=${item}`).join("")
+    }
+    return ""
+}
+
 export const searchRequest = async (params: SearchParams) => {
-    return await axiosInstance.get(`/search_v2${ (params.inventory ? `?inventory=${ params.inventory }` : "")}`)
+    const url = "/search_v2"
+    + "?search=" + (params.searchQuery ? params.searchQuery : "")
+    + composeSearchParams(params.inventories, "inventory")
+    + composeSearchParams(params.rooms, "room")
+    + composeSearchParams(params.artists, "persname")
+    + composeSearchParams(params.nationalities, "nationality")
+    // TODO add other search params
+    log.debug("searchRequest url: " + url)
+    return await axiosInstance.get(url)
+
 }
\ No newline at end of file
diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx
index 38fd5fc..4b785c4 100644
--- a/src/components/Navigation.tsx
+++ b/src/components/Navigation.tsx
@@ -20,7 +20,7 @@ const Navigation = () => {
             <Drawer.Navigator useLegacyImplementation
                 screenOptions={({ navigation }) => ({
                     headerStyle: {
-                        backgroundColor: nativeBaseTheme.colors.primary[50],
+                        backgroundColor: nativeBaseTheme.colors.primary[800],
                     },
                     headerTintColor: '#fff',
                     headerTitleStyle: {
diff --git a/src/components/listView/ItemPreview.tsx b/src/components/listView/ItemPreview.tsx
index 6b5233b..a222747 100644
--- a/src/components/listView/ItemPreview.tsx
+++ b/src/components/listView/ItemPreview.tsx
@@ -1,4 +1,5 @@
 import { Center, HStack, Image, Text, VStack } from "native-base"
+import { useEffect } from "react"
 
 interface ItemPreviewProps {
     caption: string
@@ -9,23 +10,26 @@ interface ItemPreviewProps {
 
 const ItemPreview = (props: ItemPreviewProps) => {
 
+    useEffect(() => {
+        console.log("ItemPreview", "Props:", props)
+    }, [props])
+
     return (
         <>
-
             <HStack
                 space={ 2 }
                 flex={ 1 }
                 alignItems={ "start" }
             >
                 <Image
-                    source={ {uri: `http:/147.228.173.159/static/images/${ props.image ? props.image : "thumb-Rel-78.png" }`} }
+                    source={ {uri: `http:/147.228.173.159/static/images/${ props.image ? "thumb-" + props.image : "thumb-Rel-78.png" }`} }
                     size={ "sm" }
                     alt={ props.image ? props.image : "thumb-Rel-78.png" }
                 />
-                <VStack>
-                    <Text>{ props.name }</Text>
-                    <Text>{ props.caption }</Text>
-                    <Text>{ props.title }</Text>
+                <VStack h={70}>
+                    <Text fontSize={"sm"} italic>{ props.name }</Text>
+                    <Text fontSize={"sm"} bold>{ props.caption }</Text>
+                    <Text fontSize={"xs"}>{ props.title }</Text>
                 </VStack>
             </HStack>
         </>
diff --git a/src/components/listView/ListView.tsx b/src/components/listView/ListView.tsx
index d02c496..d2a5943 100644
--- a/src/components/listView/ListView.tsx
+++ b/src/components/listView/ListView.tsx
@@ -3,34 +3,71 @@ import { ScrollView, Text, VStack } from "native-base"
 import { useSelector } from "react-redux"
 import { RootState } from "../../stores/store"
 import ItemPreview from "./ItemPreview"
+import { ItemPreviewType } from "../../types/listViewTypes"
+import { log } from "../../logging/logger"
+
 
 const ListView = () => {
     const items = useSelector((state: RootState) => state.listView.data)
 
+    /**
+     * Searches through names by given role, return getty_data.display_name if exists otherwise name.value
+     * @param item
+     * @param role
+     */
+    const parseNameByRole = (item: ItemPreviewType, role: string) => {
+        // @ts-ignore
+        const name = item.object[0].name?.find((name) => name.role === role)
+        return name && name ?
+            name.getty_data ?
+                name.getty_data.display_name : name.value
+            : ""
+    }
+
+    /**
+     * Returns artist if it is original, otherwise returns copist and original artist in copy of
+     * @param item
+     */
+    const parseArtists = (item: ItemPreviewType) => {
+        // if is copy - display copist and copy of original artist if they are present in data
+        if (item.src?.value && item.src?.value == "copy") {
+            const copist = parseNameByRole(item, "copist")
+            const artist = parseNameByRole(item, "artist")
+            return `${ copist } ${ artist !== "" ? `(copy of ${ artist })` : "" }`
+        } else {
+            // if is original - display artist
+            return parseNameByRole(item, "artist")
+        }
+    }
+
+    /**
+     * Parses image name
+     * cycles through all objects and returns first image name with changed suffix to .png of undefined if not found
+     * @param item
+     */
+    const parseImage = (item: ItemPreviewType) => {
+        // @ts-ignore
+        const image = item.object.find((object) => object.images)
+        // @ts-ignore
+        return image && image.images ? image.images[0].file.split('.')[0] + '.png' : undefined
+    }
+
+    useEffect(() => {
+        log.debug("ListView", "Items:", items)
+    }, [items])
+
     return (
-        <VStack
-            space={ 2 }
-            flex={ 1 }
-            p={ 4 }
-            alignItems={ "start" }
-        >
+        <>
             { items.map((item) => (
                 <ItemPreview
+                    // @ts-ignore
                     caption={ item.object[0].caption }
                     title={ item.text }
-                    name={
-                        item.object[0].name ?
-                            item.object[0].name[0].getty_data ?
-                                item.object[0].name[0].getty_data.display_name
-                                :
-                                item.object[0].name[0].value
-                            :
-                            undefined
-                    }
-                    image={ item.object[1] && item.object[1].images && item.object[1].images ? item.object[1].images[0].file : undefined }
+                    name={ parseArtists(item) }
+                    image={ parseImage(item) }
                 />
             )) }
-        </VStack>
+        </>
     )
 }
 
diff --git a/src/components/search/MultiSelect.tsx b/src/components/search/MultiSelect.tsx
new file mode 100644
index 0000000..2c2a31a
--- /dev/null
+++ b/src/components/search/MultiSelect.tsx
@@ -0,0 +1,210 @@
+import {
+    Actionsheet, Badge,
+    Box, Button, CloseIcon, Divider, HStack,
+    Icon,
+    Input,
+    KeyboardAvoidingView,
+    Pressable,
+    ScrollView, SearchIcon, Spinner,
+    Text,
+    useDisclose, View
+} from "native-base"
+import { FlatList, GestureResponderEvent, Platform } from "react-native"
+import { useEffect, useMemo, useState } from "react"
+import { Ionicons } from "@expo/vector-icons"
+import { log } from "../../logging/logger"
+
+interface MultiSelectProps {
+    data: { label: string, value: string, index: number }[],
+    label: string,
+    selectedItems: { label: string, value: string }[],
+    onSelectedItemsChange: (selectedItems: { label: string, value: string }[]) => void,
+}
+
+const MultiSelect = (props: MultiSelectProps) => {
+    const [isSelected, setIsSelected] = useState(Array(props.data.length).fill(false))
+    const [query, setQuery] = useState("")
+    const {
+        isOpen,
+        onOpen,
+        onClose,
+    } = useDisclose()
+
+    const filteredData = useMemo(() => {
+        log.debug("Multiselect", "Filtering data")
+        if (!query || query.trim() == "") {
+            return props.data
+        }
+        log.debug("Multiselect", "Filtering data", "Query:", query)
+        log.debug("Multiselect", "Filtering data", "Data:", props.data)
+        return props.data.filter((row) => row.label?.toLowerCase().includes(query.toLowerCase()))
+    }, [query, props.data])
+
+    const updateSelected = (index: number) => {
+        isSelected[index] = !isSelected[index]
+        setIsSelected([...isSelected])
+    }
+
+    useEffect(() => {
+        log.debug("Multiselect", "Updating selected items before render")
+
+        const newSelected = Array(props.data.length).fill(false)
+        props.selectedItems.forEach((item) => {
+            const index = props.data.findIndex((i) => i.value === item.value)
+            if (index !== -1) {
+                newSelected[index] = true
+            }
+        })
+        setIsSelected(newSelected)
+
+        log.debug("Multiselect", "Updated selected items before render")
+    }, [props.selectedItems])
+
+    const onCancel = () => {
+        onClose()
+    }
+
+    const onDone = () => {
+        log.debug("Multiselect", "Done clicked")
+
+        const selectedItems = props.data.filter((row, index) => isSelected[index]).map((row) => ({
+            label: row.label,
+            value: row.value
+        }))
+        props.onSelectedItemsChange(selectedItems)
+        onClose()
+    }
+
+    const unselectItem = (index: number) => {
+        log.debug("Multiselect", "Unselecting item")
+
+        props.selectedItems.splice(index, 1)
+        props.onSelectedItemsChange([...props.selectedItems])
+    }
+
+    return (
+        <>
+            <Pressable
+                onPress={ onOpen }
+                rounded="md"
+                mt={ 2 }
+            >
+                <Text>{ props.label }</Text>
+            </Pressable>
+
+            <Box flex={ 1 }>
+                <ScrollView horizontal pb={ 2 }>
+                    <HStack space={ 1 } flexWrap="wrap">
+                        { props.selectedItems.map((item, index) => (
+                            <Badge
+                                endIcon={
+                                    <CloseIcon
+                                        size={ 4 }
+                                        onPress={ () => {
+                                            unselectItem(index)
+                                        } }
+                                    />
+                                }
+                                rounded="md"
+                                key={ item.value }
+                                variant="solid"
+                            >{ item.label }</Badge>
+                        )) }
+                    </HStack>
+                </ScrollView>
+            </Box>
+
+
+            <Divider background={ "primary.500" }/>
+            { isOpen && (
+                <Actionsheet isOpen={ isOpen } onClose={ onClose }>
+                    <Actionsheet.Content>
+                        <KeyboardAvoidingView
+                            h={ {lg: "auto"} }
+                            behavior={ "padding" }
+                            keyboardVerticalOffset={ 160 }
+                        >
+                            <Input
+                                placeholder="Search"
+                                variant="filled"
+                                width="100%"
+                                borderRadius="10"
+                                py="1"
+                                px="2"
+                                value={ query }
+                                onChangeText={ setQuery }
+                                InputLeftElement={
+                                    <SearchIcon
+                                        ml="2"
+                                        size="4"
+                                        color="gray.400"
+                                    />
+                                }
+                                InputRightElement={
+                                    <CloseIcon
+                                        mr="2"
+                                        size="4"
+                                        color="gray.400"
+                                        onPress={ () => setQuery("") }
+                                    />
+                                }
+                            />
+                            <FlatList
+                                data={ filteredData }
+                                renderItem={ ({item}) => (
+                                    <Actionsheet.Item
+                                        _pressed={ {bg: "primary.100"} }
+                                        onPress={ () => updateSelected(item.index) }
+                                        key={ item.value }
+                                        backgroundColor={ isSelected[item.index] ? "primary.100" : {} }
+                                    >
+                                        { item.label }
+                                    </Actionsheet.Item>
+                                ) }
+                                keyExtractor={ item => item.value }
+                                keyboardShouldPersistTaps={ "always" }
+                            />
+                            <HStack justifyContent={ "flex-end" } px={ 3 } space={ 2 }>
+                                <Button
+                                    onPress={ onCancel }
+                                    colorScheme={ "error" }
+                                    borderRadius={ 10 }
+                                    variant={ "subtle" }
+                                    startIcon={
+                                        <Icon
+                                            ml="0"
+                                            size="4"
+                                            color="error.400"
+                                            as={ <Ionicons name="ios-close"/> }
+                                        />
+                                    }
+                                >
+                                    Cancel
+                                </Button>
+                                <Button
+                                    onPress={ onDone }
+                                    colorScheme={ "primary" }
+                                    borderRadius={ 10 }
+                                    variant={ "subtle" }
+                                    startIcon={
+                                        <Icon
+                                            size="4"
+                                            color="primary.700"
+                                            as={ <Ionicons name="ios-checkmark"/> }
+                                        />
+                                    }
+                                >
+                                    Done
+                                </Button>
+                            </HStack>
+                        </KeyboardAvoidingView>
+                    </Actionsheet.Content>
+                </Actionsheet>
+            ) }
+
+        </>
+    )
+
+}
+
+export default MultiSelect
\ No newline at end of file
diff --git a/src/components/search/SearchForm.tsx b/src/components/search/SearchForm.tsx
index dba305d..2358048 100644
--- a/src/components/search/SearchForm.tsx
+++ b/src/components/search/SearchForm.tsx
@@ -1,125 +1,206 @@
-import { Button, Center, CheckIcon, FormControl, KeyboardAvoidingView, ScrollView, Select, Text } from "native-base"
+import {
+    Box,
+    Button,
+    CloseIcon,
+    ScrollView,
+    VStack
+} from "native-base"
 import { useDispatch, useSelector } from "react-redux"
-import React, { useEffect, useState } from "react"
+import { useEffect, useState } from "react"
 import { AppDispatch, RootState } from "../../stores/store"
 import { Inventory } from "../../types/searchFormTypes"
-import {
-    fetchArtists, fetchCities, fetchCountries, fetchInstitutions,
-    fetchInventories,
-    fetchNationalities,
-    fetchPlans,
-    fetchSubjects
-} from "../../stores/actions/searchFormThunks"
-import SearchFormControl from "./SearchFormControl"
-import { Platform } from "react-native"
 import { search } from "../../stores/actions/listViewThunks"
+import MultiSelect from "./MultiSelect"
+import SwitchWithLabel from "./SwitchWithLabel"
+import { log } from "../../logging/logger"
 
+interface SearchFormProps {
+    isFilterOpen: boolean,
+}
 
-const SearchForm = () => {
+
+const SearchForm = (props: SearchFormProps) => {
     const inventories: Inventory[] = useSelector((state: RootState) => state.searchForm.inventories)
     const nationalities = useSelector((state: RootState) => state.searchForm.nationalities)
     const artists = useSelector((state: RootState) => state.searchForm.artists)
     const subjects = useSelector((state: RootState) => state.searchForm.subjects)
     const rooms = useSelector((state: RootState) => state.searchForm.rooms)
+    const techniques = useSelector((state: RootState) => state.searchForm.techniques)
     const countries = useSelector((state: RootState) => state.searchForm.countries)
     const cities = useSelector((state: RootState) => state.searchForm.cities)
     const institutions = useSelector((state: RootState) => state.searchForm.institutions)
 
+    const [selectedInventories, setSelectedInventories] = useState<{ label: string, value: string }[]>([])
+    const [selectedNationalities, setSelectedNationalities] = useState<{ label: string, value: string }[]>([])
+    const [selectedArtists, setSelectedArtists] = useState<{ label: string, value: string }[]>([])
+    const [selectedSubjects, setSelectedSubjects] = useState<{ label: string, value: string }[]>([])
+    const [selectedRooms, setSelectedRooms] = useState<{ label: string, value: string }[]>([])
+    const [selectedTechniques, setSelectedTechniques] = useState<{ label: string, value: string }[]>([])
+    const [selectedCountries, setSelectedCountries] = useState<{ label: string, value: string }[]>([])
+    const [selectedCities, setSelectedCities] = useState<{ label: string, value: string }[]>([])
+    const [selectedInstitutions, setSelectedInstitutions] = useState<{ label: string, value: string }[]>([])
 
-    const [selectedInventories, setSelectedInventories] = useState<string[]>([])
-    const [selectedNationalities, setSelectedNationalities] = useState<string[]>([])
-    const [selectedArtists, setSelectedArtists] = useState<string[]>([])
-    const [selectedSubjects, setSelectedSubjects] = useState<string[]>([])
-    const [selectedRooms, setSelectedRooms] = useState<string[]>([])
-    const [selectedCountries, setSelectedCountries] = useState<string[]>([])
-    const [selectedCities, setSelectedCities] = useState<string[]>([])
-    const [selectedInstitutions, setSelectedInstitutions] = useState<string[]>([])
+    const [isSchoolOfPrague, setIsSchoolOfPrague] = useState(false)
+    const [isOriginal, setIsOriginal] = useState(false)
+    const [isCopy, setIsCopy] = useState(false)
+    const [isHighQuality, setIsHighQuality] = useState(false)
+    const [isLowQuality, setIsLowQuality] = useState(false)
 
     const dispatch = useDispatch<AppDispatch>()
 
-    useEffect(() => {
-        dispatch(fetchInventories())
-        dispatch(fetchNationalities())
-        dispatch(fetchArtists())
-        dispatch(fetchSubjects())
-        dispatch(fetchPlans())
-        dispatch(fetchCountries())
-        dispatch(fetchCities())
-        dispatch(fetchInstitutions())
-    }, [dispatch])
+    const searchSubmit = () => {
+        dispatch(search({
+            inventories: selectedInventories.map(i => i.value),
+            nationalities: selectedNationalities.map(n => n.value),
+            artists: selectedArtists.map(a => a.value),
+            subjects: selectedSubjects.map(s => s.value),
+            rooms: selectedRooms.map(r => r.value),
+            techniques: selectedTechniques.map(t => t.value),
+            countries: selectedCountries.map(c => c.value),
+            cities: selectedCities.map(c => c.value),
+            institutions: selectedInstitutions.map(i => i.value),
+            isSchoolOfPrague,
+            isOriginal,
+            isCopy,
+            isHighQuality,
+            isLowQuality
+        }))
+    }
 
+    const clearForm = () => {
+        log.debug("SearchForm", "clearForm")
 
-    const searchSubmit = () => {
-        dispatch(search({inventory: selectedInventories ? selectedInventories[0] : undefined}))
+        setSelectedInventories([])
+        setSelectedNationalities([])
+        setSelectedArtists([])
+        setSelectedSubjects([])
+        setSelectedRooms([])
+        setSelectedTechniques([])
+        setSelectedCountries([])
+        setSelectedCities([])
+        setSelectedInstitutions([])
     }
 
     return (
-        <Center>
-            <ScrollView>
-                <SearchFormControl
-                    data={ inventories.map(inventory => {
-                        return {label: inventory.label, value: inventory.name, key: inventory.name}
-                    }) }
-                    label="Inventory"
-                    placeholder="Choose Inventory"
-                    selectedItems={ selectedInventories }
-                    onSelectedItemsChange={ setSelectedInventories }
-                />
-                <SearchFormControl
-                    data={ rooms.map(room => {
-                        return {label: room.label, value: room.id.toString(), key: room.id.toString()}
-                    }) }
-                    label="Rooms"
-                    placeholder="Room..."
-                    selectedItems={ selectedRooms }
-                    onSelectedItemsChange={ setSelectedRooms }
-                />
-                <SearchFormControl
-                    data={ artists.map(art => {
-                        return {label: art.display_name, value: art.display_name, key: art.display_name}
-                    }) }
-                    label="Artists/Copyists"
-                    placeholder="Artist/Copyist..."
-                    selectedItems={ selectedArtists }
-                    onSelectedItemsChange={ setSelectedArtists }
-                />
-                <SearchFormControl
-                    data={ nationalities.map(nat => {
-                        return {label: nat, value: nat, key: nat}
-                    }) }
-                    label="Artist`s Origin"
-                    placeholder="Nationality..."
-                    selectedItems={ selectedNationalities }
-                    onSelectedItemsChange={ setSelectedNationalities }
-                />
-                <FormControl key={ "lab" }>
-                    <FormControl.Label>label</FormControl.Label>
-                    <Select
-                        placeholder={ "Select" }
-                        minWidth="100"
-                        accessibilityLabel="Choose Service"
-                        _selectedItem={ {
-                            bg: "teal.600",
-                            endIcon: <CheckIcon size={ 5 }/>
-                        } }
-                        mt="1"
-                        key={ "props.label" }
-
+        <>
+            { props.isFilterOpen && (
+                <>
+                    <MultiSelect
+                        data={ inventories.map((inventory, index) => {
+                            return {label: inventory.label, value: inventory.name, index}
+                        }) }
+                        label="Inventory (OR)"
+                        selectedItems={ selectedInventories }
+                        onSelectedItemsChange={ setSelectedInventories }
+                    />
+                    <MultiSelect
+                        data={ rooms.map((room, index) => {
+                            return {label: `${ room.id } - ${ room.label }`, value: room.id.toString(), index}
+                        }) }
+                        label="Rooms (OR)"
+                        selectedItems={ selectedRooms }
+                        onSelectedItemsChange={ setSelectedRooms }
+                    />
+                    <MultiSelect
+                        data={ artists.map((art, index) => {
+                            return {label: art.display_name, value: art.getty_id, index}
+                        }) }
+                        label="Artists/Copyists (OR)"
+                        selectedItems={ selectedArtists }
+                        onSelectedItemsChange={ setSelectedArtists }
+                    />
+                    <MultiSelect
+                        data={ nationalities.map((nat, index) => {
+                            return {label: nat, value: nat, index}
+                        }) }
+                        label="Artist`s Origin (OR)"
+                        selectedItems={ selectedNationalities }
+                        onSelectedItemsChange={ setSelectedNationalities }
+                    />
+                    <MultiSelect
+                        data={ subjects.map((subj, index) => {
+                            return {label: subj, value: subj, index}
+                        }) }
+                        label="Subject (AND)"
+                        selectedItems={ selectedSubjects }
+                        onSelectedItemsChange={ setSelectedSubjects }
+                    />
+                    <MultiSelect
+                        data={ techniques.map((tech, index) => {
+                            return {label: tech, value: tech, index}
+                        }) }
+                        label="Technique (OR)"
+                        selectedItems={ selectedTechniques }
+                        onSelectedItemsChange={ setSelectedTechniques }
+                    />
+                    <MultiSelect
+                        data={ institutions.map((institution, index) => {
+                            return {label: institution, value: institution, index}
+                        }) }
+                        label="Institution (OR)"
+                        selectedItems={ selectedInstitutions }
+                        onSelectedItemsChange={ setSelectedInstitutions }
+                    />
+                    <MultiSelect
+                        data={ cities.map((city, index) => {
+                            return {label: city, value: city, index}
+                        }) }
+                        label="City (OR)"
+                        selectedItems={ selectedCities }
+                        onSelectedItemsChange={ setSelectedCities }
+                    />
+                    <MultiSelect
+                        data={ countries.map((country, index) => {
+                            return {label: country, value: country, index}
+                        }) }
+                        label="Country (OR)"
+                        selectedItems={ selectedCountries }
+                        onSelectedItemsChange={ setSelectedCountries }
+                    />
+                    <VStack space={ 2 } mt={ 1 }>
+                        <SwitchWithLabel label={ "School of Prague" } value={ isSchoolOfPrague }
+                                         onValueChange={ setIsSchoolOfPrague }/>
+                        <SwitchWithLabel label={ "Original" } value={ isOriginal } onValueChange={ setIsOriginal }/>
+                        <SwitchWithLabel label={ "Copy" } value={ isCopy } onValueChange={ setIsCopy }/>
+                        <SwitchWithLabel label={ "High Quality" } value={ isHighQuality }
+                                         onValueChange={ setIsHighQuality }/>
+                        <SwitchWithLabel label={ "Low Quality" } value={ isLowQuality }
+                                         onValueChange={ setIsLowQuality }/>
+                    </VStack>
+                    <Box
+                        flex={ 1 }
+                        flexDirection="row"
+                        justifyContent={ "flex-end" }
+                        pt={ 2 }
                     >
-                        { inventories.map((row) => (
-                            <Select.Item label={ row.label } value={ row.name } key={ row.name }/>
-                        )) }
-                    </Select>
-                </FormControl>
-                <Button
-                    onPress={ () => searchSubmit()}
-                    colorScheme="primary.100"
-                >
-                    Submit
-                </Button>
-            </ScrollView>
-
-        </Center>
+                        <Button
+                            borderRadius={ 10 }
+                            startIcon={
+                                <CloseIcon size="xs"/>
+                            }
+                            onPress={ clearForm }
+                            variant="outline"
+                            color="primary.500"
+                            borderColor="primary.500"
+                            mr={ 2 }
+                            size={ "sm" }
+                        >
+                            Reset
+                        </Button>
+                        <Button
+                            borderRadius={ 10 }
+                            onPress={ () => searchSubmit() }
+                            colorScheme="primary"
+                            background={ "primary.500" }
+                            variant="solid"
+                            size={ "sm" }
+                        >
+                            Search
+                        </Button>
+                    </Box>
+                </>
+            ) }
+        </>
     )
 }
 
diff --git a/src/components/search/SearchFormControl.tsx b/src/components/search/SearchFormControl.tsx
deleted file mode 100644
index 6d8bce3..0000000
--- a/src/components/search/SearchFormControl.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { CheckIcon, FormControl, Select, View } from "native-base"
-import MultiSelect from "react-native-multiple-select"
-
-export interface SearchFormProps {
-    data: { label: string, value: string, key: string }[],
-    label: string,
-    placeholder: string,
-    selectedItems: string[],
-    onSelectedItemsChange: (selectedItems: string[]) => void,
-}
-
-const SearchFormControl = (props: SearchFormProps) => {
-    return (
-        <View w={350}>
-            <MultiSelect
-                items={ props.data }
-                uniqueKey="key"
-                onSelectedItemsChange={ props.onSelectedItemsChange }
-                selectedItems={ props.selectedItems }
-                selectText={ props.label }
-                searchInputPlaceholderText={ props.placeholder }
-                displayKey="label"
-                submitButtonText={ "Submit" }
-                onChangeInput={ (text: string) => console.log(text) }
-                tagRemoveIconColor="#CCC"
-                tagBorderColor="#CCC"
-                tagTextColor="#CCC"
-                selectedItemTextColor="#CCC"
-                selectedItemIconColor="#CCC"
-                itemTextColor="#000"
-                searchInputStyle={ { color: "#CCC" } }
-                submitButtonColor="#CCC"
-
-            />
-        </View>
-    )
-}
-
-export default SearchFormControl
\ No newline at end of file
diff --git a/src/components/search/SwitchWithLabel.tsx b/src/components/search/SwitchWithLabel.tsx
new file mode 100644
index 0000000..b5a5234
--- /dev/null
+++ b/src/components/search/SwitchWithLabel.tsx
@@ -0,0 +1,23 @@
+import { Switch, View, Text } from "native-base"
+
+interface SwitchWithLabelProps {
+    label: string,
+    value: boolean,
+    onValueChange: (value: boolean) => void,
+}
+
+const SwitchWithLabel = (props: SwitchWithLabelProps) => {
+
+    return (
+        <View
+            flexDirection={ "row" }
+            alignItems={ "center" }
+            justifyContent={ "space-between" }
+        >
+            <Text>{ props.label }</Text>
+            <Switch value={ props.value } onValueChange={ props.onValueChange } size={"sm"} key={props.label}/>
+        </View>
+    )
+}
+
+export default SwitchWithLabel
\ No newline at end of file
diff --git a/src/logging/logger.ts b/src/logging/logger.ts
new file mode 100644
index 0000000..9e25134
--- /dev/null
+++ b/src/logging/logger.ts
@@ -0,0 +1,23 @@
+import { logger } from 'react-native-logs'
+
+const config = {
+    severity: 'debug',
+    transportOptions: {
+        colors: false,
+        printLevel: true,
+        printDate: true,
+        enabled: true,
+        tag: 'custom-tag',
+        format: (msg: string) => msg,
+        dateFormat: 'hh:mm:ss',
+    },
+    levels: {
+        debug: 0,
+        info: 1,
+        warn: 2,
+        error: 3,
+    },
+    async: false,
+}
+
+export const log = logger.createLogger(config)
\ No newline at end of file
diff --git a/src/pages/SearchPage.tsx b/src/pages/SearchPage.tsx
index 6dfb5c1..e02e7e2 100644
--- a/src/pages/SearchPage.tsx
+++ b/src/pages/SearchPage.tsx
@@ -1,24 +1,71 @@
-import { Center, KeyboardAvoidingView, ScrollView, Text, VStack } from "native-base"
+import {
+    Button,
+    Center,
+    ChevronDownIcon,
+    ChevronUpIcon, ScrollView,
+    VStack
+} from "native-base"
 import ListView from "../components/listView/ListView"
 import SearchForm from "../components/search/SearchForm"
-import { Platform } from "react-native"
+import { useEffect, useState } from "react"
+import {
+    fetchArtists, fetchCities, fetchCountries, fetchInstitutions,
+    fetchInventories,
+    fetchNationalities,
+    fetchPlans,
+    fetchSubjects, fetchTechniques
+} from "../stores/actions/searchFormThunks"
+import { useDispatch } from "react-redux"
+import { AppDispatch } from "../stores/store"
+import { log } from "../logging/logger"
 
 const SearchPage = () => {
+    const [isFilterOpen, setIsFilterOpen] = useState(true)
+
+    const dispatch = useDispatch<AppDispatch>()
+
+    useEffect(() => {
+        log.debug("SearchPage", "useEffect", "fetchEverything")
+
+        dispatch(fetchInventories())
+        dispatch(fetchNationalities())
+        dispatch(fetchArtists())
+        dispatch(fetchSubjects())
+        dispatch(fetchPlans())
+        dispatch(fetchTechniques())
+        dispatch(fetchCountries())
+        dispatch(fetchCities())
+        dispatch(fetchInstitutions())
+
+        log.debug("SearchPage", "useEffect", "fetchEverything", "done")
+    }, [dispatch])
 
     return (
-        <KeyboardAvoidingView
-            h={ {
-                lg: "auto"
-            } }
-            behavior={ Platform.OS === "ios" ? "padding" : "height" }
-        >
-            <ScrollView>
-                <VStack>
-                    <SearchForm/>
+        <Center m={ 2 } mr={ 4 } flex={1}>
+            <Button
+                alignSelf={ "start" }
+                onPress={ () => setIsFilterOpen(!isFilterOpen) }
+                variant="outline"
+                endIcon={
+                    <>
+                        { isFilterOpen ?
+                            (<ChevronUpIcon size={ 4 } color={ "primary.500" }/>)
+                            : (<ChevronDownIcon size={ 4 } color={ "primary.500" }/>) }
+                    </>
+                }
+                flexWrap={ "nowrap" }
+                borderColor={ "primary.500" }
+                mb={ 2 }
+            >
+                Filter
+            </Button>
+            <ScrollView flex={1} w={"100%"} >
+                <VStack space={ 1 }>
+                    <SearchForm isFilterOpen={ isFilterOpen }/>
                     <ListView/>
                 </VStack>
             </ScrollView>
-        </KeyboardAvoidingView>
+        </Center>
     )
 }
 
diff --git a/src/stores/reducers/listViewSlice.ts b/src/stores/reducers/listViewSlice.ts
index 15c2e5c..57af4ab 100644
--- a/src/stores/reducers/listViewSlice.ts
+++ b/src/stores/reducers/listViewSlice.ts
@@ -1,11 +1,11 @@
 import { createSlice } from "@reduxjs/toolkit"
 import { Inventory } from "../../types/searchFormTypes"
-import { ItemPreview } from "../../types/listViewTypes"
+import { ItemPreviewType } from "../../types/listViewTypes"
 import { search } from "../actions/listViewThunks"
 
 export interface ListViewState {
     inventories: Inventory[]
-    data: ItemPreview[]
+    data: ItemPreviewType[]
     loading: boolean
     lastError?: string
 }
diff --git a/src/theme/nativeBaseTheme.ts b/src/theme/nativeBaseTheme.ts
index 19edd59..3c92c8d 100644
--- a/src/theme/nativeBaseTheme.ts
+++ b/src/theme/nativeBaseTheme.ts
@@ -3,8 +3,16 @@ import { extendTheme } from "native-base"
 export const nativeBaseTheme = extendTheme({
     colors: {
         primary: {
-            50: "#4F4537",
-            100: "#E3A400",
+            50: '#FFF8E1',
+            100: '#FFE082',
+            200: '#FFD54F',
+            300: '#FFCA28',
+            400: '#FFC107',
+            500: '#E3A400',
+            600: '#C88700',
+            700: '#AD6F00',
+            800: '#8B5800',
+            900: '#5D3A00',
         },
 
     }
diff --git a/src/types/listViewTypes.ts b/src/types/listViewTypes.ts
index a5f0014..9cc2da8 100644
--- a/src/types/listViewTypes.ts
+++ b/src/types/listViewTypes.ts
@@ -3,7 +3,7 @@ import { Inventory } from "./searchFormTypes"
 
 export type SearchResponse = {
     pagination: Pagination
-    data: ItemPreview[]
+    data: ItemPreviewType[]
 }
 
 export type Pagination = {
@@ -13,7 +13,7 @@ export type Pagination = {
     inventories: Inventory[]
 }
 
-export type ItemPreview = {
+export type ItemPreviewType = {
     xml_id: string
     iconclass_external_id: string
     text: string
@@ -33,7 +33,11 @@ export type Item = [
         images?: ItemImage[]
         origDate?: string
     }
-]
+] | {
+    images?: ItemImage[]
+    origDate?: string
+}[]
+
 
 export type PersonName = {
     value?: string
