diff options
author | Ivan Chen <ivan@tagg.id> | 2021-04-21 15:43:03 -0400 |
---|---|---|
committer | Ivan Chen <ivan@tagg.id> | 2021-04-21 15:43:03 -0400 |
commit | 0dd0a4ac4343df036a1f16cbde070c524405bd21 (patch) | |
tree | 292a30ce0228560720214645805deb4b89f2eeae /src | |
parent | 5c438df5f6787cdc6c393873a98590cc827667b9 (diff) | |
parent | 4e8e1c0d58424e6b63cfb8470fc0a73c0e6b102b (diff) |
Merge branch 'master' into hotfix-linting-fixup
# Conflicts:
# .eslintrc.js
# src/components/notifications/Notification.tsx
# src/screens/onboarding/legacy/SocialMedia.tsx
# src/screens/onboarding/legacy/WaitlistSuccessScreen.tsx
# src/screens/profile/CategorySelection.tsx
Diffstat (limited to 'src')
50 files changed, 458 insertions, 439 deletions
diff --git a/src/assets/icons/messages/delivered_icon.png b/src/assets/icons/messages/delivered_icon.png Binary files differnew file mode 100644 index 00000000..0afa7e90 --- /dev/null +++ b/src/assets/icons/messages/delivered_icon.png diff --git a/src/assets/icons/messages/read_icon.png b/src/assets/icons/messages/read_icon.png Binary files differnew file mode 100644 index 00000000..a82b705d --- /dev/null +++ b/src/assets/icons/messages/read_icon.png diff --git a/src/assets/icons/messages/sent_icon.png b/src/assets/icons/messages/sent_icon.png Binary files differnew file mode 100644 index 00000000..55988c78 --- /dev/null +++ b/src/assets/icons/messages/sent_icon.png 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<PostCarouselProps> = ({ activeDotIndex={currentPage} dotsLength={data.length} containerStyle={{marginBottom: marginBottom}} - dotColor={'#6ee7e7'} + dotColor={TAGG_LIGHT_BLUE_2} inactiveDotColor={'#e0e0e0'} /> </> 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/components/friends/InviteFriendTile.tsx b/src/components/friends/InviteFriendTile.tsx index 95ebf16a..5237389a 100644 --- a/src/components/friends/InviteFriendTile.tsx +++ b/src/components/friends/InviteFriendTile.tsx @@ -8,25 +8,37 @@ import { View, } from 'react-native'; import {TAGG_LIGHT_BLUE} from '../../constants'; -import {ERROR_SOMETHING_WENT_WRONG} from '../../constants/strings'; +import { + ERROR_NO_CONTACT_INVITE_LEFT, + ERROR_SOMETHING_WENT_WRONG, + SUCCESS_INVITE_CONTACT, + SUCCESS_LAST_CONTACT_INVITE, +} from '../../constants/strings'; +import {InviteContactType} from '../../screens/profile/InviteFriendsScreen'; import {inviteFriendService} from '../../services'; import {normalize} from '../../utils'; interface InviteFriendTileProps { - item: Object; + item: InviteContactType; } const InviteFriendTile: React.FC<InviteFriendTileProps> = ({item}) => { const [invited, setInvited] = useState<boolean>(false); const [formatedPhoneNumber, setFormattedPhoneNumber] = useState<string>(''); const handleInviteFriend = async () => { - const response = await inviteFriendService( + const invites_left = await inviteFriendService( item.phoneNumber, item.firstName, item.lastName, ); - if (response) { - setInvited(response); + if (invites_left > 0) { + setInvited(true); + Alert.alert(SUCCESS_INVITE_CONTACT(invites_left)); + } else if (invites_left === 0) { + setInvited(true); + Alert.alert(SUCCESS_LAST_CONTACT_INVITE); + } else if (invites_left === -1) { + Alert.alert(ERROR_NO_CONTACT_INVITE_LEFT); } else { Alert.alert(ERROR_SOMETHING_WENT_WRONG); } 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/messages/DateHeader.tsx b/src/components/messages/DateHeader.tsx new file mode 100644 index 00000000..cc7dce2c --- /dev/null +++ b/src/components/messages/DateHeader.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import {View, Text, StyleSheet} from 'react-native'; +import {getFormatedDate, normalize} from '../../utils'; + +interface DateHeaderProps { + date: object; +} + +const DateHeader: React.FC<DateHeaderProps> = ({date}) => { + return ( + <View style={styles.dateContainer}> + <Text style={styles.dateHeader}>{getFormatedDate(date)}</Text> + </View> + ); +}; + +const styles = StyleSheet.create({ + dateHeader: { + color: '#7A7A7A', + fontWeight: '600', + fontSize: normalize(11), + textAlign: 'center', + marginVertical: '5%', + }, + dateContainer: {backgroundColor: 'transparent'}, +}); + +export default DateHeader; diff --git a/src/components/messages/MessageFooter.tsx b/src/components/messages/MessageFooter.tsx new file mode 100644 index 00000000..2ed8c6ed --- /dev/null +++ b/src/components/messages/MessageFooter.tsx @@ -0,0 +1,75 @@ +import moment from 'moment'; +import React from 'react'; +import {normalize} from '../../utils'; +import {useMessageContext} from 'stream-chat-react-native-core'; +import {View, Text, Image, StyleSheet} from 'react-native'; + +const MessageFooter: React.FC = () => { + const message = useMessageContext(); + + if (message.message.type === 'deleted') { + return <></>; + } else { + const printTime = moment(message.message.created_at).format('h:mmA'); + if (message.lastGroupMessage) { + return ( + <View + style={[ + message.isMyMessage ? styles.userMessage : styles.userXMessage, + styles.generalMessage, + ]}> + {readReceipts(message)} + <Text style={styles.time}>{printTime}</Text> + </View> + ); + } else { + return <></>; + } + } +}; + +const readReceipts = (message) => { + const readByLocal = message.message.readBy; + if (message.isMyMessage) { + if (readByLocal) { + return ( + <Image + source={require('../../assets/icons/messages/read_icon.png')} + style={styles.icon} + /> + ); + } else if (message.message.status === 'received') { + return ( + <Image + source={require('../../assets/icons/messages/delivered_icon.png')} + style={styles.icon} + /> + ); + } else if (message.message.status === 'sending') { + return ( + <Image + source={require('../../assets/icons/messages/sent_icon.png')} + style={styles.icon} + /> + ); + } else { + return <></>; + } + } +}; + +export const styles = StyleSheet.create({ + time: { + fontSize: normalize(11), + color: '#7A7A7A', + lineHeight: normalize(13), + }, + userMessage: { + marginRight: 5, + }, + userXMessage: {marginLeft: 5}, + generalMessage: {marginTop: 4, flexDirection: 'row'}, + icon: {width: 15, height: 15}, +}); + +export default MessageFooter; diff --git a/src/components/messages/index.ts b/src/components/messages/index.ts index d08e9454..b19067ca 100644 --- a/src/components/messages/index.ts +++ b/src/components/messages/index.ts @@ -5,3 +5,5 @@ export {default as ChatHeader} from './ChatHeader'; export {default as ChatInputSubmit} from './ChatInputSubmit'; export {default as MessageAvatar} from './MessageAvatar'; export {default as TypingIndicator} from './TypingIndicator'; +export {default as MessageFooter} from './MessageFooter'; +export {default as DateHeader} from './DateHeader'; diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx index 87309c53..3cc1c7f1 100644 --- a/src/components/notifications/Notification.tsx +++ b/src/components/notifications/Notification.tsx @@ -208,6 +208,9 @@ const Notification: React.FC<NotificationProps> = (props) => { const isOwnProfile = id === loggedInUser.userId; const navigateToProfile = async () => { + if (notification_type === 'SYSTEM_MSG') { + return; + } if (!userXInStore(state, screenType, id)) { await fetchUserX(dispatch, {userId: id, username: username}, screenType); } @@ -231,34 +234,47 @@ const Notification: React.FC<NotificationProps> = (props) => { } /> </TouchableWithoutFeedback> - <View style={styles.contentContainer}> - <TouchableWithoutFeedback onPress={navigateToProfile}> - <Text style={styles.actorName}> - {first_name} {last_name} - </Text> - </TouchableWithoutFeedback> - <TouchableWithoutFeedback onPress={onNotificationTap}> - <Text>{verbage}</Text> - </TouchableWithoutFeedback> - </View> - {notification_type === 'FRD_REQ' && ( - <View style={styles.buttonsContainer}> - <AcceptDeclineButtons - onAccept={handleAcceptRequest} - onReject={handleDeclineFriendRequest} - /> + {notification_type === 'SYSTEM_MSG' ? ( + // Only verbage + <View style={styles.contentContainer}> + <Text style={styles.actorName}>{verbage}</Text> </View> + ) : ( + <> + {/* Text content: Actor name and verbage*/} + <View style={styles.contentContainer}> + <TouchableWithoutFeedback onPress={navigateToProfile}> + <Text style={styles.actorName}> + {first_name} {last_name} + </Text> + </TouchableWithoutFeedback> + <TouchableWithoutFeedback onPress={onNotificationTap}> + <Text>{verbage}</Text> + </TouchableWithoutFeedback> + </View> + {/* Friend request accept/decline button */} + {notification_type === 'FRD_REQ' && ( + <View style={styles.buttonsContainer}> + <AcceptDeclineButtons + requester={{id, username, first_name, last_name}} + onAccept={handleAcceptRequest} + onReject={handleDeclineFriendRequest} + /> + </View> + )} + {/* Moment Image Preview */} + {(notification_type === 'CMT' || + notification_type === 'MOM_3+' || + notification_type === 'MOM_FRIEND') && + notification_object && ( + <TouchableWithoutFeedback + style={styles.moment} + onPress={onNotificationTap}> + <Image style={styles.imageFlex} source={{uri: momentURI}} /> + </TouchableWithoutFeedback> + )} + </> )} - {(notification_type === 'CMT' || - notification_type === 'MOM_3+' || - notification_type === 'MOM_FRIEND') && - notification_object && ( - <TouchableWithoutFeedback - style={styles.moment} - onPress={onNotificationTap}> - <Image style={styles.imageFlex} source={{uri: momentURI}} /> - </TouchableWithoutFeedback> - )} </View> ); diff --git a/src/screens/onboarding/UpdateRequired.tsx b/src/components/onboarding/UpdateRequired.tsx index adf7ba71..93e4e36d 100644 --- a/src/screens/onboarding/UpdateRequired.tsx +++ b/src/components/onboarding/UpdateRequired.tsx @@ -1,7 +1,7 @@ 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 {CenteredView, TaggSquareButton} from '..'; import {normalize, SCREEN_WIDTH} from '../../utils'; interface UpdateRequiredProps { 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/components/profile/PublicProfile.tsx b/src/components/profile/PublicProfile.tsx index 1c49bff5..d2ee8626 100644 --- a/src/components/profile/PublicProfile.tsx +++ b/src/components/profile/PublicProfile.tsx @@ -243,8 +243,7 @@ const PublicProfile: React.FC<ContentProps> = ({ <TouchableOpacity onPress={() => navigation.navigate('CategorySelection', { - screenType: CategorySelectionScreenType.Profile, - user: loggedInUser, + newCustomCategory: undefined, }) } style={styles.createCategoryButton}> @@ -258,10 +257,6 @@ const PublicProfile: React.FC<ContentProps> = ({ }; const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#fff', - }, momentsContainer: { backgroundColor: '#f2f2f2', paddingBottom: SCREEN_HEIGHT * 0.15, 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/constants/api.ts b/src/constants/api.ts index cb45b238..dd934f0e 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -16,6 +16,7 @@ export const EDIT_PROFILE_ENDPOINT: string = API_URL + 'edit-profile/'; export const SEND_OTP_ENDPOINT: string = API_URL + 'send-otp/'; export const VERIFY_OTP_ENDPOINT: string = API_URL + 'verify-otp/'; export const USER_PROFILE_ENDPOINT: string = API_URL + 'profile/'; +export const USER_PROFILE_VISITED_ENDPOINT: string = API_URL + 'profile/visited/'; export const PROFILE_INFO_ENDPOINT: string = API_URL + 'user-profile-info/'; export const HEADER_PHOTO_ENDPOINT: string = API_URL + 'header-pic/'; export const PROFILE_PHOTO_ENDPOINT: string = API_URL + 'profile-pic/'; diff --git a/src/constants/strings.ts b/src/constants/strings.ts index bdb94fba..50e4518b 100644 --- a/src/constants/strings.ts +++ b/src/constants/strings.ts @@ -30,6 +30,7 @@ export const ERROR_LINK = (str: string) => `Unable to link with ${str}, Please c export const ERROR_LOGIN = 'There was a problem logging you in, please refresh and try again'; export const ERROR_LOGIN_FAILED = 'Login failed. Check your username and password, and try again'; export const ERROR_NEXT_PAGE = 'There was a problem while loading the next page 😓, try again in a couple minutes'; +export const ERROR_NO_CONTACT_INVITE_LEFT = 'You have no more invites left!' export const ERROR_NOT_ONBOARDED = 'You are now on waitlist, please enter your invitation code if you have one'; export const ERROR_PHONE_IN_USE = 'Phone already in use, please try another one'; export const ERROR_PROFILE_CREATION_SHORT = 'Profile creation failed 😓'; @@ -62,7 +63,9 @@ export const NO_RESULTS_FOUND = 'No Results Found!'; export const PRIVATE_ACCOUNT = 'This account is private'; export const SUCCESS_BADGES_UPDATE = 'Badges updated successfully!' export const SUCCESS_CATEGORY_DELETE = 'Category successfully deleted, but its memory will live on'; +export const SUCCESS_LAST_CONTACT_INVITE = 'Done! That was your last invite, hope you used it wisely!'; export const SUCCESS_INVITATION_CODE = 'Welcome to Tagg!'; +export const SUCCESS_INVITE_CONTACT = (str: string) => `Success! You now have ${str} invites left!`; export const SUCCESS_LINK = (str: string) => `Successfully linked ${str} 🎉`; export const SUCCESS_PIC_UPLOAD = 'Beautiful, the picture was uploaded successfully!'; export const SUCCESS_PWD_RESET = 'Your password was reset successfully!'; 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..4726a47d 100644 --- a/src/routes/onboarding/OnboardingStackNavigator.tsx +++ b/src/routes/onboarding/OnboardingStackNavigator.tsx @@ -1,41 +1,16 @@ import {createStackNavigator} from '@react-navigation/stack'; -import {TaggPopupType, 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; + PasswordVerification: {id: string}; + PhoneVerification: {firstName: string; lastName: string; phone: string}; + WelcomeScreen: undefined; }; export const OnboardingStack = createStackNavigator<OnboardingStackParams>(); diff --git a/src/routes/onboarding/OnboardingStackScreen.tsx b/src/routes/onboarding/OnboardingStackScreen.tsx index 79171efd..339c3d0d 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, @@ -8,8 +7,8 @@ import { OnboardingStepTwo, PasswordReset, PasswordResetRequest, + PasswordVerification, PhoneVerification, - Verification, WelcomeScreen, } from '../../screens'; import OnboardingStepOne from '../../screens/onboarding/OnboardingStepOne'; @@ -45,14 +44,6 @@ const Onboarding: React.FC = () => { /> <OnboardingStack.Screen name="WelcomeScreen" component={WelcomeScreen} /> <OnboardingStack.Screen - name="TaggPopup" - component={TaggPopup} - options={{ - gestureEnabled: false, - ...modalStyle, - }} - /> - <OnboardingStack.Screen name="PasswordReset" component={PasswordReset} options={{ @@ -61,8 +52,8 @@ const Onboarding: React.FC = () => { }} /> <OnboardingStack.Screen - name="Verification" - component={Verification} + name="PasswordVerification" + component={PasswordVerification} options={{ ...modalStyle, }} diff --git a/src/screens/badge/BadgeSelection.tsx b/src/screens/badge/BadgeSelection.tsx index 640a9ea1..91617377 100644 --- a/src/screens/badge/BadgeSelection.tsx +++ b/src/screens/badge/BadgeSelection.tsx @@ -66,13 +66,16 @@ const BadgeSelection: React.FC<BadgeSelectionProps> = ({route}) => { style={styles.rightButtonContainer} onPress={async () => { if (editing) { - updateBadgesService(selectedBadges); + updateBadgesService(selectedBadges, university); navigation.navigate('UpdateSPPicture', { editing: true, }); } else { if (selectedBadges.length !== 0) { - const success = await addBadgesService(selectedBadges); + const success = await addBadgesService( + selectedBadges, + university, + ); if (success) { dispatch(suggestedPeopleBadgesFinished()); navigation.navigate('SuggestedPeople'); diff --git a/src/screens/chat/ChatScreen.tsx b/src/screens/chat/ChatScreen.tsx index 656c1c47..57f2232e 100644 --- a/src/screens/chat/ChatScreen.tsx +++ b/src/screens/chat/ChatScreen.tsx @@ -16,7 +16,9 @@ import {ChatContext} from '../../App'; import { ChatHeader, ChatInput, + DateHeader, MessageAvatar, + MessageFooter, TabsGradient, TypingIndicator, } from '../../components'; @@ -37,6 +39,9 @@ const ChatScreen: React.FC<ChatScreenProps> = () => { const {setTopInset} = useAttachmentPickerContext(); const insets = useSafeAreaInsets(); const chatTheme: DeepPartial<Theme> = { + colors: { + accent_blue: '#6EE7E7', + }, messageList: { container: { backgroundColor: 'white', @@ -70,6 +75,24 @@ const ChatScreen: React.FC<ChatScreenProps> = () => { flexDirection: 'row', }, content: { + deletedContainer: {}, + deletedContainerInner: { + borderColor: 'transparent', + borderBottomLeftRadius: 10, + borderTopLeftRadius: 10, + borderBottomRightRadius: 10, + borderTopRightRadius: 10, + }, + deletedMetaText: { + paddingHorizontal: 10, + }, + deletedText: { + em: { + fontSize: 15, + fontStyle: 'italic', + fontWeight: '400', + }, + }, metaContainer: { marginLeft: 5, }, @@ -123,6 +146,10 @@ const ChatScreen: React.FC<ChatScreenProps> = () => { copyMessage, deleteMessage, ]} + InlineDateSeparator={DateHeader} + StickyHeader={() => null} + ScrollToBottomButton={() => null} + MessageFooter={MessageFooter} TypingIndicator={TypingIndicator} myMessageTheme={loggedInUsersMessageTheme} MessageAvatar={MessageAvatar}> diff --git a/src/screens/onboarding/InvitationCodeVerification.tsx b/src/screens/onboarding/InvitationCodeVerification.tsx index e160b4b7..d84b2ba2 100644 --- a/src/screens/onboarding/InvitationCodeVerification.tsx +++ b/src/screens/onboarding/InvitationCodeVerification.tsx @@ -198,10 +198,6 @@ const styles = StyleSheet.create({ flexDirection: 'row', justifyContent: 'space-around', }, - noInviteCode: { - flexDirection: 'row', - justifyContent: 'center', - }, youveBeenAddedLabel: { marginVertical: '5%', width: SCREEN_WIDTH * 0.8, @@ -211,11 +207,6 @@ const styles = StyleSheet.create({ fontWeight: '500', marginBottom: '10%', }, - inviteCodeLink: { - color: 'white', - fontSize: 18, - textDecorationLine: 'underline', - }, }); export default InvitationCodeVerification; 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<OnboardingStackParams, 'Login'>; type VerificationScreenNavigationProp = StackNavigationProp< diff --git a/src/screens/onboarding/PasswordResetRequest.tsx b/src/screens/onboarding/PasswordResetRequest.tsx index a63eae81..8a891bbb 100644 --- a/src/screens/onboarding/PasswordResetRequest.tsx +++ b/src/screens/onboarding/PasswordResetRequest.tsx @@ -74,9 +74,8 @@ const PasswordResetRequest: React.FC<PasswordResetRequestProps> = ({ handlePasswordResetRequest(form.value), ); if (success) { - navigation.navigate('Verification', { + navigation.navigate('PasswordVerification', { id: form.value, - screenType: VerificationScreenType.Password, }); } } else { diff --git a/src/screens/onboarding/Verification.tsx b/src/screens/onboarding/PasswordVerification.tsx index dda18364..6bda37a7 100644 --- a/src/screens/onboarding/Verification.tsx +++ b/src/screens/onboarding/PasswordVerification.tsx @@ -21,7 +21,6 @@ import { ArrowButton, Background, LoadingIndicator, - RegistrationWizard, SubmitButton, } from '../../components'; import {codeRegex} from '../../constants'; @@ -33,18 +32,16 @@ import {OnboardingStackParams} from '../../routes'; import { handlePasswordCodeVerification, handlePasswordResetRequest, - sendOtp, - verifyOtp, } from '../../services'; -import {BackgroundGradientType, VerificationScreenType} from '../../types'; +import {BackgroundGradientType} from '../../types'; type VerificationScreenRouteProp = RouteProp< OnboardingStackParams, - 'Verification' + 'PasswordVerification' >; type VerificationScreenNavigationProp = StackNavigationProp< OnboardingStackParams, - 'Verification' + 'PasswordVerification' >; interface VerificationProps { route: VerificationScreenRouteProp; @@ -58,39 +55,16 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => { value, setValue, }); - const {id, screenType} = route.params; - const isPhoneVerification = screenType === VerificationScreenType.Phone; + const {id} = route.params; - const handlePhoneVerification = async () => { - const success = await trackPromise(verifyOtp(id, value)); - if (success) { - navigation.navigate('RegistrationTwo', {phone: id}); - } - }; - - const handlePasswordVerification = async () => { - const success = await trackPromise( - handlePasswordCodeVerification(id, value), - ); - if (success) { - navigation.navigate('PasswordReset', {value: id}); - } - }; - - /** - * Sends the verify_otp request upon tapping the Verify button. - * If successful, it navigates to the respected page. - */ const handleVerification = async () => { if (codeRegex.test(value)) { try { - switch (screenType) { - case VerificationScreenType.Phone: - handlePhoneVerification(); - break; - case VerificationScreenType.Password: - handlePasswordVerification(); - break; + const success = await trackPromise( + handlePasswordCodeVerification(id, value), + ); + if (success) { + navigation.navigate('PasswordReset', {value: id}); } } catch (error) { console.log(error); @@ -106,34 +80,19 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => { */ const handleResend = async () => { try { - switch (screenType) { - case VerificationScreenType.Phone: - trackPromise(sendOtp(id)); - break; - case VerificationScreenType.Password: - trackPromise(handlePasswordResetRequest(id)); - break; - } + trackPromise(handlePasswordResetRequest(id)); } catch (error) { console.log(error); Alert.alert(ERROR_SOMETHING_WENT_WRONG); } }; - const handleGoBack = () => { - switch (screenType) { - case VerificationScreenType.Phone: - navigation.navigate('RegistrationOne'); - break; - case VerificationScreenType.Password: - navigation.navigate('PasswordResetRequest'); - break; - } - }; - const Footer = () => ( <View style={styles.footer}> - <ArrowButton direction="backward" onPress={() => handleGoBack()} /> + <ArrowButton + direction="backward" + onPress={() => navigation.navigate('PasswordResetRequest')} + /> </View> ); @@ -142,16 +101,9 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => { centered style={styles.container} gradientType={BackgroundGradientType.Light}> - {isPhoneVerification ? ( - <RegistrationWizard style={styles.wizard} step="three" /> - ) : ( - <React.Fragment /> - )} <KeyboardAvoidingView behavior="padding" - style={ - isPhoneVerification ? styles.form : styles.formPasswordVerification - }> + style={styles.formPasswordVerification}> <Text style={styles.formHeader}>Enter 6 digit code</Text> <Text style={styles.description}> We sent a 6 digit verification code to the phone number you provided. @@ -200,16 +152,6 @@ const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'center', }, - wizard: { - marginTop: '3.5%', - flex: 1, - justifyContent: 'center', - }, - form: { - alignItems: 'center', - justifyContent: 'flex-start', - flex: 3, - }, formPasswordVerification: { alignItems: 'center', justifyContent: 'flex-start', @@ -261,9 +203,6 @@ const styles = StyleSheet.create({ button: { marginVertical: '5%', }, - loadingIndicator: { - marginVertical: '5%', - }, footer: { width: '100%', flexDirection: 'row', diff --git a/src/screens/onboarding/index.ts b/src/screens/onboarding/index.ts index 49d7cfb9..7eb0587f 100644 --- a/src/screens/onboarding/index.ts +++ b/src/screens/onboarding/index.ts @@ -1,21 +1,10 @@ -export {default as Login} from './Login'; -export {default as RegistrationOne} from './RegistrationOne'; -export {default as RegistrationTwo} from './RegistrationTwo'; -export {default as RegistrationThree} from './RegistrationThree'; -export {default as Verification} from './Verification'; -export {default as Checkpoint} from './Checkpoint'; -export {default as ProfileOnboarding} from './ProfileOnboarding'; export {default as InvitationCodeVerification} from './InvitationCodeVerification'; -export {default as SocialMedia} from './SocialMedia'; -export {default as PasswordResetRequest} from './PasswordResetRequest'; -export {default as PasswordReset} from './PasswordReset'; -export {default as WelcomeScreen} from './WelcomeScreen'; -export {default as CategorySelection} from './CategorySelection'; -export {default as AddWaitlistUserScreen} from './AddWaitlistUserScreen'; -export {default as WaitlistSuccessScreen} from './WaitlistSuccessScreen'; -export {default as CreateCustomCategory} from './CreateCustomCategory'; -export {default as UpdateRequired} from './UpdateRequired'; +export {default as Login} from './Login'; export {default as OnboardingStepOne} from './OnboardingStepOne'; -export {default as PhoneVerification} from './PhoneVerification'; -export {default as OnboardingStepTwo} from './OnboardingStepTwo'; export {default as OnboardingStepThree} from './OnboardingStepThree'; +export {default as OnboardingStepTwo} from './OnboardingStepTwo'; +export {default as PasswordReset} from './PasswordReset'; +export {default as PasswordResetRequest} from './PasswordResetRequest'; +export {default as PhoneVerification} from './PhoneVerification'; +export {default as PasswordVerification} from './PasswordVerification'; +export {default as WelcomeScreen} from './WelcomeScreen'; diff --git a/src/screens/onboarding/AddWaitlistUserScreen.tsx b/src/screens/onboarding/legacy/AddWaitlistUserScreen.tsx index 489c30f1..489c30f1 100644 --- a/src/screens/onboarding/AddWaitlistUserScreen.tsx +++ b/src/screens/onboarding/legacy/AddWaitlistUserScreen.tsx diff --git a/src/screens/onboarding/Checkpoint.tsx b/src/screens/onboarding/legacy/Checkpoint.tsx index b0b42203..93ff0b7f 100644 --- a/src/screens/onboarding/Checkpoint.tsx +++ b/src/screens/onboarding/legacy/Checkpoint.tsx @@ -1,18 +1,17 @@ -import React from 'react'; import {RouteProp} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; +import React from 'react'; import { - View, - Text, - StyleSheet, - StatusBar, Platform, + StatusBar, + StyleSheet, + Text, TouchableOpacity, + View, } from 'react-native'; - -import {OnboardingStackParams} from '../../routes'; -import {RegistrationWizard, Background} from '../../components'; -import {BackgroundGradientType} from '../../types'; +import {Background, RegistrationWizard} from '../../../components'; +import {OnboardingStackParams} from '../../../routes'; +import {BackgroundGradientType} from '../../../types'; type CheckpointRouteProp = RouteProp<OnboardingStackParams, 'Checkpoint'>; type CheckpointNavigationProp = StackNavigationProp< diff --git a/src/screens/onboarding/ProfileOnboarding.tsx b/src/screens/onboarding/legacy/ProfileOnboarding.tsx index 03ca858e..e994c1e6 100644 --- a/src/screens/onboarding/ProfileOnboarding.tsx +++ b/src/screens/onboarding/legacy/ProfileOnboarding.tsx @@ -20,7 +20,7 @@ import { TaggBigInput, TaggDropDown, TaggInput, -} from '../../components'; +} from '../../../components'; import { bioRegex, CLASS_YEAR_LIST, @@ -28,7 +28,7 @@ import { genderRegex, TAGG_PURPLE, websiteRegex, -} from '../../constants'; +} from '../../../constants'; import { ERROR_DOUBLE_CHECK_CONNECTION, ERROR_PROFILE_CREATION_SHORT, @@ -36,10 +36,10 @@ import { ERROR_SOMETHING_WENT_WRONG_REFRESH, ERROR_UPLOAD_LARGE_PROFILE_PIC, ERROR_UPLOAD_SMALL_PROFILE_PIC, -} from '../../constants/strings'; -import {OnboardingStackParams} from '../../routes/onboarding'; -import {BackgroundGradientType} from '../../types'; -import {SCREEN_WIDTH} from '../../utils'; +} from '../../../constants/strings'; +import {OnboardingStackParams} from '../../../routes/onboarding'; +import {BackgroundGradientType} from '../../../types'; +import {SCREEN_WIDTH} from '../../../utils'; type ProfileOnboardingScreenRouteProp = RouteProp< OnboardingStackParams, diff --git a/src/screens/onboarding/RegistrationOne.tsx b/src/screens/onboarding/legacy/RegistrationOne.tsx index c9822f76..4bcc2720 100644 --- a/src/screens/onboarding/RegistrationOne.tsx +++ b/src/screens/onboarding/legacy/RegistrationOne.tsx @@ -1,34 +1,31 @@ -import React, {useState, useRef} from 'react'; import {RouteProp} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; +import React, {useRef, useState} from 'react'; import { - View, - Text, - StyleSheet, - StatusBar, Alert, + KeyboardAvoidingView, Platform, + StatusBar, + StyleSheet, + Text, TouchableOpacity, - KeyboardAvoidingView, + View, } from 'react-native'; - -import {OnboardingStackParams} from '../../routes'; - +import {trackPromise} from 'react-promise-tracker'; import { ArrowButton, - RegistrationWizard, - TaggInput, Background, LoadingIndicator, -} from '../../components'; - -import {trackPromise} from 'react-promise-tracker'; - -import {SEND_OTP_ENDPOINT} from '../../constants'; - -import {phoneRegex} from '../../constants'; -import {BackgroundGradientType, VerificationScreenType} from '../../types'; -import {ERROR_EMAIL_IN_USE, ERROR_SERVER_DOWN} from '../../constants/strings'; + RegistrationWizard, + TaggInput, +} from '../../../components'; +import {phoneRegex, SEND_OTP_ENDPOINT} from '../../../constants'; +import { + ERROR_EMAIL_IN_USE, + ERROR_SERVER_DOWN, +} from '../../../constants/strings'; +import {OnboardingStackParams} from '../../../routes'; +import {BackgroundGradientType, VerificationScreenType} from '../../../types'; type RegistrationScreenOneRouteProp = RouteProp< OnboardingStackParams, diff --git a/src/screens/onboarding/RegistrationThree.tsx b/src/screens/onboarding/legacy/RegistrationThree.tsx index 1f4266ff..1f4266ff 100644 --- a/src/screens/onboarding/RegistrationThree.tsx +++ b/src/screens/onboarding/legacy/RegistrationThree.tsx diff --git a/src/screens/onboarding/RegistrationTwo.tsx b/src/screens/onboarding/legacy/RegistrationTwo.tsx index 6d7b2226..2dd86f90 100644 --- a/src/screens/onboarding/RegistrationTwo.tsx +++ b/src/screens/onboarding/legacy/RegistrationTwo.tsx @@ -1,29 +1,26 @@ -import React, {useState, useRef} from 'react'; import {RouteProp} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; +import React, {useRef, useState} from 'react'; import { - View, - Text, - StyleSheet, - StatusBar, Alert, + KeyboardAvoidingView, Platform, + StatusBar, + StyleSheet, + Text, TouchableOpacity, - KeyboardAvoidingView, + View, } from 'react-native'; - -import {OnboardingStackParams} from '../../routes'; - import { ArrowButton, + Background, RegistrationWizard, TaggInput, - Background, } from '../../components'; - -import {nameRegex, emailRegex} from '../../constants'; -import {BackgroundGradientType} from '../../types'; +import {emailRegex, nameRegex} from '../../constants'; import {ERROR_NEXT_PAGE} from '../../constants/strings'; +import {OnboardingStackParams} from '../../routes'; +import {BackgroundGradientType} from '../../types'; type RegistrationScreenTwoRouteProp = RouteProp< OnboardingStackParams, diff --git a/src/screens/onboarding/SocialMedia.tsx b/src/screens/onboarding/legacy/SocialMedia.tsx index 0ded7d3e..c1edef00 100644 --- a/src/screens/onboarding/SocialMedia.tsx +++ b/src/screens/onboarding/legacy/SocialMedia.tsx @@ -1,5 +1,5 @@ -import {RouteProp} from '@react-navigation/native'; -import {StackNavigationProp} from '@react-navigation/stack'; +import { RouteProp } from '@react-navigation/native'; +import { StackNavigationProp } from '@react-navigation/stack'; import React from 'react'; import { KeyboardAvoidingView, @@ -8,20 +8,20 @@ import { StyleSheet, Text, TouchableOpacity, - View, + View } from 'react-native'; import { - BackgroundGradientType, - CategorySelectionScreenType, - LinkerType, -} from '../..//types'; -import { Background, LinkSocialMedia, - RegistrationWizard, -} from '../../components'; -import {SOCIAL_LIST} from '../../constants/'; -import {OnboardingStackParams} from '../../routes'; + RegistrationWizard +} from '../../../components'; +import { SOCIAL_LIST } from '../../../constants'; +import { OnboardingStackParams } from '../../../routes'; +import { + BackgroundGradientType, + CategorySelectionScreenType, + LinkerType +} from '../../../types'; /** * Social Media Screen for displaying social media linkers diff --git a/src/components/common/TaggPopup.tsx b/src/screens/onboarding/legacy/TaggPopup.tsx index f9929580..e71a4d2a 100644 --- a/src/components/common/TaggPopup.tsx +++ b/src/screens/onboarding/legacy/TaggPopup.tsx @@ -1,13 +1,13 @@ +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, Text, StyleSheet, TouchableOpacity} from 'react-native'; +import {Platform, StyleSheet, Text, 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'; +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<OnboardingStackParams, 'TaggPopup'>; type TaggPopupNavigationProps = StackNavigationProp< @@ -41,7 +41,7 @@ const TaggPopup: React.FC<TaggPopupProps> = ({route, navigation}) => { <View style={styles.popup}> <Image style={styles.icon} - source={require('../../assets/icons/notificationPrompts/plus-logo.png')} + source={require('../../../assets/icons/notificationPrompts/plus-logo.png')} /> <View style={styles.textContainer}> <Text style={styles.header}>{messageHeader}</Text> diff --git a/src/screens/onboarding/WaitlistSuccessScreen.tsx b/src/screens/onboarding/legacy/WaitlistSuccessScreen.tsx index f21672f1..39e3b3b9 100644 --- a/src/screens/onboarding/WaitlistSuccessScreen.tsx +++ b/src/screens/onboarding/legacy/WaitlistSuccessScreen.tsx @@ -1,5 +1,5 @@ -import {StackNavigationProp} from '@react-navigation/stack'; -import * as React from 'react'; +import { StackNavigationProp } from '@react-navigation/stack'; +import React from 'react'; import { KeyboardAvoidingView, Linking, @@ -8,14 +8,14 @@ import { StyleSheet, Text, TouchableOpacity, - View, + View } from 'react-native'; +import { ArrowButton, Background } from '../../../components'; +import { TAGG_WEBSITE } from '../../../constants'; +import { OnboardingStackParams } from '../../../routes'; +import { BackgroundGradientType } from '../../../types'; +import { SCREEN_HEIGHT } from '../../../utils'; import CelebrationLogo from '../../assets/icons/celebration-logo.svg'; -import {ArrowButton, Background} from '../../components'; -import {TAGG_WEBSITE} from '../../constants'; -import {OnboardingStackParams} from '../../routes'; -import {BackgroundGradientType} from '../../types'; -import {SCREEN_HEIGHT} from '../../utils'; type WaitlistSuccessScreenProp = StackNavigationProp< OnboardingStackParams, 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 && ( <Switch - trackColor={{false: 'red', true: '#6EE7E7'}} + trackColor={{false: 'red', true: TAGG_LIGHT_BLUE_2}} thumbColor={'white'} ios_backgroundColor="transparent" style={styles.switchStyles} diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx index c039b8cb..156ee41c 100644 --- a/src/screens/profile/CaptionScreen.tsx +++ b/src/screens/profile/CaptionScreen.tsx @@ -13,11 +13,12 @@ import { } from 'react-native'; import {Button} from 'react-native-elements'; import {useDispatch, useSelector} from 'react-redux'; -import {MainStackParams} from '../../routes'; import {SearchBackground, TaggBigInput} from '../../components'; import {CaptionScreenHeader} from '../../components/'; import TaggLoadingIndicator from '../../components/common/TaggLoadingIndicator'; +import {TAGG_LIGHT_BLUE_2} from '../../constants'; import {ERROR_UPLOAD, SUCCESS_PIC_UPLOAD} from '../../constants/strings'; +import {MainStackParams} from '../../routes'; import {postMoment} from '../../services'; import { loadUserMoments, @@ -140,7 +141,7 @@ const styles = StyleSheet.create({ }, shareButtonTitle: { fontWeight: 'bold', - color: '#6EE7E7', + color: TAGG_LIGHT_BLUE_2, }, header: { marginVertical: 20, diff --git a/src/screens/onboarding/CategorySelection.tsx b/src/screens/profile/CategorySelection.tsx index 9d5fbe4d..c02eef0d 100644 --- a/src/screens/onboarding/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,25 +13,21 @@ 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 {OnboardingStackParams} from '../../routes'; -import {postMomentCategories} from '../../services'; -import { - updateIsOnboardedUser, - updateMomentCategories, -} from '../../store/actions/'; +import {MainStackParams} from '../../routes'; +import {updateMomentCategories} from '../../store/actions'; import {RootState} from '../../store/rootReducer'; -import {BackgroundGradientType, CategorySelectionScreenType} from '../../types'; -import {getTokenOrLogout, SCREEN_WIDTH, userLogin} from '../../utils'; +import {BackgroundGradientType} from '../../types'; +import {normalize, SCREEN_WIDTH} from '../../utils'; type CategorySelectionRouteProps = RouteProp< - OnboardingStackParams, + MainStackParams, 'CategorySelection' >; type CategorySelectionNavigationProps = StackNavigationProp< - OnboardingStackParams, + MainStackParams, 'CategorySelection' >; @@ -45,15 +40,8 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({ route, navigation, }) => { - /** - * Same component to be used for category selection while onboarding and while on profile - */ - const {screenType, user} = route.params; - const isOnBoarding: boolean = - screenType === CategorySelectionScreenType.Onboarding; - const {userId, username} = user; - - // During onboarding this will fail and default to [] + const dispatch = useDispatch(); + const {newCustomCategory} = route.params; const {momentCategories = []} = useSelector( (state: RootState) => state.momentCategories, ); @@ -76,10 +64,15 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({ (mc) => !MOMENT_CATEGORIES.includes(mc), ); - const dispatch = useDispatch(); + navigation.setOptions({ + headerRight: () => ( + <TouchableOpacity onPress={handleButtonPress}> + <Text style={styles.createLabel}>Create</Text> + </TouchableOpacity> + ), + }); useEffect(() => { - const newCustomCategory = route.params.newCustomCategory; if (newCustomCategory) { setUncommitedCustomCategories([ ...uncommitedCustomCategories, @@ -87,23 +80,7 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({ ]); 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]); + }, [newCustomCategory]); /** * Handle selection of a new category @@ -164,20 +141,13 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({ 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(); - } + dispatch( + updateMomentCategories( + momentCategories.concat(selectedCategories), + true, + ), + ); + navigation.goBack(); } catch (error) { console.log(error); Alert.alert(ERROR_SOMETHING_WENT_WRONG); @@ -195,24 +165,18 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({ <StatusBar barStyle="light-content" /> <Text style={styles.subtext}>Create Categories</Text> <View style={styles.container}> - {!isOnBoarding && ( - <TouchableOpacity - style={styles.createCategory} - onPress={() => { - navigation.push('CreateCustomCategory', { - screenType, - user, - existingCategories: momentCategories.concat( - selectedCategories, - ), - }); - }}> - <PlusIcon width={30} height={30} color="white" /> - <Text style={styles.createCategoryLabel}> - Create your own category - </Text> - </TouchableOpacity> - )} + <TouchableOpacity + style={styles.createCategory} + onPress={() => { + navigation.push('CreateCustomCategory', { + existingCategories: momentCategories.concat(selectedCategories), + }); + }}> + <PlusIcon width={30} height={30} color="white" /> + <Text style={styles.createCategoryLabel}> + Create your own category + </Text> + </TouchableOpacity> <View style={styles.linkerContainer}> {/* commited custom categories */} {customCategories.map((category, index) => ( @@ -246,13 +210,6 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({ /> ))} </View> - <TouchableOpacity - onPress={handleButtonPress} - style={styles.finalAction}> - <Text style={styles.finalActionLabel}> - {isOnBoarding ? 'Login' : 'Create'} - </Text> - </TouchableOpacity> </View> </Background> </ScrollView> @@ -266,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', @@ -284,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, @@ -300,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, @@ -332,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; diff --git a/src/screens/onboarding/CreateCustomCategory.tsx b/src/screens/profile/CreateCustomCategory.tsx index eab72c7d..c4b17b1e 100644 --- a/src/screens/onboarding/CreateCustomCategory.tsx +++ b/src/screens/profile/CreateCustomCategory.tsx @@ -11,17 +11,17 @@ import { TouchableOpacity, } from 'react-native'; import {Background} from '../../components'; -import {OnboardingStackParams} from '../../routes'; +import {MainStackParams} from '../../routes'; import {BackgroundGradientType} from '../../types'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; type CreateCustomCategoryRouteProps = RouteProp< - OnboardingStackParams, + MainStackParams, 'CreateCustomCategory' >; type CreateCustomCategoryNavigationProps = StackNavigationProp< - OnboardingStackParams, + MainStackParams, 'CreateCustomCategory' >; @@ -45,8 +45,6 @@ const CreateCustomCategory: React.FC<CreateCustomCategoryProps> = ({ Alert.alert('Looks like you already have that one created!'); } else { navigation.navigate('CategorySelection', { - screenType: route.params.screenType, - user: route.params.user, newCustomCategory: newCategory, }); } diff --git a/src/screens/profile/IndividualMoment.tsx b/src/screens/profile/IndividualMoment.tsx index 871d62bf..515cbacf 100644 --- a/src/screens/profile/IndividualMoment.tsx +++ b/src/screens/profile/IndividualMoment.tsx @@ -114,10 +114,6 @@ const styles = StyleSheet.create({ flex: 1, paddingBottom: 0, }, - shareButtonTitle: { - fontWeight: 'bold', - color: '#6EE7E7', - }, content: { flex: 9, }, diff --git a/src/screens/profile/InviteFriendsScreen.tsx b/src/screens/profile/InviteFriendsScreen.tsx index ad9e382e..e1f739c5 100644 --- a/src/screens/profile/InviteFriendsScreen.tsx +++ b/src/screens/profile/InviteFriendsScreen.tsx @@ -36,6 +36,17 @@ import {MainStackParams} from '../../routes'; import {RouteProp} from '@react-navigation/native'; const AnimatedIcon = Animated.createAnimatedComponent(Icon); +export type InviteContactType = { + firstName: string; + lastName: string; + phoneNumber: string; +}; + +type SearchResultType = { + usersFromContacts: ProfilePreviewType[]; + nonUsersFromContacts: InviteContactType[]; +}; + type InviteFriendsScreenRouteProp = RouteProp< MainStackParams, 'InviteFriendsScreen' @@ -53,10 +64,6 @@ const InviteFriendsScreen: React.FC<InviteFriendsScreenProps> = ({route}) => { ProfilePreviewType[] >([]); const [nonUsersFromContacts, setNonUsersFromContacts] = useState<[]>([]); - type SearchResultType = { - usersFromContacts: ProfilePreviewType[]; - nonUsersFromContacts: []; - }; const [results, setResults] = useState<SearchResultType>({ usersFromContacts: usersFromContacts, nonUsersFromContacts: nonUsersFromContacts, @@ -98,7 +105,7 @@ const InviteFriendsScreen: React.FC<InviteFriendsScreenProps> = ({route}) => { item.last_name.toLowerCase().startsWith(query), ); const searchResultsNonUsers = nonUsersFromContacts.filter( - (item) => + (item: InviteContactType) => (item.firstName + ' ' + item.lastName) .toLowerCase() .startsWith(query) || diff --git a/src/screens/profile/ProfileScreen.tsx b/src/screens/profile/ProfileScreen.tsx index 6d9ef020..3dd142e1 100644 --- a/src/screens/profile/ProfileScreen.tsx +++ b/src/screens/profile/ProfileScreen.tsx @@ -1,8 +1,9 @@ -import React from 'react'; +import React, {useEffect} from 'react'; import {StatusBar} from 'react-native'; import {Content, TabsGradient} from '../../components'; import {RouteProp} from '@react-navigation/native'; import {MainStackParams} from '../../routes/'; +import {visitedUserProfile} from '../../services'; type ProfileScreenRouteProps = RouteProp<MainStackParams, 'Profile'>; @@ -14,6 +15,12 @@ const ProfileScreen: React.FC<ProfileOnboardingProps> = ({route}) => { const {screenType} = route.params; let {userXId} = route.params; + useEffect(() => { + if (userXId) { + visitedUserProfile(userXId); + } + }); + return ( <> <StatusBar barStyle="dark-content" /> 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'; diff --git a/src/services/SuggestedPeopleService.ts b/src/services/SuggestedPeopleService.ts index 4f56feb9..617f3970 100644 --- a/src/services/SuggestedPeopleService.ts +++ b/src/services/SuggestedPeopleService.ts @@ -136,11 +136,15 @@ export const getMutualBadgeHolders = async (badge_id: string) => { } }; -export const addBadgesService = async (selectedBadges: string[]) => { +export const addBadgesService = async ( + selectedBadges: string[], + university: string, +) => { try { const token = await AsyncStorage.getItem('token'); const form = new FormData(); form.append('badges', JSON.stringify(selectedBadges)); + form.append('university', JSON.stringify(university)); const response = await fetch(ADD_BADGES_ENDPOINT, { method: 'POST', headers: { @@ -161,11 +165,15 @@ export const addBadgesService = async (selectedBadges: string[]) => { } }; -export const updateBadgesService = async (selectedBadges: string[]) => { +export const updateBadgesService = async ( + selectedBadges: string[], + university: string, +) => { try { const token = await AsyncStorage.getItem('token'); const form = new FormData(); form.append('badges', JSON.stringify(selectedBadges)); + form.append('university', JSON.stringify(university)); const response = await fetch(UPDATE_BADGES_ENDPOINT, { method: 'POST', headers: { diff --git a/src/services/UserFriendsService.ts b/src/services/UserFriendsService.ts index 5c41e988..deb3ec6d 100644 --- a/src/services/UserFriendsService.ts +++ b/src/services/UserFriendsService.ts @@ -233,7 +233,10 @@ export const inviteFriendService = async ( }), }); if (response.status === 201 || response.status === 200) { - return await response.json(); + const data = await response.json(); + return data.invites_left; + } else if (response.status === 400) { + return -1; } return false; }; diff --git a/src/services/UserProfileService.ts b/src/services/UserProfileService.ts index 9e93d479..c11d874f 100644 --- a/src/services/UserProfileService.ts +++ b/src/services/UserProfileService.ts @@ -14,6 +14,7 @@ import { SEND_OTP_ENDPOINT, TAGG_CUSTOMER_SUPPORT, USER_PROFILE_ENDPOINT, + USER_PROFILE_VISITED_ENDPOINT, VERIFY_OTP_ENDPOINT, } from '../constants'; import { @@ -410,3 +411,24 @@ export const patchEditProfile = async (form: FormData, userId: string) => { throw ERROR_DOUBLE_CHECK_CONNECTION; } }; + +export const visitedUserProfile = async (userId: string) => { + try { + const token = await AsyncStorage.getItem('token'); + const form = new FormData(); + form.append('user_id', userId); + const response = await fetch(USER_PROFILE_VISITED_ENDPOINT, { + method: 'POST', + headers: { + 'Content-Type': 'multipart/form-data', + Authorization: 'Token ' + token, + }, + body: form, + }); + if (response.status !== 200) { + console.error('Failed to submit a profile visit'); + } + } catch (error) { + return undefined; + } +}; diff --git a/src/types/types.ts b/src/types/types.ts index 376c4be0..e7f651dc 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -165,22 +165,6 @@ export interface UserXType { } /** - * We have two verification screen types, this enum is used to display proper content based on the type - */ -export enum VerificationScreenType { - Phone, - Password, -} - -/** - * Two types for category selection screen - */ -export enum CategorySelectionScreenType { - Onboarding, - Profile, -} - -/** * Gradient type to accomodate new g background gradients for Tagg */ export enum BackgroundGradientType { @@ -251,7 +235,9 @@ export type TypeOfNotification = // notification_object is MomentType | 'MOM_FRIEND' // notification_object is undefined - | 'INVT_ONBRD'; + | 'INVT_ONBRD' + // notification_object is undefined + | 'SYSTEM_MSG'; export type UniversityBadge = { id: number; diff --git a/src/utils/messages.ts b/src/utils/messages.ts index f4215bf0..0e73f639 100644 --- a/src/utils/messages.ts +++ b/src/utils/messages.ts @@ -137,3 +137,28 @@ export const createChannel = async ( throw error; } }; + +export const getFormatedDate = (date: object) => { + const dateMoment = moment(date).startOf('day'); + let dateToRender = ''; + + const TODAY = moment().startOf('day'); + const YESTERDAY = moment().subtract(1, 'day').startOf('day'); + const LAST_7_DAYS = moment().subtract(7, 'day').startOf('day'); + + if (TODAY.isSame(dateMoment)) { + dateToRender = 'Today'; + } else if (YESTERDAY.isSame(dateMoment)) { + dateToRender = 'Yesterday'; + } else if (dateMoment.isBetween(LAST_7_DAYS, YESTERDAY)) { + dateToRender = dateMoment.format('dddd'); + } else { + if (dateMoment.get('year') === TODAY.get('year')) { + dateToRender = dateMoment.format('MMMM D') + 'th'; + } else { + dateToRender = + dateMoment.format('MMMM D ') + 'th' + dateMoment.get('year'); + } + } + return dateToRender; +}; |