Skip to content

Commit

Permalink
Solution
Browse files Browse the repository at this point in the history
  • Loading branch information
DimaK88 committed Aug 12, 2024
1 parent 4c69cd2 commit 29f428f
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 58 deletions.
9 changes: 7 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ export const App: React.FC = () => {
.finally(() => setIsLoading(false));
}, [selectedUser]);

const displayComponent =
!posts.length && !error && !isLoading && selectedUser;

const postList = !!posts.length && !isLoading && selectedUser;

return (
<main className="section">
<div className="container">
Expand Down Expand Up @@ -62,13 +67,13 @@ export const App: React.FC = () => {
</div>
)}

{!posts.length && !error && !isLoading && selectedUser && (
{displayComponent && (
<div className="notification is-warning" data-cy="NoPostsYet">
No posts yet
</div>
)}

{!!posts.length && !isLoading && selectedUser && (
{postList && (
<PostsList
posts={posts}
selectedPost={selectedPost}
Expand Down
40 changes: 40 additions & 0 deletions src/components/Comment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';

type Props = {
id: number;
name: string;
email: string;
body: string;
handleDelete: (id: number) => void;
};

export const Comment: React.FC<Props> = ({
id,
name,
email,
body,
handleDelete,
}) => {
return (
<article className="message is-small" data-cy="Comment" key={id}>
<div className="message-header">
<a href={`mailto:${email}`} data-cy="CommentAuthor">
{name}
</a>
<button
data-cy="CommentDelete"
type="button"
className="delete is-small"
aria-label="delete"
onClick={() => handleDelete(id)}
>
delete button
</button>
</div>

<div className="message-body" data-cy="CommentBody">
{body}
</div>
</article>
);
};
29 changes: 29 additions & 0 deletions src/components/CommentList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { Comment } from './Comment';

type Props = {
comments: Array<{
id: number;
name: string;
email: string;
body: string;
}>;
handleDelete: (id: number) => void;
};

export const CommentList: React.FC<Props> = ({ comments, handleDelete }) => {
return (
<>
{comments.map(({ id, email, name, body }) => (
<Comment
key={id}
id={id}
name={name}
email={email}
body={body}
handleDelete={handleDelete}
/>
))}
</>
);
};
25 changes: 14 additions & 11 deletions src/components/NewCommentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export const NewCommentForm: React.FC<Props> = ({
});
const [isLoading, setIsLoading] = useState(false);

const { name: commentName, email: commentEmail, body: commentBody } = addComment;
const { name: nameError, email: emailError, body: bodyError } = commentError;

const handleOnChange = (
event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
Expand Down Expand Up @@ -137,17 +140,17 @@ export const NewCommentForm: React.FC<Props> = ({
id="comment-author-name"
placeholder="Name Surname"
className={classNames('input', {
'is-danger': commentError.name,
'is-danger': nameError,
})}
value={addComment.name}
value={commentName}
onChange={handleOnChange}
/>

<span className="icon is-small is-left">
<i className="fas fa-user" />
</span>

{commentError.name && (
{nameError && (
<span
className="icon is-small is-right has-text-danger"
data-cy="ErrorIcon"
Expand All @@ -157,7 +160,7 @@ export const NewCommentForm: React.FC<Props> = ({
)}
</div>

{commentError.name && (
{nameError && (
<p className="help is-danger" data-cy="ErrorMessage">
Name is required
</p>
Expand All @@ -176,17 +179,17 @@ export const NewCommentForm: React.FC<Props> = ({
id="comment-author-email"
placeholder="[email protected]"
className={classNames('input', {
'is-danger': commentError.email,
'is-danger': emailError,
})}
value={addComment.email}
value={commentEmail}
onChange={handleOnChange}
/>

<span className="icon is-small is-left">
<i className="fas fa-envelope" />
</span>

{commentError.email && (
{emailError && (
<span
className="icon is-small is-right has-text-danger"
data-cy="ErrorIcon"
Expand All @@ -196,7 +199,7 @@ export const NewCommentForm: React.FC<Props> = ({
)}
</div>

{commentError.email && (
{emailError && (
<p className="help is-danger" data-cy="ErrorMessage">
Email is required
</p>
Expand All @@ -214,14 +217,14 @@ export const NewCommentForm: React.FC<Props> = ({
name="body"
placeholder="Type comment here"
className={classNames('textarea', {
'is-danger': commentError.body,
'is-danger': bodyError,
})}
value={addComment.body}
value={commentBody}
onChange={handleOnChange}
/>
</div>

{commentError.body && (
{bodyError && (
<p className="help is-danger" data-cy="ErrorMessage">
Enter some text
</p>
Expand Down
35 changes: 7 additions & 28 deletions src/components/PostDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { NewCommentForm } from './NewCommentForm';
import { Post } from '../types/Post';
import { Comment } from '../types/Comment';
import { getComment, deleteComment } from '../api/comment';
import { CommentList } from './CommentList';

type Props = {
selectedPost: Post;
Expand Down Expand Up @@ -38,6 +39,10 @@ export const PostDetails: React.FC<Props> = ({ selectedPost }) => {
});
};

const handleShowFrom = () => {
setShowForm(true);
};

return (
<div className="content" data-cy="PostDetails">
<div className="content" data-cy="PostDetails">
Expand Down Expand Up @@ -67,33 +72,7 @@ export const PostDetails: React.FC<Props> = ({ selectedPost }) => {
{!!comments.length && (
<>
<p className="title is-4">Comments:</p>

{comments.map(({ id, email, name, body }) => (
<article
className="message is-small"
data-cy="Comment"
key={id}
>
<div className="message-header">
<a href={`mailto:${email}`} data-cy="CommentAuthor">
{name}
</a>
<button
data-cy="CommentDelete"
type="button"
className="delete is-small"
aria-label="delete"
onClick={() => handleDelete(id)}
>
delete button
</button>
</div>

<div className="message-body" data-cy="CommentBody">
{body}
</div>
</article>
))}
<CommentList comments={comments} handleDelete={handleDelete} />
</>
)}

Expand All @@ -102,7 +81,7 @@ export const PostDetails: React.FC<Props> = ({ selectedPost }) => {
data-cy="WriteCommentButton"
type="button"
className="button is-link"
onClick={() => setShowForm(true)}
onClick={handleShowFrom}
>
Write a comment
</button>
Expand Down
28 changes: 16 additions & 12 deletions src/components/PostsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ export const PostsList: React.FC<Props> = ({
selectedPost,
setSelectedPost,
}) => {
const handleSelectPost = (post: Post) => {
if (selectedPost?.id === post.id) {
setSelectedPost(null);
} else {
setSelectedPost(post);
const handleSelectPost = (postId: number) => {
const post = posts.find(a => a.id === postId);

if (post) {
if (selectedPost?.id === postId) {
setSelectedPost(null);
} else {
setSelectedPost(post);
}
}
};

Expand All @@ -36,22 +40,22 @@ export const PostsList: React.FC<Props> = ({
</thead>

<tbody>
{posts.map(post => (
<tr data-cy="Post" key={post.id}>
<td data-cy="PostId">{post.id}</td>
{posts.map(({ id, title }) => (
<tr data-cy="Post" key={id}>
<td data-cy="PostId">{id}</td>

<td data-cy="PostTitle">{post.title}</td>
<td data-cy="PostTitle">{title}</td>

<td className="has-text-right is-vcentered">
<button
type="button"
data-cy="PostButton"
className={classNames('button is-link', {
'is-light': selectedPost?.id !== post.id,
'is-light': selectedPost?.id !== id,
})}
onClick={() => handleSelectPost(post)}
onClick={() => handleSelectPost(id)}
>
{selectedPost?.id === post.id ? 'Close' : 'Open'}
{selectedPost?.id === id ? 'Close' : 'Open'}
</button>
</td>
</tr>
Expand Down
12 changes: 7 additions & 5 deletions src/components/UserSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ export const UserSelector: React.FC<Props> = ({
setIsLoading(!isLoading);
};

const handleSelectUser = (user: User) => {
setSelectedPost(null);
setIsLoading(false);
setSelectedUser(user);
};

return (
<div
data-cy="UserSelector"
Expand Down Expand Up @@ -61,11 +67,7 @@ export const UserSelector: React.FC<Props> = ({
className={classNames('dropdown-item', {
'is-active': selectedUser?.id === user.id,
})}
onMouseDown={() => {
setSelectedPost(null);
setIsLoading(false);
setSelectedUser(user);
}}
onMouseDown={() => handleSelectUser(user)}
>
{user.name}
</a>
Expand Down

0 comments on commit 29f428f

Please sign in to comment.