Skip to content

Instantly share code, notes, and snippets.

@heygema
Last active May 11, 2018 06:43
Show Gist options
  • Save heygema/be3cd645abf38842041e02510bed39c5 to your computer and use it in GitHub Desktop.
Save heygema/be3cd645abf38842041e02510bed39c5 to your computer and use it in GitHub Desktop.
type action =
| AddTodo
| DeleteTodo(int)
| CheckTodo(int)
| CheckAll
| HandleInput(string)
| ShowCompleted
| ShowDoing
| ShowAll;
type visibility = [ | `completed | `doing | `all];
type todo = {
id: int,
name: string,
completed: bool,
};
type state = {
todos: option(list(todo)),
todoNameInput: string,
visibility,
};
let unwrap = item =>
switch (item) {
| None => []
| Some(value) => value
};
let initTodos = () => [
{id: 1, name: "buy a house", completed: true},
{id: 2, name: "buy oreos", completed: false},
{id: 3, name: "buy a motorcycle", completed: false},
{id: 4, name: "give charity", completed: false},
{id: 5, name: "buy a hospital", completed: false},
];
let createState = () => {
todos: Some(initTodos()),
todoNameInput: "",
visibility: `all,
};
let todoID = ref(List.length(initTodos()));
let createTodo = text => {
todoID := todoID^ + 1;
{id: todoID^, name: text, completed: false};
};
module TodoItem = {
let component = ReasonReact.statelessComponent("TodoItem");
let make = (~name, ~completed, ~onClick, _children) => {
...component,
render: _self => {
let n = name |> ReasonReact.string;
<li onClick> (completed ? <s> n </s> : n) </li>;
},
};
};
let component = ReasonReact.reducerComponent("TodoTwo");
let make = _children => {
...component,
initialState: () => createState(),
reducer: (action, state) =>
switch (action) {
| AddTodo =>
let {todoNameInput, todos} = state;
let newTodo = createTodo(todoNameInput);
let newTodos = List.append(unwrap(todos), [newTodo]);
todoNameInput !== "" ?
ReasonReact.Update({
...state,
todoNameInput: "",
todos: Some(newTodos),
}) :
ReasonReact.NoUpdate;
| CheckTodo(id) =>
let {todos} = state;
let updatedTodos =
List.map(
todo =>
todo.id === id ? {...todo, completed: ! todo.completed} : todo,
unwrap(todos),
);
ReasonReact.Update({...state, todos: Some(updatedTodos)});
| HandleInput(input) =>
ReasonReact.Update({...state, todoNameInput: input})
| CheckAll =>
let {todos} = state;
let updatedTodos =
unwrap(todos) |> List.map(todo => {...todo, completed: true});
ReasonReact.Update({...state, todos: Some(updatedTodos)});
| ShowCompleted => ReasonReact.Update({...state, visibility: `completed})
| ShowDoing => ReasonReact.Update({...state, visibility: `doing})
| ShowAll => ReasonReact.Update({...state, visibility: `all})
| _ => ReasonReact.NoUpdate
},
render: self => {
let {todos, todoNameInput, visibility} = self.state;
let visibleTodos =
switch (visibility) {
| `all => unwrap(todos)
| `doing =>
List.filter(item => item.completed === false, unwrap(todos))
| `completed =>
List.filter(item => item.completed === true, unwrap(todos))
};
<div>
<h1> ("TODOS" |> ReasonReact.string) </h1>
<ol>
(
visibleTodos
|> List.map(todo => {
let {id, name, completed} = todo;
<TodoItem
key=(string_of_int(id))
name
completed
onClick=(_e => self.send(CheckTodo(todo.id)))
/>;
})
|> Array.of_list
|> ReasonReact.array
)
</ol>
<input
onKeyDown=(
e =>
if (ReactEventRe.Keyboard.keyCode(e) === 13) {
ReactEventRe.Keyboard.preventDefault(e);
self.send(AddTodo);
}
)
onChange=(
e =>
self.send(
HandleInput(
ReactDOMRe.domElementToObj(ReactEventRe.Form.target(e))##value,
),
)
)
_type="text"
value=todoNameInput
/>
<button onClick=(_e => self.send(CheckAll))>
("check all" |> ReasonReact.string)
</button>
<button onClick=(_e => self.send(ShowDoing))>
("show doing" |> ReasonReact.string)
</button>
<button onClick=(_e => self.send(ShowCompleted))>
("show done" |> ReasonReact.string)
</button>
<button onClick=(_e => self.send(ShowAll))>
("show all" |> ReasonReact.string)
</button>
</div>;
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment