Skip to content

Commit

Permalink
Implement comment deletion
Browse files Browse the repository at this point in the history
Individual comments now separate component.
Adjusted textarea inline padding.
  • Loading branch information
MaoShizhong committed Jan 2, 2024
1 parent e35b4fd commit 5e895b9
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 49 deletions.
63 changes: 63 additions & 0 deletions src/components/post/Comment.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useState } from 'react';
import { Link, useOutletContext } from 'react-router-dom';
import { DEFAULT_PROFILE_PICTURE, SERVER_ERROR } from '../../helpers/constants';
import { fetchData } from '../../helpers/fetch';
import { getFullNameFromDetails, getRelativeTimestamp } from '../../helpers/util';
import { Loading } from '../loading/Loading';
import commentStyles from './css/comment.module.css';
import postStyles from './css/post.module.css';

export function Comment({ postID, comment, setComments }) {
const { user } = useOutletContext();
const [loading, setLoading] = useState(false);

async function deleteComment() {
setLoading(true);

const deleteRes = await fetchData(
`/posts/${postID}/comments/${comment._id}?userID=${user._id}`,
'DELETE'
);

if (deleteRes instanceof Error || !deleteRes.ok) {
alert(SERVER_ERROR);
} else {
setComments((prev) => prev.filter((postComment) => postComment._id !== comment._id));
}

setLoading(false);
}

return (
<div key={comment._id} className={commentStyles.comment}>
<img
src={comment.author.profilePicture ?? DEFAULT_PROFILE_PICTURE}
alt="comment profile picture"
/>

<div className={commentStyles.content}>
<div className={commentStyles.top}>
<Link to={`/${comment.author.handle}`}>
{getFullNameFromDetails(comment.author.details)}
</Link>

{user._id === comment.author._id && (
<button
onClick={deleteComment}
className={commentStyles.delete}
disabled={loading}
>
{loading ? <Loading isInButton={true} /> : 'Delete'}
</button>
)}
</div>

<p>{comment.body}</p>

<div className={postStyles.timestamp}>
{getRelativeTimestamp(comment.timestamp)}
</div>
</div>
</div>
);
}
104 changes: 59 additions & 45 deletions src/components/post/Comments.jsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,74 @@
import { Link, useOutletContext } from 'react-router-dom';
import { DEFAULT_PROFILE_PICTURE } from '../../helpers/constants';
import {
autoResizeTextarea,
getFullNameFromDetails,
getRelativeTimestamp,
} from '../../helpers/util';
import { useState } from 'react';
import { SERVER_ERROR } from '../../helpers/constants';
import { fetchData } from '../../helpers/fetch';
import { autoResizeTextarea } from '../../helpers/util';
import { Loading } from '../loading/Loading';
import { Comment } from './Comment';
import commentStyles from './css/comment.module.css';
import postStyles from './css/post.module.css';

export function Comments({ postID, comments }) {
const { user } = useOutletContext();
const [postComments, setPostComments] = useState(comments ?? []);
const [loading, setLoading] = useState(false);
const [commentError, setCommentError] = useState(null);

async function postComment(e) {
e.preventDefault();
setCommentError(null);
setLoading(true);
const textarea = e.target.body;

const commentRes = await fetchData(`/posts/${postID}/comments`, 'POST', {
data: { body: textarea.value },
urlEncoded: true,
});

if (commentRes instanceof Error) {
alert(SERVER_ERROR);
} else if (!commentRes.ok) {
const { error } = await commentRes.json();
setCommentError(error);
} else {
const { newComment } = await commentRes.json();
setPostComments((prev) => [...prev, newComment]);
textarea.value = '';
}

setLoading(false);
}

return (
<div className={commentStyles.comments}>
{comments.map((comment) => (
<div key={comment._id} className={commentStyles.comment}>
<img
src={comment.author.profilePicture ?? DEFAULT_PROFILE_PICTURE}
alt="comment profile picture"
/>

<div className={commentStyles.content}>
<div className={commentStyles.top}>
<Link to={`/${comment.author.handle}`}>
{getFullNameFromDetails(comment.author.details)}
</Link>

{user._id === comment.author._id && (
<button className={commentStyles.delete}>Delete</button>
)}
</div>

<p>{comment.body}</p>

<div className={postStyles.timestamp}>
{getRelativeTimestamp(comment.timestamp)}
</div>
</div>
</div>
{postComments.map((comment) => (
<Comment
key={comment._id}
postID={postID}
comment={comment}
setComments={setPostComments}
/>
))}

<form onSubmit={postComment} className={commentStyles.reply}>
<label htmlFor={`reply_${postID}`}>Reply:</label>
<textarea
name="body"
id={`reply_${postID}`}
rows="1"
placeholder="Comment on this post..."
onInput={autoResizeTextarea}
></textarea>
<button className={commentStyles.postComment}>Post</button>
</form>
<div className={commentStyles.reply}>
<form onSubmit={postComment}>
<label htmlFor={`reply_${postID}`}>Reply:</label>
<textarea
name="body"
id={`reply_${postID}`}
rows="1"
maxLength={2000}
placeholder="Comment on this post..."
onInput={(e) => {
autoResizeTextarea(e);
setCommentError(null);
}}
required
></textarea>
<button className={commentStyles.postComment} disabled={loading}>
{loading ? <Loading isInButton={true} /> : 'Post'}
</button>
</form>

{commentError && <p className={commentStyles.error}>{commentError}</p>}
</div>
</div>
);
}
14 changes: 11 additions & 3 deletions src/components/post/css/comment.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,27 @@
}

.reply {
display: flex;
flex-direction: column;
gap: 6px;
}

.reply > form {
align-items: center;
display: flex;
gap: 6px;

& > textarea {
flex: 1;
padding-inline: 4px;
resize: none;
}
}

.postComment {
align-self: flex-end;
composes: bold from '../../buttons/css/button.module.css';
font-size: small;
}

.error {
align-self: flex-end;
composes: error from '../../login/css/login.module.css';
}
5 changes: 4 additions & 1 deletion src/global_stylesheets/reset.css
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ textarea {
background-color: var(--bg);
}


a,
button {
cursor: pointer;
Expand Down Expand Up @@ -168,6 +167,10 @@ dialog {
padding: 0;
}

textarea {
padding-inline: 4px;
}

/* Screen reader only - visually hidden */
.sr-only {
border-width: 0;
Expand Down

0 comments on commit 5e895b9

Please sign in to comment.