Skip to content

Commit

Permalink
not final version
Browse files Browse the repository at this point in the history
  • Loading branch information
Svimpik committed Feb 6, 2025
1 parent 611a1dc commit 6b7afb1
Show file tree
Hide file tree
Showing 6 changed files with 418 additions and 258 deletions.
85 changes: 46 additions & 39 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,54 +7,61 @@ import './App.scss';
import { PostsList } from './components/PostsList';
import { PostDetails } from './components/PostDetails';
import { UserSelector } from './components/UserSelector';
import { Loader } from './components/Loader';

export const App = () => (
<main className="section">
<div className="container">
<div className="tile is-ancestor">
<div className="tile is-parent">
<div className="tile is-child box is-success">
<div className="block">
<UserSelector />
</div>
import { useState } from 'react';
import { Post } from './types/Post';

<div className="block" data-cy="MainContent">
<p data-cy="NoSelectedUser">No user selected</p>
export const App = () => {
const [selectedUser, setSelectedUser] = useState<number | null>(null);
const [selectedPost, setSelectedPost] = useState<Post | null>(null);
const [postId, setPostId] = useState<number>();

<Loader />
const handleUserSelect = (id: number) => {
setSelectedUser(id);
};

<div
className="notification is-danger"
data-cy="PostsLoadingError"
>
Something went wrong!
</div>
const handlePostSelect = (post: Post) => {
setSelectedPost(post);
setPostId(post.id);
};

<div className="notification is-warning" data-cy="NoPostsYet">
No posts yet
return (
<main className="section">
<div className="container">
<div className="tile is-ancestor">
<div className="tile is-parent">
<div className="tile is-child box is-success">
<div className="block">
<UserSelector onUserSelect={handleUserSelect} />
</div>

<PostsList />
<div className="block" data-cy="MainContent">
{!selectedUser && (
<p data-cy="NoSelectedUser">No user selected</p>
)}

{selectedUser && (
<PostsList userId={selectedUser} onOpen={handlePostSelect} />
)}
</div>
</div>
</div>
</div>

<div
data-cy="Sidebar"
className={classNames(
'tile',
'is-parent',
'is-8-desktop',
'Sidebar',
'Sidebar--open',
)}
>
<div className="tile is-child box is-success ">
<PostDetails />
<div
data-cy="Sidebar"
className={classNames(
'tile',
'is-parent',
'is-8-desktop',
'Sidebar',
{ 'Sidebar--open': selectedPost },
)}
>
<div className="tile is-child box is-success ">
<PostDetails post={selectedPost} postId={postId} />
</div>
</div>
</div>
</div>
</div>
</main>
);
</main>
);
};
170 changes: 141 additions & 29 deletions src/components/NewCommentForm.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,97 @@
import React from 'react';
import classNames from 'classnames';
import React, { useState } from 'react';
import { Comment } from '../types/Comment';
import { client } from '../utils/fetchClient';

interface Props {
postId: number;
onAddComment: (newComment: Comment) => void;
}

export const NewCommentForm: React.FC<Props> = ({ postId, onAddComment }) => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [comment, setComment] = useState('');
const [nameError, setNameError] = useState(false);
const [emailError, setEmailError] = useState(false);
const [commentError, setCommentError] = useState(false);
const [loading, setLoading] = useState(false);

function handleNameChange(event: React.ChangeEvent<HTMLInputElement>) {
setName(event.target.value);
setNameError(false);
}

function handleEmailChange(event: React.ChangeEvent<HTMLInputElement>) {
setEmail(event.target.value);
setEmailError(false);
}

function handleCommentChange(event: React.ChangeEvent<HTMLTextAreaElement>) {
setComment(event.target.value);
setCommentError(false);
}

const validate = (names: string, emaill: string, coment: string) => {
let isValid = true;

if (!names.trim()) {
setNameError(true);
isValid = false;
}

if (!emaill.trim() || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emaill)) {
setEmailError(true);
isValid = false;
}

if (!coment.trim()) {
setCommentError(true);
isValid = false;
}

return isValid;
};

const reset = () => {
setName('');
setEmail('');
setComment('');
setNameError(false);
setEmailError(false);
setCommentError(false);
};

const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();

if (!validate(name, email, comment)) {
return; // Вихід, якщо валідація не пройдена
}

const newComment: Comment = {
id: Date.now(),
postId,
name,
email,
body: comment,
};

try {
setLoading(true);

const response = await client.post<Comment>('/comments', newComment);

onAddComment(response);
reset();
} catch {
} finally {
setLoading(false);
}
};

export const NewCommentForm: React.FC = () => {
return (
<form data-cy="NewCommentForm">
<form data-cy="NewCommentForm" noValidate onSubmit={handleSubmit}>
<div className="field" data-cy="NameField">
<label className="label" htmlFor="comment-author-name">
Author Name
Expand All @@ -14,24 +103,30 @@ export const NewCommentForm: React.FC = () => {
name="name"
id="comment-author-name"
placeholder="Name Surname"
className="input is-danger"
className={classNames('input', { 'is-danger': nameError })}
value={name}
onChange={handleNameChange}
/>

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

<span
className="icon is-small is-right has-text-danger"
data-cy="ErrorIcon"
>
<i className="fas fa-exclamation-triangle" />
</span>
{nameError && (
<span
className="icon is-small is-right has-text-danger"
data-cy="ErrorIcon"
>
<i className="fas fa-exclamation-triangle" />
</span>
)}
</div>

<p className="help is-danger" data-cy="ErrorMessage">
Name is required
</p>
{nameError && (
<p className="help is-danger" data-cy="ErrorMessage">
Name is required
</p>
)}
</div>

<div className="field" data-cy="EmailField">
Expand All @@ -45,24 +140,30 @@ export const NewCommentForm: React.FC = () => {
name="email"
id="comment-author-email"
placeholder="[email protected]"
className="input is-danger"
className={classNames('input', { 'is-danger': emailError })}
value={email}
onChange={handleEmailChange}
/>

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

<span
className="icon is-small is-right has-text-danger"
data-cy="ErrorIcon"
>
<i className="fas fa-exclamation-triangle" />
</span>
{emailError && (
<span
className="icon is-small is-right has-text-danger"
data-cy="ErrorIcon"
>
<i className="fas fa-exclamation-triangle" />
</span>
)}
</div>

<p className="help is-danger" data-cy="ErrorMessage">
Email is required
</p>
{emailError && (
<p className="help is-danger" data-cy="ErrorMessage">
Email is required
</p>
)}
</div>

<div className="field" data-cy="BodyField">
Expand All @@ -75,25 +176,36 @@ export const NewCommentForm: React.FC = () => {
id="comment-body"
name="body"
placeholder="Type comment here"
className="textarea is-danger"
className={classNames('textarea', { 'is-danger': commentError })}
value={comment}
onChange={handleCommentChange}
/>
</div>

<p className="help is-danger" data-cy="ErrorMessage">
Enter some text
</p>
{commentError && (
<p className="help is-danger" data-cy="ErrorMessage">
Enter some text
</p>
)}
</div>

<div className="field is-grouped">
<div className="control">
<button type="submit" className="button is-link is-loading">
<button
type="submit"
className={classNames('button is-link', { 'is-loading': loading })}
>
Add
</button>
</div>

<div className="control">
{/* eslint-disable-next-line react/button-has-type */}
<button type="reset" className="button is-link is-light">
<button
type="reset"
className="button is-link is-light"
onClick={reset}
>
Clear
</button>
</div>
Expand Down
Loading

0 comments on commit 6b7afb1

Please sign in to comment.