diff --git a/assets/search/materials.svg b/assets/search/materials.svg new file mode 100644 index 00000000..d6771cf4 --- /dev/null +++ b/assets/search/materials.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/search/news.svg b/assets/search/news.svg new file mode 100644 index 00000000..5bf27248 --- /dev/null +++ b/assets/search/news.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/search/notifications.svg b/assets/search/notifications.svg new file mode 100644 index 00000000..556aae6a --- /dev/null +++ b/assets/search/notifications.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/search/sections.svg b/assets/search/sections.svg new file mode 100644 index 00000000..f4b42e33 --- /dev/null +++ b/assets/search/sections.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/GlobalSearch/SearchTagFilter.tsx b/src/components/GlobalSearch/SearchTagFilter.tsx new file mode 100644 index 00000000..01d6c42a --- /dev/null +++ b/src/components/GlobalSearch/SearchTagFilter.tsx @@ -0,0 +1,59 @@ +import { Pressable } from "react-native" +import { SearchTag, getSearchTagIcon } from "utils/search" + +import { BodyText } from "components/Text" +import { Icon } from "components/Icon" +import { usePalette } from "utils/colors" + +interface SearchTagFilterProps { + tag: SearchTag + title: string + onClick: () => void + isSelected: boolean +} + +export const SearchTagFilter = ({ + tag, + title, + onClick, + isSelected, +}: SearchTagFilterProps) => { + const { isLight, buttonFill } = usePalette() + const icon = getSearchTagIcon(tag) + + return ( + + + + {title} + + + ) +} diff --git a/src/components/GlobalSearch/SearchTile.tsx b/src/components/GlobalSearch/SearchTile.tsx new file mode 100644 index 00000000..807645b8 --- /dev/null +++ b/src/components/GlobalSearch/SearchTile.tsx @@ -0,0 +1,81 @@ +import { Pressable, View } from "react-native" +import { SearchTag, getSearchTagIcon } from "utils/search" + +import { BodyText } from "components/Text" +import { Icon } from "components/Icon" +import { usePalette } from "utils/colors" +import { Divider } from "components/Divider" + +interface SearchTileProps { + tag: SearchTag + title: string + subtitle?: string + onClick?: () => void +} + +export const SearchTile = ({ + tag, + title, + subtitle, + onClick, +}: SearchTileProps) => { + const { isLight, buttonFill } = usePalette() + const icon = getSearchTagIcon(tag) + + return ( + + + + + + + + + {title} + + + {subtitle && ( + + {subtitle} + + )} + + + + + + ) +} diff --git a/src/components/Home/MainMenu.tsx b/src/components/Home/MainMenu.tsx index 8a35c008..82d6ba96 100644 --- a/src/components/Home/MainMenu.tsx +++ b/src/components/Home/MainMenu.tsx @@ -1,4 +1,4 @@ -import { FC, useEffect, useState } from "react" +import { useEffect, useState } from "react" import { ScrollView, View } from "react-native" import { useNavigation } from "navigation/NavigationTypes" @@ -25,7 +25,7 @@ type ButtonState = ButtonInterface & { shown: boolean } /** * the main menu of the app, an horizontal scroll view with the buttons to navigate to the different pages */ -export const MainMenu: FC<{ filter?: string }> = ({ filter }) => { +export const MainMenu = () => { const { navigate } = useNavigation() const defaultIcons: ButtonInterface[] = [ @@ -110,7 +110,7 @@ export const MainMenu: FC<{ filter?: string }> = ({ filter }) => { useEffect(() => { scrollView.current?.scrollTo({ x: 0, y: 0, animated: true }) - }, [filter, scrollView]) + }, [scrollView]) useEffect(() => { AsyncStorage.getItem("menu:icons") @@ -206,13 +206,6 @@ export const MainMenu: FC<{ filter?: string }> = ({ filter }) => { {icons .filter(i => i.shown) - .filter( - i => - i.type === ButtonType.ADD || - (filter - ? i.title.toLowerCase().includes(filter.toLowerCase()) - : true) - ) .map(buttonIcon => ( { diff --git a/src/components/Home/SearchButton.tsx b/src/components/Home/SearchButton.tsx new file mode 100644 index 00000000..9dc68645 --- /dev/null +++ b/src/components/Home/SearchButton.tsx @@ -0,0 +1,39 @@ +import { Pressable } from "react-native" +import { useTranslation } from "react-i18next" +import { useNavigation } from "navigation/NavigationTypes" + +import searchDark from "assets/menu/searchDark.svg" +import { Icon } from "components/Icon" +import { BodyText } from "components/Text" +import { usePalette } from "utils/colors" + +export const SearchButton = () => { + const navigation = useNavigation() + const { fieldBackground, buttonFill } = usePalette() + + const { t } = useTranslation() //i18n hook + + return ( + navigation.navigate("GlobalSearch")} + > + + + {"" + t("search")} + + + ) +} diff --git a/src/components/Home/index.tsx b/src/components/Home/index.tsx index d8f369f8..64fc4c4d 100644 --- a/src/components/Home/index.tsx +++ b/src/components/Home/index.tsx @@ -2,4 +2,4 @@ export * from "./MainMenu" export * from "./MainTitle" export * from "./MenuButton" export * from "./StickyHeader" -export * from "./PoliSearchBar" +export * from "./SearchButton" diff --git a/src/components/Home/PoliSearchBar.tsx b/src/components/PoliSearchBar.tsx similarity index 89% rename from src/components/Home/PoliSearchBar.tsx rename to src/components/PoliSearchBar.tsx index 4372586e..86759c6e 100644 --- a/src/components/Home/PoliSearchBar.tsx +++ b/src/components/PoliSearchBar.tsx @@ -1,6 +1,7 @@ -import { FC, useEffect, useState, useRef } from "react" +import { useEffect, useState, useRef } from "react" import { TextInput, + TextInputProps, Animated, Pressable, StyleProp, @@ -12,17 +13,23 @@ import searchDark from "assets/menu/searchDark.svg" import { Icon } from "components/Icon" import { useTranslation } from "react-i18next" +interface PoliSearchBarProps extends Pick { + onChange: (searchKey: string) => void + style?: StyleProp +} + /** * the search bar, which requests a search everytime the input text changes */ -export const PoliSearchBar: FC<{ - onChange: (searchKey: string) => void - style?: StyleProp -}> = ({ onChange, style }) => { +export const PoliSearchBar = ({ + autoFocus = false, + onChange, + style, +}: PoliSearchBarProps) => { const { fieldBackground, fieldText, bodyText, isLight, palette } = usePalette() - const [isFocused, setIsFocused] = useState(false) + const [isFocused, setIsFocused] = useState(autoFocus) const shadowAnim = useRef(new Animated.Value(0)).current const inputText = useRef(null) @@ -98,6 +105,7 @@ export const PoliSearchBar: FC<{ onChangeText={onChange} onFocus={() => setIsFocused(true)} onBlur={() => setIsFocused(false)} + autoFocus={autoFocus} /> { initialRouteName="Home" > + = () => { + const [selectedTag, setSelectedTag] = React.useState(null) + const [input, setInput] = React.useState("") + + // temporary result + const resultData = [ + { + tag: "news" as const, + title: "Titolo News", + subtitle: "Questo e un risultato di ricerca", + key: 0, + }, + { + tag: "sections" as const, + title: "Titolo sezione", + subtitle: "Questo e un risultato di ricerca", + key: 1, + }, + { + tag: "notifications" as const, + title: "Titolo notifica", + subtitle: "Questo e un risultato di ricerca", + key: 2, + }, + { + tag: "materials" as const, + title: "Titolo materiali", + subtitle: "Questo e un risultato di ricerca", + key: 3, + }, + { + tag: "news" as const, + title: "Titolo News", + subtitle: "Questo e un risultato di ricerca", + key: 4, + }, + { + tag: "sections" as const, + title: "Titolo sezione", + subtitle: "Questo e un risultato di ricerca", + key: 5, + }, + { + tag: "notifications" as const, + title: "Titolo notifica", + subtitle: "Questo e un risultato di ricerca", + key: 6, + }, + { + tag: "materials" as const, + title: "Titolo materiali", + subtitle: "Questo e un risultato di ricerca", + key: 7, + }, + { + tag: "news" as const, + title: "Titolo News", + subtitle: "Questo e un risultato di ricerca", + key: 8, + }, + { + tag: "sections" as const, + title: "Titolo sezione", + subtitle: "Questo e un risultato di ricerca", + key: 9, + }, + { + tag: "notifications" as const, + title: "Titolo notifica", + subtitle: "Questo e un risultato di ricerca", + key: 10, + }, + { + tag: "materials" as const, + title: "Titolo materiali", + subtitle: "Questo e un risultato di ricerca", + key: 11, + }, + ] + + return ( + + setInput(input)} + autoFocus + /> + + {SEARCH_TAGS.map(tag => ( + + + tag === selectedTag + ? setSelectedTag(null) + : setSelectedTag(tag) + } + isSelected={tag === selectedTag} + /> + + ))} + + + } + data={ + input + ? resultData.filter( + result => !selectedTag || result.tag === selectedTag + ) + : [] + } + renderItem={({ item }) => ( + + )} + /> + ) +} + +const styles = StyleSheet.create({ + searchBar: { + marginBottom: 0, + }, + tagsContainer: { + flexDirection: "row", + flexWrap: "wrap", + marginTop: 16, + marginBottom: 10, + alignSelf: "center", + justifyContent: "center", + }, + tag: { + width: "50%", + minWidth: 130, + paddingHorizontal: 4, + paddingVertical: 6, + }, +}) diff --git a/src/pages/Groups.tsx b/src/pages/Groups.tsx index 22eddb40..2748d023 100644 --- a/src/pages/Groups.tsx +++ b/src/pages/Groups.tsx @@ -15,7 +15,7 @@ import { import { GroupTile } from "components/Groups/GroupTile" import { ModalGroup } from "components/Groups/ModalGroup" -import { PoliSearchBar } from "components/Home/PoliSearchBar" +import { PoliSearchBar } from "components/PoliSearchBar" import { useTranslation } from "react-i18next" import { useApiCall } from "api/useApiCall" import { ListPage } from "components/PageLayout" diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 0e75be55..f8cdaa81 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,9 +1,8 @@ -import { useState } from "react" import { View } from "react-native" import { NewsManager } from "components/Home/News" import { MainStackScreen } from "navigation/NavigationTypes" -import { MainMenu, MainTitle, PoliSearchBar } from "components/Home" +import { MainMenu, MainTitle, SearchButton } from "components/Home" import { HighlightsManager } from "components/Home/Highlights/HighlightsManager" import { usePalette } from "utils/colors" import { BoxShadowView } from "components/BoxShadow" @@ -15,8 +14,6 @@ import { BoxShadowView } from "components/BoxShadow" export const Home: MainStackScreen<"Home"> = () => { const { homeBackground, background } = usePalette() - const [search, setSearch] = useState("") - return ( = () => { borderTopRightRadius: 30, }} > - setSearch(searchKey)} /> - + + diff --git a/src/utils/search.ts b/src/utils/search.ts new file mode 100644 index 00000000..c1eb7da5 --- /dev/null +++ b/src/utils/search.ts @@ -0,0 +1,33 @@ +import news from "assets/search/news.svg" +import notifications from "assets/search/notifications.svg" +import sections from "assets/search/sections.svg" +import materials from "assets/search/materials.svg" + +export const SEARCH_TAGS = [ + "sections", + "news", + "notifications", + "materials", +] as const + +export type SearchTag = (typeof SEARCH_TAGS)[number] + +export const SEARCH_TAG_TO_LABEL: Record = { + sections: "Sezioni dell'app", + news: "News & Avvisi", + notifications: "Notifiche", + materials: "Materiali", +} + +export const getSearchTagIcon = (type: SearchTag) => { + switch (type) { + case "news": + return news + case "notifications": + return notifications + case "sections": + return sections + case "materials": + return materials + } +}