diff --git a/.gitignore b/.gitignore index 8335cec..76e620e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ prisma/migrations/* output.xml report.html log.html -.expo \ No newline at end of file +.expo +node_modules/ \ No newline at end of file diff --git a/front/Navigation.tsx b/front/Navigation.tsx index 276cb43..3292f76 100644 --- a/front/Navigation.tsx +++ b/front/Navigation.tsx @@ -2,6 +2,7 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack'; import React from 'react'; import AuthenticationView from './views/AuthenticationView'; import HomeView from './views/HomeView'; +import SearchView from './views/SearchView'; import SetttingsNavigator from './views/SettingsView'; import { NavigationContainer } from '@react-navigation/native'; import { useSelector } from './state/Store'; @@ -14,6 +15,7 @@ export const protectedRoutes = <> + ; export const publicRoutes = diff --git a/front/components/SearchBar.tsx b/front/components/SearchBar.tsx new file mode 100644 index 0000000..2429814 --- /dev/null +++ b/front/components/SearchBar.tsx @@ -0,0 +1,150 @@ +import { + Input, + Column, + Row, + Text, + Pressable, + HStack, + VStack, + Image, + Icon, + Square, +} from "native-base"; +import React from "react"; +import { Ionicons, FontAwesome } from "@expo/vector-icons"; + +export enum SuggestionType { + TEXT, + ILLUSTRATED, +} + +export type SuggestionList = { + type: SuggestionType; + data: SuggestionProps | IllustratedSuggestionProps; +}[]; + +export interface SearchBarProps { + onTextChange: (text: string) => void; + onTextSubmit: (text: string) => void; + suggestions: SuggestionList; +} +export interface IllustratedSuggestionProps { + text: string; + subtext: string; + imageSrc: string; + onPress: () => void; +} + +export interface SuggestionProps { + text: string; + onPress: () => void; +} + +// debounce function +const debounce = (func: any, delay: number) => { + let inDebounce: any; + return function (this: any) { + const context = this; + const args = arguments; + clearTimeout(inDebounce); + inDebounce = setTimeout(() => func.apply(context, args), delay); + }; +}; + +const IllustratedSuggestion = ({ + text, + subtext, + imageSrc, + onPress, +}: IllustratedSuggestionProps) => { + return ( + + + + Alternate Text + + + {text} + + {subtext} + + + + + ); +}; + +const TextSuggestion = ({ text, onPress }: SuggestionProps) => { + return ( + + + + + + {text} + + + ); +}; + +// render the suggestions based on the type +const SuggestionRenderer = (suggestions: SuggestionList) => { + const suggestionRenderers = { + [SuggestionType.TEXT]: TextSuggestion, + [SuggestionType.ILLUSTRATED]: IllustratedSuggestion, + }; + return suggestions.map((suggestion, index) => { + const SuggestionComponent = suggestionRenderers[suggestion.type]; + return ; + }); +}; + +const SearchBar = ({ + onTextChange, + onTextSubmit, + suggestions, +}: SearchBarProps) => { + const debouncedOnTextChange = React.useRef( + debounce((t: string) => onTextChange(t), 70) + ).current; + return ( + <> + onTextSubmit(event.nativeEvent.text)} + /> + {SuggestionRenderer(suggestions)} + + ); +}; + +export default SearchBar; \ No newline at end of file diff --git a/front/components/SearchBarSuggestions.tsx b/front/components/SearchBarSuggestions.tsx new file mode 100644 index 0000000..3772a95 --- /dev/null +++ b/front/components/SearchBarSuggestions.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import SearchBar from "../components/SearchBar"; +import { SuggestionList, SuggestionType } from "../components/SearchBar"; +interface SearchBarSuggestionsProps { + onTextSubmit: (text: string) => void; + suggestions: SuggestionList; +} + +// do a function that takes in a string and returns a list of filtered suggestions +const filterSuggestions = (text: string, suggestions: SuggestionList) => { + return suggestions.filter((suggestion) => { + switch (suggestion.type) { + case SuggestionType.TEXT: + return suggestion.data.text.toLowerCase().includes(text.toLowerCase()); + case SuggestionType.ILLUSTRATED: + return ( + suggestion.data.text.toLowerCase().includes(text.toLowerCase()) || + suggestion.data.subtext.toLowerCase().includes(text.toLowerCase()) + ); + } + }); +}; + +const SearchBarSuggestions = ({ + onTextSubmit, + suggestions, +}: SearchBarSuggestionsProps) => { + const [searchText, setSearchText] = React.useState(""); + + return ( + setSearchText(t)} + onTextSubmit={onTextSubmit} + suggestions={ + searchText === "" ? [] : filterSuggestions(searchText, suggestions) + } + /> + ); +}; + +export default SearchBarSuggestions; diff --git a/front/components/SongCard.tsx b/front/components/SongCard.tsx index 98bc10a..3216fa0 100644 --- a/front/components/SongCard.tsx +++ b/front/components/SongCard.tsx @@ -18,7 +18,7 @@ const SongCard = (props: SongCardProps) => { shadow={3} flexDirection='column' alignContent='space-around' - bg={(isHovered || isFocused) ? 'coolGray.200' : undefined } + bg={(isHovered || isFocused) ? 'coolGray.200' : 'background.50' } > { + console.log(text); +}; + +const SearchView = () => { + const navigation = useNavigation(); + + const IllustratedSuggestion: IllustratedSuggestionProps = { + text: "Love Story", + subtext: "Taylor Swift", + imageSrc: + "https://i.discogs.com/yHqu3pnLgJq-cVpYNVYu6mE-fbzIrmIRxc6vES5Oi48/rs:fit/g:sm/q:90/h:556/w:600/czM6Ly9kaXNjb2dz/LWRhdGFiYXNlLWlt/YWdlcy9SLTE2NjQ2/ODUwLTE2MDkwNDU5/NzQtNTkxOS5qcGVn.jpeg", + onPress: () => navigation.navigate("Song", { songId: 1 }), + }; + // fill the suggestions with the data from the backend + const suggestions: SuggestionList = [ + { + type: SuggestionType.ILLUSTRATED, + data: IllustratedSuggestion, + }, + { + type: SuggestionType.ILLUSTRATED, + data: IllustratedSuggestion, + }, + { + type: SuggestionType.ILLUSTRATED, + data: { + text: "Shed a Light", + subtext: "Robin Schulz & David Guetta", + imageSrc: + "https://imgs.search.brave.com/O9j2Z-oWiniq3lj7d-dAOgXLWCIqnHaFegmaSeIkWOY/rs:fit:560:320:1/g:ce/aHR0cHM6Ly91cGxv/YWQud2lraW1lZGlh/Lm9yZy93aWtpcGVk/aWEvZW4vdGh1bWIv/OC84ZS9TaGVkX2Ff/TGlnaHRfUm9iaW5f/U2NodWx6LmpwZy81/MTJweC1TaGVkX2Ff/TGlnaHRfUm9iaW5f/U2NodWx6LmpwZw", + onPress: () => navigation.navigate("Song", { songId: 1 }), + }, + }, + { + type: SuggestionType.TEXT, + data: { + text: "Lady Gaga", + onPress: () => navigation.navigate("Song", { songId: 1 }), + }, + }, + ]; + + return ( + + + + ); +}; + +export default SearchView; diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 64e05ed..0000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Chromacase", - "lockfileVersion": 2, - "requires": true, - "packages": {} -} diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index fb57ccd..0000000 --- a/yarn.lock +++ /dev/null @@ -1,4 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - -