Skip to content
Snippets Groups Projects
Commit c4ad89b0 authored by Chloé JACOB's avatar Chloé JACOB :alien:
Browse files

intégration de la vue post/X

parent bae6f4a7
Branches
Tags
No related merge requests found
......@@ -66,7 +66,7 @@ return <>
{caption && <p className="text-red-500 mb-3">{caption}</p>}
<div className="flex gap-2">
{isLiked ? (
<button className={`px-4 py-1 bg-${isLiked ? 'red-500' : 'slate-400'} rounded-full flex items-center gap-2`}
<button className={`px-4 py-1 bg-${isLiked ? 'red-500' : 'gray-400'} rounded-full flex items-center gap-2`}
onClick={() => {
dispatch(unlikePostAsync(postid));
}}
......@@ -75,7 +75,7 @@ return <>
<span className="mt-1">{likes}</span>
</button>
) : (
<button className={`px-4 py-1 bg-${isLiked ? 'red-500' : 'slate-400'} rounded-full flex items-center gap-2`}
<button className={`px-4 py-1 bg-${isLiked ? 'red-500' : 'gray-400'} rounded-full flex items-center gap-2`}
onClick={() => {
dispatch(likepostAsync(postid));
}}
......
import { selectPost } from '../redux/post/selectors';
import useAppSelector from './useAppSelector';
const usePost = () => {
const items = useAppSelector(selectPost);
return { items };
};
export default usePost;
......@@ -16,24 +16,6 @@ export const fetchFeedUserAsync = (): AppThunkAction<Promise<void>> => {
};
};
// Calcul temps de publication d'un post / commentaire
export const calculateTime = (createdAt: string): string => {
const createdDate = new Date(createdAt);
const currentDate = new Date();
const timeDiff = Math.abs(currentDate.getTime() - createdDate.getTime());
const diffMinutes = Math.floor(timeDiff / (1000 * 60)); //"Math.ceil" -> entier supérieur / "Math.floor" -> entier inférieur
const diffHours = Math.floor(timeDiff / (1000 * 60 * 60));
const diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
if (diffMinutes < 60) {
return diffMinutes === 1 ? `${diffMinutes} minute ago` : `${diffMinutes} minutes ago`;
} else if (diffHours < 24) {
return diffHours === 1 ? `${diffHours} hour ago` : `${diffHours} hours ago`;
} else {
return diffDays === 1 ? `${diffDays} day ago` : `${diffDays} days ago`;
}
}
// Like post
export const likepostAsync = (postId: number): AppThunkAction<Promise<void>> => {
return async (dispatch, getState, api) => {
......
import { Instalike } from '@jmetterrothan/instalike';
import { AppAction } from '../types';
export const SET_POST = 'POST/SET_POST';
export const REQUEST_POST_START = 'POST/REQUEST_FEED_START';
export const REQUEST_POST_SUCCESS = 'POST/REQUEST_FEED_SUCCESS';
export const REQUEST_POST_FAILURE = 'POST/REQUEST_FEED_FAILURE';
export type setPostAction = AppAction<typeof SET_POST, Instalike.Post>;
export type LoadPostStartAction = AppAction<typeof REQUEST_POST_START>;
export type LoadPostEndSucessAction = AppAction<typeof REQUEST_POST_SUCCESS>;
export type LoadPostEndFailureAction = AppAction<typeof REQUEST_POST_FAILURE>;
export type PostAction = setPostAction | LoadPostStartAction | LoadPostEndSucessAction | LoadPostEndFailureAction;
export const setPost = (data: Instalike.Post): setPostAction => ({
type: SET_POST,
payload: data,
});
export const loadPostAction = (): LoadPostStartAction => ({
type: REQUEST_POST_START,
payload: undefined,
});
export const sucessPostAction = (): LoadPostEndSucessAction => ({
type: REQUEST_POST_SUCCESS,
payload: undefined,
});
export const failurePostAction = (): LoadPostEndFailureAction => ({
type: REQUEST_POST_FAILURE,
payload: undefined,
});
\ No newline at end of file
import { Instalike } from '@jmetterrothan/instalike';
import { Reducer } from 'redux';
import { PostAction, SET_POST } from './actions';
type PostState = {
data?: Instalike.Post;
};
const intialState: PostState = {
data: undefined,
};
const postReducer: Reducer<PostState, PostAction> = (state = intialState, action) => {
switch (action.type) {
case SET_POST:
return { ...state, data: action.payload };
default:
return state;
}
};
export default postReducer;
\ No newline at end of file
import { RootState } from '../store';
export const selectPost = (state: RootState) => state.post.data;
\ No newline at end of file
import { Instalike } from '@jmetterrothan/instalike';
import { data } from 'autoprefixer';
import { AppThunkAction } from '../types';
import { failurePostAction, loadPostAction, setPost, sucessPostAction } from './actions';
export const fetchPostAsync = (postid: number): AppThunkAction<Promise<void>> => {
return async (dispatch, getState, api) => {
dispatch(loadPostAction());
try {
const { data } = await api.posts.find(postid).fetch();
dispatch(setPost(data));
dispatch(sucessPostAction());
} catch (eee) {
dispatch(failurePostAction());
throw eee;
}
};
};
// Calcul temps de publication d'un post / commentaire
export const calculateTime = (createdAt: string): string => {
const createdDate = new Date(createdAt);
const currentDate = new Date();
const timeDiff = Math.abs(currentDate.getTime() - createdDate.getTime());
const diffMinutes = Math.floor(timeDiff / (1000 * 60)); //"Math.ceil" -> entier supérieur / "Math.floor" -> entier inférieur
const diffHours = Math.floor(timeDiff / (1000 * 60 * 60));
const diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
if (diffMinutes < 60) {
return diffMinutes === 1 ? `${diffMinutes} minute ago` : `${diffMinutes} minutes ago`;
} else if (diffHours < 24) {
return diffHours === 1 ? `${diffHours} hour ago` : `${diffHours} hours ago`;
} else {
return diffDays === 1 ? `${diffDays} day ago` : `${diffDays} days ago`;
}
}
......@@ -5,12 +5,14 @@ import thunk from 'redux-thunk';
import instalikeApi from '../instalikeApi';
import authReducer from './auth/reducer';
import feedReducer from './feed/reducer';
import postReducer from './post/reducer';
const rootReducer = combineReducers({
auth: authReducer,
feed: feedReducer,
post: postReducer,
});
const middleware: Middleware[] = [];
......
......@@ -10,7 +10,9 @@ import Post from '../components/Post';
import useAppDispatch from '../hooks/useAppDispatch';
import useFeedItems from '../hooks/useFeedItems';
import useUserStoryItems from '../hooks/useUserStoryItems';
import { fetchFeedUserAsync, calculateTime } from '../redux/feed/thunks';
import { fetchFeedUserAsync } from '../redux/feed/thunks';
import { calculateTime } from '../redux/post/thunks';
// import { Link } from 'react-router-dom';
const FeedView = () => {
......@@ -48,22 +50,22 @@ return <>
{feedItems &&
feedItems.map((post: Instalike.Post) => {
console.log(post)
const time_post = calculateTime(post.createdAt);
return (
<Post key={post.id}
postid={post.id}
username={post.owner.userName}
location={post.location}
time_post={time_post}
img={post.resources[0]}
caption={post.caption}
isLiked={post.viewerHasLiked}
likes={post.likesCount}
comments={post.commentsCount}
comment_post={post.previewComments}
></Post>
// <Link key={post.id} to={`/post/${post.id}`}>
<Post key={post.id}
postid={post.id}
username={post.owner.userName}
location={post.location}
time_post={calculateTime(post.createdAt)}
img={post.resources[0]}
caption={post.caption}
isLiked={post.viewerHasLiked}
likes={post.likesCount}
comments={post.commentsCount}
comment_post={post.previewComments}
></Post>
// </Link>
);
})}
......
import { useEffect } from 'react';
import { Navigate, useParams } from 'react-router-dom';
import useAppDispatch from '../hooks/useAppDispatch';
import usePost from '../hooks/usePostItems';
import { fetchPostAsync, calculateTime } from '../redux/post/thunks';
import Post from '../components/Post';
// ICONS
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faLocationDot, faEllipsisVertical, faHeart, faCommentDots } from '@fortawesome/free-solid-svg-icons';
import { faFaceSmile } from '@fortawesome/free-regular-svg-icons';
const usePostId = () => {
const { id } = useParams();
return id ? parseInt(id, 10) : -1;
const { id } = useParams();
return id ? parseInt(id, 10) : -1;
};
const PostView = () => {
const id = usePostId();
const dispatch = useAppDispatch();
const id = usePostId();
useEffect(() => {
dispatch(fetchPostAsync(id));
}, []);
const post = usePost().items;
if (id === -1) {
return <Navigate to=".." />;
}
if (id === -1) {
return <Navigate to="feed" />;
}
return <>
<div className="bg-gray-900/50 h-full">
<div className="max-w-[640px] mx-auto py-16 px-4">
{/* A POST */}
Post #{id}
<div className="rounded-xl overflow-hidden shadow-post shadow-gray-900 border-none bg-white">
{/* HEADER POST */}
<div className="flex justify-between p-4">
<div className="flex items-center gap-4">
<div className="rounded-full overflow-hidden w-12 h-12">
<img
src="https://cdn4.vectorstock.com/i/1000x1000/82/53/white-letter-a-logo-on-red-background-vector-26888253.jpg"
alt="" />
</div>
<div>
<p className="font-bold">j.metterrothan</p>
<div className="flex items-center gap-1">
<FontAwesomeIcon className="text-[14px]" icon={faLocationDot} />
<p className="text-sm mt-[2px]">Italy, 13 days ago</p>
</div>
</div>
</div>
<div className="w-10 flex justify-center items-center">
<FontAwesomeIcon className="text-[22px]" icon={faEllipsisVertical} />
</div>
</div>
{/* IMAGE POST */}
<div className="flex justify-center items-center">
<img
src="https://cdn4.vectorstock.com/i/1000x1000/82/53/white-letter-a-logo-on-red-background-vector-26888253.jpg"
alt="" />
</div>
{/* BIO POST */}
<div className="p-4">
<p className="text-red-500">Quo praesentium facilis voluptatibus consequatur.</p>
<div className="flex mt-3 gap-2">
<button type="button" className="px-4 py-1 bg-slate-400 rounded-full flex items-center gap-2">
<FontAwesomeIcon className="text-[20px]" icon={faHeart} />
<span className="mt-1">0</span>
</button>
<button type="button" className="px-4 flex items-center gap-2">
<FontAwesomeIcon className="text-[20px]" icon={faCommentDots} />
<span className="mt-1">0</span>
</button>
</div>
</div>
{/* WRITE A COMMENT POST */}
<div className="p-4 border-t-[0.8px]">
<form action="" className="flex gap-4">
<div>
<div className="rounded-full overflow-hidden w-12 h-12">
<img
src="https://cdn4.vectorstock.com/i/1000x1000/82/53/white-letter-a-logo-on-red-background-vector-26888253.jpg"
alt="" />
</div>
</div>
<input className="w-full" placeholder="Add a comment..."></input>
<div className="flex items-center gap-4">
<FontAwesomeIcon className="text-[24px]" icon={faFaceSmile} />
<button type="button" className="px-4 pt-[8px] pb-[6px] bg-slate-400 rounded-md font-bold capitalize">send</button>
</div>
</form>
</div>
{/* COMMENTS POST -> à cacher s'il y en a pas */}
<div className="flex justify-between p-4 border-t-[0.8px]">
<div className="flex items-center gap-4">
<div className="rounded-full overflow-hidden w-8 h-8">
<img
src="https://cdn4.vectorstock.com/i/1000x1000/82/53/white-letter-a-logo-on-red-background-vector-26888253.jpg"
alt="" />
</div>
<div>
<p><span className="font-bold mr-1">j.metterrothan</span>test</p>
<p className="text-sm">7 days ago</p>
</div>
</div>
<div className="w-10 flex justify-center items-center">
<FontAwesomeIcon className="text-[28px]" icon={faEllipsisVertical} />
</div>
</div>
{post && (
<Post key={post.id}
postid={post.id}
username={post.owner.userName}
location={post.location}
time_post={calculateTime(post.createdAt)}
img={post.resources[0]}
caption={post.caption}
isLiked={post.viewerHasLiked}
likes={post.likesCount}
comments={post.commentsCount}
comment_post={post.previewComments}
></Post>
)}
</div>
</div>
</div>
</>;
};
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment