From 941233128c446fe040d4f1ab307cd698cd21f1ec Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Tue, 25 May 2021 12:58:10 -0700 Subject: Add component for individual moment --- src/components/moments/MomentPost.tsx | 117 ++++++++++++++++++++++++++++++++++ src/components/moments/index.ts | 1 + 2 files changed, 118 insertions(+) create mode 100644 src/components/moments/MomentPost.tsx (limited to 'src') diff --git a/src/components/moments/MomentPost.tsx b/src/components/moments/MomentPost.tsx new file mode 100644 index 00000000..804d089f --- /dev/null +++ b/src/components/moments/MomentPost.tsx @@ -0,0 +1,117 @@ +import React, {useEffect, useState} from 'react'; +import {Alert, StyleSheet, View} from 'react-native'; +import {useSelector} from 'react-redux'; +import {MomentPostContent, MomentPostHeader} from '.'; +import {deleteMomentTag, loadMomentTags} from '../../services'; +import {RootState} from '../../store/rootReducer'; +import {MomentTagType, MomentType, ScreenType} from '../../types'; +import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; + +interface MomentPostProps { + item: MomentType; + userXId: string | undefined; + screenType: ScreenType; +} + +const ITEM_HEIGHT = SCREEN_HEIGHT * 0.9; + +const MomentPost: React.FC = ({item, userXId, screenType}) => { + const {userId: loggedInUserId, username: loggedInUsername} = useSelector( + (state: RootState) => state.user.user, + ); + + const { + user: {username}, + } = useSelector((state: RootState) => + userXId ? state.userX[screenType][userXId] : state.user, + ); + const [tags, setTags] = useState([]); + const [momentTagId, setMomentTagId] = useState(''); + + const isOwnProfile = username === loggedInUsername; + + const loadTags = async () => { + const response = await loadMomentTags(item.moment_id); + setTags(response ? response : []); + }; + + /* + * Load tags on initial render to pass tags data to moment header and content + */ + useEffect(() => { + loadTags(); + }, []); + + /* + * Check if loggedInUser has been tagged in the picture and set the id + */ + useEffect(() => { + tags.forEach((tag) => { + if (tag.user.id === loggedInUserId) { + setMomentTagId(tag.id); + } + }); + }, [tags]); + + /* + * Remove tag and update the current tags + */ + const removeTag = async () => { + const success = await deleteMomentTag(momentTagId); + Alert.alert(success ? 'Success' : 'Failed'); + if (success) { + const filteredTags = tags.filter((tag) => tag.user.id !== loggedInUserId); + setTags(filteredTags); + } + }; + + return ( + + + + + ); +}; + +const styles = StyleSheet.create({ + contentContainer: { + width: SCREEN_WIDTH, + height: SCREEN_HEIGHT, + paddingTop: StatusBarHeight, + flex: 1, + paddingBottom: 0, + }, + content: { + flex: 9, + }, + header: { + flex: 1, + }, + postContainer: { + height: ITEM_HEIGHT, + width: SCREEN_WIDTH, + flex: 1, + }, + postHeader: { + flex: 1, + }, + postContent: {flex: 9}, +}); + +export default MomentPost; diff --git a/src/components/moments/index.ts b/src/components/moments/index.ts index 6af29bc5..c1419cfd 100644 --- a/src/components/moments/index.ts +++ b/src/components/moments/index.ts @@ -4,3 +4,4 @@ export {default as MomentPostHeader} from './MomentPostHeader'; export {default as MomentPostContent} from './MomentPostContent'; export {default as Moment} from './Moment'; export {default as TagFriendsFooter} from './TagFriendsFoooter'; +export {default as MomentPost} from './MomentPost'; -- cgit v1.2.3-70-g09d2 From b3041bb521fc4f52b414151eb4d8220791f6c874 Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Tue, 25 May 2021 13:00:10 -0700 Subject: Load tags in PostContent when moment tags changes --- src/components/moments/MomentPostContent.tsx | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index 6953dca4..c3cb03f5 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -4,7 +4,7 @@ import {Image, StyleSheet, Text, View, ViewProps} from 'react-native'; import {TouchableWithoutFeedback} from 'react-native-gesture-handler'; import Animated, {Easing} from 'react-native-reanimated'; import {useDispatch, useStore} from 'react-redux'; -import {getCommentsCount, loadMomentTags} from '../../services'; +import {getCommentsCount} from '../../services'; import {RootState} from '../../store/rootReducer'; import {MomentTagType, ScreenType, UserType} from '../../types'; import { @@ -24,6 +24,7 @@ interface MomentPostContentProps extends ViewProps { caption: string; pathHash: string; dateTime: string; + momentTags: MomentTagType[]; } const MomentPostContent: React.FC = ({ screenType, @@ -32,10 +33,11 @@ const MomentPostContent: React.FC = ({ pathHash, dateTime, style, + momentTags, }) => { const [elapsedTime, setElapsedTime] = useState(''); const [comments_count, setCommentsCount] = useState(''); - const [tags, setTags] = useState([]); + const [tags, setTags] = useState(momentTags); const [visible, setVisible] = useState(false); const state: RootState = useStore().getState(); const navigation = useNavigation(); @@ -47,14 +49,8 @@ const MomentPostContent: React.FC = ({ ); useEffect(() => { - const loadTags = async () => { - const response = await loadMomentTags(momentId); - if (response) { - setTags(response); - } - }; - loadTags(); - }, []); + setTags(momentTags); + }, [momentTags]); useEffect(() => { const fetchCommentsCount = async () => { -- cgit v1.2.3-70-g09d2 From f25b4d4309bead2d9d5a5d9e8cc198d978deb875 Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Tue, 25 May 2021 13:59:12 -0700 Subject: Pass remove() down, Add/remove removeTag btn --- src/components/moments/MomentPostHeader.tsx | 8 +- src/components/profile/MomentMoreInfoDrawer.tsx | 105 ++++++++++++++++++++---- 2 files changed, 94 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/components/moments/MomentPostHeader.tsx b/src/components/moments/MomentPostHeader.tsx index 3c3ee4c3..ae9e96a0 100644 --- a/src/components/moments/MomentPostHeader.tsx +++ b/src/components/moments/MomentPostHeader.tsx @@ -1,5 +1,5 @@ import {useNavigation} from '@react-navigation/native'; -import React, {useState} from 'react'; +import React, {useEffect, useState} from 'react'; import { StyleSheet, Text, @@ -20,6 +20,8 @@ interface MomentPostHeaderProps extends ViewProps { screenType: ScreenType; username: string; momentId: string; + momentTagId: string; + removeTag: () => Promise; } const MomentPostHeader: React.FC = ({ @@ -28,6 +30,8 @@ const MomentPostHeader: React.FC = ({ username, momentId, style, + momentTagId, + removeTag, }) => { const [drawerVisible, setDrawerVisible] = useState(false); const dispatch = useDispatch(); @@ -66,6 +70,8 @@ const MomentPostHeader: React.FC = ({ setIsOpen={setDrawerVisible} momentId={momentId} isOwnProfile={isOwnProfile} + momentTagId={momentTagId} + removeTag={removeTag} dismissScreenAndUpdate={() => { dispatch(loadUserMoments(loggedInUserId)); navigation.pop(); diff --git a/src/components/profile/MomentMoreInfoDrawer.tsx b/src/components/profile/MomentMoreInfoDrawer.tsx index 77c349ca..1ac05fb0 100644 --- a/src/components/profile/MomentMoreInfoDrawer.tsx +++ b/src/components/profile/MomentMoreInfoDrawer.tsx @@ -1,20 +1,40 @@ -import React from 'react'; -import {Alert, StyleSheet, TouchableOpacity, ViewProps} from 'react-native'; +import React, {useEffect, useState} from 'react'; +import { + Alert, + GestureResponderEvent, + StyleSheet, + TouchableOpacity, + ViewProps, +} from 'react-native'; import MoreIcon from '../../assets/icons/more_horiz-24px.svg'; import {ERROR_DELETE_MOMENT, MOMENT_DELETED_MSG} from '../../constants/strings'; import {deleteMoment, sendReport} from '../../services'; import {GenericMoreInfoDrawer} from '../common'; +enum MomentDrawerOptions { + DeleteMoment = 'Delete Moment', + ReportIssue = 'Report an Issue', + RemoveTag = 'Remove yourself from moment', +} interface MomentMoreInfoDrawerProps extends ViewProps { isOpen: boolean; setIsOpen: (visible: boolean) => void; momentId: string; isOwnProfile: boolean; + momentTagId: string; + removeTag: () => Promise; dismissScreenAndUpdate: () => void; } const MomentMoreInfoDrawer: React.FC = (props) => { - const {momentId, setIsOpen, isOwnProfile, dismissScreenAndUpdate} = props; + const { + momentId, + setIsOpen, + isOwnProfile, + dismissScreenAndUpdate, + momentTagId, + removeTag, + } = props; const handleDeleteMoment = async () => { setIsOpen(false); @@ -38,6 +58,27 @@ const MomentMoreInfoDrawer: React.FC = (props) => { }); }; + const handleRemoveTag = () => { + setIsOpen(false); + setTimeout(() => { + Alert.alert( + MomentDrawerOptions.RemoveTag, + 'Are you sure you want to be removed from this moment?', + [ + { + text: 'Remove', + onPress: removeTag, + }, + { + text: 'Cancel', + style: 'cancel', + }, + ], + {cancelable: false}, + ); + }, 500); + }; + const handleReportMoment = async () => { setIsOpen(false); setTimeout(() => { @@ -63,6 +104,43 @@ const MomentMoreInfoDrawer: React.FC = (props) => { }, 500); }; + const [drawerButtons, setDrawerButtons] = useState< + [string, (event: GestureResponderEvent) => void, JSX.Element?][] + >([ + isOwnProfile + ? [MomentDrawerOptions.DeleteMoment, handleDeleteMoment] + : [MomentDrawerOptions.ReportIssue, handleReportMoment], + ]); + + /* + * Update bottom drawer options to contain/not contain 'remove tag' option + */ + useEffect(() => { + const setupBottomDrawer = async () => { + const present = drawerButtons.findIndex( + (button) => button[0] === MomentDrawerOptions.RemoveTag, + ); + if (momentTagId !== '') { + if (present === -1) { + const localDrawerButtons = drawerButtons; + localDrawerButtons.push([ + MomentDrawerOptions.RemoveTag, + handleRemoveTag, + ]); + setDrawerButtons(localDrawerButtons); + } + } else { + if (present !== -1) { + const filteredButtons = drawerButtons.filter( + (button) => button[0] !== MomentDrawerOptions.RemoveTag, + ); + setDrawerButtons(filteredButtons); + } + } + }; + setupBottomDrawer(); + }, [momentTagId]); + return ( <> = (props) => { }}> - {isOwnProfile ? ( - - ) : ( - - )} + ); }; -- cgit v1.2.3-70-g09d2 From a0b6cbaba61f8eb26ecb1e1f7ba15770c8c19b8d Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Tue, 25 May 2021 14:00:22 -0700 Subject: Use MomentPost component, Remove unused functions --- src/screens/profile/IndividualMoment.tsx | 39 ++++---------------------------- 1 file changed, 4 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/screens/profile/IndividualMoment.tsx b/src/screens/profile/IndividualMoment.tsx index 515cbacf..4ad4515d 100644 --- a/src/screens/profile/IndividualMoment.tsx +++ b/src/screens/profile/IndividualMoment.tsx @@ -4,11 +4,7 @@ import {StackNavigationProp} from '@react-navigation/stack'; import React from 'react'; import {FlatList, StyleSheet, View} from 'react-native'; import {useSelector} from 'react-redux'; -import { - IndividualMomentTitleBar, - MomentPostContent, - MomentPostHeader, -} from '../../components'; +import {IndividualMomentTitleBar, MomentPost} from '../../components'; import {MainStackParams} from '../../routes'; import {RootState} from '../../store/rootreducer'; import {MomentType} from '../../types'; @@ -35,45 +31,16 @@ const IndividualMoment: React.FC = ({ }) => { const {moment_category, moment_id} = route.params.moment; const {userXId, screenType} = route.params; - const {username: loggedInUsername} = useSelector( - (state: RootState) => state.user.user, - ); - const { - user: {username}, - } = useSelector((state: RootState) => - userXId ? state.userX[screenType][userXId] : state.user, - ); const {moments} = useSelector((state: RootState) => userXId ? state.userX[screenType][userXId] : state.moments, ); - const isOwnProfile = username === loggedInUsername; const momentData = moments.filter( (m) => m.moment_category === moment_category, ); const initialIndex = momentData.findIndex((m) => m.moment_id === moment_id); - const renderMomentPost = ({item}: {item: MomentType}) => ( - - - - - ); - return ( = ({ ( + + )} keyExtractor={(item, index) => index.toString()} showsVerticalScrollIndicator={false} snapToAlignment={'start'} -- cgit v1.2.3-70-g09d2 From 5100fd682c5cb026d8f35098455e5bb6a068afaf Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Tue, 25 May 2021 14:00:38 -0700 Subject: Add service to delete tag --- src/services/MomentService.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/services/MomentService.ts b/src/services/MomentService.ts index 46b55066..7d141984 100644 --- a/src/services/MomentService.ts +++ b/src/services/MomentService.ts @@ -171,3 +171,19 @@ export const postMomentTags = async ( return false; } }; + +export const deleteMomentTag = async (moment_tag_id: string) => { + try { + const token = await AsyncStorage.getItem('token'); + const response = await fetch(MOMENTTAG_ENDPOINT + `${moment_tag_id}/`, { + method: 'DELETE', + headers: { + Authorization: 'Token ' + token, + }, + }); + return response.status === 200; + } catch (error) { + console.error(error); + return false; + } +}; -- cgit v1.2.3-70-g09d2 From 43e44ae964d3102949d8eb79d2525434826b97a0 Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Tue, 25 May 2021 14:27:37 -0700 Subject: Remove success message --- src/components/moments/MomentPost.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/components/moments/MomentPost.tsx b/src/components/moments/MomentPost.tsx index 804d089f..72d669a2 100644 --- a/src/components/moments/MomentPost.tsx +++ b/src/components/moments/MomentPost.tsx @@ -58,7 +58,6 @@ const MomentPost: React.FC = ({item, userXId, screenType}) => { */ const removeTag = async () => { const success = await deleteMomentTag(momentTagId); - Alert.alert(success ? 'Success' : 'Failed'); if (success) { const filteredTags = tags.filter((tag) => tag.user.id !== loggedInUserId); setTags(filteredTags); -- cgit v1.2.3-70-g09d2 From 534a90b35f3b6694cac2b99989b5f4777d2bdb19 Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Tue, 25 May 2021 14:40:43 -0700 Subject: Fix lint error --- src/components/moments/MomentPost.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/components/moments/MomentPost.tsx b/src/components/moments/MomentPost.tsx index 72d669a2..1ab7c1fa 100644 --- a/src/components/moments/MomentPost.tsx +++ b/src/components/moments/MomentPost.tsx @@ -1,5 +1,5 @@ import React, {useEffect, useState} from 'react'; -import {Alert, StyleSheet, View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import {useSelector} from 'react-redux'; import {MomentPostContent, MomentPostHeader} from '.'; import {deleteMomentTag, loadMomentTags} from '../../services'; -- cgit v1.2.3-70-g09d2 From b0b5f7aefb58aad74c4f75d521c7416d393e43f4 Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Tue, 25 May 2021 15:37:34 -0700 Subject: Fix lint error, Make function async --- src/components/moments/MomentPostHeader.tsx | 2 +- src/components/profile/MomentMoreInfoDrawer.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/components/moments/MomentPostHeader.tsx b/src/components/moments/MomentPostHeader.tsx index ae9e96a0..dc6a3cd9 100644 --- a/src/components/moments/MomentPostHeader.tsx +++ b/src/components/moments/MomentPostHeader.tsx @@ -1,5 +1,5 @@ import {useNavigation} from '@react-navigation/native'; -import React, {useEffect, useState} from 'react'; +import React, {useState} from 'react'; import { StyleSheet, Text, diff --git a/src/components/profile/MomentMoreInfoDrawer.tsx b/src/components/profile/MomentMoreInfoDrawer.tsx index 1ac05fb0..3f8707e8 100644 --- a/src/components/profile/MomentMoreInfoDrawer.tsx +++ b/src/components/profile/MomentMoreInfoDrawer.tsx @@ -58,7 +58,7 @@ const MomentMoreInfoDrawer: React.FC = (props) => { }); }; - const handleRemoveTag = () => { + const handleRemoveTag = async () => { setIsOpen(false); setTimeout(() => { Alert.alert( -- cgit v1.2.3-70-g09d2 From 67e809a85b625d13f1a0c5a8995d007bbcf4a37f Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Wed, 26 May 2021 14:56:40 -0700 Subject: Set id to '', Remove drawer btn after remove tag --- src/components/moments/MomentPost.tsx | 18 ++++++++++--- src/components/profile/MomentMoreInfoDrawer.tsx | 34 ++++++++++++------------- 2 files changed, 31 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/components/moments/MomentPost.tsx b/src/components/moments/MomentPost.tsx index 1ab7c1fa..e2875b9a 100644 --- a/src/components/moments/MomentPost.tsx +++ b/src/components/moments/MomentPost.tsx @@ -46,11 +46,17 @@ const MomentPost: React.FC = ({item, userXId, screenType}) => { * Check if loggedInUser has been tagged in the picture and set the id */ useEffect(() => { - tags.forEach((tag) => { - if (tag.user.id === loggedInUserId) { - setMomentTagId(tag.id); + const getMomentTagId = () => { + const ownTag: MomentTagType[] = tags.filter( + (tag) => tag.user.id === loggedInUserId, + ); + if (ownTag?.length > 0) { + setMomentTagId(ownTag[0].id); + } else { + setMomentTagId(''); } - }); + }; + getMomentTagId(); }, [tags]); /* @@ -64,6 +70,10 @@ const MomentPost: React.FC = ({item, userXId, screenType}) => { } }; + useEffect(() => { + console.log('Tags have been altered'); + }, [tags]); + return ( = (props) => { * Update bottom drawer options to contain/not contain 'remove tag' option */ useEffect(() => { - const setupBottomDrawer = async () => { + const setupBottomDrawer = () => { const present = drawerButtons.findIndex( (button) => button[0] === MomentDrawerOptions.RemoveTag, ); - if (momentTagId !== '') { - if (present === -1) { - const localDrawerButtons = drawerButtons; - localDrawerButtons.push([ - MomentDrawerOptions.RemoveTag, - handleRemoveTag, - ]); - setDrawerButtons(localDrawerButtons); - } - } else { - if (present !== -1) { - const filteredButtons = drawerButtons.filter( - (button) => button[0] !== MomentDrawerOptions.RemoveTag, - ); - setDrawerButtons(filteredButtons); - } + /* + * If user is not tagged but button is present, remove button from bottom drawer + * If user is tagged but button is not present, add button to bottom drawer + */ + if (momentTagId !== '' && present === -1) { + const localDrawerButtons = drawerButtons; + localDrawerButtons.push([ + MomentDrawerOptions.RemoveTag, + handleRemoveTag, + ]); + setDrawerButtons(localDrawerButtons); + } else if (momentTagId === '' && present !== -1) { + const filteredButtons = drawerButtons.filter( + (button) => button[0] !== MomentDrawerOptions.RemoveTag, + ); + setDrawerButtons(filteredButtons); } }; setupBottomDrawer(); -- cgit v1.2.3-70-g09d2 From 907e8fb4c12b53448e22d230d62dd42b9b1c93ed Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 27 May 2021 11:40:08 -0400 Subject: Update src/components/moments/MomentPost.tsx --- src/components/moments/MomentPost.tsx | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/components/moments/MomentPost.tsx b/src/components/moments/MomentPost.tsx index e2875b9a..7149a5b4 100644 --- a/src/components/moments/MomentPost.tsx +++ b/src/components/moments/MomentPost.tsx @@ -70,10 +70,6 @@ const MomentPost: React.FC = ({item, userXId, screenType}) => { } }; - useEffect(() => { - console.log('Tags have been altered'); - }, [tags]); - return (