Skip to content

Commit 40c1c16

Browse files
committed
Functioning React Redux To Do list app, decoupled code
1 parent 15ee4e3 commit 40c1c16

19 files changed

+391
-17
lines changed

.vscode/launch.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"command": "npm start",
9+
"name": "Run npm start",
10+
"request": "launch",
11+
"type": "node-terminal"
12+
},
13+
{
14+
"type": "pwa-chrome",
15+
"request": "launch",
16+
"name": "Launch Chrome against localhost",
17+
"url": "http://localhost:8080",
18+
"webRoot": "${workspaceFolder}"
19+
}
20+
]
21+
}

package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
"@testing-library/jest-dom": "^4.2.4",
88
"@testing-library/react": "^9.5.0",
99
"@testing-library/user-event": "^7.2.1",
10+
"classname": "0.0.0",
11+
"classnames": "^2.2.6",
1012
"react": "^16.14.0",
1113
"react-dom": "^16.14.0",
1214
"react-redux": "^7.2.1",

src/TodoApp.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import AddTodo from './components/AddTodo';
3+
import TodoList from './components/TodoList';
4+
import VisibilityFilters from './components/VisibilityFilters';
5+
import "./styles.css";
6+
7+
export default function TodoApp(){
8+
return (
9+
<div className="todo-app">
10+
<h1>Todo List</h1>
11+
<AddTodo />
12+
<TodoList />
13+
<VisibilityFilters />
14+
</div>
15+
);
16+
}

src/app/store.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { configureStore } from '@reduxjs/toolkit';
2-
import counterReducer from '../features/counter/counterSlice';
1+
// import { configureStore } from '@reduxjs/toolkit';
2+
// import counterReducer from '../features/counter/counterSlice';
33

4-
export default configureStore({
5-
reducer: {
6-
counter: counterReducer,
7-
},
8-
});
4+
// export default configureStore({
5+
// reducer: {
6+
// counter: counterReducer,
7+
// },
8+
// });

src/components/AddTodo.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from "react";
2+
import { connect } from "react-redux";
3+
import { addTodo } from "../redux/actions";
4+
5+
class AddTodo extends React.Component {
6+
constructor(props) {
7+
super(props);
8+
this.state = { input: "" };
9+
}
10+
11+
updateInput = input => {
12+
this.setState({ input });
13+
};
14+
15+
handleAddTodo = () => {
16+
this.props.addTodo(this.state.input);
17+
this.setState({ input: "" });
18+
};
19+
20+
render() {
21+
return (
22+
<div>
23+
<input
24+
onChange={e => this.updateInput(e.target.value)}
25+
value={this.state.input}
26+
/>
27+
<button className="add-todo" onClick={this.handleAddTodo}>
28+
Add Todo
29+
</button>
30+
</div>
31+
);
32+
}
33+
}
34+
35+
export default connect(
36+
null,
37+
{ addTodo }
38+
)(AddTodo);
39+
// export default AddTodo;

src/components/Todo.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from "react";
2+
import { connect } from "react-redux";
3+
import cx from "classnames";
4+
import { toggleTodo } from "../redux/actions";
5+
6+
const Todo = ({ todo, toggleTodo }) => (
7+
<li className="todo-item" onClick={() => toggleTodo(todo.id)}>
8+
{todo && todo.completed ? "👌" : "👋"}{" "}
9+
<span
10+
className={cx(
11+
"todo-item__text",
12+
todo && todo.completed && "todo-item__text--completed"
13+
)}
14+
>
15+
{todo.content}
16+
</span>
17+
</li>
18+
);
19+
20+
// export default Todo;
21+
export default connect(
22+
null,
23+
{ toggleTodo }
24+
)(Todo);

src/components/TodoList.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React from "react";
2+
import { connect } from "react-redux";
3+
import Todo from "./Todo";
4+
// import { getTodos } from "../redux/selectors";
5+
import { getTodosByVisibilityFilter } from "../redux/selectors";
6+
import { VISIBILITY_FILTERS } from "../constants";
7+
8+
const TodoList = ({ todos }) => (
9+
<ul className="todo-list">
10+
{todos && todos.length
11+
? todos.map((todo, index) => {
12+
return <Todo key={`todo-${todo.id}`} todo={todo} />;
13+
})
14+
: "No todos, yay!"}
15+
</ul>
16+
);
17+
18+
// const mapStateToProps = state => {
19+
// const { byIds, allIds } = state.todos || {};
20+
// const todos =
21+
// allIds && state.todos.allIds.length
22+
// ? allIds.map(id => (byIds ? { ...byIds[id], id } : null))
23+
// : null;
24+
// return { todos };
25+
// };
26+
27+
const mapStateToProps = state => {
28+
const { visibilityFilter } = state;
29+
const todos = getTodosByVisibilityFilter(state, visibilityFilter);
30+
return { todos };
31+
// const allTodos = getTodos(state);
32+
// return {
33+
// todos:
34+
// visibilityFilter === VISIBILITY_FILTERS.ALL
35+
// ? allTodos
36+
// : visibilityFilter === VISIBILITY_FILTERS.COMPLETED
37+
// ? allTodos.filter(todo => todo.completed)
38+
// : allTodos.filter(todo => !todo.completed)
39+
// };
40+
};
41+
// export default TodoList;
42+
export default connect(mapStateToProps)(TodoList);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React from "react";
2+
import cx from "classnames";
3+
import { connect } from "react-redux";
4+
import { setFilter } from "../redux/actions";
5+
import { VISIBILITY_FILTERS } from "../constants";
6+
7+
const VisibilityFilters = ({ activeFilter, setFilter }) => {
8+
return (
9+
<div className="visibility-filters">
10+
{Object.keys(VISIBILITY_FILTERS).map(filterKey => {
11+
const currentFilter = VISIBILITY_FILTERS[filterKey];
12+
return (
13+
<span
14+
key={`visibility-filter-${currentFilter}`}
15+
className={cx(
16+
"filter",
17+
currentFilter === activeFilter && "filter--active"
18+
)}
19+
onClick={() => {
20+
setFilter(currentFilter);
21+
}}
22+
>
23+
{currentFilter}
24+
</span>
25+
);
26+
})}
27+
</div>
28+
);
29+
};
30+
31+
const mapStateToProps = state => {
32+
return { activeFilter: state.visibilityFilter };
33+
};
34+
// export default VisibilityFilters;
35+
export default connect(
36+
mapStateToProps,
37+
{ setFilter }
38+
)(VisibilityFilters);

src/constants.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const VISIBILITY_FILTERS = {
2+
ALL: "all",
3+
COMPLETED: "completed",
4+
INCOMPLETE: 'incomplete'
5+
};

0 commit comments

Comments
 (0)