From a839fdd8632eb31bfdf572fbefec96fcb138288b Mon Sep 17 00:00:00 2001 From: edwin6666 Date: Tue, 19 Dec 2023 14:59:25 -0400 Subject: [PATCH 01/13] Feat: View implementation to see the details of a post Details: -posts now have a see more button -all posts have a maximum size -changed the way of organizing from the backend using a best practice --- src/App.js | 4 +- src/components/PostCard.jsx | 23 +++++++++--- src/components/PostDetailsCard.jsx | 59 ++++++++++++++++++++++++++++++ src/pages/HomePage.js | 4 +- src/pages/PostDetails.js | 39 ++++++++++++++++++++ 5 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 src/components/PostDetailsCard.jsx create mode 100644 src/pages/PostDetails.js diff --git a/src/App.js b/src/App.js index 0dae341..f6abc00 100644 --- a/src/App.js +++ b/src/App.js @@ -10,6 +10,7 @@ import Navbar from "./components/Navbar/Navbar"; import ContactForm from "./pages/Contact"; import { DefaultCarousel } from "./components/Carousel/Carousel"; import UserList from "./pages/Users"; +import { PostDetailsCard } from "./components/PostDetailsCard"; function App() { return ( @@ -23,11 +24,12 @@ function App() { } /> } /> } /> + } /> {/* Private routes */} }> } /> - } /> + } /> } /> } /> diff --git a/src/components/PostCard.jsx b/src/components/PostCard.jsx index 53f5ecd..447323c 100644 --- a/src/components/PostCard.jsx +++ b/src/components/PostCard.jsx @@ -4,7 +4,7 @@ import ReactMarkdown from "react-markdown"; import { useNavigate } from "react-router-dom"; import moment from "moment"; import logoImg from "../Images/postimg.jpg"; - +import { Link } from "react-router-dom"; export function insertMedia(filePath) { var extension = filePath.split(".").pop().toLowerCase(); @@ -31,7 +31,6 @@ export function insertMedia(filePath) { export function PostCard({ post }) { const { deletePost } = usePosts(); const navigate = useNavigate(); - const normalDate = moment(post.createdAt).format("DD/MM/YYYY"); const handleDelete = (id) => { @@ -101,7 +100,7 @@ export function PostCard({ post }) {
); diff --git a/src/components/PostDetailsCard.jsx b/src/components/PostDetailsCard.jsx new file mode 100644 index 0000000..55994b3 --- /dev/null +++ b/src/components/PostDetailsCard.jsx @@ -0,0 +1,59 @@ +import moment from "moment"; +import ReactMarkdown from "react-markdown"; +import { insertMedia } from "./PostCard"; +import logoImg from "../Images/postimg.jpg"; +import { useLocation } from "react-router-dom"; + +export function PostDetailsCard( ) { + let {state}= useLocation(); + const normalDate = moment(state.post.createdAt).format("DD/MM/YYYY"); + + return ( +
+
+
+ logo +
+

+ {state.post.author} +

+

+ {normalDate} +

+

{state.post.categories}

+
+
+
+ + + +
+
+ + {state.post.image && insertMedia(state.post.image.url)} + +
+

{state.post.title}

+ + {state.post.description} + +

+ {" "} + Source: {state.post.source} +

+

{state.post.comments}

+
+
+ ); +} diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index 501e51c..90918a9 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -20,11 +20,11 @@ export function HomePage() { ); } - const reversedPosts = [...posts].reverse(); + return (
- {reversedPosts.map((post) => ( + {posts.map((post) => (
diff --git a/src/pages/PostDetails.js b/src/pages/PostDetails.js new file mode 100644 index 0000000..fee9463 --- /dev/null +++ b/src/pages/PostDetails.js @@ -0,0 +1,39 @@ +import { useEffect } from "react"; +import { useParams } from "react-router-dom"; // Importa useParams de React Router +import { usePosts } from "../context/postContext"; +import { VscEmptyWindow } from "react-icons/vsc"; +import { PostdetailsCard } from "../components/PostDetailsCard"; + +export function HomePage() { + const { posts, getPost } = usePosts(); + const { postId } = useParams(); // Obtén el ID de la ruta + + useEffect(() => { + + // Si hay un ID en la ruta, obtén solo ese post + getPost(postId); + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); // Asegúrate de ejecutar el efecto cuando cambia el ID + + if (posts.length === 0) { + return ( +
+ +

There are no posts

+
+ ); + } + + + + return ( +
+ {posts.map((post) => ( +
+ +
+ ))} +
+ ); +} From a3ffa99980a92d2ec3def77510abd55b211a10bf Mon Sep 17 00:00:00 2001 From: edwin6666 Date: Wed, 20 Dec 2023 21:21:55 -0400 Subject: [PATCH 02/13] Feat: implementation of view where comments are seen --- src/components/Comments.jsx | 20 ++++++++++++++++++++ src/components/PostCardUser.jsx | 15 +++++++++++++-- src/components/PostDetailsCard.jsx | 19 ++++++++++++------- src/pages/PostDetails.js | 11 ++++++----- 4 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 src/components/Comments.jsx diff --git a/src/components/Comments.jsx b/src/components/Comments.jsx new file mode 100644 index 0000000..241780c --- /dev/null +++ b/src/components/Comments.jsx @@ -0,0 +1,20 @@ +import React from "react"; + +export const Comment = ({ author, text }) => ( +
+ {author}: {text} +
+); + +export const Comments = ({ comments }) => ( +
+

Comentarios

+ {comments.map((comment) => ( + + ))} +
+); diff --git a/src/components/PostCardUser.jsx b/src/components/PostCardUser.jsx index a696402..54d1c3f 100644 --- a/src/components/PostCardUser.jsx +++ b/src/components/PostCardUser.jsx @@ -2,7 +2,7 @@ import moment from "moment"; import ReactMarkdown from "react-markdown"; import { insertMedia } from "./PostCard"; import logoImg from "../Images/postimg.jpg"; - +import { Link } from "react-router-dom"; export function PostCardUser({ post }) { const normalDate = moment(post.createdAt).format("DD/MM/YYYY"); @@ -44,8 +44,19 @@ export function PostCardUser({ post }) {

{post.title}

- {post.description} + {post.description + ? `${post.description.substr(0, 330)}...` + : "sin descripción"} + + + Read more +

{" "} Source: {post.source} diff --git a/src/components/PostDetailsCard.jsx b/src/components/PostDetailsCard.jsx index 55994b3..ae4744b 100644 --- a/src/components/PostDetailsCard.jsx +++ b/src/components/PostDetailsCard.jsx @@ -3,11 +3,12 @@ import ReactMarkdown from "react-markdown"; import { insertMedia } from "./PostCard"; import logoImg from "../Images/postimg.jpg"; import { useLocation } from "react-router-dom"; +import { Comments } from "./Comments"; -export function PostDetailsCard( ) { - let {state}= useLocation(); +export function PostDetailsCard() { + let { state } = useLocation(); const normalDate = moment(state.post.createdAt).format("DD/MM/YYYY"); - + return (
@@ -20,7 +21,10 @@ export function PostDetailsCard( ) {

{normalDate}

-

{state.post.categories}

+

+ {" "} + {state.post.categories} +

@@ -44,15 +48,16 @@ export function PostDetailsCard( ) { {state.post.image && insertMedia(state.post.image.url)}
-

{state.post.title}

+

+ {state.post.title} +

{state.post.description}

- {" "} Source: {state.post.source}

-

{state.post.comments}

+
); diff --git a/src/pages/PostDetails.js b/src/pages/PostDetails.js index fee9463..020c359 100644 --- a/src/pages/PostDetails.js +++ b/src/pages/PostDetails.js @@ -1,20 +1,21 @@ import { useEffect } from "react"; -import { useParams } from "react-router-dom"; // Importa useParams de React Router +import { useParams } from "react-router-dom"; import { usePosts } from "../context/postContext"; import { VscEmptyWindow } from "react-icons/vsc"; import { PostdetailsCard } from "../components/PostDetailsCard"; export function HomePage() { const { posts, getPost } = usePosts(); - const { postId } = useParams(); // Obtén el ID de la ruta + const { postId } = useParams(); useEffect(() => { - // Si hay un ID en la ruta, obtén solo ese post + getPost(postId); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); // Asegúrate de ejecutar el efecto cuando cambia el ID + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); if (posts.length === 0) { return ( From 89121d128110afeeede1e41a6d46129e239b17c6 Mon Sep 17 00:00:00 2001 From: edwin6666 Date: Wed, 3 Jan 2024 16:09:49 -0400 Subject: [PATCH 03/13] Feat: comments in the app --- package-lock.json | 32 +++++++------- package.json | 2 +- src/components/Comments.jsx | 8 ++-- src/components/PostDetailsCard.jsx | 71 +++++++++++++++++++++++++----- src/pages/HomePageUser.js | 18 ++++---- src/pages/PostDetails.js | 40 ----------------- src/pages/PostForm.js | 1 - 7 files changed, 91 insertions(+), 81 deletions(-) delete mode 100644 src/pages/PostDetails.js diff --git a/package-lock.json b/package-lock.json index 5c35d07..5831e0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,7 @@ "react-hot-toast": "^2.4.1", "react-icons": "^4.8.0", "react-markdown": "^9.0.0", - "react-router-dom": "^6.14.2", + "react-router-dom": "^6.21.1", "react-scripts": "5.0.1", "react-simplemde-editor": "^5.2.0", "simplemde": "^1.11.2", @@ -3616,11 +3616,11 @@ } }, "node_modules/@remix-run/router": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.7.2.tgz", - "integrity": "sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.1.tgz", + "integrity": "sha512-Qg4DMQsfPNAs88rb2xkdk03N3bjK4jgX5fR24eHCTR9q6PrhZQZ4UJBPzCHJkIpTRN1UKxx2DzjZmnC+7Lj0Ow==", "engines": { - "node": ">=14" + "node": ">=14.0.0" } }, "node_modules/@rollup/plugin-babel": { @@ -15475,29 +15475,29 @@ } }, "node_modules/react-router": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.14.2.tgz", - "integrity": "sha512-09Zss2dE2z+T1D03IheqAFtK4UzQyX8nFPWx6jkwdYzGLXd5ie06A6ezS2fO6zJfEb/SpG6UocN2O1hfD+2urQ==", + "version": "6.21.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.1.tgz", + "integrity": "sha512-W0l13YlMTm1YrpVIOpjCADJqEUpz1vm+CMo47RuFX4Ftegwm6KOYsL5G3eiE52jnJpKvzm6uB/vTKTPKM8dmkA==", "dependencies": { - "@remix-run/router": "1.7.2" + "@remix-run/router": "1.14.1" }, "engines": { - "node": ">=14" + "node": ">=14.0.0" }, "peerDependencies": { "react": ">=16.8" } }, "node_modules/react-router-dom": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.14.2.tgz", - "integrity": "sha512-5pWX0jdKR48XFZBuJqHosX3AAHjRAzygouMTyimnBPOLdY3WjzUSKhus2FVMihUFWzeLebDgr4r8UeQFAct7Bg==", + "version": "6.21.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.1.tgz", + "integrity": "sha512-QCNrtjtDPwHDO+AO21MJd7yIcr41UetYt5jzaB9Y1UYaPTCnVuJq6S748g1dE11OQlCFIQg+RtAA1SEZIyiBeA==", "dependencies": { - "@remix-run/router": "1.7.2", - "react-router": "6.14.2" + "@remix-run/router": "1.14.1", + "react-router": "6.21.1" }, "engines": { - "node": ">=14" + "node": ">=14.0.0" }, "peerDependencies": { "react": ">=16.8", diff --git a/package.json b/package.json index 8904574..1c8cf0e 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "react-hot-toast": "^2.4.1", "react-icons": "^4.8.0", "react-markdown": "^9.0.0", - "react-router-dom": "^6.14.2", + "react-router-dom": "^6.21.1", "react-scripts": "5.0.1", "react-simplemde-editor": "^5.2.0", "simplemde": "^1.11.2", diff --git a/src/components/Comments.jsx b/src/components/Comments.jsx index 241780c..14f2378 100644 --- a/src/components/Comments.jsx +++ b/src/components/Comments.jsx @@ -8,12 +8,12 @@ export const Comment = ({ author, text }) => ( export const Comments = ({ comments }) => (
-

Comentarios

+ {comments.map((comment) => ( ))}
diff --git a/src/components/PostDetailsCard.jsx b/src/components/PostDetailsCard.jsx index ae4744b..d765935 100644 --- a/src/components/PostDetailsCard.jsx +++ b/src/components/PostDetailsCard.jsx @@ -1,14 +1,49 @@ +import React, { useState} from "react"; import moment from "moment"; import ReactMarkdown from "react-markdown"; import { insertMedia } from "./PostCard"; import logoImg from "../Images/postimg.jpg"; +import axios from "axios"; import { useLocation } from "react-router-dom"; import { Comments } from "./Comments"; +import toast from "react-hot-toast"; export function PostDetailsCard() { - let { state } = useLocation(); + const { state } = useLocation(); const normalDate = moment(state.post.createdAt).format("DD/MM/YYYY"); + const [commentText, setCommentText] = useState(""); + + const handleCommentSubmit = async (e) => { + e.preventDefault(); + + const postId = state.post._id; + + try { + const response = await axios.post( + `http://localhost:4000/api/posts/${postId}/comments`, + { text: commentText }, + { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${""}`, + }, + } + ); + + if (response.status === 201) { + toast.success('successful comment') + setCommentText(""); + + } else { + + } + } catch (error) { + toast.error("This didn't work.") + } + }; + + return (
@@ -21,10 +56,7 @@ export function PostDetailsCard() {

{normalDate}

-

- {" "} - {state.post.categories} -

+

{state.post.categories}

@@ -48,15 +80,32 @@ export function PostDetailsCard() { {state.post.image && insertMedia(state.post.image.url)}
-

- {state.post.title} -

+

{state.post.title}

{state.post.description} -

- Source: {state.post.source} -

+

Source: {state.post.source}

+ + +
+ +