Skip to content

Commit

Permalink
feat: add get home tweets
Browse files Browse the repository at this point in the history
  • Loading branch information
neysidev committed Aug 29, 2021
1 parent 6d5b9c3 commit 5a9bd96
Show file tree
Hide file tree
Showing 16 changed files with 239 additions and 47 deletions.
15 changes: 10 additions & 5 deletions client/src/components/Common/Tweet.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import styled, { css } from 'styled-components'
import { Link } from 'react-router-dom'

import theme from '../../styles/ThemeStyles'
import TwitterBox from './TwitterBox'
import TwitterCard from './TwitterCard'
import {
ChatboxOutline,
HeartOutline,
RepeatOutline,
ShareSocialOutline
} from 'react-ionicons'

import useAuth from '../../hooks/useAuth'
import theme from '../../styles/ThemeStyles'
import TwitterBox from './TwitterBox'
import TwitterCard from './TwitterCard'

interface ITweet {
username: string
text: string
Expand All @@ -27,7 +28,11 @@ type ActionProps = {
}

export default function Tweet(props: ITweet) {
const url = `/user/${props.username}`
const { user } = useAuth()
const url =
user.username === props.username
? `/${props.username}`
: `/user/${props.username}`

return (
<Wrapper>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Core/UserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import theme from '../../styles/ThemeStyles'
import TwitterBox from '../Common/TwitterBox'

import { IUser } from '../../store/state'
import { useUsersTweets } from '../../hooks/tweets'
import { useUsersTweets } from '../../hooks/useTweets'

type Props = {
user: IUser
Expand Down
31 changes: 27 additions & 4 deletions client/src/components/Home/WhatsHappening.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,58 @@
import styled from 'styled-components'
import { useState } from 'react'
import { Link } from 'react-router-dom'
import { useSelector } from 'react-redux'
import { useDispatch, useSelector } from 'react-redux'
import { CalendarOutline, HappyOutline, ImageOutline } from 'react-ionicons'

import * as authAction from '../../store/actions/auth'
import * as tweetService from '../../services/tweet'
import { RootState } from '../../store/state'
import theme from '../../styles/ThemeStyles'
import TwitterBox from '../Common/TwitterBox'
import TwitterButton from '../Common/TwitterButton'

export default function WhatsHappening() {
const dispatch = useDispatch()
const { user } = useSelector((state: RootState) => state.authorize)

const [text, setText] = useState<string>('')
const [loading, setLoading] = useState<boolean>(false)

const createTweet = async () => {
setText('')
setLoading(true)
await tweetService.createTweet(text)
setLoading(false)
dispatch(authAction.getHomeTweets())
}

return (
<TwitterBox>
<Wrapper>
<Link to={`/user/${user?.username}`}>
<Link to={`/${user?.username}`}>
<Profile
src={`/img/users/${user.image || 'not_found.jpg'}`}
alt={user?.name}
/>
</Link>
<div>
<TextArea placeholder="What's happening?" />
<TextArea
value={text}
onChange={e => setText(e.target.value)}
placeholder="What's happening?"
/>
<Divider />
<Footer>
<Actions>
<ImageOutline />
<HappyOutline />
<CalendarOutline />
</Actions>
<TwitterButton disabled variant="solid">
<TwitterButton
disabled={loading || text.length === 0}
variant="solid"
onClick={createTweet}
>
Tweet
</TwitterButton>
</Footer>
Expand Down
1 change: 1 addition & 0 deletions client/src/containers/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default function App() {

useEffect(() => {
dispatch(authAction.getUser())
dispatch(authAction.getHomeTweets())
// eslint-disable-next-line
}, [])

Expand Down
92 changes: 72 additions & 20 deletions client/src/containers/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,68 @@
import styled from 'styled-components'
import Tweet from '../components/Common/Tweet'
import { useEffect } from 'react'
import { People } from 'react-ionicons'
import { useDispatch } from 'react-redux'
import { Link } from 'react-router-dom'

import { home_tweets } from '../constants/tweets'
import * as authAction from '../store/actions/auth'
import { useHomeTweets } from '../hooks/useTweets'
import TrendsForYou from '../components/Core/TrendsForYou'
import YouShouldFollow from '../components/Core/YouShouldFollow'
import Tweet from '../components/Common/Tweet'
import TweetSkeleton from '../components/Skeleton/TweetSkeleton'
import TwitterContainer from '../components/Common/TwitterContainer'
import WhatsHappening from '../components/Home/WhatsHappening'
import YouShouldFollow from '../components/Core/YouShouldFollow'
import TwitterBox from '../components/Common/TwitterBox'
import TwitterButton from '../components/Common/TwitterButton'

export default function Home() {
const dispatch = useDispatch()
const { loading, tweets } = useHomeTweets()

useEffect(() => {
dispatch(authAction.getHomeTweets())
}, [dispatch])

let $tweets_content = null
if (loading) {
$tweets_content = <TweetSkeleton />
} else {
if (tweets.length === 0) {
$tweets_content = (
<TweetsEmpty>
<TwitterBox>
<People width="4rem" height="4rem" color="#ffffff" />
<h2>Do you like to follow your friends?</h2>
<Link to="/connect-people">
<TwitterButton variant="solid">Connect people</TwitterButton>
</Link>
</TwitterBox>
</TweetsEmpty>
)
} else {
$tweets_content = tweets
.map(({ tweet, user }) => (
<Tweet
key={tweet.id}
text={tweet.text}
image={user.image || ''}
name={user.name}
username={user.username || ''}
replies={tweet.replies || 0}
retweet={tweet.retweet || 0}
likes={tweet.likes || 0}
/>
))
.reverse()
}
}

return (
<TwitterContainer size="md">
<Wrapper>
<Content>
<WhatsHappening />
<Tweets>
{home_tweets
.map(tweet => (
<Tweet
key={tweet.id}
text={tweet.text}
image={tweet.user.image}
name={tweet.user.name}
username={tweet.user.username}
replies={tweet.replies}
retweet={tweet.retweet}
likes={tweet.likes}
/>
))
.reverse()}
</Tweets>
<Tweets>{$tweets_content}</Tweets>
</Content>
<Aside>
<TrendsForYou />
Expand All @@ -47,7 +81,8 @@ const Wrapper = styled.div`

const Content = styled.div`
flex: 1;
display: grid;
display: flex;
flex-direction: column;
gap: 1rem;
`

Expand All @@ -61,4 +96,21 @@ const Aside = styled.aside`
gap: 1rem;
display: flex;
flex-direction: column;
position: sticky;
`

const TweetsEmpty = styled.li`
text-align: center;
& > div {
padding: 3rem;
h2 {
margin-bottom: 0.75rem;
}
button {
padding: 0.5rem 1rem;
}
}
`
28 changes: 15 additions & 13 deletions client/src/containers/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import theme from '../styles/ThemeStyles'
import useAuth from '../hooks/useAuth'
import TwitterBox from '../components/Common/TwitterBox'
import Tweet from '../components/Common/Tweet'
import { useUsersTweets } from '../hooks/tweets'
import { useUsersTweets } from '../hooks/useTweets'
import TwitterFullscreen from '../components/Common/TwitterFullscreen'

type Params = { username: string }
Expand Down Expand Up @@ -96,18 +96,20 @@ export default function Profile() {
</Header>
<ul>
{tweets?.length !== 0 ? (
tweets?.map(tweet => (
<Tweet
key={tweet.id}
username={user?.username || ''}
image={user?.image || ''}
name={user?.name}
text={tweet.text}
likes={tweet.likes || 0}
replies={tweet.replies || 0}
retweet={tweet.retweet || 0}
/>
))
tweets
?.map(tweet => (
<Tweet
key={tweet.id}
username={user?.username || ''}
image={user?.image || ''}
name={user?.name}
text={tweet.text}
likes={tweet.likes || 0}
replies={tweet.replies || 0}
retweet={tweet.retweet || 0}
/>
))
.reverse()
) : (
<NotTwitted>{user?.name} has not tweeted yet</NotTwitted>
)}
Expand Down
10 changes: 10 additions & 0 deletions client/src/hooks/tweets.tsx → client/src/hooks/useTweets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,13 @@ export function useUsersTweets() {
tweetsCount: userTweets.tweets.length
}
}

export function useHomeTweets() {
const homeTweets = useSelector((state: RootState) => state.homeTweets)

return {
loading: homeTweets.loading,
error: homeTweets.error,
tweets: homeTweets.tweets
}
}
24 changes: 24 additions & 0 deletions client/src/services/tweet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,27 @@ export async function getUserTweets() {
return { success: false, message: err }
}
}

export async function getHomeTweets() {
try {
const { data } = await axios.get('/tweets/timeline')

return data.error
? { success: false, message: data.error }
: { success: true, tweets: data }
} catch (err) {
return { success: false, message: err }
}
}

export async function createTweet(text: string) {
try {
const { data } = await axios.post('/tweets', { text })

return data.error
? { success: false, message: data.error }
: { success: true, tweet: data }
} catch (err) {
return { success: false, message: err }
}
}
16 changes: 16 additions & 0 deletions client/src/store/actions/auth.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Dispatch } from 'redux'
import * as types from '../types'

import * as authService from '../../services/auth'
import * as tweetService from '../../services/tweet'

interface User {
email: string
Expand Down Expand Up @@ -28,6 +30,20 @@ export const getUser = () => async (dispatch: Dispatch) => {
}
}

export const getHomeTweets = () => async (dispatch: Dispatch) => {
dispatch({ type: types.GET_HOME_TWEETS_REQUEST })

try {
const res = await tweetService.getHomeTweets()

res.success
? dispatch({ type: types.GET_HOME_TWEETS_SUCCESS, tweets: res.tweets })
: dispatch({ type: types.GET_HOME_TWEETS_FAILURE, error: res.message })
} catch (error) {
dispatch({ type: types.GET_HOME_TWEETS_FAILURE, error })
}
}

export const loginUser = (user: User) => async (dispatch: Dispatch) => {
const { email, password } = user
dispatch({ type: types.LOGIN_USER_REQUEST })
Expand Down
5 changes: 3 additions & 2 deletions client/src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import {
registerReducer
} from './reducers/auth'
import { profileReducer } from './reducers/profile'
import { userTweetsReducer } from './reducers/tweet'
import { userTweetsReducer, homeTweetsReducer } from './reducers/tweet'

const reducer = combineReducers({
authorize: authorizeReducer,
login: loginReducer,
profile: profileReducer,
register: registerReducer,
userTweets: userTweetsReducer
userTweets: userTweetsReducer,
homeTweets: homeTweetsReducer
})

const initialState = {}
Expand Down
13 changes: 13 additions & 0 deletions client/src/store/reducers/tweet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ interface State {

const initialState: State = { loading: false, tweets: [] }

export function homeTweetsReducer(state = initialState, action: Action) {
switch (action.type) {
case types.GET_HOME_TWEETS_REQUEST:
return { loading: true, tweets: [] }
case types.GET_HOME_TWEETS_SUCCESS:
return { loading: false, tweets: action.tweets }
case types.GET_HOME_TWEETS_FAILURE:
return { loading: false, error: action.error }
default:
return state
}
}

export function userTweetsReducer(state = initialState, action: Action) {
switch (action.type) {
case types.GET_USER_TWEETS_REQUEST:
Expand Down
Loading

0 comments on commit 5a9bd96

Please sign in to comment.