From 22142e2f8aa7d5eed8de1e520fd5ce825d2c63ca Mon Sep 17 00:00:00 2001 From: Shravya Ramesh <37447613+shravyaramesh@users.noreply.github.com> Date: Tue, 13 Oct 2020 13:34:42 -0700 Subject: TMA - 232 Create caption screen with image picker (#53) * Added image picture functionality * Created caption screen and uploads to moments endpoint consisting of the picture and caption only Co-authored-by: Husam Salhab <47015061+hsalhab@users.noreply.github.com> --- src/components/profile/CaptionScreenHeader.tsx | 37 ++++++ src/components/profile/Moment.tsx | 19 ++- src/components/profile/index.ts | 1 + src/constants/api.ts | 1 + src/routes/profile/Profile.tsx | 3 +- src/routes/profile/ProfileStack.tsx | 1 + src/screens/profile/CaptionScreen.tsx | 156 +++++++++++++++++++++++++ src/screens/profile/index.ts | 1 + 8 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 src/components/profile/CaptionScreenHeader.tsx create mode 100644 src/screens/profile/CaptionScreen.tsx (limited to 'src') diff --git a/src/components/profile/CaptionScreenHeader.tsx b/src/components/profile/CaptionScreenHeader.tsx new file mode 100644 index 00000000..4715b4ef --- /dev/null +++ b/src/components/profile/CaptionScreenHeader.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import {Text, View, StyleSheet, ViewProps} from 'react-native'; +interface CaptionScreenHeaderProps extends ViewProps { + title: string; +} +const CaptionScreenHeader: React.FC = ({ + title, + style, +}) => { + return ( + + + {title} + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + justifyContent: 'center', + height: 30, + }, + headerContainer: { + position: 'absolute', + left: '50%', + }, + header: { + position: 'relative', + right: '50%', + fontSize: 20, + fontWeight: 'bold', + color: 'white', + }, +}); +export default CaptionScreenHeader; diff --git a/src/components/profile/Moment.tsx b/src/components/profile/Moment.tsx index 0fbabe8f..6ae8d38e 100644 --- a/src/components/profile/Moment.tsx +++ b/src/components/profile/Moment.tsx @@ -1,6 +1,6 @@ import {useNavigation} from '@react-navigation/native'; import React from 'react'; -import {Alert, StyleSheet, View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import {Text} from 'react-native-animatable'; import {ScrollView, TouchableOpacity} from 'react-native-gesture-handler'; import LinearGradient from 'react-native-linear-gradient'; @@ -8,6 +8,7 @@ import PlusIcon from '../../assets/icons/plus_icon-01.svg'; import BigPlusIcon from '../../assets/icons/plus_icon-02.svg'; import {MOMENTS_TITLE_COLOR} from '../../constants'; import {SCREEN_WIDTH} from '../../utils'; +import ImagePicker from 'react-native-image-crop-picker'; interface MomentProps { title: string; @@ -16,9 +17,21 @@ interface MomentProps { const Moment: React.FC = ({title, images}) => { const navigation = useNavigation(); + const navigateToImagePicker = () => { - Alert.alert('Perform navigation to Image Picker with Caption screen'); - // navigation.navigate('') + ImagePicker.openPicker({ + width: 580, + height: 580, + cropping: true, + cropperToolbarTitle: 'Upload a moment', + mediaType: 'photo', + }) + .then((picture) => { + if ('path' in picture) { + navigation.navigate('CaptionScreen', {title: title, image: picture}); + } + }) + .catch(() => {}); }; return ( diff --git a/src/components/profile/index.ts b/src/components/profile/index.ts index 2d16c830..4eb435df 100644 --- a/src/components/profile/index.ts +++ b/src/components/profile/index.ts @@ -5,3 +5,4 @@ export {default as ProfileCutout} from './ProfileCutout'; export {default as ProfileBody} from './ProfileBody'; export {default as ProfileHeader} from './ProfileHeader'; export {default as Feed} from './Feed'; +export {default as CaptionScreenHeader} from './CaptionScreenHeader'; diff --git a/src/constants/api.ts b/src/constants/api.ts index fa8cd0b3..b1ec19aa 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -12,4 +12,5 @@ export const COVER_PHOTO_ENDPOINT: string = API_URL + 'large-profile-pic/'; export const AVATAR_PHOTO_ENDPOINT: string = API_URL + 'small-profile-pic/'; export const GET_IG_POSTS_ENDPOINT: string = API_URL + 'posts-ig/'; export const SEARCH_ENDPOINT: string = API_URL + 'search/'; +export const MOMENTS_UPLOAD_ENDPOINT: string = API_URL + 'upload-moments/'; export const VERIFY_INVITATION_CODE_ENDPOUNT: string = API_URL + 'verify-code/'; diff --git a/src/routes/profile/Profile.tsx b/src/routes/profile/Profile.tsx index caa75f3b..eaf5f3aa 100644 --- a/src/routes/profile/Profile.tsx +++ b/src/routes/profile/Profile.tsx @@ -1,6 +1,6 @@ import React from 'react'; import {AvatarTitle} from '../../components'; -import {ProfileScreen, SocialMediaTaggs} from '../../screens'; +import {ProfileScreen, CaptionScreen, SocialMediaTaggs} from '../../screens'; import {ProfileStack} from './ProfileStack'; const Profile: React.FC = () => { @@ -20,6 +20,7 @@ const Profile: React.FC = () => { headerTitle: () => , }} /> + ); }; diff --git a/src/routes/profile/ProfileStack.tsx b/src/routes/profile/ProfileStack.tsx index 9a39aa97..c1da67c1 100644 --- a/src/routes/profile/ProfileStack.tsx +++ b/src/routes/profile/ProfileStack.tsx @@ -6,6 +6,7 @@ export type ProfileStackParams = { socialMediaType: string; socialMediaHandle: string; }; + CaptionScreen: {title: string; image: object}; }; export const ProfileStack = createStackNavigator(); diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx new file mode 100644 index 00000000..3eb6c47b --- /dev/null +++ b/src/screens/profile/CaptionScreen.tsx @@ -0,0 +1,156 @@ +import React, {useState} from 'react'; +import {StyleSheet, View, Image, Alert} from 'react-native'; +import {Button} from 'react-native-elements'; +import {SearchBackground, TabsGradient, TaggBigInput} from '../../components'; +import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; +import AsyncStorage from '@react-native-community/async-storage'; +import {UserType} from '../../types'; +import {RouteProp} from '@react-navigation/native'; +import {ProfileStackParams} from 'src/routes'; +import {StackNavigationProp} from '@react-navigation/stack'; +import {CaptionScreenHeader} from '../../components/profile'; +import {MOMENTS_UPLOAD_ENDPOINT} from '../../constants'; +import {AuthContext} from '../../routes/authentication'; + +const NO_USER: UserType = { + userId: '', + username: '', +}; + +/** + * Upload Screen to allow users to upload posts to Tagg + */ +type CaptionScreenRouteProp = RouteProp; +type CaptionScreenNavigationProp = StackNavigationProp< + ProfileStackParams, + 'CaptionScreen' +>; +interface CaptionScreenProps { + route: CaptionScreenRouteProp; + navigation: CaptionScreenNavigationProp; +} + +const CaptionScreen: React.FC = ({route, navigation}) => { + const {title, image} = route.params; + const { + user: {userId}, + } = React.useContext(AuthContext); + const [user, setUser] = useState(NO_USER); + const [caption, setCaption] = React.useState(''); + + const handleCaptionUpdate = (caption: string) => { + setCaption(caption); + }; + + const handleShare = async () => { + try { + const token = await AsyncStorage.getItem('token'); + if (!token) { + setUser(NO_USER); + return; + } + const request = new FormData(); + const uri = image.path; + const name = image.filename; + request.append('image', { + uri: uri, + name: name, + type: 'image/jpg', + }); + request.append('moment', title); + request.append('user_id', userId); + request.append('caption', caption); + let response = await fetch(MOMENTS_UPLOAD_ENDPOINT, { + method: 'POST', + headers: { + 'Content-Type': 'multipart/form-data', + Authorization: 'Token ' + token, + }, + body: request, + }); + let statusCode = response.status; + if (statusCode === 200) { + navigation.navigate('Profile'); + } else { + Alert.alert('An error occured while uploading. Please try again!'); + } + } catch (err) { + Alert.alert('An error occured during authenticaion. Please login again!'); + } + }; + return ( + + + +