From 611dac558d37ce8153dfbef00964833fd976cc31 Mon Sep 17 00:00:00 2001 From: Leon Jiang <35908040+leonyjiang@users.noreply.github.com> Date: Mon, 17 Aug 2020 15:23:39 -0700 Subject: [TMA-25] Search Functionality (#33) * Create tabs gradient component * Add endpoint constant and types for search * Create search functionality * [TMA-19*] Abstracted out Social Icon logic (#32) * Basic mostly functional implementation Need to figure out why API is being called so much * Hey it works now! Without a million API calls! * Fixed bug where app would crash upon login Also updated property names to be more appropriate * Added post datetime and social icon * Updated error message * Fixed typecheck errors I don't know that these fixes are the best since I don't think they're generalizable * Formatted datetime in PostHeader * Abstracted out social icon switching logic * Basic mostly functional implementation Need to figure out why API is being called so much * Hey it works now! Without a million API calls! * Fixed bug where app would crash upon login Also updated property names to be more appropriate * Added post datetime and social icon * Updated error message * Fixed typecheck errors I don't know that these fixes are the best since I don't think they're generalizable * Abstracted out social icon switching logic * Change View to TouchableOpacity * Create tabs gradient component * Add endpoint constant and types for search * Create search functionality * Change View to TouchableOpacity Co-authored-by: Justin Shillingford --- src/components/common/TabsGradient.tsx | 23 ++++ src/components/common/index.ts | 1 + src/components/profile/Content.tsx | 17 +-- src/components/search/Explore.tsx | 35 ++++++ src/components/search/ExploreSection.tsx | 42 +++++++ src/components/search/ExploreSectionUser.tsx | 70 +++++++++++ src/components/search/SearchBar.tsx | 105 ++++++++++------ src/components/search/SearchHeader.tsx | 60 +++++++++ src/components/search/SearchResult.tsx | 94 ++++++++++++++ src/components/search/SearchResults.tsx | 28 +++++ src/components/search/SearchResultsBackground.tsx | 48 ++++++++ src/components/search/SuggestedSection.tsx | 42 ------- src/components/search/SuggestedUser.tsx | 61 --------- src/components/search/index.ts | 7 +- src/constants/api.ts | 1 + src/screens/profile/ProfileScreen.tsx | 3 +- src/screens/search/SearchScreen.tsx | 143 +++++++++++++--------- src/types/types.ts | 10 ++ 18 files changed, 574 insertions(+), 216 deletions(-) create mode 100644 src/components/common/TabsGradient.tsx create mode 100644 src/components/search/Explore.tsx create mode 100644 src/components/search/ExploreSection.tsx create mode 100644 src/components/search/ExploreSectionUser.tsx create mode 100644 src/components/search/SearchHeader.tsx create mode 100644 src/components/search/SearchResult.tsx create mode 100644 src/components/search/SearchResults.tsx create mode 100644 src/components/search/SearchResultsBackground.tsx delete mode 100644 src/components/search/SuggestedSection.tsx delete mode 100644 src/components/search/SuggestedUser.tsx (limited to 'src') diff --git a/src/components/common/TabsGradient.tsx b/src/components/common/TabsGradient.tsx new file mode 100644 index 00000000..a95e8bc3 --- /dev/null +++ b/src/components/common/TabsGradient.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import LinearGradient from 'react-native-linear-gradient'; +import {StyleSheet} from 'react-native'; +import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; + +const TabsGradient: React.FC = () => { + return ( + + ); +}; +const styles = StyleSheet.create({ + gradient: { + position: 'absolute', + top: (SCREEN_HEIGHT / 10) * 9, + height: SCREEN_HEIGHT / 10, + width: SCREEN_WIDTH, + }, +}); +export default TabsGradient; diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 8d0ef778..63a7b9c2 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -5,3 +5,4 @@ export {default as NavigationIcon} from './NavigationIcon'; export {default as GradientBackground} from './GradientBackground'; export {default as Post} from './post'; export {default as SocialIcon} from './SocialIcon'; +export {default as TabsGradient} from './TabsGradient'; diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx index 82b5fdc0..49cc2c35 100644 --- a/src/components/profile/Content.tsx +++ b/src/components/profile/Content.tsx @@ -1,7 +1,6 @@ import React, {useState} from 'react'; import {StyleSheet, LayoutChangeEvent} from 'react-native'; import Animated from 'react-native-reanimated'; -const {ScrollView} = Animated; import {UserType} from '../../types'; import ProfileCutout from './ProfileCutout'; @@ -9,8 +8,6 @@ import ProfileHeader from './ProfileHeader'; import ProfileBody from './ProfileBody'; import MomentsBar from './MomentsBar'; import Feed from './Feed'; -import LinearGradient from 'react-native-linear-gradient'; -import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; interface ContentProps { y: Animated.Value; @@ -23,7 +20,7 @@ const Content: React.FC = ({y, user}) => { setProfileBodyHeight(height); }; return ( - y.setValue(e.nativeEvent.contentOffset.y)} showsVerticalScrollIndicator={false} @@ -35,12 +32,7 @@ const Content: React.FC = ({y, user}) => { - - + ); }; @@ -48,11 +40,6 @@ const styles = StyleSheet.create({ container: { flex: 1, }, - gradient: { - height: SCREEN_HEIGHT, - width: SCREEN_WIDTH, - position: 'absolute', - }, }); export default Content; diff --git a/src/components/search/Explore.tsx b/src/components/search/Explore.tsx new file mode 100644 index 00000000..a02205a4 --- /dev/null +++ b/src/components/search/Explore.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import {View, StyleSheet} from 'react-native'; +import ExploreSection from './ExploreSection'; + +const Explore: React.FC = () => { + const sections: Array = [ + 'People you follow', + 'People you may know', + 'Trending in sports', + 'Trending on Tagg', + 'Trending in music', + ]; + const users: Array = [ + 'Sam Davis', + 'Becca Smith', + 'Ann Taylor', + 'Clara Johnson', + 'Sarah Jung', + 'Lila Hernandez', + ]; + return ( + + {sections.map((title) => ( + + ))} + + ); +}; + +const styles = StyleSheet.create({ + container: { + zIndex: 0, + }, +}); +export default Explore; diff --git a/src/components/search/ExploreSection.tsx b/src/components/search/ExploreSection.tsx new file mode 100644 index 00000000..8e826bd9 --- /dev/null +++ b/src/components/search/ExploreSection.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import {View, Text, ScrollView, StyleSheet} from 'react-native'; +import ExploreSectionUser from './ExploreSectionUser'; + +/** + * Search Screen for user recommendations and a search + * tool to allow user to find other users + */ + +interface ExploreSectionProps { + title: string; + users: Array; +} +const ExploreSection: React.FC = ({title, users}) => { + return ( + + {title} + + {users.map((name, key) => ( + + ))} + + + ); +}; + +const styles = StyleSheet.create({ + container: { + marginBottom: 30, + }, + header: { + fontWeight: '600', + fontSize: 20, + color: '#fff', + marginBottom: 20, + }, + user: { + marginHorizontal: 15, + }, +}); + +export default ExploreSection; diff --git a/src/components/search/ExploreSectionUser.tsx b/src/components/search/ExploreSectionUser.tsx new file mode 100644 index 00000000..a9fce063 --- /dev/null +++ b/src/components/search/ExploreSectionUser.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { + StyleSheet, + Text, + ViewProps, + Image, + TouchableOpacity, +} from 'react-native'; +import LinearGradient from 'react-native-linear-gradient'; + +/** + * Search Screen for user recommendations and a search + * tool to allow user to find other users + */ + +interface ExploreSectionUserProps extends ViewProps { + name: string; +} +const ExploreSectionUser: React.FC = ({ + name, + style, +}) => { + return ( + + + + + {name} + {`@${name.split(' ').join('')}`} + + ); +}; + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + }, + gradient: { + height: 80, + width: 80, + borderRadius: 40, + justifyContent: 'center', + alignItems: 'center', + marginBottom: 10, + }, + profile: { + height: 76, + width: 76, + borderRadius: 38, + }, + name: { + fontWeight: '600', + fontSize: 16, + color: '#fff', + }, + username: { + fontWeight: '600', + fontSize: 14, + color: '#fff', + }, +}); +export default ExploreSectionUser; diff --git a/src/components/search/SearchBar.tsx b/src/components/search/SearchBar.tsx index 283b6d59..8bb93d54 100644 --- a/src/components/search/SearchBar.tsx +++ b/src/components/search/SearchBar.tsx @@ -2,71 +2,97 @@ import React from 'react'; import { StyleSheet, TextInput, - TextInputProps, - NativeSyntheticEvent, - TextInputFocusEventData, TouchableOpacity, Text, View, + TextInputProps, + Keyboard, + NativeSyntheticEvent, + TextInputSubmitEditingEventData, } from 'react-native'; +import Animated, { + interpolate, + interpolateColors, +} from 'react-native-reanimated'; +import {SCREEN_HEIGHT} from '../../utils'; import Icon from 'react-native-vector-icons/Feather'; -import Animated from 'react-native-reanimated'; interface SearchBarProps extends TextInputProps { - active: boolean; + onCancel: () => void; + top: Animated.Value; } -const SearchBar: React.FC = ({onFocus, onBlur, active}) => { - const handleFocus = (e: NativeSyntheticEvent) => { - // TODO: animate Icon & View.inputContainer.borderColor color to '#000' - // TODO: animate background color (& page color in results ScrollView) to '#ffff' (last f for opacity) - // TODO: animate TextInput width and mount "Cancel" button (& animate opacity) - // OR - // TODO: just animate "Cancel" button width and opacity (this might be easier) - onFocus && onFocus(e); - }; - const handleBlur = (e: NativeSyntheticEvent) => { - // TODO: animate Icon color & View.inputContainer borderColor back - // TODO: animate background color (and page color in ScrollView) back to '#fff3' - // TODO: unmount Cancel button (and animate width change) - onBlur && onBlur(e); +const SearchBar: React.FC = ({ + onFocus, + onBlur, + onChangeText, + value, + onCancel, + top, + style, +}) => { + const opacity: Animated.Node = interpolate(top, { + inputRange: [-SCREEN_HEIGHT, 0], + outputRange: [0, 1], + }); + const marginRight: Animated.Node = interpolate(top, { + inputRange: [-SCREEN_HEIGHT, 0], + outputRange: [0, 57], + }); + const color: Animated.Node = interpolateColors(top, { + inputRange: [-SCREEN_HEIGHT, 0], + outputColorRange: ['#fff', '#000'], + }); + const handleSubmit = ( + e: NativeSyntheticEvent, + ) => { + e.preventDefault(); + Keyboard.dismiss(); }; + const AnimatedTextInput = Animated.createAnimatedComponent(TextInput); + const AnimatedIcon = Animated.createAnimatedComponent(Icon); return ( - - - - + + + - {active && ( - - Cancel + + + Cancel - )} + ); }; const styles = StyleSheet.create({ container: { - flexDirection: 'row', - alignItems: 'center', height: 40, + flexDirection: 'row', + alignItems: 'stretch', + zIndex: 2, }, inputContainer: { + flexGrow: 1, flexDirection: 'row', alignItems: 'center', - flex: 1, - height: '100%', paddingHorizontal: 8, - backgroundColor: '#fff3', - borderColor: '#fff', borderWidth: 1.5, borderRadius: 20, + backgroundColor: '#fff3', }, searchIcon: { marginRight: 8, @@ -76,9 +102,12 @@ const styles = StyleSheet.create({ fontSize: 16, }, cancelButton: { - marginHorizontal: 5, + position: 'absolute', + height: '100%', + justifyContent: 'center', + paddingHorizontal: 5, }, - cancel: { + cancelText: { color: '#818181', fontWeight: '600', }, diff --git a/src/components/search/SearchHeader.tsx b/src/components/search/SearchHeader.tsx new file mode 100644 index 00000000..2a022f50 --- /dev/null +++ b/src/components/search/SearchHeader.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import {SCREEN_HEIGHT} from '../../utils'; +import {View, StyleSheet, ViewProps} from 'react-native'; +import Animated, { + Value, + interpolateColors, + interpolate, +} from 'react-native-reanimated'; + +interface SearchHeaderProps extends ViewProps { + top: Value; +} +const SearchHeader: React.FC = ({top, style}) => { + const color: Animated.Node = interpolateColors(top, { + inputRange: [-SCREEN_HEIGHT, 0], + outputColorRange: ['#fff', '#000'], + }); + const searchOpacity: Animated.Node = interpolate(top, { + inputRange: [-SCREEN_HEIGHT, 0], + outputRange: [0, 1], + }); + const exploreOpacity: Animated.Node = interpolate(top, { + inputRange: [-SCREEN_HEIGHT, 0], + outputRange: [1, 0], + }); + return ( + + + + Explore + + + + + Search + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + justifyContent: 'center', + height: 30, + }, + headerContainer: { + position: 'absolute', + left: '50%', + }, + header: { + position: 'relative', + right: '50%%', + fontSize: 24, + fontWeight: 'bold', + }, +}); +export default SearchHeader; diff --git a/src/components/search/SearchResult.tsx b/src/components/search/SearchResult.tsx new file mode 100644 index 00000000..60c22d41 --- /dev/null +++ b/src/components/search/SearchResult.tsx @@ -0,0 +1,94 @@ +import React, {useEffect, useState} from 'react'; +import {ProfilePreviewType} from '../../types'; +import { + View, + Text, + Image, + StyleSheet, + ViewProps, + TouchableOpacity, +} from 'react-native'; +import RNFetchBlob from 'rn-fetch-blob'; +import {AVATAR_PHOTO_ENDPOINT} from '../../constants'; + +interface SearchResultProps extends ViewProps { + profilePreview: ProfilePreviewType; +} +const SearchResult: React.FC = ({ + profilePreview: {username, first_name, last_name, id}, + style, +}) => { + const [avatarURI, setAvatarURI] = useState(null); + + useEffect(() => { + let mounted = true; + const loadAvatar = async () => { + try { + const response = await RNFetchBlob.config({ + fileCache: true, + appendExt: 'jpg', + }).fetch('GET', AVATAR_PHOTO_ENDPOINT + `${id}`); + const status = response.info().status; + if (status === 200) { + if (mounted) { + setAvatarURI(response.path()); + } + return; + } + if (mounted) { + setAvatarURI(''); + } + } catch (error) { + console.log(error); + } + }; + loadAvatar(); + return () => { + mounted = false; + }; + }, [id]); + + return ( + + + + @{username} + {first_name.concat(' ', last_name)} + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + alignItems: 'center', + }, + avatar: { + height: 60, + width: 60, + borderRadius: 30, + marginRight: 15, + }, + nameContainer: { + justifyContent: 'space-evenly', + alignSelf: 'stretch', + }, + username: { + fontSize: 18, + fontWeight: '500', + }, + name: { + fontSize: 16, + color: '#333', + }, +}); + +export default SearchResult; diff --git a/src/components/search/SearchResults.tsx b/src/components/search/SearchResults.tsx new file mode 100644 index 00000000..16bff818 --- /dev/null +++ b/src/components/search/SearchResults.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import {ProfilePreviewType} from '../../types'; +import SearchResult from './SearchResult'; +import {StyleSheet, View} from 'react-native'; +interface SearchResultsProps { + results: Array; +} +const SearchResults: React.FC = ({results}) => { + return ( + + {results.map((profilePreview) => ( + + ))} + + ); +}; + +const styles = StyleSheet.create({ + result: { + marginVertical: 10, + }, +}); + +export default SearchResults; diff --git a/src/components/search/SearchResultsBackground.tsx b/src/components/search/SearchResultsBackground.tsx new file mode 100644 index 00000000..3e1e4fdc --- /dev/null +++ b/src/components/search/SearchResultsBackground.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import Animated, {interpolate} from 'react-native-reanimated'; +import {StyleSheet} from 'react-native'; +import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; + +interface SearchResultsBackgroundProps { + top: Animated.Value; +} +const SearchResultsBackground: React.FC = ({ + top, + children, +}) => { + const opacityBackground: Animated.Node = interpolate(top, { + inputRange: [-SCREEN_HEIGHT, 0], + outputRange: [0, 1], + }); + const opacityContent: Animated.Node = interpolate(top, { + inputRange: [-SCREEN_HEIGHT / 40, 0], + outputRange: [0, 1], + }); + return ( + + + {children} + + + ); +}; +const styles = StyleSheet.create({ + container: { + height: SCREEN_HEIGHT, + width: SCREEN_WIDTH, + padding: 20, + position: 'absolute', + backgroundColor: '#fff', + zIndex: 0, + }, + contentContainer: { + flex: 1, + }, + results: { + marginTop: StatusBarHeight + 110, + }, +}); +export default SearchResultsBackground; diff --git a/src/components/search/SuggestedSection.tsx b/src/components/search/SuggestedSection.tsx deleted file mode 100644 index af0323a5..00000000 --- a/src/components/search/SuggestedSection.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import {View, Text, ScrollView, StyleSheet} from 'react-native'; -import SuggestedUser from './SuggestedUser'; - -/** - * Search Screen for user recommendations and a search - * tool to allow user to find other users - */ - -interface SuggestedSectionProps { - title: string; - users: Array; -} -const SuggestedSection: React.FC = ({title, users}) => { - return ( - - {title} - - {users.map((name, key) => ( - - ))} - - - ); -}; - -const styles = StyleSheet.create({ - container: { - marginBottom: 30, - }, - header: { - fontWeight: '600', - fontSize: 20, - color: '#fff', - marginBottom: 20, - }, - user: { - marginHorizontal: 15, - }, -}); - -export default SuggestedSection; diff --git a/src/components/search/SuggestedUser.tsx b/src/components/search/SuggestedUser.tsx deleted file mode 100644 index 467e5e6c..00000000 --- a/src/components/search/SuggestedUser.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import React from 'react'; -import {View, StyleSheet, Text, ViewProps, Image} from 'react-native'; -import LinearGradient from 'react-native-linear-gradient'; - -/** - * Search Screen for user recommendations and a search - * tool to allow user to find other users - */ - -interface SuggestedUserProps extends ViewProps { - name: string; -} -const SuggestedUser: React.FC = ({name, style}) => { - return ( - - - - - {name} - {`@${name.split(' ').join('')}`} - - ); -}; - -const styles = StyleSheet.create({ - container: { - alignItems: 'center', - }, - gradient: { - height: 80, - width: 80, - borderRadius: 40, - justifyContent: 'center', - alignItems: 'center', - marginBottom: 10, - }, - profile: { - height: 76, - width: 76, - borderRadius: 38, - }, - name: { - fontWeight: '600', - fontSize: 16, - color: '#fff', - }, - username: { - fontWeight: '600', - fontSize: 14, - color: '#fff', - }, -}); -export default SuggestedUser; diff --git a/src/components/search/index.ts b/src/components/search/index.ts index 4e1d2b14..47dccd8b 100644 --- a/src/components/search/index.ts +++ b/src/components/search/index.ts @@ -1,3 +1,6 @@ -export {default as SearchBar} from './SearchBar'; -export {default as SuggestedSection} from './SuggestedSection'; export {default as SearchBackground} from './SearchBackground'; +export {default as SearchHeader} from './SearchHeader'; +export {default as SearchBar} from './SearchBar'; +export {default as Explore} from './Explore'; +export {default as SearchResultsBackground} from './SearchResultsBackground'; +export {default as SearchResults} from './SearchResults'; diff --git a/src/constants/api.ts b/src/constants/api.ts index 057b5da7..5eb07980 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -9,3 +9,4 @@ export const PROFILE_INFO_ENDPOINT: string = API_URL + 'user-profile-info/'; export const COVER_PHOTO_ENDPOINT: string = API_URL + 'large-profile-pic/'; export const AVATAR_PHOTO_ENDPOINT: string = API_URL + 'small-profile-pic/'; export const GET_IG_POSTS_ENDPOINT: string = API_URL + 'posts-ig/'; +export const SEARCH_ENDPOINT: string = API_URL + 'search/'; diff --git a/src/screens/profile/ProfileScreen.tsx b/src/screens/profile/ProfileScreen.tsx index 3d1ef2a8..9da9a3d8 100644 --- a/src/screens/profile/ProfileScreen.tsx +++ b/src/screens/profile/ProfileScreen.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {Cover, Content} from '../../components'; +import {Cover, Content, TabsGradient} from '../../components'; import Animated from 'react-native-reanimated'; import {AuthContext} from '../../routes/authentication'; import {StatusBar} from 'react-native'; @@ -19,6 +19,7 @@ const ProfileScreen: React.FC = () => { + ); }; diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx index 8ef56b73..94b9ab41 100644 --- a/src/screens/search/SearchScreen.tsx +++ b/src/screens/search/SearchScreen.tsx @@ -1,83 +1,112 @@ -import React, {useState} from 'react'; +import React, {useEffect, useState} from 'react'; +import {StatusBar, StyleSheet, ScrollView, Keyboard} from 'react-native'; import { - StatusBar, - SafeAreaView, - StyleSheet, - Text, - View, - ScrollView, -} from 'react-native'; -import {SearchBar, SuggestedSection, SearchBackground} from '../../components'; -import {SCREEN_HEIGHT} from '../../utils'; + SearchBackground, + SearchHeader, + SearchBar, + Explore, + SearchResultsBackground, + SearchResults, + TabsGradient, +} from '../../components'; +import {SCREEN_HEIGHT, StatusBarHeight} from '../../utils'; +import Animated, {Easing, timing} from 'react-native-reanimated'; +import {ProfilePreviewType} from '../../types'; +import {SEARCH_ENDPOINT} from '../../constants'; +const {Value} = Animated; /** * Search Screen for user recommendations and a search * tool to allow user to find other users */ +const top: Animated.Value = new Value(-SCREEN_HEIGHT); const SearchScreen: React.FC = () => { - const sections: Array = [ - 'People you follow', - 'People you may know', - 'Trending in sports', - 'Trending on Tagg', - 'Trending in music', - ]; - // dummy user data - const users: Array = [ - 'Sam Davis', - 'Becca Smith', - 'Ann Taylor', - 'Clara Johnson', - 'Sarah Jung', - 'Lila Hernandez', - ]; - const [isSearching, setIsSearching] = useState(false); + const [query, setQuery] = useState(''); + const [results, setResults] = useState>([]); + useEffect(() => { + if (query.length < 3) { + setResults([]); + return; + } + const loadResults = async (q: string) => { + try { + const response = await fetch(`${SEARCH_ENDPOINT}?query=${q}`, { + method: 'GET', + }); + const status = response.status; + if (status === 200) { + let searchResults = await response.json(); + setResults(searchResults); + return; + } + setResults([]); + } catch (error) { + console.log(error); + setResults([]); + } + }; + loadResults(query); + }, [query]); + const handleFocus = () => { - setIsSearching(true); + const topInConfig = { + duration: 180, + toValue: 0, + easing: Easing.bezier(0.31, 0.14, 0.66, 0.82), + }; + timing(top, topInConfig).start(); }; const handleBlur = () => { - setIsSearching(false); + Keyboard.dismiss(); + const topOutConfig = { + duration: 180, + toValue: -SCREEN_HEIGHT, + easing: Easing.inOut(Easing.ease), + }; + timing(top, topOutConfig).start(); }; + return ( - + - - - Explore - - {!isSearching && ( - - {sections.map((title) => ( - - ))} - - )} - - + + + + + + + + + ); }; const styles = StyleSheet.create({ - screen: { - paddingTop: 50, - paddingBottom: SCREEN_HEIGHT / 10, + contentContainer: { + paddingTop: StatusBarHeight, + paddingBottom: SCREEN_HEIGHT / 15, paddingHorizontal: 15, }, - content: { - paddingVertical: 20, + searchBar: { + marginBottom: 20, }, header: { - fontWeight: 'bold', - fontSize: 24, - color: '#fff', - marginBottom: 20, - textAlign: 'center', + marginVertical: 20, + zIndex: 1, }, }); export default SearchScreen; diff --git a/src/types/types.ts b/src/types/types.ts index 6dabc0bc..c01ee045 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -3,6 +3,16 @@ export interface UserType { username: string; } +/** + * User profile information that only conntains a few key fields. + */ +export interface ProfilePreviewType { + id: string; + username: string; + first_name: string; + last_name: string; +} + export interface ProfileType { name: string; biography: string; -- cgit v1.2.3-70-g09d2