diff options
author | Justin Shillingford <jgs272@cornell.edu> | 2020-08-14 16:39:26 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-14 16:39:26 -0400 |
commit | 59ea758ba64dd4e00f12b5ceb941d0ea5e273210 (patch) | |
tree | 6a698457be38c484bb9f93e3caf2f8e32bb7be8d | |
parent | 1979a2b55ebe560b9d20862bd835343516b40379 (diff) |
[TMA-19] Social Media Post Container (#31)
* Basic mostly functional implementation
Need to figure out why API is being called so much
* Hey it works now! Without a million API calls!
* Fixed bug where app would crash upon login
Also updated property names to be more appropriate
* Added post datetime and social icon
* Updated error message
* Fixed typecheck errors
I don't know that these fixes are the best since I don't think they're generalizable
* Formatted datetime in PostHeader
-rw-r--r-- | src/components/common/post/Post.tsx | 12 | ||||
-rw-r--r-- | src/components/common/post/PostHeader.tsx | 68 | ||||
-rw-r--r-- | src/components/profile/Feed.tsx | 14 | ||||
-rw-r--r-- | src/constants/api.ts | 1 | ||||
-rw-r--r-- | src/routes/authentication/AuthProvider.tsx | 24 | ||||
-rw-r--r-- | src/types/types.ts | 12 |
6 files changed, 116 insertions, 15 deletions
diff --git a/src/components/common/post/Post.tsx b/src/components/common/post/Post.tsx index d6c5a7d6..e5f68917 100644 --- a/src/components/common/post/Post.tsx +++ b/src/components/common/post/Post.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {StyleSheet, View} from 'react-native'; +import {StyleSheet, View, Image} from 'react-native'; import {PostType} from '../../../types'; import PostHeader from './PostHeader'; import {SCREEN_WIDTH} from '../../../utils'; @@ -7,11 +7,15 @@ import {SCREEN_WIDTH} from '../../../utils'; interface PostProps { post: PostType; } -const Post: React.FC<PostProps> = ({post: {owner}}) => { +const Post: React.FC<PostProps> = ({post: {owner, instagram, social}}) => { return ( <> - <PostHeader owner={owner} /> - <View style={styles.image} /> + <PostHeader post={instagram} owner={owner} social={social} /> + <View style={styles.image}> + {instagram && ( + <Image style={styles.image} source={{uri: instagram.media_url}} /> + )} + </View> </> ); }; diff --git a/src/components/common/post/PostHeader.tsx b/src/components/common/post/PostHeader.tsx index 8558d21d..a07efd10 100644 --- a/src/components/common/post/PostHeader.tsx +++ b/src/components/common/post/PostHeader.tsx @@ -1,17 +1,57 @@ import React from 'react'; -import {UserType} from '../../../types'; +import {UserType, InstagramPostType} from '../../../types'; import {View, StyleSheet, Image, Text} from 'react-native'; import {AuthContext} from '../../../routes/authentication'; +import moment from 'moment'; const AVATAR_DIM = 35; interface PostHeaderProps { owner: UserType; + post: InstagramPostType | undefined; + social: string; } -const PostHeader: React.FC<PostHeaderProps> = ({owner: {username}}) => { +const PostHeader: React.FC<PostHeaderProps> = ({ + owner: {username}, + post, + social, +}) => { const {avatar} = React.useContext(AuthContext); + switch (social) { + case 'Instagram': + var icon = require('../../../assets/images/instagram-icon.png'); + break; + case 'Facebook': + var icon = require('../../../assets/images/facebook-icon.png'); + break; + case 'Twitter': + var icon = require('../../../assets/images/twitter-icon.png'); + break; + case 'Twitch': + var icon = require('../../../assets/images/twitch-icon.png'); + break; + case 'Pinterest': + var icon = require('../../../assets/images/pinterest-icon.png'); + break; + case 'Whatsapp': + var icon = require('../../../assets/images/whatsapp-icon.png'); + break; + case 'Linkedin': + var icon = require('../../../assets/images/linkedin-icon.png'); + break; + case 'Snapchat': + var icon = require('../../../assets/images/snapchat-icon.png'); + break; + case 'Youtube': + var icon = require('../../../assets/images/youtube-icon.png'); + break; + default: + var icon = require('../../../assets/images/logo.png'); + break; + } + return ( <View style={styles.container}> - <View style={styles.leftElem}> + <View style={styles.topRow}> <Image style={styles.avatar} source={ @@ -21,19 +61,26 @@ const PostHeader: React.FC<PostHeaderProps> = ({owner: {username}}) => { } /> <Text style={styles.username}>{username}</Text> + {post && <Image style={styles.icon} source={icon} />} </View> + {post && ( + <Text style={styles.timestamp}> + {moment(post.timestamp).format('LL')} at{' '} + {moment(post.timestamp).format('LT')} + </Text> + )} </View> ); }; const styles = StyleSheet.create({ container: { - flexDirection: 'row', + flexDirection: 'column', justifyContent: 'space-between', padding: 10, backgroundColor: 'white', }, - leftElem: { + topRow: { flexDirection: 'row', alignItems: 'center', }, @@ -43,9 +90,20 @@ const styles = StyleSheet.create({ borderRadius: AVATAR_DIM / 2, marginRight: 10, }, + icon: { + width: AVATAR_DIM, + height: AVATAR_DIM, + borderRadius: AVATAR_DIM / 2, + marginLeft: '55%', + }, username: { fontSize: 18, }, + timestamp: { + color: '#6A757D', + fontSize: 11, + marginLeft: AVATAR_DIM + 10, + }, }); export default PostHeader; diff --git a/src/components/profile/Feed.tsx b/src/components/profile/Feed.tsx index 6780f8c5..a10d8d6d 100644 --- a/src/components/profile/Feed.tsx +++ b/src/components/profile/Feed.tsx @@ -1,17 +1,21 @@ import React from 'react'; import {PostType, UserType} from '../../types'; import {Post} from '../common'; +import {AuthContext} from '../../routes/authentication'; interface FeedProps { user: UserType; } const Feed: React.FC<FeedProps> = ({user}) => { + const {instaPosts} = React.useContext(AuthContext); const posts: Array<PostType> = []; - const dummyPost: PostType = { - owner: user, - }; - for (let i = 0; i < 20; i++) { - posts.push(dummyPost); + for (let i = 0; i < 10; i++) { + const testPost: PostType = { + owner: user, + instagram: instaPosts[i], + social: 'Instagram', + }; + posts.push(testPost); } return ( <> diff --git a/src/constants/api.ts b/src/constants/api.ts index fd654c53..057b5da7 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -8,3 +8,4 @@ export const VERIFY_OTP_ENDPOINT: string = API_URL + 'verify-otp/'; export const PROFILE_INFO_ENDPOINT: string = API_URL + 'user-profile-info/'; 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/'; diff --git a/src/routes/authentication/AuthProvider.tsx b/src/routes/authentication/AuthProvider.tsx index bd5706f3..e52d56bc 100644 --- a/src/routes/authentication/AuthProvider.tsx +++ b/src/routes/authentication/AuthProvider.tsx @@ -1,11 +1,12 @@ import React, {useEffect} from 'react'; import {createContext, useState} from 'react'; import RNFetchBlob from 'rn-fetch-blob'; -import {UserType, ProfileType} from '../../types'; +import {UserType, ProfileType, InstagramPostType} from '../../types'; import { PROFILE_INFO_ENDPOINT, AVATAR_PHOTO_ENDPOINT, COVER_PHOTO_ENDPOINT, + GET_IG_POSTS_ENDPOINT, } from '../../constants'; interface AuthContextProps { @@ -15,6 +16,7 @@ interface AuthContextProps { logout: () => void; avatar: string | null; cover: string | null; + instaPosts: Array<InstagramPostType>; } const NO_USER: UserType = { userId: '', @@ -32,6 +34,7 @@ export const AuthContext = createContext<AuthContextProps>({ logout: () => {}, avatar: null, cover: null, + instaPosts: [], }); /** @@ -42,6 +45,7 @@ const AuthProvider: React.FC = ({children}) => { const [profile, setProfile] = useState<ProfileType>(NO_PROFILE); const [avatar, setAvatar] = useState<string | null>(null); const [cover, setCover] = useState<string | null>(null); + const [instaPosts, setInstaPosts] = useState<Array<InstagramPostType>>([]); const {userId} = user; useEffect(() => { @@ -95,9 +99,26 @@ const AuthProvider: React.FC = ({children}) => { console.log(error); } }; + const loadInstaPosts = async () => { + try { + const response = await fetch(GET_IG_POSTS_ENDPOINT + `${userId}/`, { + method: 'GET', + }); + const status = response.status; + if (status === 200) { + let ig_posts = await response.json(); + setInstaPosts(ig_posts); + } else { + setInstaPosts([]); + } + } catch (error) { + console.log(error); + } + }; loadProfileInfo(); loadAvatar(); loadCover(); + loadInstaPosts(); }, [userId]); return ( @@ -107,6 +128,7 @@ const AuthProvider: React.FC = ({children}) => { profile, avatar, cover, + instaPosts, login: (id, username) => { setUser({...user, userId: id, username}); }, diff --git a/src/types/types.ts b/src/types/types.ts index d6f69b85..6dabc0bc 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -9,8 +9,20 @@ export interface ProfileType { website: string; } +export interface InstagramPostType { + post_id: string; + username: string; + media_url: string; + media_type: string; + caption: string; + timestamp: string; + permalink: string; +} + export interface PostType { owner: UserType; + social: string; + instagram: InstagramPostType | undefined; } export interface LinkerType { |