-
Notifications
You must be signed in to change notification settings - Fork 522
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
17b7731
commit c91eb25
Showing
9 changed files
with
203 additions
and
162 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |
This file was deleted.
Oops, something went wrong.
77 changes: 77 additions & 0 deletions
77
apps/react/src/challenges/nested-comments/CommentsTree.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file was deleted.
Oops, something went wrong.
24 changes: 0 additions & 24 deletions
24
apps/react/src/challenges/nested-comments/hook/useFunction.jsx
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters