From bf85e56a4f8e0f16a446ec7df8d7f4eba624c213 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 15 Apr 2021 16:53:28 -0400 Subject: moved TaggPopup to legacy --- src/components/common/TaggPopup.tsx | 143 ---------------------------- src/components/common/index.ts | 1 - src/screens/onboarding/legacy/TaggPopup.tsx | 143 ++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 144 deletions(-) delete mode 100644 src/components/common/TaggPopup.tsx create mode 100644 src/screens/onboarding/legacy/TaggPopup.tsx (limited to 'src') diff --git a/src/components/common/TaggPopup.tsx b/src/components/common/TaggPopup.tsx deleted file mode 100644 index f9929580..00000000 --- a/src/components/common/TaggPopup.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import {RouteProp} from '@react-navigation/native'; -import {StackNavigationProp} from '@react-navigation/stack'; -import * as React from 'react'; -import {Platform, Text, StyleSheet, TouchableOpacity} from 'react-native'; -import {Image, View} from 'react-native-animatable'; -import {ArrowButton} from '../onboarding'; -import {OnboardingStackParams} from '../../routes'; -import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; -import CloseIcon from '../../assets/ionicons/close-outline.svg'; -import {BlurView} from '@react-native-community/blur'; - -type TaggPopupRouteProps = RouteProp; -type TaggPopupNavigationProps = StackNavigationProp< - OnboardingStackParams, - 'TaggPopup' ->; - -interface TaggPopupProps { - route: TaggPopupRouteProps; - navigation: TaggPopupNavigationProps; -} - -const TaggPopup: React.FC = ({route, navigation}) => { - /** - * Custom popup / Tutorial screen for Tagg - * Just like a Singly Linked List, we have a next node - * if (next !== undefined) - * Display the next button and navigate to next popup node on click - * else - * Display close button, navigate back on close - */ - const {messageHeader, messageBody, next} = route.params.popupProps; - - return ( - - { - navigation.goBack(); - }}> - - - - {messageHeader} - {messageBody} - - {!next && ( - { - navigation.goBack(); - }}> - - - )} - - {next && ( - - { - navigation.navigate('TaggPopup', {popupProps: next}); - }} - /> - - )} - - - ); -}; - -const styles = StyleSheet.create({ - container: { - flex: 1, - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - width: '100%', - height: '100%', - }, - whiteColor: { - color: 'white', - }, - closeButton: { - position: 'relative', - height: '50%', - aspectRatio: 1, - left: '20%', - }, - textContainer: { - flex: 1, - flexDirection: 'column', - }, - icon: { - width: 40, - height: 40, - marginVertical: '1%', - }, - header: { - color: '#fff', - fontSize: SCREEN_WIDTH / 25, - fontWeight: '600', - textAlign: 'justify', - marginBottom: '2%', - marginLeft: '4%', - }, - subtext: { - color: '#fff', - fontSize: SCREEN_WIDTH / 30, - fontWeight: '600', - textAlign: 'justify', - marginBottom: '15%', - marginLeft: '3%', - }, - popup: { - width: SCREEN_WIDTH * 0.8, - height: SCREEN_WIDTH * 0.24, - backgroundColor: 'black', - borderRadius: 8, - flexDirection: 'row', - alignSelf: 'auto', - flexWrap: 'wrap', - position: 'absolute', - bottom: SCREEN_HEIGHT * 0.7, - padding: SCREEN_WIDTH / 40, - }, - footer: { - marginLeft: '50%', - flexDirection: 'column-reverse', - ...Platform.select({ - ios: { - bottom: '20%', - }, - android: { - bottom: '10%', - }, - }), - }, -}); -export default TaggPopup; diff --git a/src/components/common/index.ts b/src/components/common/index.ts index b5fd0542..5a601f1d 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -17,7 +17,6 @@ export {default as TaggDatePicker} from './TaggDatePicker'; export {default as BottomDrawer} from './BottomDrawer'; export {default as TaggLoadingIndicator} from './TaggLoadingIndicator'; export {default as GenericMoreInfoDrawer} from './GenericMoreInfoDrawer'; -export {default as TaggPopUp} from './TaggPopup'; export {default as TaggPrompt} from './TaggPrompt'; export {default as AcceptDeclineButtons} from './AcceptDeclineButtons'; export {default as FriendsButton} from './FriendsButton'; diff --git a/src/screens/onboarding/legacy/TaggPopup.tsx b/src/screens/onboarding/legacy/TaggPopup.tsx new file mode 100644 index 00000000..e71a4d2a --- /dev/null +++ b/src/screens/onboarding/legacy/TaggPopup.tsx @@ -0,0 +1,143 @@ +import {BlurView} from '@react-native-community/blur'; +import {RouteProp} from '@react-navigation/native'; +import {StackNavigationProp} from '@react-navigation/stack'; +import * as React from 'react'; +import {Platform, StyleSheet, Text, TouchableOpacity} from 'react-native'; +import {Image, View} from 'react-native-animatable'; +import {ArrowButton} from '../../../components/onboarding'; +import {OnboardingStackParams} from '../../../routes'; +import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../../utils'; +import CloseIcon from '../../../assets/ionicons/close-outline.svg'; + +type TaggPopupRouteProps = RouteProp; +type TaggPopupNavigationProps = StackNavigationProp< + OnboardingStackParams, + 'TaggPopup' +>; + +interface TaggPopupProps { + route: TaggPopupRouteProps; + navigation: TaggPopupNavigationProps; +} + +const TaggPopup: React.FC = ({route, navigation}) => { + /** + * Custom popup / Tutorial screen for Tagg + * Just like a Singly Linked List, we have a next node + * if (next !== undefined) + * Display the next button and navigate to next popup node on click + * else + * Display close button, navigate back on close + */ + const {messageHeader, messageBody, next} = route.params.popupProps; + + return ( + + { + navigation.goBack(); + }}> + + + + {messageHeader} + {messageBody} + + {!next && ( + { + navigation.goBack(); + }}> + + + )} + + {next && ( + + { + navigation.navigate('TaggPopup', {popupProps: next}); + }} + /> + + )} + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: '100%', + height: '100%', + }, + whiteColor: { + color: 'white', + }, + closeButton: { + position: 'relative', + height: '50%', + aspectRatio: 1, + left: '20%', + }, + textContainer: { + flex: 1, + flexDirection: 'column', + }, + icon: { + width: 40, + height: 40, + marginVertical: '1%', + }, + header: { + color: '#fff', + fontSize: SCREEN_WIDTH / 25, + fontWeight: '600', + textAlign: 'justify', + marginBottom: '2%', + marginLeft: '4%', + }, + subtext: { + color: '#fff', + fontSize: SCREEN_WIDTH / 30, + fontWeight: '600', + textAlign: 'justify', + marginBottom: '15%', + marginLeft: '3%', + }, + popup: { + width: SCREEN_WIDTH * 0.8, + height: SCREEN_WIDTH * 0.24, + backgroundColor: 'black', + borderRadius: 8, + flexDirection: 'row', + alignSelf: 'auto', + flexWrap: 'wrap', + position: 'absolute', + bottom: SCREEN_HEIGHT * 0.7, + padding: SCREEN_WIDTH / 40, + }, + footer: { + marginLeft: '50%', + flexDirection: 'column-reverse', + ...Platform.select({ + ios: { + bottom: '20%', + }, + android: { + bottom: '10%', + }, + }), + }, +}); +export default TaggPopup; -- cgit v1.2.3-70-g09d2 From 658bf732e05c183d311b62a52be3729c942c9eb9 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 15 Apr 2021 16:54:01 -0400 Subject: moved update required to component/onboarding --- src/components/onboarding/UpdateRequired.tsx | 84 ++++++++++++++++++++++++++++ src/components/onboarding/index.ts | 1 + src/screens/onboarding/UpdateRequired.tsx | 84 ---------------------------- 3 files changed, 85 insertions(+), 84 deletions(-) create mode 100644 src/components/onboarding/UpdateRequired.tsx delete mode 100644 src/screens/onboarding/UpdateRequired.tsx (limited to 'src') diff --git a/src/components/onboarding/UpdateRequired.tsx b/src/components/onboarding/UpdateRequired.tsx new file mode 100644 index 00000000..93e4e36d --- /dev/null +++ b/src/components/onboarding/UpdateRequired.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import {Image, Linking, Modal, StyleSheet, View} from 'react-native'; +import {Text} from 'react-native-animatable'; +import {CenteredView, TaggSquareButton} from '..'; +import {normalize, SCREEN_WIDTH} from '../../utils'; + +interface UpdateRequiredProps { + visible: boolean; +} + +const UpdateRequired: React.FC = ({visible}) => { + return ( + + + + + Update Required + + You have to update your app to continue using Tagg, please download + the latest version from the app store + + { + Linking.openURL( + 'https://apps.apple.com/us/app/tagg-discover-your-community/id1537853613', + ); + }} + buttonStyle={'normal'} + buttonColor={'purple'} + labelColor={'white'} + labelStyle={styles.button} + /> + + + + ); +}; + +const styles = StyleSheet.create({ + contentContainer: { + marginTop: '20%', + width: SCREEN_WIDTH * 0.9, + backgroundColor: 'white', + borderRadius: 5, + padding: '10%', + alignItems: 'center', + shadowColor: '#000', + shadowOffset: { + width: 0, + height: 2, + }, + shadowOpacity: 0.25, + shadowRadius: 3.84, + elevation: 5, + }, + logo: { + width: normalize(60), + height: normalize(60), + marginBottom: '10%', + }, + header: { + fontSize: normalize(17), + fontWeight: '700', + lineHeight: 20, + marginBottom: '5%', + }, + body: { + fontSize: normalize(13), + color: 'grey', + lineHeight: 20, + textAlign: 'center', + width: SCREEN_WIDTH * 0.8, + marginBottom: '10%', + }, + button: { + fontWeight: '700', + }, +}); + +export default UpdateRequired; diff --git a/src/components/onboarding/index.ts b/src/components/onboarding/index.ts index fdb85090..aad77f96 100644 --- a/src/components/onboarding/index.ts +++ b/src/components/onboarding/index.ts @@ -11,3 +11,4 @@ export {default as SocialMediaLinker} from './SocialMediaLinker'; export {default as LinkSocialMedia} from './LinkSocialMedia'; export {default as MomentCategory} from './MomentCategory'; export {default as UniversitySelection} from './UniversitySelection'; +export {default as UpdateRequired} from './UpdateRequired'; diff --git a/src/screens/onboarding/UpdateRequired.tsx b/src/screens/onboarding/UpdateRequired.tsx deleted file mode 100644 index adf7ba71..00000000 --- a/src/screens/onboarding/UpdateRequired.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import React from 'react'; -import {Image, Linking, Modal, StyleSheet, View} from 'react-native'; -import {Text} from 'react-native-animatable'; -import {CenteredView, TaggSquareButton} from '../../components'; -import {normalize, SCREEN_WIDTH} from '../../utils'; - -interface UpdateRequiredProps { - visible: boolean; -} - -const UpdateRequired: React.FC = ({visible}) => { - return ( - - - - - Update Required - - You have to update your app to continue using Tagg, please download - the latest version from the app store - - { - Linking.openURL( - 'https://apps.apple.com/us/app/tagg-discover-your-community/id1537853613', - ); - }} - buttonStyle={'normal'} - buttonColor={'purple'} - labelColor={'white'} - labelStyle={styles.button} - /> - - - - ); -}; - -const styles = StyleSheet.create({ - contentContainer: { - marginTop: '20%', - width: SCREEN_WIDTH * 0.9, - backgroundColor: 'white', - borderRadius: 5, - padding: '10%', - alignItems: 'center', - shadowColor: '#000', - shadowOffset: { - width: 0, - height: 2, - }, - shadowOpacity: 0.25, - shadowRadius: 3.84, - elevation: 5, - }, - logo: { - width: normalize(60), - height: normalize(60), - marginBottom: '10%', - }, - header: { - fontSize: normalize(17), - fontWeight: '700', - lineHeight: 20, - marginBottom: '5%', - }, - body: { - fontSize: normalize(13), - color: 'grey', - lineHeight: 20, - textAlign: 'center', - width: SCREEN_WIDTH * 0.8, - marginBottom: '10%', - }, - button: { - fontWeight: '700', - }, -}); - -export default UpdateRequired; -- cgit v1.2.3-70-g09d2 From e4a3fb8f1d45a83440454c2eefeea7d312cbe0c5 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 15 Apr 2021 16:55:22 -0400 Subject: cleaned up stack navigators --- src/routes/main/MainStackNavigator.tsx | 14 +++----- src/routes/onboarding/OnboardingStackNavigator.tsx | 40 +++++----------------- src/routes/onboarding/OnboardingStackScreen.tsx | 9 ----- 3 files changed, 12 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/routes/main/MainStackNavigator.tsx b/src/routes/main/MainStackNavigator.tsx index 64ad9198..1f173569 100644 --- a/src/routes/main/MainStackNavigator.tsx +++ b/src/routes/main/MainStackNavigator.tsx @@ -3,13 +3,7 @@ */ import {createStackNavigator} from '@react-navigation/stack'; import {Image} from 'react-native-image-crop-picker'; -import { - CategorySelectionScreenType, - MomentType, - ScreenType, - SearchCategoryType, - UserType, -} from '../../types'; +import {MomentType, ScreenType, SearchCategoryType} from '../../types'; export type MainStackParams = { SuggestedPeople: { @@ -61,11 +55,11 @@ export type MainStackParams = { username: string; }; CategorySelection: { - screenType: CategorySelectionScreenType; - user: UserType; newCustomCategory: string | undefined; }; - CreateCustomCategory: {}; + CreateCustomCategory: { + existingCategories: string[]; + }; Notifications: { screenType: ScreenType; }; diff --git a/src/routes/onboarding/OnboardingStackNavigator.tsx b/src/routes/onboarding/OnboardingStackNavigator.tsx index a51a6c86..7d8a751a 100644 --- a/src/routes/onboarding/OnboardingStackNavigator.tsx +++ b/src/routes/onboarding/OnboardingStackNavigator.tsx @@ -1,41 +1,17 @@ import {createStackNavigator} from '@react-navigation/stack'; -import {TaggPopupType, VerificationScreenType} from '../../types'; +import {VerificationScreenType} from '../../types'; export type OnboardingStackParams = { + InvitationCodeVerification: {userId: string; username: string}; Login: undefined; - WelcomeScreen: undefined; - PasswordResetRequest: undefined; - PasswordReset: {value: string}; - Verification: {id: string; screenType: VerificationScreenType}; - // RegistrationOne: undefined; - // RegistrationTwo: {phone: string}; - // RegistrationThree: { - // firstName: string; - // lastName: string; - // phone: string; - // email: string; - // }; - // Checkpoint: {username: string; userId: string}; - // ProfileOnboarding: {username: string; userId: string}; - // SocialMedia: {username: string; userId: string}; - // CategorySelection: { - // screenType: CategorySelectionScreenType; - // user: UserType; - // newCustomCategory: string | undefined; - // }; - // CreateCustomCategory: { - // screenType: CategorySelectionScreenType; - // user: UserType; - // existingCategories: string[]; - // }; - TaggPopup: { - popupProps: TaggPopupType; - }; OnboardingStepOne: undefined; - PhoneVerification: {firstName: string; lastName: string; phone: string}; - OnboardingStepTwo: {firstName: string; lastName: string; phone: string}; OnboardingStepThree: {userId: string; username: string}; - InvitationCodeVerification: {userId: string; username: string}; + OnboardingStepTwo: {firstName: string; lastName: string; phone: string}; + PasswordReset: {value: string}; + PasswordResetRequest: undefined; + PhoneVerification: {firstName: string; lastName: string; phone: string}; + Verification: {id: string; screenType: VerificationScreenType}; + WelcomeScreen: undefined; }; export const OnboardingStack = createStackNavigator(); diff --git a/src/routes/onboarding/OnboardingStackScreen.tsx b/src/routes/onboarding/OnboardingStackScreen.tsx index 79171efd..5e1de2dd 100644 --- a/src/routes/onboarding/OnboardingStackScreen.tsx +++ b/src/routes/onboarding/OnboardingStackScreen.tsx @@ -1,6 +1,5 @@ import {StackCardInterpolationProps} from '@react-navigation/stack'; import React from 'react'; -import TaggPopup from '../../components/common/TaggPopup'; import { InvitationCodeVerification, Login, @@ -44,14 +43,6 @@ const Onboarding: React.FC = () => { }} /> - Date: Thu, 15 Apr 2021 16:56:10 -0400 Subject: moved CategorySelection and CreateCustomCategory to profile folder --- src/screens/onboarding/CategorySelection.tsx | 348 ------------------------ src/screens/onboarding/CreateCustomCategory.tsx | 123 --------- src/screens/profile/CategorySelection.tsx | 302 ++++++++++++++++++++ src/screens/profile/CreateCustomCategory.tsx | 121 ++++++++ src/screens/profile/index.ts | 2 + 5 files changed, 425 insertions(+), 471 deletions(-) delete mode 100644 src/screens/onboarding/CategorySelection.tsx delete mode 100644 src/screens/onboarding/CreateCustomCategory.tsx create mode 100644 src/screens/profile/CategorySelection.tsx create mode 100644 src/screens/profile/CreateCustomCategory.tsx (limited to 'src') diff --git a/src/screens/onboarding/CategorySelection.tsx b/src/screens/onboarding/CategorySelection.tsx deleted file mode 100644 index ab5ff3be..00000000 --- a/src/screens/onboarding/CategorySelection.tsx +++ /dev/null @@ -1,348 +0,0 @@ -import {RouteProp} from '@react-navigation/native'; -import {StackNavigationProp} from '@react-navigation/stack'; -import React, {useContext, 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 {ChatContext} from '../../App'; -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 {OnboardingStackParams} from '../../routes'; -import {postMomentCategories} from '../../services'; -import { - updateIsOnboardedUser, - updateMomentCategories, -} from '../../store/actions/'; -import {RootState} from '../../store/rootReducer'; -import {BackgroundGradientType, CategorySelectionScreenType} from '../../types'; -import {getTokenOrLogout, SCREEN_WIDTH, userLogin} from '../../utils'; - -type CategorySelectionRouteProps = RouteProp< - OnboardingStackParams, - 'CategorySelection' ->; - -type CategorySelectionNavigationProps = StackNavigationProp< - OnboardingStackParams, - 'CategorySelection' ->; - -interface CategorySelectionProps { - route: CategorySelectionRouteProps; - navigation: CategorySelectionNavigationProps; -} - -const CategorySelection: React.FC = ({ - route, - navigation, -}) => { - /** - * Same component to be used for category selection while onboarding and while on profile - */ - const {screenType, user} = route.params; - const {chatClient} = useContext(ChatContext); - const isOnBoarding: boolean = - screenType === CategorySelectionScreenType.Onboarding; - const {userId, username} = user; - - // During onboarding this will fail and default to [] - 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(() => { - const newCustomCategory = route.params.newCustomCategory; - if (newCustomCategory) { - setUncommitedCustomCategories([ - ...uncommitedCustomCategories, - newCustomCategory, - ]); - selectedCategories.push(newCustomCategory); - } - }, [route.params?.newCustomCategory]); - - /** - * Show the tutorial if a new user is OnBoarding - */ - useEffect(() => { - if (isOnBoarding) { - navigation.navigate('TaggPopup', { - popupProps: { - messageHeader: 'Category And Moments', - messageBody: - 'Use pictures and videos to share \ndifferent aspects of you', - next: undefined, - }, - }); - } - }, [isOnBoarding]); - - /** - * 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 { - if (isOnBoarding) { - dispatch(updateIsOnboardedUser(true)); - const token = await getTokenOrLogout(dispatch); - await postMomentCategories(selectedCategories, token); - userLogin(dispatch, {userId: userId, username: username}); - } else { - 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 - - {!isOnBoarding && ( - { - navigation.push('CreateCustomCategory', { - screenType, - user, - 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) => ( - - ))} - - - - {isOnBoarding ? 'Login' : '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/onboarding/CreateCustomCategory.tsx b/src/screens/onboarding/CreateCustomCategory.tsx deleted file mode 100644 index eab72c7d..00000000 --- a/src/screens/onboarding/CreateCustomCategory.tsx +++ /dev/null @@ -1,123 +0,0 @@ -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 {OnboardingStackParams} from '../../routes'; -import {BackgroundGradientType} from '../../types'; -import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; - -type CreateCustomCategoryRouteProps = RouteProp< - OnboardingStackParams, - 'CreateCustomCategory' ->; - -type CreateCustomCategoryNavigationProps = StackNavigationProp< - OnboardingStackParams, - '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', { - screenType: route.params.screenType, - user: route.params.user, - 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/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 6352704e91f33442a4e016efefcf3e8ef92fa9bb Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 15 Apr 2021 16:56:41 -0400 Subject: fixed path for UpdateRequired --- src/screens/onboarding/Login.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/screens/onboarding/Login.tsx b/src/screens/onboarding/Login.tsx index 6d9abf82..041fba05 100644 --- a/src/screens/onboarding/Login.tsx +++ b/src/screens/onboarding/Login.tsx @@ -30,7 +30,7 @@ import {fcmService} from '../../services'; import {RootState} from '../../store/rootReducer'; import {BackgroundGradientType, UniversityType} from '../../types'; import {connectChatAccount, normalize, userLogin} from '../../utils'; -import UpdateRequired from './UpdateRequired'; +import UpdateRequired from '../../components/onboarding/UpdateRequired'; type VerificationScreenRouteProp = RouteProp; type VerificationScreenNavigationProp = StackNavigationProp< -- cgit v1.2.3-70-g09d2 From fd72bd92b64a13bccd2cfbd944de078690b0d134 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 15 Apr 2021 16:56:59 -0400 Subject: moved unused files to legacy --- src/screens/onboarding/AddWaitlistUserScreen.tsx | 237 --------- src/screens/onboarding/Checkpoint.tsx | 143 ----- src/screens/onboarding/ProfileOnboarding.tsx | 575 --------------------- src/screens/onboarding/RegistrationOne.tsx | 214 -------- src/screens/onboarding/RegistrationThree.tsx | 365 ------------- src/screens/onboarding/RegistrationTwo.tsx | 278 ---------- src/screens/onboarding/SocialMedia.tsx | 162 ------ src/screens/onboarding/WaitlistSuccessScreen.tsx | 156 ------ src/screens/onboarding/index.ts | 25 +- .../onboarding/legacy/AddWaitlistUserScreen.tsx | 237 +++++++++ src/screens/onboarding/legacy/Checkpoint.tsx | 142 +++++ .../onboarding/legacy/ProfileOnboarding.tsx | 575 +++++++++++++++++++++ src/screens/onboarding/legacy/RegistrationOne.tsx | 211 ++++++++ .../onboarding/legacy/RegistrationThree.tsx | 363 +++++++++++++ src/screens/onboarding/legacy/RegistrationTwo.tsx | 275 ++++++++++ src/screens/onboarding/legacy/SocialMedia.tsx | 161 ++++++ .../onboarding/legacy/WaitlistSuccessScreen.tsx | 156 ++++++ 17 files changed, 2127 insertions(+), 2148 deletions(-) delete mode 100644 src/screens/onboarding/AddWaitlistUserScreen.tsx delete mode 100644 src/screens/onboarding/Checkpoint.tsx delete mode 100644 src/screens/onboarding/ProfileOnboarding.tsx delete mode 100644 src/screens/onboarding/RegistrationOne.tsx delete mode 100644 src/screens/onboarding/RegistrationThree.tsx delete mode 100644 src/screens/onboarding/RegistrationTwo.tsx delete mode 100644 src/screens/onboarding/SocialMedia.tsx delete mode 100644 src/screens/onboarding/WaitlistSuccessScreen.tsx create mode 100644 src/screens/onboarding/legacy/AddWaitlistUserScreen.tsx create mode 100644 src/screens/onboarding/legacy/Checkpoint.tsx create mode 100644 src/screens/onboarding/legacy/ProfileOnboarding.tsx create mode 100644 src/screens/onboarding/legacy/RegistrationOne.tsx create mode 100644 src/screens/onboarding/legacy/RegistrationThree.tsx create mode 100644 src/screens/onboarding/legacy/RegistrationTwo.tsx create mode 100644 src/screens/onboarding/legacy/SocialMedia.tsx create mode 100644 src/screens/onboarding/legacy/WaitlistSuccessScreen.tsx (limited to 'src') diff --git a/src/screens/onboarding/AddWaitlistUserScreen.tsx b/src/screens/onboarding/AddWaitlistUserScreen.tsx deleted file mode 100644 index 489c30f1..00000000 --- a/src/screens/onboarding/AddWaitlistUserScreen.tsx +++ /dev/null @@ -1,237 +0,0 @@ -import {StackNavigationProp} from '@react-navigation/stack'; -import * as React from 'react'; -import { - KeyboardAvoidingView, - Platform, - StatusBar, - StyleSheet, - Text, - TouchableOpacity, - View, -} from 'react-native'; -import { - ArrowButton, - Background, - LoadingIndicator, - TaggInput, -} from '../../components'; -import {nameRegex, phoneRegex} from '../../constants'; -import {OnboardingStackParams} from '../../routes'; -import {adduserToWaitlist} from '../../services'; -import {BackgroundGradientType} from '../../types'; -import {SCREEN_HEIGHT} from '../../utils'; - -type AddWaitlistUserScreenProp = StackNavigationProp< - OnboardingStackParams, - 'AddWaitlistUser' ->; - -interface AddWaitlistUserScreenProps { - navigation: AddWaitlistUserScreenProp; -} - -const AddWaitlistUserScreen: React.FC = ({ - navigation, -}) => { - const phoneRef = React.useRef(); - const lnameRef = React.useRef(); - - const [form, setForm] = React.useState({ - phone_number: {value: '', isValid: false}, - first_name: {value: '', isValid: false}, - last_name: {value: '', isValid: false}, - attemptedSubmit: false, - }); - - //Handlers - const handleFocusChange = (field: string): void => { - switch (field) { - case 'last_name': - const lnameField: any = lnameRef.current; - lnameField.focus(); - break; - case 'phone_number': - const phoneField: any = phoneRef.current; - phoneField.focus(); - break; - default: - return; - } - }; - - const validate = (value: string, type: string) => { - let isValid: boolean = false; - switch (type) { - case 'phone_number': - isValid = phoneRegex.test(value); - break; - default: - isValid = nameRegex.test(value); - break; - } - return isValid; - }; - - const handleUpdate = (value: string, type: string) => { - value = value.trim(); - const isValid = validate(value, type); - setForm({ - ...form, - [type]: {value, isValid}, - }); - }; - - const handleAddUser = async () => { - if (!form.attemptedSubmit) { - setForm({ - ...form, - attemptedSubmit: true, - }); - } - try { - const {phone_number, first_name, last_name} = form; - if (phone_number.isValid && first_name.isValid && last_name.isValid) { - const success = await adduserToWaitlist( - phone_number.value, - first_name.value, - last_name.value, - ); - if (success) { - navigation.navigate('WaitlistSuccess'); - } - } else { - setForm({...form, attemptedSubmit: false}); - setTimeout(() => setForm({...form, attemptedSubmit: true})); - } - } catch (err) { - console.log(err); - } - }; - - //Components - const Footer = () => ( - - navigation.navigate('InvitationCodeVerification')} - /> - - ); - - const {phone_number, first_name, last_name} = form; - - return ( - - - - - JOIN WAITLIST - - handleUpdate(text, 'first_name')} - onSubmitEditing={() => handleFocusChange('first_name')} - blurOnSubmit={false} - valid={first_name.isValid} - invalidWarning="Please enter a valid first name." - attemptedSubmit={form.attemptedSubmit} - width={280} - /> - handleUpdate(text, 'last_name')} - blurOnSubmit={false} - ref={lnameRef} - valid={last_name.isValid} - invalidWarning="Please enter a valid last name." - onSubmitEditing={() => handleFocusChange('phone_number')} - attemptedSubmit={form.attemptedSubmit} - width={280} - /> - handleUpdate(text, 'phone_number')} - blurOnSubmit={false} - ref={phoneRef} - valid={phone_number.isValid} - invalidWarning="Please enter a valid 10 digit number." - onSubmitEditing={handleAddUser} - attemptedSubmit={form.attemptedSubmit} - width={280} - /> - - Submit - - - -