From f8762fd3a0140bff92fe96985e3abdb9c2925dac Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 15 Apr 2021 16:56:10 -0400 Subject: moved CategorySelection and CreateCustomCategory to profile folder --- src/screens/profile/CategorySelection.tsx | 302 +++++++++++++++++++++++++++ src/screens/profile/CreateCustomCategory.tsx | 121 +++++++++++ src/screens/profile/index.ts | 2 + 3 files changed, 425 insertions(+) create mode 100644 src/screens/profile/CategorySelection.tsx create mode 100644 src/screens/profile/CreateCustomCategory.tsx (limited to 'src/screens/profile') diff --git a/src/screens/profile/CategorySelection.tsx b/src/screens/profile/CategorySelection.tsx new file mode 100644 index 00000000..d3958025 --- /dev/null +++ b/src/screens/profile/CategorySelection.tsx @@ -0,0 +1,302 @@ +import {RouteProp} from '@react-navigation/native'; +import {StackNavigationProp} from '@react-navigation/stack'; +import React, {useEffect, useState} from 'react'; +import { + Alert, + Platform, + StatusBar, + StyleSheet, + Text, + TouchableOpacity, + View, +} from 'react-native'; +import {ScrollView} from 'react-native-gesture-handler'; +import {useDispatch, useSelector} from 'react-redux'; +import PlusIcon from '../../assets/icons/plus_icon-01.svg'; +import {Background, MomentCategory} from '../../components'; +import {MOMENT_CATEGORIES} from '../../constants'; +import {ERROR_SOMETHING_WENT_WRONG} from '../../constants/strings'; +import {MainStackParams} from '../../routes'; +import {updateMomentCategories} from '../../store/actions'; +import {RootState} from '../../store/rootReducer'; +import {BackgroundGradientType} from '../../types'; +import {SCREEN_WIDTH} from '../../utils'; + +type CategorySelectionRouteProps = RouteProp< + MainStackParams, + 'CategorySelection' +>; + +type CategorySelectionNavigationProps = StackNavigationProp< + MainStackParams, + 'CategorySelection' +>; + +interface CategorySelectionProps { + route: CategorySelectionRouteProps; + navigation: CategorySelectionNavigationProps; +} + +const CategorySelection: React.FC = ({ + route, + navigation, +}) => { + const {newCustomCategory} = route.params; + const {momentCategories = []} = useSelector( + (state: RootState) => state.momentCategories, + ); + + // Stores all the categories that will be saved to the store + const [selectedCategories, setSelectedCategories] = useState([]); + + /** + * Stores all the custom categories for the UI, allow easier logic for + * unchecking a custom category. + * + * Each uncommited custom category should also have a copy in selectedCategories + * since that's the final value that will be stored in the store. + */ + const [uncommitedCustomCategories, setUncommitedCustomCategories] = useState< + string[] + >([]); + + const customCategories = momentCategories.filter( + (mc) => !MOMENT_CATEGORIES.includes(mc), + ); + + const dispatch = useDispatch(); + + useEffect(() => { + if (newCustomCategory) { + setUncommitedCustomCategories([ + ...uncommitedCustomCategories, + newCustomCategory, + ]); + selectedCategories.push(newCustomCategory); + } + }, [newCustomCategory]); + + /** + * Handle selection of a new category + * case isAdded: + * Return without doing anything + * case isSelected: + * Add to the selected categories + * case not isSelected: + * Remove from the selected categories + */ + const onSelect = ( + category: string, + isSelected: boolean, + isAdded: boolean, + ) => { + if (isAdded) { + return; + } + if (isSelected) { + setSelectedCategories((prev) => [...prev, category]); + } else { + setSelectedCategories( + selectedCategories.filter((item) => item !== category), + ); + } + }; + + /** + * Handle deselection of custom category. + * + * Custom categories is "added" and "selected" by CreateCustomCategory screen. + * User can only "deselect" an uncommited custom category. + * + * case isAdded || isSelected: + * Return without doing anything + * default: + * Remove from selected categories AND uncommitedCustomCategories + */ + const onDeselectCustomCategory = ( + category: string, + isSelected: boolean, + isAdded: boolean, + ) => { + if (isAdded || isSelected) { + return; + } + setSelectedCategories( + selectedCategories.filter((item) => item !== category), + ); + setUncommitedCustomCategories( + uncommitedCustomCategories.filter((item) => item !== category), + ); + }; + + const handleButtonPress = async () => { + if (momentCategories.length + selectedCategories.length === 0) { + Alert.alert('Please select at least 1 category'); + return; + } + try { + dispatch( + updateMomentCategories( + momentCategories.concat(selectedCategories), + true, + ), + ); + navigation.goBack(); + } catch (error) { + console.log(error); + Alert.alert(ERROR_SOMETHING_WENT_WRONG); + } + }; + + /** + * Using a scroll view to accomodate dynamic category creation later on + */ + return ( + + + + Create Categories + + { + navigation.push('CreateCustomCategory', { + existingCategories: momentCategories.concat(selectedCategories), + }); + }}> + + + Create your own category + + + + {/* commited custom categories */} + {customCategories.map((category, index) => ( + + ))} + {/* uncommited custom categroies */} + {uncommitedCustomCategories.map((category, index) => ( + + ))} + {customCategories.length + uncommitedCustomCategories.length !== + 0 && } + {MOMENT_CATEGORIES.map((category, index) => ( + + ))} + + + Create + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'space-around', + marginBottom: '10%', + }, + wizard: { + ...Platform.select({ + ios: { + top: 50, + }, + android: { + bottom: 40, + }, + }), + }, + linkerContainer: { + flex: 1, + flexDirection: 'row', + flexWrap: 'wrap', + justifyContent: 'center', + alignContent: 'center', + marginBottom: '10%', + }, + header: { + color: '#fff', + fontSize: 22, + fontWeight: '600', + textAlign: 'center', + marginBottom: '4%', + }, + subtext: { + color: '#fff', + fontSize: 20, + fontWeight: '600', + textAlign: 'center', + marginVertical: '8%', + marginHorizontal: '10%', + marginTop: '15%', + }, + finalAction: { + backgroundColor: 'white', + justifyContent: 'center', + alignItems: 'center', + width: 150, + height: 40, + borderRadius: 5, + borderWidth: 1, + borderColor: 'white', + marginBottom: '25%', + }, + finalActionLabel: { + fontSize: 16, + fontWeight: '500', + color: 'black', + }, + createCategory: { + backgroundColor: '#53329B', + width: SCREEN_WIDTH * 0.9, + height: 70, + alignItems: 'center', + justifyContent: 'center', + borderRadius: 10, + flexDirection: 'row', + marginBottom: '5%', + }, + createCategoryLabel: { + color: 'white', + marginLeft: '3%', + fontSize: 18, + fontWeight: '500', + }, + plusIcon: { + color: 'white', + }, + divider: { + borderColor: 'white', + borderBottomWidth: 1, + width: SCREEN_WIDTH * 0.9, + marginVertical: '2%', + }, +}); + +export default CategorySelection; diff --git a/src/screens/profile/CreateCustomCategory.tsx b/src/screens/profile/CreateCustomCategory.tsx new file mode 100644 index 00000000..c4b17b1e --- /dev/null +++ b/src/screens/profile/CreateCustomCategory.tsx @@ -0,0 +1,121 @@ +import {RouteProp} from '@react-navigation/native'; +import {StackNavigationProp} from '@react-navigation/stack'; +import React, {useState} from 'react'; +import { + Alert, + KeyboardAvoidingView, + StatusBar, + StyleSheet, + Text, + TextInput, + TouchableOpacity, +} from 'react-native'; +import {Background} from '../../components'; +import {MainStackParams} from '../../routes'; +import {BackgroundGradientType} from '../../types'; +import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; + +type CreateCustomCategoryRouteProps = RouteProp< + MainStackParams, + 'CreateCustomCategory' +>; + +type CreateCustomCategoryNavigationProps = StackNavigationProp< + MainStackParams, + 'CreateCustomCategory' +>; + +interface CreateCustomCategoryProps { + route: CreateCustomCategoryRouteProps; + navigation: CreateCustomCategoryNavigationProps; +} + +const CreateCustomCategory: React.FC = ({ + route, + navigation, +}) => { + /** + * Same component to be used for category selection while onboarding and while on profile + */ + const {existingCategories} = route.params; + const [newCategory, setNewCategory] = useState(''); + + const handleButtonPress = () => { + if (existingCategories.includes(newCategory)) { + Alert.alert('Looks like you already have that one created!'); + } else { + navigation.navigate('CategorySelection', { + newCustomCategory: newCategory, + }); + } + }; + + return ( + <> + + + + Give your category a name + + + {'Create'} + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + minHeight: SCREEN_HEIGHT, + }, + innerContainer: { + height: '40%', + top: '20%', + justifyContent: 'space-around', + alignItems: 'center', + }, + title: { + color: 'white', + fontSize: 20, + fontWeight: '600', + }, + input: { + width: SCREEN_WIDTH * 0.75, + fontSize: 30, + color: 'white', + textAlign: 'center', + borderBottomWidth: 1, + borderBottomColor: 'white', + }, + finalAction: { + backgroundColor: 'white', + justifyContent: 'center', + alignItems: 'center', + width: 150, + height: 40, + borderRadius: 5, + borderWidth: 1, + borderColor: '#8F01FF', + }, + finalActionLabel: { + fontSize: 16, + fontWeight: '500', + color: 'black', + }, +}); + +export default CreateCustomCategory; diff --git a/src/screens/profile/index.ts b/src/screens/profile/index.ts index b7efdd3b..d5377494 100644 --- a/src/screens/profile/index.ts +++ b/src/screens/profile/index.ts @@ -10,3 +10,5 @@ export {default as InviteFriendsScreen} from './InviteFriendsScreen'; export {default as SettingsScreen} from './SettingsScreen'; export {default as PrivacyScreen} from './PrivacyScreen'; export {default as AccountType} from './AccountType'; +export {default as CategorySelection} from './CategorySelection'; +export {default as CreateCustomCategory} from './CreateCustomCategory'; -- cgit v1.2.3-70-g09d2 From c477ebfd00e3898814721b8316a47cf14f1740c4 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Mon, 19 Apr 2021 16:08:32 -0400 Subject: fixed route bug --- src/components/profile/PublicProfile.tsx | 10 +++++----- src/screens/profile/CategorySelection.tsx | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/screens/profile') diff --git a/src/components/profile/PublicProfile.tsx b/src/components/profile/PublicProfile.tsx index f2d52a3d..d2ee8626 100644 --- a/src/components/profile/PublicProfile.tsx +++ b/src/components/profile/PublicProfile.tsx @@ -241,7 +241,11 @@ const PublicProfile: React.FC = ({ )} {!userXId && ( navigation.navigate('CategorySelection')} + onPress={() => + navigation.navigate('CategorySelection', { + newCustomCategory: undefined, + }) + } style={styles.createCategoryButton}> Create a new category @@ -253,10 +257,6 @@ const PublicProfile: React.FC = ({ }; const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#fff', - }, momentsContainer: { backgroundColor: '#f2f2f2', paddingBottom: SCREEN_HEIGHT * 0.15, diff --git a/src/screens/profile/CategorySelection.tsx b/src/screens/profile/CategorySelection.tsx index d3958025..c3e45e98 100644 --- a/src/screens/profile/CategorySelection.tsx +++ b/src/screens/profile/CategorySelection.tsx @@ -37,7 +37,7 @@ interface CategorySelectionProps { navigation: CategorySelectionNavigationProps; } -const CategorySelection: React.FC = ({ +const CategorySelection: React.FC = ({ route, navigation, }) => { -- cgit v1.2.3-70-g09d2 From 9458d888cc03fc61c13db69492682ac268991887 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Mon, 19 Apr 2021 16:18:44 -0400 Subject: cleaned up TAGG_LIGHT_BLUE_2 color constant --- src/components/common/PostCarousel.tsx | 3 ++- src/components/messages/ChannelPreview.tsx | 3 ++- src/components/messages/ChatHeader.tsx | 3 ++- src/components/taggs/TwitterTaggPost.tsx | 14 +++++++------- src/screens/profile/AccountType.tsx | 3 ++- src/screens/profile/CaptionScreen.tsx | 5 +++-- src/screens/profile/IndividualMoment.tsx | 4 ---- 7 files changed, 18 insertions(+), 17 deletions(-) (limited to 'src/screens/profile') diff --git a/src/components/common/PostCarousel.tsx b/src/components/common/PostCarousel.tsx index cda9d8db..be3dcb16 100644 --- a/src/components/common/PostCarousel.tsx +++ b/src/components/common/PostCarousel.tsx @@ -1,6 +1,7 @@ import React, {Fragment, useRef, useState} from 'react'; import {Image} from 'react-native'; import Carousel, {Pagination} from 'react-native-snap-carousel'; +import {TAGG_LIGHT_BLUE_2} from '../../constants'; import {SCREEN_WIDTH} from '../../utils'; interface PostCarouselProps { @@ -39,7 +40,7 @@ const PostCarousel: React.FC = ({ activeDotIndex={currentPage} dotsLength={data.length} containerStyle={{marginBottom: marginBottom}} - dotColor={'#6ee7e7'} + dotColor={TAGG_LIGHT_BLUE_2} inactiveDotColor={'#e0e0e0'} /> diff --git a/src/components/messages/ChannelPreview.tsx b/src/components/messages/ChannelPreview.tsx index a7a7268a..8bd3a745 100644 --- a/src/components/messages/ChannelPreview.tsx +++ b/src/components/messages/ChannelPreview.tsx @@ -5,6 +5,7 @@ import {TouchableOpacity} from 'react-native-gesture-handler'; import {useStore} from 'react-redux'; import {ChannelPreviewMessengerProps} from 'stream-chat-react-native'; import {ChatContext} from '../../App'; +import {TAGG_LIGHT_BLUE_2} from '../../constants'; import { LocalAttachmentType, LocalChannelType, @@ -89,7 +90,7 @@ const styles = StyleSheet.create({ }, online: { position: 'absolute', - backgroundColor: '#6EE7E7', + backgroundColor: TAGG_LIGHT_BLUE_2, width: normalize(18), height: normalize(18), borderRadius: normalize(18) / 2, diff --git a/src/components/messages/ChatHeader.tsx b/src/components/messages/ChatHeader.tsx index 67a7f1fe..7ddaa7e6 100644 --- a/src/components/messages/ChatHeader.tsx +++ b/src/components/messages/ChatHeader.tsx @@ -5,6 +5,7 @@ import {Text} from 'react-native-animatable'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {useDispatch, useStore} from 'react-redux'; import {ChatContext} from '../../App'; +import {TAGG_LIGHT_BLUE_2} from '../../constants'; import {ScreenType} from '../../types'; import { ChatHeaderHeight, @@ -87,7 +88,7 @@ const styles = StyleSheet.create({ }, online: { position: 'absolute', - backgroundColor: '#6EE7E7', + backgroundColor: TAGG_LIGHT_BLUE_2, width: normalize(16), height: normalize(16), borderRadius: normalize(16) / 2, diff --git a/src/components/taggs/TwitterTaggPost.tsx b/src/components/taggs/TwitterTaggPost.tsx index 834e32ef..b2889e3e 100644 --- a/src/components/taggs/TwitterTaggPost.tsx +++ b/src/components/taggs/TwitterTaggPost.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import {Image, Linking, StyleSheet, View} from 'react-native'; -import {Text} from 'react-native-animatable'; +import { Image, Linking, StyleSheet, View } from 'react-native'; +import { Text } from 'react-native-animatable'; import Hyperlink from 'react-native-hyperlink'; import LinearGradient from 'react-native-linear-gradient'; -import {AVATAR_DIM, TAGGS_GRADIENT, TAGG_LIGHT_BLUE} from '../../constants'; -import {TwitterPostType} from '../../types'; -import {handleOpenSocialUrlOnBrowser, SCREEN_WIDTH} from '../../utils'; -import {DateLabel, PostCarousel} from '../common'; +import { AVATAR_DIM, TAGGS_GRADIENT, TAGG_LIGHT_BLUE, TAGG_LIGHT_BLUE_2 } from '../../constants'; +import { TwitterPostType } from '../../types'; +import { handleOpenSocialUrlOnBrowser, SCREEN_WIDTH } from '../../utils'; +import { DateLabel, PostCarousel } from '../common'; interface TwitterTaggPostProps { ownerHandle: string; @@ -194,7 +194,7 @@ const styles = StyleSheet.create({ }, viewOnTwitterText: { fontSize: 12, - color: '#6ee7e7', + color: TAGG_LIGHT_BLUE_2, }, // reply post replyPostContainer: { diff --git a/src/screens/profile/AccountType.tsx b/src/screens/profile/AccountType.tsx index 60ed0668..8a3f7775 100644 --- a/src/screens/profile/AccountType.tsx +++ b/src/screens/profile/AccountType.tsx @@ -10,6 +10,7 @@ import { import {SafeAreaView} from 'react-native-safe-area-context'; import {useDispatch, useSelector} from 'react-redux'; import {Background} from '../../components'; +import {TAGG_LIGHT_BLUE_2} from '../../constants'; import {updateProfileVisibility} from '../../services'; import {NO_PROFILE} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; @@ -60,7 +61,7 @@ const AccountType: React.FC = () => { /> {!isLoading && ( Date: Mon, 19 Apr 2021 16:20:24 -0400 Subject: added create button --- src/screens/profile/CategorySelection.tsx | 61 ++++++++----------------------- 1 file changed, 16 insertions(+), 45 deletions(-) (limited to 'src/screens/profile') diff --git a/src/screens/profile/CategorySelection.tsx b/src/screens/profile/CategorySelection.tsx index c3e45e98..c02eef0d 100644 --- a/src/screens/profile/CategorySelection.tsx +++ b/src/screens/profile/CategorySelection.tsx @@ -3,7 +3,6 @@ import {StackNavigationProp} from '@react-navigation/stack'; import React, {useEffect, useState} from 'react'; import { Alert, - Platform, StatusBar, StyleSheet, Text, @@ -14,13 +13,13 @@ import {ScrollView} from 'react-native-gesture-handler'; import {useDispatch, useSelector} from 'react-redux'; import PlusIcon from '../../assets/icons/plus_icon-01.svg'; import {Background, MomentCategory} from '../../components'; -import {MOMENT_CATEGORIES} from '../../constants'; +import {MOMENT_CATEGORIES, TAGG_LIGHT_BLUE_2} from '../../constants'; import {ERROR_SOMETHING_WENT_WRONG} from '../../constants/strings'; import {MainStackParams} from '../../routes'; import {updateMomentCategories} from '../../store/actions'; import {RootState} from '../../store/rootReducer'; import {BackgroundGradientType} from '../../types'; -import {SCREEN_WIDTH} from '../../utils'; +import {normalize, SCREEN_WIDTH} from '../../utils'; type CategorySelectionRouteProps = RouteProp< MainStackParams, @@ -41,6 +40,7 @@ const CategorySelection: React.FC = ({ route, navigation, }) => { + const dispatch = useDispatch(); const {newCustomCategory} = route.params; const {momentCategories = []} = useSelector( (state: RootState) => state.momentCategories, @@ -64,7 +64,13 @@ const CategorySelection: React.FC = ({ (mc) => !MOMENT_CATEGORIES.includes(mc), ); - const dispatch = useDispatch(); + navigation.setOptions({ + headerRight: () => ( + + Create + + ), + }); useEffect(() => { if (newCustomCategory) { @@ -204,11 +210,6 @@ const CategorySelection: React.FC = ({ /> ))} - - Create - @@ -222,16 +223,6 @@ const styles = StyleSheet.create({ justifyContent: 'space-around', marginBottom: '10%', }, - wizard: { - ...Platform.select({ - ios: { - top: 50, - }, - android: { - bottom: 40, - }, - }), - }, linkerContainer: { flex: 1, flexDirection: 'row', @@ -240,13 +231,6 @@ const styles = StyleSheet.create({ alignContent: 'center', marginBottom: '10%', }, - header: { - color: '#fff', - fontSize: 22, - fontWeight: '600', - textAlign: 'center', - marginBottom: '4%', - }, subtext: { color: '#fff', fontSize: 20, @@ -256,22 +240,6 @@ const styles = StyleSheet.create({ marginHorizontal: '10%', marginTop: '15%', }, - finalAction: { - backgroundColor: 'white', - justifyContent: 'center', - alignItems: 'center', - width: 150, - height: 40, - borderRadius: 5, - borderWidth: 1, - borderColor: 'white', - marginBottom: '25%', - }, - finalActionLabel: { - fontSize: 16, - fontWeight: '500', - color: 'black', - }, createCategory: { backgroundColor: '#53329B', width: SCREEN_WIDTH * 0.9, @@ -288,15 +256,18 @@ const styles = StyleSheet.create({ fontSize: 18, fontWeight: '500', }, - plusIcon: { - color: 'white', - }, divider: { borderColor: 'white', borderBottomWidth: 1, width: SCREEN_WIDTH * 0.9, marginVertical: '2%', }, + createLabel: { + color: TAGG_LIGHT_BLUE_2, + marginRight: 20, + fontSize: normalize(15), + fontWeight: '800', + }, }); export default CategorySelection; -- cgit v1.2.3-70-g09d2