Created
July 7, 2017 05:20
-
-
Save ZucchiniZe/3327a910a5fc2066fc909646c948a5be to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let pluralize ::word numItems::items => { | |
if (items != 1) { | |
(string_of_int items) ^ " " ^ word ^ "s"; | |
} else { | |
(string_of_int items) ^ " " ^ word; | |
} | |
}; | |
type item = { | |
id: int, | |
title: string, | |
completed: bool | |
}; | |
let se = ReasonReact.stringToElement; | |
let module TodoItem = { | |
let component = ReasonReact.statelessComponent "TodoItem"; | |
let make ::item ::onToggle _children => { | |
...component, | |
render: fun _self => { | |
<div className="item" onClick=(fun _evt => onToggle())> | |
<input | |
_type="checkbox" | |
checked=(Js.Boolean.to_js_boolean item.completed) | |
/> | |
(se item.title) | |
</div> | |
} | |
}; | |
}; | |
let valueFromEvent evt: string => | |
(evt | |
|> ReactEventRe.Form.target | |
|> ReactDOMRe.domElementToObj | |
)##value; | |
let module Input = { | |
type state = string; | |
let component = ReasonReact.statefulComponent "Input"; | |
let make ::onSubmit _self => { | |
...component, | |
initialState: fun () => "", | |
render: fun {state: text, update} => { | |
<input | |
value=text | |
_type="text" | |
placeholder="Write something to do" | |
onChange=(update (fun evt _ => | |
ReasonReact.Update (valueFromEvent evt) | |
)) | |
onKeyDown=(update (fun evt {state: text} => | |
if (ReactEventRe.Keyboard.key evt == "Enter") { | |
onSubmit text; | |
ReasonReact.Update ""; | |
} else { | |
ReasonReact.NoUpdate | |
} | |
)) | |
/> | |
} | |
} | |
}; | |
type state = { | |
items: list item, | |
}; | |
let component = ReasonReact.statefulComponent "TodoApp"; | |
let lastId = ref 0; | |
let newItem text => { | |
lastId := !lastId + 1; | |
{id: !lastId, title: text, completed: true}; | |
}; | |
let toggleItem items id => { | |
List.map | |
(fun item => item.id === id | |
? {...item, completed: not item.completed} | |
: item) | |
items; | |
}; | |
let make _children => { | |
...component, | |
initialState: fun () => { | |
items: [{ | |
id: 0, | |
title: "Write somethings to do", | |
completed: false, | |
}] | |
}, | |
render: fun {state: {items}, update} => { | |
<div className="app"> | |
<div className="title"> | |
(se "What to do") | |
<Input | |
onSubmit=(update (fun text {state} => { | |
ReasonReact.Update { | |
items: [newItem text, ...state.items] | |
} | |
})) | |
/> | |
</div> | |
<div className="items"> | |
(List.map (fun item => <TodoItem | |
key=(string_of_int item.id) | |
onToggle=(update (fun _ {state} => | |
ReasonReact.Update { | |
items: toggleItem items item.id | |
} | |
)) | |
item />) items | |
|> Array.of_list | |
|> ReasonReact.arrayToElement ) | |
</div> | |
<div className="footer"> | |
(se (pluralize word::"item" numItems::(List.length items))) | |
</div> | |
</div> | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment