diff options
author | Ivan Chen <ivan@thetaggid.com> | 2021-02-05 16:50:13 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-05 16:50:13 -0500 |
commit | 55914efe03da970f03970a2a9fa85196fce41b75 (patch) | |
tree | d475e92b463926fc4430b02fb80350aa50aefa1f /src/components | |
parent | f591dd437a1273d99709aa6a3637a3a2922e6f4d (diff) | |
parent | 212eae20eb33d224525c52cea600b86fb2fd1126 (diff) |
Merge pull request #212 from shravyaramesh/tma590-friendslist-buttons
[TMA-590] New Friends Screen
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/common/FriendsButton.tsx | 111 | ||||
-rw-r--r-- | src/components/common/index.ts | 1 | ||||
-rw-r--r-- | src/components/moments/IndividualMomentTitleBar.tsx | 7 | ||||
-rw-r--r-- | src/components/profile/Content.tsx | 28 | ||||
-rw-r--r-- | src/components/profile/Friends.tsx | 133 | ||||
-rw-r--r-- | src/components/profile/ProfileBody.tsx | 47 | ||||
-rw-r--r-- | src/components/profile/ProfilePreview.tsx | 32 |
7 files changed, 256 insertions, 103 deletions
diff --git a/src/components/common/FriendsButton.tsx b/src/components/common/FriendsButton.tsx new file mode 100644 index 00000000..6ef23a96 --- /dev/null +++ b/src/components/common/FriendsButton.tsx @@ -0,0 +1,111 @@ +import React from 'react'; +import {StyleSheet} from 'react-native'; +import {Button} from 'react-native-elements'; +import {ScreenType} from '../../types'; +import {TAGG_LIGHT_BLUE} from '../../constants'; +import {handleFriendUnfriend, SCREEN_WIDTH} from '../../utils'; +import {NO_PROFILE, NO_USER} from '../../store/initialStates'; +import {useDispatch, useSelector, useStore} from 'react-redux'; +import {RootState} from '../../store/rootReducer'; + +interface ProfileBodyProps { + userXId: string | undefined; + screenType: ScreenType; +} +const FriendsButton: React.FC<ProfileBodyProps> = ({userXId, screenType}) => { + const dispatch = useDispatch(); + + const {user = NO_USER, profile = NO_PROFILE} = userXId + ? useSelector((state: RootState) => state.userX[screenType][userXId]) + : useSelector((state: RootState) => state.user); + + const {user: loggedInUser = NO_USER} = useSelector( + (state: RootState) => state.user, + ); + + const state = useStore().getState(); + + const {friendship_status} = profile; + + return ( + <> + {friendship_status === 'no_record' && ( + <Button + title={'Add Friend'} + buttonStyle={styles.button} + titleStyle={styles.buttonTitle} + onPress={() => + handleFriendUnfriend( + screenType, + user, + profile, + dispatch, + state, + loggedInUser, + ) + } // requested, requested status + /> + )} + {friendship_status === 'friends' && ( + <Button + title={'Unfriend'} + buttonStyle={styles.requestedButton} + titleStyle={styles.requestedButtonTitle} + onPress={() => + handleFriendUnfriend( + screenType, + user, + profile, + dispatch, + state, + loggedInUser, + ) + } // unfriend, no record status + /> + )} + </> + ); +}; + +const styles = StyleSheet.create({ + requestedButton: { + justifyContent: 'center', + alignItems: 'center', + width: SCREEN_WIDTH * 0.4, + height: SCREEN_WIDTH * 0.075, + borderColor: TAGG_LIGHT_BLUE, + borderWidth: 2, + borderRadius: 0, + marginRight: '2%', + marginLeft: '1%', + padding: 0, + backgroundColor: 'transparent', + }, + requestedButtonTitle: { + color: TAGG_LIGHT_BLUE, + padding: 0, + fontSize: 14, + fontWeight: '700', + }, + buttonTitle: { + color: 'white', + padding: 0, + fontSize: 14, + fontWeight: '700', + }, + button: { + justifyContent: 'center', + alignItems: 'center', + width: SCREEN_WIDTH * 0.4, + height: SCREEN_WIDTH * 0.075, + padding: 0, + borderWidth: 2, + borderColor: TAGG_LIGHT_BLUE, + borderRadius: 0, + marginRight: '2%', + marginLeft: '1%', + backgroundColor: TAGG_LIGHT_BLUE, + }, +}); + +export default FriendsButton; diff --git a/src/components/common/index.ts b/src/components/common/index.ts index a5718c1e..95854ba8 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -20,4 +20,5 @@ 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'; export {default as TaggSquareButton} from './TaggSquareButton'; diff --git a/src/components/moments/IndividualMomentTitleBar.tsx b/src/components/moments/IndividualMomentTitleBar.tsx index bd5b307f..6cdfe0e8 100644 --- a/src/components/moments/IndividualMomentTitleBar.tsx +++ b/src/components/moments/IndividualMomentTitleBar.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {TouchableOpacity} from 'react-native'; import {Text, View, StyleSheet, ViewProps} from 'react-native'; +import {normalize} from '../../utils'; import CloseIcon from '../../assets/ionicons/close-outline.svg'; interface IndividualMomentTitleBarProps extends ViewProps { @@ -30,9 +31,11 @@ const styles = StyleSheet.create({ height: '5%', }, header: { - fontSize: 20, - fontWeight: 'bold', color: 'white', + fontSize: normalize(18), + fontWeight: '700', + lineHeight: normalize(21.48), + letterSpacing: normalize(1.3), }, closeButton: { position: 'absolute', diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx index a35a5820..28000dd7 100644 --- a/src/components/profile/Content.tsx +++ b/src/components/profile/Content.tsx @@ -25,11 +25,9 @@ import { import { blockUnblockUser, deleteUserMomentsForCategory, - friendUnfriendUser, loadFriendsData, updateMomentCategories, updateUserXFriends, - updateUserXProfileAllScreens, } from '../../store/actions'; import { EMPTY_MOMENTS_LIST, @@ -216,31 +214,6 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => { } }, [blockedUsers, user]); - // Handles click on friend/requested/unfriend button - /* - * When user logged in clicks on the friend button: - A request is sent. - Which means you have to update the status of their friendshpi to requested - When the status is changed to requested the button should change to requested. - When the button is changed to requested and thr user clicks on it, - a request much go to the backend to delete that request - When that succeeds, their friendship must be updated to no-record again; - When the button is changed to no_record, the add friends button should be displayed again - */ - const handleFriendUnfriend = async () => { - const {friendship_status} = profile; - await dispatch( - friendUnfriendUser( - loggedInUser, - getUserAsProfilePreviewType(user, profile), - friendship_status, - screenType, - ), - ); - await dispatch(updateUserXFriends(user.userId, state)); - dispatch(updateUserXProfileAllScreens(user.userId, state)); - }; - /** * Handles a click on the block / unblock button. * loadFriends updates friends list for the logged in user @@ -332,7 +305,6 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => { userXId, screenType, isFriend, - handleFriendUnfriend, handleBlockUnblock, isBlocked, }} diff --git a/src/components/profile/Friends.tsx b/src/components/profile/Friends.tsx index 23ce28fe..9b9e5302 100644 --- a/src/components/profile/Friends.tsx +++ b/src/components/profile/Friends.tsx @@ -1,64 +1,123 @@ import React from 'react'; -import {View, StyleSheet, Text} from 'react-native'; +import {View, StyleSheet, ScrollView, Text} from 'react-native'; import {ProfilePreviewType, ScreenType} from '../../types'; import {ProfilePreview} from '..'; -import {useNavigation} from '@react-navigation/native'; import {Button} from 'react-native-elements'; +import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; +import {TAGG_LIGHT_BLUE} from '../../constants'; +import {RootState} from '../../store/rootReducer'; +import {useDispatch, useStore} from 'react-redux'; +import {handleUnfriend} from '../../utils/friends'; +import {NO_USER} from '../../store/initialStates'; +import {TouchableOpacity} from 'react-native-gesture-handler'; interface FriendsProps { result: Array<ProfilePreviewType>; screenType: ScreenType; + userId: string; } -const Friends: React.FC<FriendsProps> = ({result, screenType}) => { - const navigation = useNavigation(); +const Friends: React.FC<FriendsProps> = ({result, screenType, userId}) => { + const state: RootState = useStore().getState(); + const dispatch = useDispatch(); + + const {user: loggedInUser = NO_USER} = state; + return ( <> - <View style={styles.header}> - <Button - title="X" - buttonStyle={styles.button} - titleStyle={styles.buttonText} - onPress={() => { - navigation.pop(); - }} - /> - <Text style={styles.title}>Friends</Text> + <View style={styles.subheader}> + <Text style={styles.subheaderText}>Friends</Text> </View> - {result.map((profilePreview) => ( - <ProfilePreview - style={styles.friend} - key={profilePreview.id} - {...{profilePreview}} - previewType={'Friend'} - screenType={screenType} - /> - ))} + <ScrollView + keyboardShouldPersistTaps={'always'} + stickyHeaderIndices={[4]} + style={styles.scrollView} + contentContainerStyle={styles.scrollViewContent} + showsVerticalScrollIndicator={false}> + {result.map((profilePreview) => ( + <View key={profilePreview.id} style={styles.container}> + <View style={styles.friend}> + <ProfilePreview + {...{profilePreview}} + previewType={'Friend'} + screenType={screenType} + /> + </View> + {loggedInUser.userId === userId && ( + <TouchableOpacity + style={styles.button} + onPress={() => + handleUnfriend(screenType, profilePreview, dispatch, state) + }> + <Text style={styles.buttonTitle}>Unfriend</Text> + </TouchableOpacity> + )} + </View> + ))} + </ScrollView> </> ); }; const styles = StyleSheet.create({ + scrollView: { + flexDirection: 'column', + alignSelf: 'center', + width: SCREEN_WIDTH * 0.85, + height: SCREEN_HEIGHT, + }, + scrollViewContent: { + alignSelf: 'center', + paddingBottom: SCREEN_HEIGHT / 15, + width: SCREEN_WIDTH * 0.85, + height: SCREEN_HEIGHT * 0.75, + marginTop: '1%', + }, header: {flexDirection: 'row'}, - friend: { - marginVertical: 10, + subheader: { + alignSelf: 'center', + width: SCREEN_WIDTH * 0.85, + marginVertical: '3%', + }, + subheaderText: { + color: '#828282', + fontSize: normalize(12), + fontWeight: '600', + lineHeight: normalize(14.32), }, - title: { - position: 'relative', - fontSize: 17, - fontWeight: 'bold', - paddingBottom: 10, - paddingTop: 10, - flexGrow: 1, - paddingLeft: '26%', + container: { + alignSelf: 'center', + flexDirection: 'row', + justifyContent: 'space-between', + width: '100%', + height: normalize(42), + alignItems: 'center', + marginBottom: '5%', + }, + friend: { + alignSelf: 'center', + height: '100%', }, button: { + alignSelf: 'center', + justifyContent: 'center', + alignItems: 'center', + width: '100%', + height: '55%', + borderColor: TAGG_LIGHT_BLUE, + borderWidth: 2, + borderRadius: 2, + padding: 0, backgroundColor: 'transparent', }, - buttonText: { - color: 'black', - fontSize: 18, - fontWeight: '400', + buttonTitle: { + color: TAGG_LIGHT_BLUE, + padding: 0, + fontSize: normalize(11), + fontWeight: '700', + lineHeight: normalize(13.13), + letterSpacing: normalize(0.6), + paddingHorizontal: '3.8%', }, }); diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index f2d75519..106b20a7 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -9,14 +9,17 @@ import { import ToggleButton from './ToggleButton'; import {RootState} from '../../store/rootReducer'; import {useDispatch, useSelector, useStore} from 'react-redux'; -import {FriendshipStatusType, ScreenType} from '../../types'; -import {NO_PROFILE} from '../../store/initialStates'; -import {getUserAsProfilePreviewType, SCREEN_WIDTH} from '../../utils'; -import {AcceptDeclineButtons} from '../common'; +import {ScreenType} from '../../types'; +import {NO_PROFILE, NO_USER} from '../../store/initialStates'; +import { + getUserAsProfilePreviewType, + handleFriendUnfriend, + SCREEN_WIDTH, +} from '../../utils'; +import {AcceptDeclineButtons, FriendsButton} from '../common'; import { acceptFriendRequest, declineFriendRequest, - loadUserNotifications, updateUserXFriends, updateUserXProfileAllScreens, } from '../../store/actions'; @@ -24,7 +27,6 @@ import { interface ProfileBodyProps { onLayout: (event: LayoutChangeEvent) => void; isBlocked: boolean; - handleFriendUnfriend: () => void; handleBlockUnblock: () => void; userXId: string | undefined; screenType: ScreenType; @@ -32,7 +34,6 @@ interface ProfileBodyProps { const ProfileBody: React.FC<ProfileBodyProps> = ({ onLayout, isBlocked, - handleFriendUnfriend, handleBlockUnblock, userXId, screenType, @@ -41,6 +42,10 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ ? useSelector((state: RootState) => state.userX[screenType][userXId]) : useSelector((state: RootState) => state.user); + const {user: loggedInUser = NO_USER} = useSelector( + (state: RootState) => state.user, + ); + const { biography, website, @@ -94,29 +99,23 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ )} {userXId && !isBlocked && ( <View style={styles.buttonsContainer}> - {friendship_status === 'no_record' && ( - <Button - title={'Add Friend'} - buttonStyle={styles.button} - titleStyle={styles.buttonTitle} - onPress={handleFriendUnfriend} // requested, requested status - /> - )} - {friendship_status === 'friends' && ( - <Button - title={'Unfriend'} - buttonStyle={styles.requestedButton} - titleStyle={styles.requestedButtonTitle} - onPress={handleFriendUnfriend} // unfriend, no record status - /> - )} + <FriendsButton userXId={userXId} screenType={screenType} /> {(friendship_status === 'requested' && friendship_requester_id !== userXId && ( <Button title={'Requested'} buttonStyle={styles.requestedButton} titleStyle={styles.requestedButtonTitle} - onPress={handleFriendUnfriend} // delete request, no record status + onPress={() => + handleFriendUnfriend( + screenType, + user, + profile, + dispatch, + state, + loggedInUser, + ) + } // delete request, no record status /> )) || (friendship_status === 'requested' && diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx index 38defb8d..fad3ec09 100644 --- a/src/components/profile/ProfilePreview.tsx +++ b/src/components/profile/ProfilePreview.tsx @@ -15,7 +15,13 @@ import {ERROR_UNABLE_TO_VIEW_PROFILE} from '../../constants/strings'; import {loadImageFromURL} from '../../services'; import {RootState} from '../../store/rootreducer'; import {PreviewType, ProfilePreviewType, ScreenType} from '../../types'; -import {checkIfUserIsBlocked, fetchUserX, userXInStore} from '../../utils'; +import { + checkIfUserIsBlocked, + fetchUserX, + normalize, + SCREEN_WIDTH, + userXInStore, +} from '../../utils'; /** * This component returns user's profile picture friended by username as a touchable component. @@ -308,29 +314,31 @@ const styles = StyleSheet.create({ friendContainer: { flexDirection: 'row', alignItems: 'center', - marginVertical: 10, + justifyContent: 'flex-start', + width: SCREEN_WIDTH * 0.6, }, friendAvatar: { - height: 42, - width: 42, + height: normalize(42), + width: normalize(42), marginRight: 15, - borderRadius: 20, + borderRadius: 50, }, friendNameContainer: { + height: '100%', justifyContent: 'space-evenly', alignSelf: 'stretch', }, friendUsername: { - fontSize: 14, - fontWeight: '700', - color: '#3C3C3C', - letterSpacing: 0.6, + fontSize: normalize(14), + fontWeight: '500', + color: '#000', + letterSpacing: normalize(0.1), }, friendName: { - fontSize: 12, - fontWeight: '500', + fontSize: normalize(12), + fontWeight: '400', color: '#6C6C6C', - letterSpacing: 0.5, + letterSpacing: normalize(0.1), }, }); |