-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add task solution #2729
base: master
Are you sure you want to change the base?
add task solution #2729
Changes from 1 commit
64f62cd
83cc411
e1fe027
a5ff1b4
e074a03
51e29c0
5683302
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,65 @@ | ||
/* eslint-disable max-len */ | ||
import React from 'react'; | ||
import React, { useEffect, useState } from 'react'; | ||
import 'bulma/css/bulma.css'; | ||
import '@fortawesome/fontawesome-free/css/all.css'; | ||
|
||
import { TodoList } from './components/TodoList'; | ||
import { TodoFilter } from './components/TodoFilter'; | ||
import { TodoModal } from './components/TodoModal'; | ||
import { Loader } from './components/Loader'; | ||
import { Todo } from './types/Todo'; | ||
|
||
export const App: React.FC = () => { | ||
const [todos, setTodos] = useState<Todo[]>([]); | ||
const [loading, setLoading] = useState(false); | ||
const [selectedTodo, setSelectedTodo] = useState<Todo | null>(null); | ||
const [selecteValue, setSelecteValue] = useState('all'); | ||
const [inputValue, setInputValue] = useState(''); | ||
|
||
useEffect(() => { | ||
setLoading(true); | ||
setTimeout(() => { | ||
setLoading(false); | ||
}, 1000); | ||
}, []); | ||
|
||
useEffect(() => { | ||
fetch(` | ||
https://mate-academy.github.io/react_dynamic-list-of-todos/api/todos.json`) | ||
.then(response => response.json()) | ||
.then((todosFromServer: Todo[]) => { | ||
switch (selecteValue) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typographical Error: The variable |
||
case 'all': | ||
setTodos( | ||
todosFromServer.filter(todo => | ||
todo.title.toLowerCase().includes(inputValue.toLowerCase()), | ||
), | ||
); | ||
break; | ||
case 'active': | ||
setTodos( | ||
todosFromServer.filter( | ||
todo => | ||
!todo.completed && | ||
todo.title.toLowerCase().includes(inputValue.toLowerCase()), | ||
), | ||
); | ||
break; | ||
case 'completed': | ||
setTodos( | ||
todosFromServer.filter( | ||
todo => | ||
todo.completed && | ||
todo.title.toLowerCase().includes(inputValue.toLowerCase()), | ||
), | ||
); | ||
break; | ||
default: | ||
return; | ||
} | ||
}); | ||
}, [selecteValue, inputValue]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Data Fetching Logic: The |
||
|
||
return ( | ||
<> | ||
<div className="section"> | ||
|
@@ -17,18 +68,32 @@ export const App: React.FC = () => { | |
<h1 className="title">Todos:</h1> | ||
|
||
<div className="block"> | ||
<TodoFilter /> | ||
<TodoFilter | ||
selecteValue={selecteValue} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typographical Error: The prop |
||
setSelecteValue={setSelecteValue} | ||
inputValue={inputValue} | ||
setInputValue={setInputValue} | ||
/> | ||
</div> | ||
|
||
<div className="block"> | ||
<Loader /> | ||
<TodoList /> | ||
{loading && <Loader />} | ||
<TodoList | ||
todos={todos} | ||
setSelectedTodo={setSelectedTodo} | ||
selectedTodo={selectedTodo} | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<TodoModal /> | ||
{selectedTodo && ( | ||
<TodoModal | ||
selectedTodo={selectedTodo} | ||
onClose={() => setSelectedTodo(null)} | ||
/> | ||
)} | ||
</> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,24 @@ | ||
export const TodoFilter = () => ( | ||
type Props = { | ||
selecteValue: string; | ||
setSelecteValue: (selecteValue: string) => void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typographical Error: The prop |
||
inputValue: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typographical Error: The function name |
||
setInputValue: (selecteValue: string) => void; | ||
}; | ||
|
||
export const TodoFilter: React.FC<Props> = ({ | ||
selecteValue, | ||
setSelecteValue, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typographical Error: The variable |
||
inputValue, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typographical Error: The function |
||
setInputValue, | ||
}) => ( | ||
<form className="field has-addons"> | ||
<p className="control"> | ||
<span className="select"> | ||
<select data-cy="statusSelect"> | ||
<select | ||
data-cy="statusSelect" | ||
value={selecteValue} | ||
onChange={event => setSelecteValue(event.target.value)} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typographical Error: The attribute |
||
> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typographical Error: The function |
||
<option value="all">All</option> | ||
<option value="active">Active</option> | ||
<option value="completed">Completed</option> | ||
|
@@ -16,14 +32,23 @@ export const TodoFilter = () => ( | |
type="text" | ||
className="input" | ||
placeholder="Search..." | ||
value={inputValue} | ||
onChange={event => setInputValue(event.target.value)} | ||
/> | ||
<span className="icon is-left"> | ||
<i className="fas fa-magnifying-glass" /> | ||
</span> | ||
|
||
<span className="icon is-right" style={{ pointerEvents: 'all' }}> | ||
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} | ||
<button data-cy="clearSearchButton" type="button" className="delete" /> | ||
{inputValue && ( | ||
<button | ||
data-cy="clearSearchButton" | ||
type="button" | ||
className="delete" | ||
onClick={() => setInputValue('')} | ||
/> | ||
)} | ||
</span> | ||
</p> | ||
</form> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,33 @@ | ||
import React from 'react'; | ||
import React, { useEffect, useState } from 'react'; | ||
import { Loader } from '../Loader'; | ||
import { Todo } from '../../types/Todo'; | ||
import { User } from '../../types/User'; | ||
|
||
type Props = { | ||
selectedTodo: Todo; | ||
onClose: () => void; | ||
}; | ||
|
||
export const TodoModal: React.FC<Props> = ({ selectedTodo, onClose }) => { | ||
const [user, setUser] = useState<User | null>(null); | ||
const [loading, setLoading] = useState(false); | ||
|
||
useEffect(() => { | ||
setLoading(true); | ||
setTimeout(() => { | ||
fetch(` | ||
https://mate-academy.github.io/react_dynamic-list-of-todos/api/users/${selectedTodo.userId}.json`) | ||
.then(response => response.json()) | ||
.then(userFromServer => setUser(userFromServer)) | ||
.finally(() => setLoading(false)); | ||
}, 1000); | ||
}, [selectedTodo]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unnecessary Delay: The |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lack of Error Handling: The fetch request does not handle potential errors. Consider adding error handling to manage network issues or invalid responses. |
||
export const TodoModal: React.FC = () => { | ||
return ( | ||
<div className="modal is-active" data-cy="modal"> | ||
<div className="modal-background" /> | ||
|
||
{true ? ( | ||
{loading ? ( | ||
<Loader /> | ||
) : ( | ||
<div className="modal-card"> | ||
|
@@ -15,25 +36,32 @@ export const TodoModal: React.FC = () => { | |
className="modal-card-title has-text-weight-medium" | ||
data-cy="modal-header" | ||
> | ||
Todo #2 | ||
Todo #{selectedTodo.id} | ||
</div> | ||
|
||
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} | ||
<button type="button" className="delete" data-cy="modal-close" /> | ||
<button | ||
type="button" | ||
className="delete" | ||
data-cy="modal-close" | ||
onClick={onClose} | ||
/> | ||
</header> | ||
|
||
<div className="modal-card-body"> | ||
<p className="block" data-cy="modal-title"> | ||
quis ut nam facilis et officia qui | ||
{selectedTodo.title} | ||
</p> | ||
|
||
<p className="block" data-cy="modal-user"> | ||
{/* <strong className="has-text-success">Done</strong> */} | ||
<strong className="has-text-danger">Planned</strong> | ||
<strong className="has-text-danger"> | ||
{selectedTodo.completed ? 'Done' : 'Planned'} | ||
</strong> | ||
|
||
{' by '} | ||
|
||
<a href="mailto:[email protected]">Leanne Graham</a> | ||
<a href={`mailto:${user?.email}`}>{user?.name}</a> | ||
</p> | ||
</div> | ||
</div> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typographical Error: The state variable
selecteValue
seems to be a typo. It should likely beselectedValue
to better reflect its purpose and avoid confusion.