diff --git a/src/App.tsx b/src/App.tsx index 017957182..f70d28edb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,60 +1,118 @@ -import classNames from 'classnames'; +import { FC, useEffect, useState } from 'react'; +import cn from 'classnames'; -import 'bulma/css/bulma.css'; -import '@fortawesome/fontawesome-free/css/all.css'; -import './App.scss'; +import { User } from './types/User'; +import { Post } from './types/Post'; + +import { getPosts, getUsers } from './utils/api'; import { PostsList } from './components/PostsList'; import { PostDetails } from './components/PostDetails'; import { UserSelector } from './components/UserSelector'; import { Loader } from './components/Loader'; -export const App = () => ( -
-
-
-
-
-
- -
+import 'bulma/css/bulma.css'; +import '@fortawesome/fontawesome-free/css/all.css'; +import './App.scss'; -
-

No user selected

+export const App: FC = () => { + const [users, setUsers] = useState([]); + const [selectedUser, setSelectedUser] = useState(null); - + const [userPosts, setUserPosts] = useState([]); + const [selectedPost, setSelectedPost] = useState(null); -
- Something went wrong! -
+ const [isLoading, setIsLoading] = useState(false); + const [isError, setIsError] = useState(false); + + const noUsersPosts = + !userPosts.length && selectedUser && !isLoading && !isError; + + useEffect(() => { + setIsLoading(true); + setIsError(false); -
- No posts yet + getUsers() + .then(setUsers) + .catch(() => setIsError(true)) + .finally(() => setIsLoading(false)); + }, []); + + useEffect(() => { + if (!selectedUser) { + return; + } + + setIsLoading(true); + setIsError(false); + setUserPosts([]); + setSelectedPost(null); + + getPosts(selectedUser.id) + .then(setUserPosts) + .catch(() => setIsError(true)) + .finally(() => setIsLoading(false)); + }, [selectedUser]); + + return ( +
+
+
+
+
+
+
- +
+ {!selectedUser && ( +

No user selected

+ )} + + {isLoading && } + + {isError && !isLoading && ( +
+ Something went wrong! +
+ )} + + {noUsersPosts && ( +
+ No posts yet +
+ )} + + {!!userPosts.length && selectedUser && ( + + )} +
-
-
-
- +
+
+ {selectedPost && } +
-
-
-); +
+ ); +}; diff --git a/src/components/NewCommentForm.tsx b/src/components/NewCommentForm.tsx index 73a8a0b45..f19f1235b 100644 --- a/src/components/NewCommentForm.tsx +++ b/src/components/NewCommentForm.tsx @@ -1,103 +1,206 @@ -import React from 'react'; +import { + ChangeEvent, + Dispatch, + FC, + FormEvent, + SetStateAction, + useState, +} from 'react'; +import cn from 'classnames'; + +import { Comment } from '../types/Comment'; +import { addComment } from '../utils/api'; + +const initialFormData = { name: '', email: '', body: '' }; +const initialFromErrors = { name: false, email: false, body: false }; + +interface Props { + postId: number; + updateComments: Dispatch>; +} + +export const NewCommentForm: FC = ({ postId, updateComments }) => { + const [formData, setFormData] = useState(initialFormData); + const [formErrors, setFormErrors] = useState(initialFromErrors); + + const [isLoading, setIsLoading] = useState(false); + const [isError, setIsError] = useState(false); + + const handleChangeField = ( + event: ChangeEvent, + ) => { + const { name, value } = event.target; + + setFormData(prevData => ({ ...prevData, [name]: value.trimStart() })); + }; + + const handleResetForm = () => { + setFormData(initialFormData); + setFormErrors(initialFromErrors); + }; + + const handleFormSubmit = (event: FormEvent) => { + event.preventDefault(); + + const { name, email, body } = formData; + const trimmedData = { + name: name.trim(), + email: email.trim(), + body: body.trim(), + }; + + setFormErrors({ + name: !trimmedData.name, + email: !trimmedData.email, + body: !trimmedData.body, + }); + + if (!trimmedData.name && !trimmedData.email && !trimmedData.body) { + return; + } + + setIsLoading(true); + + addComment({ + postId, + ...trimmedData, + }) + .then(comment => { + updateComments(prevComments => [...prevComments, comment]); + setFormData(prevState => ({ ...prevState, body: '' })); + }) + .catch(() => setIsError(true)) + .finally(() => setIsLoading(false)); + }; -export const NewCommentForm: React.FC = () => { return ( -
-
- - -
- - - - - - - - - + <> + {isError && ( +
+ Something went wrong!
+ )} + + +
+ + +
+ + + + + + + {formErrors.name && ( + + + + )} +
-

- Name is required -

-
- -
- - -
- - - - - - - - - + {formErrors.name && ( +

+ Name is required +

+ )}
-

- Email is required -

-
- -
- - -
-