Skip to content
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

Adding in progress state to the todo app #1007

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/App/NewTodoInput/index.tsx
Original file line number Diff line number Diff line change
@@ -19,11 +19,14 @@ const NewTodoTextInput: React.FC = () => {
const todo: Todo = {
bodyText: textInput.current.value,
completed: false,
inProgress: false,
id: UUID(),
}

// add new TODO to entire TodoList
setAppState({ todoList: [todo, ...appState.todoList] })
setAppState({
todoList: [todo, ...appState.todoList],
})

// reset text input UI value
textInput.current.value = ''
39 changes: 35 additions & 4 deletions src/App/TodoList/Item/index.tsx
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ const Item: React.FC<Props> = ({ todo }) => {
// search clicked item by id...
if (t.id === id) {
// change complated status only clicked item
return { ...t, completed: !t.completed }
return { ...t, completed: !t.completed, inProgress: false }
// return other item without any changes
} else {
return t
@@ -80,7 +80,19 @@ const Item: React.FC<Props> = ({ todo }) => {
setAppState({ todoList: removed })
}

const handleTodoTextEdit = (e: React.ChangeEvent<HTMLInputElement>, onEdit: Todo['id']): void => { /* eslint-disable-line prettier/prettier */
const setInprogress = (id: Todo['id']) => {
let temp: TodoListType = appState.todoList.map((t) =>
t.inProgress ? { ...t, inProgress: false } : t
)
temp = temp.map((t) => (t.id === id ? { ...t, inProgress: true } : t))
setAppState({ todoList: temp })
}

const handleTodoTextEdit = (
e: React.ChangeEvent<HTMLInputElement>,
onEdit: Todo['id']
): void => {
/* eslint-disable-line prettier/prettier */
const edited = appState.todoList.map((t: Todo): Todo => {
if (t.id === onEdit) {
return { ...t, bodyText: e.target.value }
@@ -112,13 +124,28 @@ const Item: React.FC<Props> = ({ todo }) => {
/>

{/* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */}

<label
onClick={onClick}
data-cy="todo-body-text"
data-testid="todo-body-text"
>
{todo.bodyText}
</label>
{!todo.completed && todo.inProgress && (
<span className="inProgressActiveBadeg">In Progress</span>
)}
{!todo.completed && !todo.inProgress && (
<span
className="inProgressBadeg"
onClick={() => setInprogress(todo.id)}
>
Backlog
</span>
)}
{todo.completed && !todo.inProgress && (
<span className="completedBadeg">Completed</span>
)}
{/* eslint-enable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */}
<button
className="destroy"
@@ -132,8 +159,12 @@ const Item: React.FC<Props> = ({ todo }) => {
onBlur={(e: React.FocusEvent<HTMLInputElement>) => onBlurEdit(e)}
className="edit"
value={todo.bodyText}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleTodoTextEdit(e, todo.id)} /* eslint-disable-line prettier/prettier */
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => submitEditText(e)} /* eslint-disable-line prettier/prettier */
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
handleTodoTextEdit(e, todo.id)
} /* eslint-disable-line prettier/prettier */
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) =>
submitEditText(e)
} /* eslint-disable-line prettier/prettier */
data-cy="todo-edit-input"
data-testid="todo-edit-input"
/>
39 changes: 39 additions & 0 deletions src/App/TodoList/Item/style.ts
Original file line number Diff line number Diff line change
@@ -35,6 +35,12 @@ export const Layout = styled.div`
margin: 0 0 0 43px;
}

.view {
display: flex;
align-items: center;
justify-content: space-between;
}

.editing .view {
display: none;
}
@@ -111,4 +117,37 @@ export const Layout = styled.div`
.editing:last-child {
margin-bottom: -1px;
}

.inProgressActiveBadeg {
padding: 3px 5px;
border-radius: 3px;
font-size: 0.5em;
background-color: #f39c12;
color: white;
font-weight: 600;
margin-right: 70px;
cursor: pointer;
}

.inProgressBadeg {
padding: 3px 5px;
border-radius: 3px;
font-size: 0.5em;
background-color: #bdc3c7;
color: white;
font-weight: 600;
margin-right: 70px;
cursor: pointer;
}

.completedBadeg {
padding: 3px 5px;
border-radius: 3px;
font-size: 0.5em;
background-color: #2ecc71;
color: white;
font-weight: 600;
margin-right: 70px;
cursor: pointer;
}
`
17 changes: 12 additions & 5 deletions src/App/TodoList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ReactElement } from 'react'
import { ReactElement, useEffect } from 'react'
import React from 'react'
import { useLocation } from 'react-router-dom'
import { useRecoilState } from 'recoil'
@@ -13,9 +13,14 @@ const TodoList: React.FC = () => {
const { pathname } = useLocation()
const [appState, setAppState] = useRecoilState<AppState>(recoilState)

function toggleAllCheckbox(e: React.ChangeEvent<HTMLInputElement>): void { /* eslint-disable-line prettier/prettier */
function toggleAllCheckbox(e: React.ChangeEvent<HTMLInputElement>): void {
/* eslint-disable-line prettier/prettier */
// reverse all todo.completed: boolean flag
setAppState({ todoList: appState.todoList.map((t: Todo): Todo => ({ ...t, completed: e.target.checked })) }) /* eslint-disable-line prettier/prettier */
setAppState({
todoList: appState.todoList.map(
(t: Todo): Todo => ({ ...t, completed: e.target.checked })
),
}) /* eslint-disable-line prettier/prettier */
}

return (
@@ -36,8 +41,10 @@ const TodoList: React.FC = () => {
switch (pathname) {
case '/':
return true
case '/active':
return t.completed === false
case '/backlog':
return t.completed === false && t.inProgress === false
case '/in-progress':
return t.inProgress === true
case '/completed':
return t.completed === true
default:
15 changes: 12 additions & 3 deletions src/App/UnderBar/FilterLink/index.tsx
Original file line number Diff line number Diff line change
@@ -17,10 +17,19 @@ const FilterLink: React.FC = () => {
<li>
<Link
data-cy="active-filter"
className={pathname === '/active' ? 'selected' : ''}
to="/active"
className={pathname === '/backlog' ? 'selected' : ''}
to="/backlog"
>
Active
Backlog
</Link>
</li>
<li>
<Link
data-cy="active-filter"
className={pathname === '/in-progress' ? 'selected' : ''}
to="/in-progress"
>
In progress
</Link>
</li>
<li>
8 changes: 6 additions & 2 deletions src/App/UnderBar/index.tsx
Original file line number Diff line number Diff line change
@@ -9,8 +9,12 @@ import { Layout } from './style'

const UnderBar: React.FC = () => {
const [appState, setAppState] = useRecoilState<AppState>(recoilState)
const completed: number = appState.todoList.filter(t => t.completed === true).length /* eslint-disable-line prettier/prettier */
const backlog: number = appState.todoList.filter(t => t.completed === false).length /* eslint-disable-line prettier/prettier */
const completed: number = appState.todoList.filter(
(t) => t.completed
).length /* eslint-disable-line prettier/prettier */
const backlog: number = appState.todoList.filter(
(t) => t.completed === false
).length /* eslint-disable-line prettier/prettier */

function clearCompleted(): void {
setAppState({
3 changes: 2 additions & 1 deletion src/App/index.tsx
Original file line number Diff line number Diff line change
@@ -12,8 +12,9 @@ const App: React.FC = () => (
<RecoilRoot>
<Routes>
<Route path="/" element={<TodoMVC />} />
<Route path="/active" element={<TodoMVC />} />
<Route path="/backlog" element={<TodoMVC />} />
<Route path="/completed" element={<TodoMVC />} />
<Route path="/in-progress" element={<TodoMVC />} />
<Route path="*" element={<NotFound />} />
</Routes>
</RecoilRoot>
1 change: 1 addition & 0 deletions src/dataStructure.ts
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ export interface Todo {
id: string
bodyText: string
completed: boolean
inProgress: boolean
}

export type TodoListType = Todo[]