-
Notifications
You must be signed in to change notification settings - Fork 3
/
todo.js
76 lines (61 loc) · 2.09 KB
/
todo.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { types, createSchema } from "redux-action-schema"
import { createStore, combineReducers, applyMiddleware } from "redux"
const merge = (a, b) => Object.assign({}, a, b)
// schema
const show = ["all", "active", "completed"]
const todoID = (value) => typeof value === "number" && value > 0
const schema = createSchema([
["addTodo", "here is a docstring",
["id", todoID],
["text", types.String]],
["editTodo",
["id", "params can have docstrings too", todoID],
["text", types.String]],
["toggleTodo", todoID],
["deleteTodo", todoID],
["completeAll"],
["clearCompleted"],
["setVisibility", types.OneOf(show)]])
// actions
let id = 0
export const actionCreators = merge(schema.actionCreators, {
addTodo: (text) => {
id += 1
return schema.actionCreators.addTodo({ id, text })
},
})
// reducers
const update = (state, id, updateFn) =>
state.map((todo) => todo.id === id
? updateFn(todo)
: todo)
const todoReducer = schema.createReducer({
addTodo: (state, { id, text }) =>
state.concat([{ id, text, completed: false }]),
editTodo: (state, { id, text }) => update(state, id,
(todo) => merge(todo, { text })),
toggleTodo: (state, id) => update(state, id,
(todo) => merge(todo, { completed: !todo.completed })),
deleteTodo: (state, id) =>
state.filter((todo) => todo.id !== id),
completeAll: (state) =>
state.map((todo) => merge(todo, { completed: true })),
clearCompleted: (state) =>
state.filter((todo) => !todo.completed),
}, [])
const visibilityReducer = schema.createReducer({
set_visibility: (state, option) => option,
}, "all")
const mainReducer = combineReducers({
todos: todoReducer,
visibility: visibilityReducer,
})
export const visibleTodos = ({ todos, visibility }) => ({
all: () => todos,
active: () => todos.filter((t) => !t.completed),
completed: () => todos.filter((t) => t.completed),
}[visibility]())
// store
export const store = createStore(
mainReducer,
applyMiddleware(schema.createMiddleware()))