Conversation
Feature/prettier
Update README.md
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
Great job implementing the core functionality! The app works well, and the tests you've written are comprehensive. However, some changes are needed to align with the project's architectural requirements before this can be approved.
The primary issue is the data flow. The App component should be the single source of truth and prepare all data for its children [CHECKLIST ITEM #5]. Currently, the TodoInfo component fetches the user list itself. To fix this, you should first update the ToDo type in src/types/ToDo.ts to include the user object. Then, in App.tsx, when creating a new todo, you should find the full selectedUser object and add it to the newTask before updating the state.
Additionally, the form in App.tsx is missing <label> elements for the input and select fields, which is an important accessibility requirement. Please also address the use of one-letter variable names in your find methods [CHECKLIST ITEM #1].
Addressing these points will bring the solution in line with all the project guidelines. Keep up the great work!
✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨
Important
Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.
Tip
If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.
Caution
Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.
Footnotes
| node-version: [20.x] | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v2 |
There was a problem hiding this comment.
It's a good practice to use the latest versions of GitHub Actions. actions/checkout@v2 is outdated. Consider updating to a newer version like v4 for better performance and security.
| const [titleError, setTitleError] = useState(false); | ||
|
|
||
| const handleChangeUser = (event: React.ChangeEvent<HTMLSelectElement>) => { | ||
| const user = users.find(u => u.username === event.target.value); |
There was a problem hiding this comment.
This violates checklist item #1: 'Don't use one-letter variable naming.' Please use a more descriptive name for the parameter in the find method, for example, user instead of u.
| if (!titleTask.trim()) { | ||
| setTitleError(true); | ||
| } | ||
|
|
||
| setTitle(titleTask); | ||
| setTitleError(false); |
There was a problem hiding this comment.
The logic here is a bit confusing. The error state is set to true inside the if block, but then it's immediately set back to false on the next line. This makes the if block redundant. According to the requirements, the error should be hidden on any change, so calling setTitleError(false) is sufficient here.
| const newTask: ToDo = { | ||
| id: maxId, | ||
| title: title, | ||
| completed: false, | ||
| userId: selectedUser!.id, | ||
| }; |
There was a problem hiding this comment.
The new task object is missing the user property as required by the task description ("each TODO item must have... and a user object..."). Currently, the TodoInfo component has to import the entire list of users to find the correct one. This violates checklist item #5, which states that data should be prepared in the root component and passed down. You should add the selectedUser object to this newTask and adjust the initial todos state to also include the user object for each todo.
src/App.tsx
Outdated
| id: maxId, | ||
| title: title, | ||
| completed: false, | ||
| userId: selectedUser!.id, |
There was a problem hiding this comment.
While there's a check for selectedUser earlier in the function, using the non-null assertion operator (!) is generally considered a bad practice as it can hide potential bugs. Since you've already confirmed selectedUser is not null, you can safely access selectedUser.id without the assertion.
| <select | ||
| data-cy="userSelect" | ||
| value={selectedUser?.username ?? '0'} | ||
| onChange={handleChangeUser} | ||
| > |
There was a problem hiding this comment.
This select element is also missing an associated <label> element. All form controls should have labels for better accessibility.
src/components/TodoInfo/TodoInfo.tsx
Outdated
| export const TodoInfo = () => {}; | ||
| import { UserInfo } from '../UserInfo'; | ||
| import ToDo from '../../types/ToDo'; | ||
| import users from '../../api/users'; |
There was a problem hiding this comment.
This violates checklist item #5: 'Prepare data in one place (App component) and pass it to child components. Don't use import keyword in non-root components'. The TodoInfo component should receive a todo object that already includes the full user object, rather than looking it up here.
src/components/TodoInfo/TodoInfo.tsx
Outdated
| }; | ||
|
|
||
| export const TodoInfo = ({ todo }: Props) => { | ||
| const taskUser = users.find(u => u.id === todo.userId); |
There was a problem hiding this comment.
src/components/TodoInfo/TodoInfo.tsx
Outdated
| {taskUser ? ( | ||
| <article | ||
| data-id={todo.id} | ||
| className={`TodoInfo ${todo.completed ? 'TodoInfo--completed' : ''}`} | ||
| > | ||
| <h2 className="TodoInfo__title">{todo.title}</h2> | ||
|
|
||
| <UserInfo name={taskUser.name} email={taskUser.email} /> | ||
| </article> | ||
| ) : ( | ||
| '' | ||
| )} |
There was a problem hiding this comment.
This conditional rendering violates the principle described in checklist item #4. The parent component should be responsible for ensuring that TodoInfo receives a valid todo object with a user. This component should not have to handle the case where taskUser might not be found. The check for a valid user should happen before this component is rendered.
| type ToDo = { | ||
| id: number; | ||
| title: string; | ||
| completed: boolean; | ||
| userId: User['id']; | ||
| }; |
There was a problem hiding this comment.
The task description explicitly requires each ToDo item to have a user object containing the user's details. This type is missing the user: User; property. Adding it is a crucial first step to align with the application's data structure and fix the architectural issue in TodoInfo.tsx.
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
Great work on the form logic and state management. However, this submission requires changes because several critical requirements from the task description and previous feedback have not yet been met.
The most important issue is the application's data flow. The App component must be the single source of truth, but the TodoInfo component is currently fetching its own data by importing the users list. This violates a core architectural guideline [CHECKLIST ITEM #5].
To resolve this, you'll need to:
- Update the
ToDotype insrc/types/ToDo.tsto include the fulluser: Userobject. - In
App.tsx, when creating a new task, find the completeselectedUserobject and add it to thenewTask. - Remove the data
importand user-finding logic fromTodoInfo.tsxso it only displays the data passed via props.
Additionally, please remember to add the required <label> elements to the form in App.tsx for accessibility.
✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨
Important
Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.
Tip
If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.
Caution
Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.
Footnotes
| const [titleError, setTitleError] = useState(false); | ||
|
|
||
| const handleChangeUser = (event: React.ChangeEvent<HTMLSelectElement>) => { | ||
| const user = users.find(u => u.username === event.target.value); |
There was a problem hiding this comment.
This violates checklist item #1: 'Don't use one-letter variable naming.' Please use a more descriptive variable name like user instead of u. This was also noted in the previous review and is important for code readability.
| const handleChangeTitle = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
| const titleTask = event.target.value; | ||
|
|
||
| if (!titleTask.trim()) { | ||
| setTitleError(true); | ||
| } | ||
|
|
||
| setTitle(titleTask); | ||
| setTitleError(false); | ||
| }; |
There was a problem hiding this comment.
This handler function works, but the logic is a bit confusing. The if block on lines 35-37 sets an error that is immediately cleared by setTitleError(false) on line 40. Since the requirement is to show errors only on submission and hide them on input change, you can simplify this function by removing lines 35-37.
| const newTask: ToDo = { | ||
| id: maxId, | ||
| title: title, | ||
| completed: false, | ||
| userId: selectedUser!.id, | ||
| }; |
There was a problem hiding this comment.
This is the central part that needs adjustment based on the previous review. The task requires each new todo to have a complete user object.
Currently, you're only adding userId. To fix this:
- First, update the
ToDotype insrc/types/ToDo.tsto include auser: Userproperty. - Then, here in
App.tsx, add theselectedUserobject tonewTask:user: selectedUser.
This will make the App component the single source of truth and will allow you to remove the user lookup logic from the TodoInfo component, satisfying checklist item #5.
| <h1>Add todo form</h1> | ||
|
|
||
| <form action="/api/users" method="POST"> | ||
| <form action="/api/todos" method="POST" onSubmit={addTaskHandler}> |
There was a problem hiding this comment.
The form is missing its corresponding <label> elements for the input and select fields. This is an important accessibility requirement and was part of the feedback from the previous review. Please add labels for both form controls.
src/components/TodoInfo/TodoInfo.tsx
Outdated
| export const TodoInfo = () => {}; | ||
| import { UserInfo } from '../UserInfo'; | ||
| import ToDo from '../../types/ToDo'; | ||
| import users from '../../api/users'; |
There was a problem hiding this comment.
This violates checklist item #5. Non-root components like TodoInfo should not import data sources directly. All data should be prepared in the App component and passed down as props. This was a critical point in the previous review feedback and needs to be addressed.
src/components/TodoInfo/TodoInfo.tsx
Outdated
| }; | ||
|
|
||
| export const TodoInfo = ({ todo }: Props) => { | ||
| const taskUser = users.find(u => u.id === todo.userId); |
There was a problem hiding this comment.
This logic for finding the user should be in the App component. The todo object passed to this component should already contain the complete user object. Additionally, this violates checklist item #1 by using the one-letter variable u.
| type ToDo = { | ||
| id: number; | ||
| title: string; | ||
| completed: boolean; | ||
| userId: User['id']; | ||
| }; |
There was a problem hiding this comment.
This ToDo type is missing the required user object property. The task description and previous review feedback specified that each todo should contain the full user object. Please add user: User; to this type definition.
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
I am approving your solution as an educational override because you've done an excellent job refactoring the application's architecture! The data flow is now much cleaner with App as the single source of truth, which was the main goal of this iteration.
While your work is approved, here are a few key areas to focus on for future tasks:
- Type Safety: In
src/types/ToDo.ts, theuserproperty on theToDotype should be required (user: User) instead of optional. Since your app logic always includes a user, making the type stricter prevents potential bugs. - Code Clarity: The
ifblock within thehandleChangeTitlefunction insrc/App.tsxis redundant and can be safely removed to simplify the code. - Naming Conventions: Please avoid one-letter variable names like
u. Using descriptive names likeusermakes the code much easier to read and maintain. [CHECKLIST ITEM #1]
Keep up the great work, you're making fantastic progress!
✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨
Footnotes
| - name: Upload tests report(cypress mochaawesome merged HTML report) | ||
| if: ${{ always() }} | ||
| uses: actions/upload-artifact@v2 | ||
| uses: actions/upload-artifact@v4 |
There was a problem hiding this comment.
There seems to be a mismatch in the artifact path. According to cypress.config.ts, the test reports are generated in the raw_reports directory. However, this step attempts to upload from a reports directory (defined on line 29), which likely doesn't exist. Please update the path to match your Cypress configuration.
| const [titleError, setTitleError] = useState(false); | ||
|
|
||
| const handleChangeUser = (event: React.ChangeEvent<HTMLSelectElement>) => { | ||
| const user = users.find(u => u.username === event.target.value); |
There was a problem hiding this comment.
This violates checklist item #1: "Don't use one-letter variable naming". Please rename u to a more descriptive name like user to improve code readability.
| if (!titleTask.trim()) { | ||
| setTitleError(true); | ||
| } |
There was a problem hiding this comment.
This if block is redundant. The call to setTitleError(true) on line 40 has no effect because setTitleError(false) is called unconditionally on line 44 right after it. You can safely remove this if statement, as the requirement is only to hide the error on change, which line 44 already accomplishes.
| <h1>Add todo form</h1> | ||
|
|
||
| <form action="/api/users" method="POST"> | ||
| <form action="/api/todos" method="POST" onSubmit={addTaskHandler}> |
There was a problem hiding this comment.
The action and method attributes are not necessary for a form handled entirely by React on the client side. The onSubmit handler in React (addTaskHandler) prevents the default browser form submission, so these attributes will never be used. You can remove them for cleaner code.
| <input | ||
| type="text" | ||
| data-cy="titleInput" | ||
| value={title} | ||
| onChange={handleChangeTitle} | ||
| placeholder="Enter title of task" | ||
| /> |
There was a problem hiding this comment.
To improve accessibility and provide a better user experience, it would be beneficial to add an id attribute to this input that matches the htmlFor in the associated <label>.
| <select | ||
| data-cy="userSelect" | ||
| value={selectedUser?.username ?? '0'} | ||
| onChange={handleChangeUser} | ||
| > |
There was a problem hiding this comment.
To improve accessibility, please add an id attribute to this <select> element that matches the htmlFor attribute of its corresponding <label>.
| }; | ||
|
|
||
| export const TodoInfo = ({ todo }: Props) => { | ||
| // const taskUser = users.find(u => u.id === todo.userId); |
There was a problem hiding this comment.
This line is no longer needed and can be removed. Great job on refactoring this component to rely on props instead of fetching its own data!
| title: string; | ||
| completed: boolean; | ||
| userId: User['id']; | ||
| user?: User; |
There was a problem hiding this comment.
According to the task description, every todo item must have a user object. The logic in your App component also ensures this is always the case. To align the type with the requirements and the actual data structure, please make the user property non-optional by removing the ?.
No description provided.