Skip to content

Commit

Permalink
react: fix nested comments
Browse files Browse the repository at this point in the history
  • Loading branch information
arpansaha13 committed Apr 19, 2024
1 parent 17b7731 commit c91eb25
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 162 deletions.
28 changes: 0 additions & 28 deletions apps/react/src/challenges/nested-comments/App.jsx

This file was deleted.

101 changes: 101 additions & 0 deletions apps/react/src/challenges/nested-comments/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { useState } from 'react';
import initialData, { type Comment } from './data';
import CommentsTree from './CommentsTree';

const App = () => {
const [commentText, setCommentText] = useState('');
const [comments, setComments] = useState(initialData);

const addComment = (commentId: number, text: string) => {
if (!text) return;

if (commentId === -1) {
setComments((state) => {
const newState = structuredClone(state);
newState.unshift({ id: Date.now(), text, replies: [] });
return newState;
});
} else {
setComments((state) => {
const newState = structuredClone(state);
addCommentsToTree(newState, commentId, text);
return newState;
});
}
};

const deleteComment = (commentId: number) => {
setComments((state) => {
const newState = structuredClone(state);
deleteCommentFromTree(newState, commentId);
return newState;
});
};

const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
addComment(-1, commentText);
setCommentText('');
}
if (e.key === 'Escape') {
setCommentText('');
}
};

return (
<>
<h1>Comments</h1>

<div style={{ marginBottom: '1rem', display: 'flex', gap: '1rem' }}>
<input
type="text"
placeholder="Add comment..."
onKeyDown={onKeyDown}
value={commentText}
onChange={(e) => setCommentText(e.target.value)}
/>

<button
onClick={() => {
addComment(-1, commentText);
setCommentText('');
}}
>
Add
</button>
</div>

<CommentsTree comments={comments} addComment={addComment} deleteComment={deleteComment} />
</>
);
};

export default App;

const addCommentsToTree = (tree: Comment[], commentId: number, text: string) => {
for (const node of tree) {
if (node.id === commentId) {
node.replies.unshift({
id: Date.now(),
text,
replies: [],
});
return true;
}

if (addCommentsToTree(node.replies, commentId, text)) return true;
}
return false;
};

const deleteCommentFromTree = (tree: Comment[], commentId: number) => {
for (let i = 0; i < tree.length; i++) {
if (tree[i].id === commentId) {
tree.splice(i, 1);
return true;
}

if (deleteCommentFromTree(tree[i].replies, commentId)) return true;
}
return false;
};
74 changes: 0 additions & 74 deletions apps/react/src/challenges/nested-comments/Comments.jsx

This file was deleted.

77 changes: 77 additions & 0 deletions apps/react/src/challenges/nested-comments/CommentsTree.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { useState } from 'react';
import styles from './style.module.css';
import { type Comment } from './data';

interface CommentsTreeProps {
comments: Comment[];
addComment: (commentId: number, text: string) => void;
deleteComment: (commentId: number) => void;
}

const CommentsTree = ({ comments, addComment, deleteComment }: CommentsTreeProps) => {
const [showInput, setShowInput] = useState(-1);
const [commentText, setCommentText] = useState('');

const handleAdd = (commentId: number) => {
if (commentText) {
addComment(commentId, commentText);
setShowInput(-1);
}
setCommentText('');
};

const cancelReply = () => {
setShowInput(-1);
setCommentText('');
};

const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>, commentId: number) => {
if (e.key === 'Enter') handleAdd(commentId);
else if (e.key === 'Escape') cancelReply();
};

return comments.map((comment) => (
<div key={comment.id}>
<div className={styles.comment}>
<img
src="https://www.iconpacks.net/icons/2/free-user-icon-3296-thumb.png"
alt={comment.text}
/>
<div>
<p>{comment.text}</p>
{showInput === comment.id && (
<input
type="text"
placeholder="Reply..."
autoFocus
value={commentText}
onKeyDown={(e) => onKeyDown(e, comment.id)}
onChange={(e) => setCommentText(e.target.value)}
/>
)}
{showInput === comment.id ? (
<>
<button onClick={() => handleAdd(comment.id)}>Add</button>
<button onClick={cancelReply}>Cancel</button>
</>
) : (
<>
<button onClick={() => setShowInput(comment.id)}>Reply</button>
<button onClick={() => deleteComment(comment.id)}>Delete</button>
</>
)}
</div>
</div>

<div className={styles.comment_replies}>
<CommentsTree
comments={comment.replies}
addComment={addComment}
deleteComment={deleteComment}
/>
</div>
</div>
));
};

export default CommentsTree;
21 changes: 21 additions & 0 deletions apps/react/src/challenges/nested-comments/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface Comment {
id: number;
text: string;
replies: Comment[];
}

const initialData: Comment[] = [
{
id: 1,
text: 'Hello world! How are you?',
replies: [
{
id: 2,
text: 'Hey, I am fine, wau?',
replies: [],
},
],
},
];

export default initialData;
29 changes: 0 additions & 29 deletions apps/react/src/challenges/nested-comments/data/data.jsx

This file was deleted.

24 changes: 0 additions & 24 deletions apps/react/src/challenges/nested-comments/hook/useFunction.jsx

This file was deleted.

6 changes: 1 addition & 5 deletions apps/react/src/challenges/nested-comments/style.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@
margin-right: 0.8rem;
}

.comment_details h4 {
margin-bottom: 0.1rem;
}

.comment_replie {
.comment_replies {
margin-left: 1rem;
padding-left: 1rem;
}
Expand Down
5 changes: 3 additions & 2 deletions shared/data/content/react-challenges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -570,18 +570,19 @@ const challenges = new Map<string, IChallenge>([
isNew: true,
},
],
[
[
'nested-comments',
{
title: 'Nested Comments',
link: 'nested-comments',
difficulty: EDifficulty.Medium,
developer: 'Akshay-Omkar',
// contributors: ['arpansaha13'],
tags: [],
isNew: true,
},
],
[
[
'15puzzle',
{
title: '15 Puzzle',
Expand Down

0 comments on commit c91eb25

Please sign in to comment.