Skip to content

Commit a400813

Browse files
committed
add task solution
1 parent 593e3fc commit a400813

File tree

5 files changed

+265
-153
lines changed

5 files changed

+265
-153
lines changed

src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import { PostDetails } from './components/PostDetails';
88
import { UserSelector } from './components/UserSelector';
99
import { useEffect, useState } from 'react';
1010
import { User } from './types/User';
11-
import { getUsers } from './api/posts';
1211
import { Post } from './types/Post';
12+
import { getUsers } from './api/fetchPosts';
1313

1414
export const App = () => {
1515
const [usersList, setUsersList] = useState<User[]>([]);
@@ -59,7 +59,7 @@ export const App = () => {
5959
'is-8-desktop',
6060
'Sidebar',
6161
{
62-
'Sidebar--open': post,
62+
'Sidebar--open': post && post.userId === user?.id,
6363
},
6464
)}
6565
>

src/api/posts.ts renamed to src/api/fetchPosts.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { client } from '../../src/utils/fetchClient';
1+
import { client } from '../utils/fetchClient';
22
import { Post } from '../types/Post';
33
import { User } from '../types/User';
44
import { Comment } from '../types/Comment';
@@ -20,3 +20,25 @@ export const getComments = async (id: number | undefined) => {
2020

2121
return comments;
2222
};
23+
24+
export const deleteComment = async (postId: number | undefined) => {
25+
const deleteSelectedComment = client.delete(`/comments/${postId}`);
26+
27+
return deleteSelectedComment;
28+
};
29+
30+
export const createComment = async ({
31+
postId,
32+
name,
33+
email,
34+
body,
35+
}: Omit<Comment, 'id'>) => {
36+
const createNewComment = client.post('/comments', {
37+
postId,
38+
name,
39+
email,
40+
body,
41+
});
42+
43+
return createNewComment;
44+
};

src/components/NewCommentForm.tsx

Lines changed: 157 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,140 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
2+
import { Comment } from '../types/Comment';
3+
import classNames from 'classnames';
4+
import { Post } from '../types/Post';
5+
import { createComment } from '../api/fetchPosts';
6+
7+
interface Props {
8+
post: Post | null;
9+
setCommentsList: (value: (prev: Comment[]) => Comment[]) => void;
10+
setIsError: (value: boolean) => void;
11+
commentsList: Comment[];
12+
}
13+
14+
export const NewCommentForm: React.FC<Props> = ({
15+
post,
16+
setCommentsList,
17+
commentsList,
18+
setIsError,
19+
}) => {
20+
const [nameInput, setNameInput] = useState('');
21+
const [emailInput, setEmailInput] = useState('');
22+
const [bodyInput, setBodyInput] = useState('');
23+
const [isLoading, setIsLoading] = useState(false);
24+
const [nameError, setNameError] = useState(false);
25+
const [emailError, setEmailError] = useState(false);
26+
const [bodyError, setBodyError] = useState(false);
27+
28+
const resetFormAfterSuccesSubmit = () => {
29+
setNameInput(nameInput);
30+
setEmailInput(emailInput);
31+
setBodyInput('');
32+
};
33+
34+
const resetForm = () => {
35+
setNameInput('');
36+
setEmailInput('');
37+
setBodyInput('');
38+
setNameError(false);
39+
setEmailError(false);
40+
setBodyError(false);
41+
};
42+
43+
const submitForm = async () => {
44+
if (!nameInput) {
45+
setNameError(true);
46+
}
47+
48+
if (!emailInput) {
49+
setEmailError(true);
50+
}
51+
52+
if (!bodyInput) {
53+
setBodyError(true);
54+
}
55+
56+
if (!post?.id) {
57+
setIsError(true);
58+
59+
return;
60+
}
61+
62+
if (!nameInput || !emailInput || !bodyInput) {
63+
return;
64+
}
65+
66+
setIsLoading(true);
67+
68+
const newComment = {
69+
postId: post?.id,
70+
name: nameInput,
71+
email: emailInput,
72+
body: bodyInput,
73+
};
74+
75+
try {
76+
await createComment(newComment);
77+
setCommentsList(prev => [
78+
...prev,
79+
{ ...newComment, id: commentsList.length + 1 },
80+
]);
81+
resetFormAfterSuccesSubmit();
82+
} catch {
83+
setIsError(true);
84+
} finally {
85+
setIsLoading(false);
86+
}
87+
};
288

3-
export const NewCommentForm: React.FC = () => {
489
return (
5-
<form data-cy="NewCommentForm">
90+
<form
91+
data-cy="NewCommentForm"
92+
onSubmit={e => {
93+
e.preventDefault();
94+
submitForm();
95+
}}
96+
onReset={resetForm}
97+
>
698
<div className="field" data-cy="NameField">
799
<label className="label" htmlFor="comment-author-name">
8100
Author Name
9101
</label>
10102

11103
<div className="control has-icons-left has-icons-right">
12104
<input
105+
value={nameInput}
13106
type="text"
14107
name="name"
15108
id="comment-author-name"
16109
placeholder="Name Surname"
17-
className="input is-danger"
110+
className={classNames('input', {
111+
'is-danger': nameError && !nameInput,
112+
})}
113+
onChange={e => {
114+
setNameInput(e.target.value);
115+
setNameError(false);
116+
}}
18117
/>
19118

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

24-
<span
25-
className="icon is-small is-right has-text-danger"
26-
data-cy="ErrorIcon"
27-
>
28-
<i className="fas fa-exclamation-triangle" />
29-
</span>
123+
{nameError && !nameInput && (
124+
<span
125+
className="icon is-small is-right has-text-danger"
126+
data-cy="ErrorIcon"
127+
>
128+
<i className="fas fa-exclamation-triangle" />
129+
</span>
130+
)}
30131
</div>
31132

32-
<p className="help is-danger" data-cy="ErrorMessage">
33-
Name is required
34-
</p>
133+
{nameError && !nameInput && (
134+
<p className="help is-danger" data-cy="ErrorMessage">
135+
Name is required
136+
</p>
137+
)}
35138
</div>
36139

37140
<div className="field" data-cy="EmailField">
@@ -41,28 +144,39 @@ export const NewCommentForm: React.FC = () => {
41144

42145
<div className="control has-icons-left has-icons-right">
43146
<input
147+
value={emailInput}
44148
type="text"
45149
name="email"
46150
id="comment-author-email"
47151
placeholder="[email protected]"
48-
className="input is-danger"
152+
className={classNames('input', {
153+
'is-danger': emailError,
154+
})}
155+
onChange={e => {
156+
setEmailInput(e.target.value);
157+
setEmailError(false);
158+
}}
49159
/>
50160

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

55-
<span
56-
className="icon is-small is-right has-text-danger"
57-
data-cy="ErrorIcon"
58-
>
59-
<i className="fas fa-exclamation-triangle" />
60-
</span>
165+
{emailError && !emailInput && (
166+
<span
167+
className="icon is-small is-right has-text-danger"
168+
data-cy="ErrorIcon"
169+
>
170+
<i className="fas fa-exclamation-triangle" />
171+
</span>
172+
)}
61173
</div>
62174

63-
<p className="help is-danger" data-cy="ErrorMessage">
64-
Email is required
65-
</p>
175+
{emailError && !emailInput && (
176+
<p className="help is-danger" data-cy="ErrorMessage">
177+
Email is required
178+
</p>
179+
)}
66180
</div>
67181

68182
<div className="field" data-cy="BodyField">
@@ -72,23 +186,38 @@ export const NewCommentForm: React.FC = () => {
72186

73187
<div className="control">
74188
<textarea
189+
value={bodyInput}
75190
id="comment-body"
76191
name="body"
77192
placeholder="Type comment here"
78-
className="textarea is-danger"
193+
className={classNames('textarea', {
194+
'is-danger': bodyError && !bodyInput,
195+
})}
196+
onChange={e => {
197+
setBodyInput(e.target.value);
198+
setBodyError(false);
199+
}}
79200
/>
80201
</div>
81202

82-
<p className="help is-danger" data-cy="ErrorMessage">
83-
Enter some text
84-
</p>
203+
{bodyError && !bodyInput && (
204+
<p className="help is-danger" data-cy="ErrorMessage">
205+
Enter some text
206+
</p>
207+
)}
85208
</div>
86209

87210
<div className="field is-grouped">
88211
<div className="control">
89-
<button type="submit" className="button is-link is-loading">
212+
<button
213+
type="submit"
214+
className={classNames('button is-link', {
215+
'is-loading': isLoading,
216+
})}
217+
>
90218
Add
91219
</button>
220+
{/* */}
92221
</div>
93222

94223
<div className="control">

0 commit comments

Comments
 (0)