parent
d73bd1dd04
commit
ca4fb32413
|
|
@ -7,12 +7,14 @@ interface postSliceInterface {
|
|||
status: Status;
|
||||
followedPosts: Post[];
|
||||
globalPosts: Post[];
|
||||
aPost: Post | null;
|
||||
}
|
||||
|
||||
const initialState: postSliceInterface = {
|
||||
status: Status.idle,
|
||||
followedPosts: [],
|
||||
globalPosts: [],
|
||||
aPost: null,
|
||||
};
|
||||
|
||||
export const postSlice = createSlice({
|
||||
|
|
@ -28,6 +30,9 @@ export const postSlice = createSlice({
|
|||
setGlobalPosts: (state, action) => {
|
||||
state.globalPosts = action.payload;
|
||||
},
|
||||
setAPost: (state, action) => {
|
||||
state.aPost = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -69,7 +74,29 @@ export const unLikePost =
|
|||
dispatch(setStatus(Status.idle));
|
||||
};
|
||||
|
||||
export const { setFollowedPosts, setGlobalPosts, setStatus } =
|
||||
export const fetchAPost =
|
||||
(postId: number): AppThunk =>
|
||||
async (dispatch: any) => {
|
||||
const postApi = createApi(store);
|
||||
|
||||
dispatch(setStatus(Status.loading));
|
||||
const response = await postApi.getPost(postId);
|
||||
dispatch(setAPost(response.data));
|
||||
dispatch(setStatus(Status.idle));
|
||||
};
|
||||
|
||||
export const commentAPost =
|
||||
(postId: number, comment: string): AppThunk =>
|
||||
async (dispatch: any) => {
|
||||
const postApi = createApi(store);
|
||||
|
||||
dispatch(setStatus(Status.loading));
|
||||
await postApi.commentPost(postId, { content: comment });
|
||||
dispatch(fetchAPost(postId));
|
||||
dispatch(setStatus(Status.idle));
|
||||
};
|
||||
|
||||
export const { setFollowedPosts, setGlobalPosts, setStatus, setAPost } =
|
||||
postSlice.actions;
|
||||
|
||||
export default postSlice.reducer;
|
||||
|
|
@ -77,6 +104,7 @@ export default postSlice.reducer;
|
|||
export const selectFollowedPosts = (state: any) => state.post.followedPosts;
|
||||
export const selectAllPosts = (state: any) => state.post.globalPosts;
|
||||
export const selectStatus = (state: any) => state.post.status;
|
||||
export const selectAPost = (state: any) => state.post.aPost;
|
||||
|
||||
function createApi(store: Store) {
|
||||
return new PostsApi(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { User, UserWithRelations } from "../api";
|
|||
|
||||
interface AppAvatarProps {
|
||||
user: User | UserWithRelations;
|
||||
small?: boolean;
|
||||
}
|
||||
|
||||
export function AppAvatar(props: AppAvatarProps) {
|
||||
|
|
@ -10,6 +11,10 @@ export function AppAvatar(props: AppAvatarProps) {
|
|||
<Avatar
|
||||
alt={`${props.user.firstName} ${props.user.lastName}`}
|
||||
src={`/images/${props.user.profilePictureId}`}
|
||||
sx={{
|
||||
width: props.small ? "24px" : "42px",
|
||||
height: props.small ? "24px" : "42px",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { Provider } from "react-redux";
|
|||
import { store } from "./app/store";
|
||||
import PostList from "./routes/postList";
|
||||
import Profile from "./routes/profile";
|
||||
import Post from "./routes/post";
|
||||
import PostView from "./routes/post";
|
||||
import NewPost from "./routes/newPost";
|
||||
import Search from "./routes/search";
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ const router = createBrowserRouter([
|
|||
},
|
||||
{
|
||||
path: "post/:id",
|
||||
element: <Post />,
|
||||
element: <PostView />,
|
||||
},
|
||||
{
|
||||
path: "search",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,134 @@
|
|||
export default function Post() {
|
||||
return <>Post</>;
|
||||
import { useSelector } from "react-redux";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { commentAPost, fetchAPost, selectAPost } from "../app/postSlice";
|
||||
import { useAppDispatch } from "../app/store";
|
||||
import { useEffect } from "react";
|
||||
import React from "react";
|
||||
import { Post } from "../api";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Divider,
|
||||
Paper,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { AppAvatar } from "../components/appAvatar";
|
||||
|
||||
export default function PostView() {
|
||||
const postId = useParams<{ id: string }>().id;
|
||||
const storePost = useSelector(selectAPost);
|
||||
const [postToDisplay, setPostToDisplay] = React.useState<Post | null>(null);
|
||||
const [newComentText, setNewCommentText] = React.useState("");
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchAPost(parseInt(postId!, 10)));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setPostToDisplay(storePost);
|
||||
}, [storePost]);
|
||||
|
||||
const handleCommentPost = () => {
|
||||
if (newComentText.length > 0) {
|
||||
dispatch(commentAPost(postToDisplay!.id!, newComentText));
|
||||
setNewCommentText("");
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancelComment = () => {
|
||||
setNewCommentText("");
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
width: "60%",
|
||||
margin: "auto",
|
||||
minWidth: "330px",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ width: "100%" }}>
|
||||
<Paper>
|
||||
<Box sx={{ margin: "1rem" }}>
|
||||
<Box
|
||||
sx={{ display: "flex", alignItems: "center", paddingTop: "1rem" }}
|
||||
>
|
||||
{postToDisplay?.createdBy && (
|
||||
<AppAvatar user={postToDisplay?.createdBy!} />
|
||||
)}
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
sx={{ mb: "0.2rem", ml: "0.3rem" }}
|
||||
>
|
||||
{postToDisplay?.createdBy?.firstName}{" "}
|
||||
{postToDisplay?.createdBy?.lastName}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Divider sx={{ mb: "0.3rem" }} />
|
||||
<Typography variant="h4">{postToDisplay?.title}</Typography>
|
||||
<Typography variant="body1">{postToDisplay?.content}</Typography>
|
||||
</Box>
|
||||
</Paper>
|
||||
</Box>
|
||||
<Box sx={{ width: "100%" }}>
|
||||
<TextField
|
||||
label="Add a comment..."
|
||||
fullWidth
|
||||
multiline
|
||||
value={newComentText}
|
||||
onChange={(e) => setNewCommentText(e.target.value)}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleCommentPost}
|
||||
sx={{
|
||||
display: `${newComentText.length > 0 ? "inherit" : "none"}`,
|
||||
}}
|
||||
>
|
||||
Accept
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={handleCancelComment}
|
||||
sx={{
|
||||
display: `${newComentText.length > 0 ? "inherit" : "none"}`,
|
||||
ml: "0.5rem",
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</>
|
||||
),
|
||||
}}
|
||||
sx={{
|
||||
mb: "1rem",
|
||||
}}
|
||||
/>
|
||||
<Box>
|
||||
{postToDisplay?.comments?.map((comment) => (
|
||||
<Paper>
|
||||
<Box sx={{ margin: "1rem" }}>
|
||||
<Box sx={{ display: "flex", mb: "0.3rem" }}>
|
||||
<AppAvatar user={comment.createdBy!} small />
|
||||
<Typography variant="subtitle2" sx={{ ml: "0.5rem" }}>
|
||||
{comment.createdBy?.firstName} {comment.createdBy?.lastName}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Divider sx={{ mb: "0.3rem" }} />
|
||||
<Typography variant="body1">{comment.content}</Typography>
|
||||
</Box>
|
||||
</Paper>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue