diff options
author | Leon Jiang <35908040+leonyjiang@users.noreply.github.com> | 2020-08-10 15:14:26 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-10 18:14:26 -0400 |
commit | 1979a2b55ebe560b9d20862bd835343516b40379 (patch) | |
tree | 64745f07ef24e748cb4fbdd9c29170b61d497f8d | |
parent | ebf69b2dc12b3109e3556c7e3a07ea3037a2ae53 (diff) |
[TMA-160] Search Page Suggestions ("Explore") UI (#30)
* Fix require cycle in Checkpoint.tsx
* Create file structure for search
* Add react-native-vector-icons to project
* Create search page UI
* Create search page UI
* [TMA-65] Onboarding Link Social Media UI (#29)
* Basic setup for SocialMediaLinker component
* Added social media icons
* Displayed 3 main social components
* Layout components in a row
* Added base Show More/Less button
* Display all 9 socials with Show More button
* Added different font colors for each linker
* Realized that the check doesn't replace the text
* Added type-checking to some constants
* Updated state name
* Fixed Checkpoint.tsx merge issue
* Removed unnecessary path element
* Fixed type issues on Verification.tsx
* Create file structure for search
* Add react-native-vector-icons to project
* Create search page UI
* Replace avatars with image placeholder
* Add search bar placeholder
Co-authored-by: Justin Shillingford <jgs272@cornell.edu>
-rw-r--r-- | ios/Frontend.xcodeproj/project.pbxproj | 74 | ||||
-rw-r--r-- | ios/Frontend/Info.plist | 4 | ||||
-rw-r--r-- | ios/Podfile.lock | 6 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | src/components/index.ts | 1 | ||||
-rw-r--r-- | src/components/search/SearchBackground.tsx | 27 | ||||
-rw-r--r-- | src/components/search/SearchBar.tsx | 87 | ||||
-rw-r--r-- | src/components/search/SuggestedSection.tsx | 42 | ||||
-rw-r--r-- | src/components/search/SuggestedUser.tsx | 61 | ||||
-rw-r--r-- | src/components/search/index.ts | 3 | ||||
-rw-r--r-- | src/routes/tabs/NavigationBar.tsx | 4 | ||||
-rw-r--r-- | src/screens/index.ts | 1 | ||||
-rw-r--r-- | src/screens/main/Search.tsx | 24 | ||||
-rw-r--r-- | src/screens/main/index.ts | 1 | ||||
-rw-r--r-- | src/screens/search/SearchScreen.tsx | 83 | ||||
-rw-r--r-- | src/screens/search/index.ts | 1 | ||||
-rw-r--r-- | yarn.lock | 19 |
17 files changed, 412 insertions, 28 deletions
diff --git a/ios/Frontend.xcodeproj/project.pbxproj b/ios/Frontend.xcodeproj/project.pbxproj index 03406070..8857e752 100644 --- a/ios/Frontend.xcodeproj/project.pbxproj +++ b/ios/Frontend.xcodeproj/project.pbxproj @@ -56,6 +56,7 @@ 545F2AEA87DB571518CCFA32 /* Pods-Frontend.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Frontend.debug.xcconfig"; path = "Target Support Files/Pods-Frontend/Pods-Frontend.debug.xcconfig"; sourceTree = "<group>"; }; 567A4E39A63C7DE8FD446FC2 /* Pods-Frontend-FrontendTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Frontend-FrontendTests.release.xcconfig"; path = "Target Support Files/Pods-Frontend-FrontendTests/Pods-Frontend-FrontendTests.release.xcconfig"; sourceTree = "<group>"; }; 602415FF24B9FF3F87744F70 /* Pods-Frontend-tvOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Frontend-tvOSTests.debug.xcconfig"; path = "Target Support Files/Pods-Frontend-tvOSTests/Pods-Frontend-tvOSTests.debug.xcconfig"; sourceTree = "<group>"; }; + 69C3C9D324E1B851003075D8 /* Feather.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = "<group>"; }; 6CAFA98ACCF23BEB39AD0A53 /* libPods-Frontend-tvOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Frontend-tvOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 9F8E4573A72CA8220DAA9AF5 /* libPods-Frontend-tvOSTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Frontend-tvOSTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A25FA993A8B7865AC123945B /* libPods-Frontend.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Frontend.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -125,6 +126,7 @@ 13B07FAE1A68108700A75B9A /* Frontend */ = { isa = PBXGroup; children = ( + 69C3C9D224E1B813003075D8 /* Fonts */, 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, @@ -149,6 +151,14 @@ name = Frameworks; sourceTree = "<group>"; }; + 69C3C9D224E1B813003075D8 /* Fonts */ = { + isa = PBXGroup; + children = ( + 69C3C9D324E1B851003075D8 /* Feather.ttf */, + ); + name = Fonts; + sourceTree = "<group>"; + }; 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( @@ -466,11 +476,43 @@ inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Frontend/Pods-Frontend-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf", "${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle", ); runOnlyForDeploymentPostprocessing = 0; @@ -486,11 +528,43 @@ inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Frontend-FrontendTests/Pods-Frontend-FrontendTests-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf", "${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle", ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/Frontend/Info.plist b/ios/Frontend/Info.plist index 357d12ab..438498de 100644 --- a/ios/Frontend/Info.plist +++ b/ios/Frontend/Info.plist @@ -53,6 +53,10 @@ <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> + <key>UIAppFonts</key> + <array> + <string>Feather.ttf</string> + </array> <key>UIViewControllerBasedStatusBarAppearance</key> <false/> </dict> diff --git a/ios/Podfile.lock b/ios/Podfile.lock index f4d97ee4..87cc0258 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -317,6 +317,8 @@ PODS: - React - RNSVG (12.1.0): - React + - RNVectorIcons (7.0.0): + - React - TOCropViewController (2.5.3) - Yoga (1.14.0) - YogaKit (1.18.1): @@ -378,6 +380,7 @@ DEPENDENCIES: - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) - RNSVG (from `../node_modules/react-native-svg`) + - RNVectorIcons (from `../node_modules/react-native-vector-icons`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: @@ -463,6 +466,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-screens" RNSVG: :path: "../node_modules/react-native-svg" + RNVectorIcons: + :path: "../node_modules/react-native-vector-icons" Yoga: :path: "../node_modules/react-native/ReactCommon/yoga" @@ -511,6 +516,7 @@ SPEC CHECKSUMS: RNReanimated: c2bb7438b57a3d987bb2e4e6e4bca94787e30b02 RNScreens: b748efec66e095134c7166ca333b628cd7e6f3e2 RNSVG: ce9d996113475209013317e48b05c21ee988d42e + RNVectorIcons: da6fe858f5a65d7bbc3379540a889b0b12aa5976 TOCropViewController: 20a14b6a7a098308bf369e7c8d700dc983a974e6 Yoga: 3ebccbdd559724312790e7742142d062476b698e YogaKit: f782866e155069a2cca2517aafea43200b01fd5a diff --git a/package.json b/package.json index 9d930a70..7f47e1af 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@react-navigation/bottom-tabs": "^5.7.2", "@react-navigation/native": "^5.6.1", "@react-navigation/stack": "^5.6.2", + "@types/react-native-vector-icons": "^6.4.5", "moment": "^2.27.0", "react": "16.11.0", "react-native": "0.62.2", @@ -29,6 +30,7 @@ "react-native-safe-area-context": "^3.0.6", "react-native-screens": "^2.9.0", "react-native-svg": "^12.1.0", + "react-native-vector-icons": "^7.0.0", "react-promise-tracker": "^2.1.0", "rn-fetch-blob": "^0.12.0" }, diff --git a/src/components/index.ts b/src/components/index.ts index 48b7df05..77ba0f67 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,3 +1,4 @@ export * from './common'; export * from './onboarding'; export * from './profile'; +export * from './search'; diff --git a/src/components/search/SearchBackground.tsx b/src/components/search/SearchBackground.tsx new file mode 100644 index 00000000..66e3dbdb --- /dev/null +++ b/src/components/search/SearchBackground.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import {StyleSheet, ViewProps} from 'react-native'; +import LinearGradient from 'react-native-linear-gradient'; + +interface SearchBackgroundProps extends ViewProps {} +const SearchBackground: React.FC<SearchBackgroundProps> = ({ + style, + children, +}) => { + return ( + <LinearGradient + useAngle={true} + angle={167} + colors={['#421566', '#385D5E']} + style={[styles.container, style]}> + {children} + </LinearGradient> + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); + +export default SearchBackground; diff --git a/src/components/search/SearchBar.tsx b/src/components/search/SearchBar.tsx new file mode 100644 index 00000000..283b6d59 --- /dev/null +++ b/src/components/search/SearchBar.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { + StyleSheet, + TextInput, + TextInputProps, + NativeSyntheticEvent, + TextInputFocusEventData, + TouchableOpacity, + Text, + View, +} from 'react-native'; +import Icon from 'react-native-vector-icons/Feather'; +import Animated from 'react-native-reanimated'; + +interface SearchBarProps extends TextInputProps { + active: boolean; +} +const SearchBar: React.FC<SearchBarProps> = ({onFocus, onBlur, active}) => { + const handleFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => { + // 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<TextInputFocusEventData>) => { + // 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); + }; + + return ( + <View style={styles.container}> + <Animated.View style={styles.inputContainer}> + <Icon name="search" size={25} color="#fff" style={styles.searchIcon} /> + <TextInput + onFocus={handleFocus} + onBlur={handleBlur} + style={styles.input} + placeholder={'Search...'} + /> + </Animated.View> + {active && ( + <TouchableOpacity style={styles.cancelButton}> + <Text style={styles.cancel}>Cancel</Text> + </TouchableOpacity> + )} + </View> + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + alignItems: 'center', + height: 40, + }, + inputContainer: { + flexDirection: 'row', + alignItems: 'center', + flex: 1, + height: '100%', + paddingHorizontal: 8, + backgroundColor: '#fff3', + borderColor: '#fff', + borderWidth: 1.5, + borderRadius: 20, + }, + searchIcon: { + marginRight: 8, + }, + input: { + flex: 1, + fontSize: 16, + }, + cancelButton: { + marginHorizontal: 5, + }, + cancel: { + color: '#818181', + fontWeight: '600', + }, +}); + +export default SearchBar; diff --git a/src/components/search/SuggestedSection.tsx b/src/components/search/SuggestedSection.tsx new file mode 100644 index 00000000..af0323a5 --- /dev/null +++ b/src/components/search/SuggestedSection.tsx @@ -0,0 +1,42 @@ +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<string>; +} +const SuggestedSection: React.FC<SuggestedSectionProps> = ({title, users}) => { + return ( + <View style={styles.container}> + <Text style={styles.header}>{title}</Text> + <ScrollView horizontal showsHorizontalScrollIndicator={false}> + {users.map((name, key) => ( + <SuggestedUser {...{name, key}} style={styles.user} /> + ))} + </ScrollView> + </View> + ); +}; + +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 new file mode 100644 index 00000000..467e5e6c --- /dev/null +++ b/src/components/search/SuggestedUser.tsx @@ -0,0 +1,61 @@ +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<SuggestedUserProps> = ({name, style}) => { + return ( + <View style={[styles.container, style]}> + <LinearGradient + colors={['#9F00FF', '#27EAE9']} + useAngle + angle={90} + angleCenter={{x: 0.5, y: 0.5}} + style={styles.gradient}> + <Image + source={require('../../assets/images/avatar-placeholder.png')} + style={styles.profile} + /> + </LinearGradient> + <Text style={styles.name}>{name}</Text> + <Text style={styles.username}>{`@${name.split(' ').join('')}`}</Text> + </View> + ); +}; + +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 new file mode 100644 index 00000000..4e1d2b14 --- /dev/null +++ b/src/components/search/index.ts @@ -0,0 +1,3 @@ +export {default as SearchBar} from './SearchBar'; +export {default as SuggestedSection} from './SuggestedSection'; +export {default as SearchBackground} from './SearchBackground'; diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index aca968c2..d36b02ae 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -3,9 +3,9 @@ import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; import {NavigationIcon} from '../../components'; import { ProfileScreen, + SearchScreen, Home, Notifications, - Search, Upload, } from '../../screens'; @@ -62,7 +62,7 @@ const NavigationBar: React.FC = () => { }, }}> <Tabs.Screen name="Home" component={Home} /> - <Tabs.Screen name="Search" component={Search} /> + <Tabs.Screen name="Search" component={SearchScreen} /> <Tabs.Screen name="Upload" component={Upload} /> <Tabs.Screen name="Notifications" component={Notifications} /> <Tabs.Screen name="Profile" component={ProfileScreen} /> diff --git a/src/screens/index.ts b/src/screens/index.ts index 5dd3007a..13a9799c 100644 --- a/src/screens/index.ts +++ b/src/screens/index.ts @@ -1,3 +1,4 @@ export * from './main'; export * from './onboarding'; export * from './profile'; +export * from './search'; diff --git a/src/screens/main/Search.tsx b/src/screens/main/Search.tsx deleted file mode 100644 index 19e35d04..00000000 --- a/src/screens/main/Search.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; -import {Text} from 'react-native-animatable'; -import {StyleSheet} from 'react-native'; -import {GradientBackground} from '../../components'; - -/** - * Search Screen for user recommendations and a search - * tool to allow user to find other users - */ - -const Search: React.FC = () => { - return ( - <GradientBackground> - <Text style={styles.text}> Search for people here 👀 </Text> - </GradientBackground> - ); -}; -const styles = StyleSheet.create({ - text: { - justifyContent: 'center', - backgroundColor: 'transparent', - }, -}); -export default Search; diff --git a/src/screens/main/index.ts b/src/screens/main/index.ts index fb1bf49b..b15f76da 100644 --- a/src/screens/main/index.ts +++ b/src/screens/main/index.ts @@ -1,4 +1,3 @@ export {default as Home} from './Home'; export {default as Notifications} from './Notifications'; -export {default as Search} from './Search'; export {default as Upload} from './Upload'; diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx new file mode 100644 index 00000000..8ef56b73 --- /dev/null +++ b/src/screens/search/SearchScreen.tsx @@ -0,0 +1,83 @@ +import React, {useState} from 'react'; +import { + StatusBar, + SafeAreaView, + StyleSheet, + Text, + View, + ScrollView, +} from 'react-native'; +import {SearchBar, SuggestedSection, SearchBackground} from '../../components'; +import {SCREEN_HEIGHT} from '../../utils'; + +/** + * Search Screen for user recommendations and a search + * tool to allow user to find other users + */ + +const SearchScreen: React.FC = () => { + const sections: Array<string> = [ + 'People you follow', + 'People you may know', + 'Trending in sports', + 'Trending on Tagg', + 'Trending in music', + ]; + // dummy user data + const users: Array<string> = [ + 'Sam Davis', + 'Becca Smith', + 'Ann Taylor', + 'Clara Johnson', + 'Sarah Jung', + 'Lila Hernandez', + ]; + const [isSearching, setIsSearching] = useState<boolean>(false); + const handleFocus = () => { + setIsSearching(true); + }; + const handleBlur = () => { + setIsSearching(false); + }; + return ( + <SearchBackground style={styles.screen}> + <StatusBar /> + <SafeAreaView> + <ScrollView showsVerticalScrollIndicator={false}> + <Text style={styles.header}>Explore</Text> + <SearchBar + active={isSearching} + onFocus={handleFocus} + onBlur={handleBlur} + /> + {!isSearching && ( + <View style={styles.content}> + {sections.map((title) => ( + <SuggestedSection key={title} title={title} users={users} /> + ))} + </View> + )} + </ScrollView> + </SafeAreaView> + </SearchBackground> + ); +}; + +const styles = StyleSheet.create({ + screen: { + paddingTop: 50, + paddingBottom: SCREEN_HEIGHT / 10, + paddingHorizontal: 15, + }, + content: { + paddingVertical: 20, + }, + header: { + fontWeight: 'bold', + fontSize: 24, + color: '#fff', + marginBottom: 20, + textAlign: 'center', + }, +}); +export default SearchScreen; diff --git a/src/screens/search/index.ts b/src/screens/search/index.ts new file mode 100644 index 00000000..b6680aa4 --- /dev/null +++ b/src/screens/search/index.ts @@ -0,0 +1 @@ +export {default as SearchScreen} from './SearchScreen'; @@ -1150,6 +1150,14 @@ "@types/react-native" "*" moment ">=2.14.0" +"@types/react-native-vector-icons@^6.4.5": + version "6.4.5" + resolved "https://registry.yarnpkg.com/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.5.tgz#74cbfc564bd8435e43ad6728572a0e5b49c335d1" + integrity sha512-JBpcjWQE4n0GlE0p6HpDDclT+uXpFC453T5k4h+B38q0utlGJhvgNr8899BoJGc1xOktA2cgqFKmFMJd0h7YaA== + dependencies: + "@types/react" "*" + "@types/react-native" "*" + "@types/react-native@*": version "0.63.4" resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.63.4.tgz#4610b0df0e5f0db4c68d495754ad9f8bc3b8893f" @@ -5312,6 +5320,15 @@ react-native-svg@^12.1.0: css-select "^2.1.0" css-tree "^1.0.0-alpha.39" +react-native-vector-icons@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-7.0.0.tgz#5b92ed363c867645daad48c559e1f99efcfbb813" + integrity sha512-Ku8+dTUAnR9pexRPQqsUcQEZlxEpFZsIy8iOFqVL/3mrUyncZJHtqJyx2cUOmltZIC6W2GI4IkD3EYzPerXV5g== + dependencies: + lodash "^4.17.15" + prop-types "^15.7.2" + yargs "^15.0.2" + react-native@0.62.2: version "0.62.2" resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.62.2.tgz#d831e11a3178705449142df19a70ac2ca16bad10" @@ -6780,7 +6797,7 @@ yargs@^14.2.0: y18n "^4.0.0" yargs-parser "^15.0.1" -yargs@^15.1.0: +yargs@^15.0.2, yargs@^15.1.0: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== |