Last active
April 27, 2016 16:27
-
-
Save scott-fleischman/4a9dcf7cdf1645daa1b2803054bc15a1 to your computer and use it in GitHub Desktop.
PureScript Todo app
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
module App.Todo where | |
import Prelude (const, (+), class Show, class Eq, eq, show, map, ($)) | |
import Data.Array (snoc, filter) | |
import Pux.CSS (textDecoration, lineThrough, noneTextDecoration, style, TextDecoration, color, rgb) | |
import Pux.Html (Html, div, input, button, text, ul, li, p, a) | |
import Pux.Html.Attributes (type_, value, key) | |
import Pux.Html.Events (onChange, onClick) | |
data Action | |
= SetTodoText String | |
| AddTodo | |
| ToggleTodo TodoId | |
| SetVisible Visible | |
newtype TodoId = TodoId Int | |
instance showTodoId :: Show TodoId where | |
show (TodoId x) = show x | |
instance eqTodoId :: Eq TodoId where | |
eq (TodoId x) (TodoId y) = eq x y | |
nextTodoId :: TodoId -> TodoId | |
nextTodoId (TodoId x) = TodoId (x + 1) | |
data IsDone = NotDone | Done | |
instance eqIsDone :: Eq IsDone where | |
eq Done Done = true | |
eq NotDone NotDone = true | |
eq _ _ = false | |
toggleIsDone :: IsDone -> IsDone | |
toggleIsDone NotDone = Done | |
toggleIsDone Done = NotDone | |
data Visible = AllVisible | DoneVisible | NotDoneVisible | |
instance eqVisible :: Eq Visible where | |
eq AllVisible AllVisible = true | |
eq DoneVisible DoneVisible = true | |
eq NotDoneVisible NotDoneVisible = true | |
eq _ _ = false | |
type Todo = | |
{ id :: TodoId | |
, text :: String | |
, isDone :: IsDone | |
} | |
type State = | |
{ nextTodo :: Todo | |
, todos :: Array Todo | |
, visible :: Visible | |
} | |
init :: State | |
init = | |
{ nextTodo: | |
{ id: TodoId 0 | |
, text: "" | |
, isDone: NotDone | |
} | |
, todos: [] | |
, visible: AllVisible | |
} | |
update :: Action -> State -> State | |
update (SetTodoText d) s = s { nextTodo = s.nextTodo { text = d } } | |
update AddTodo s = s | |
{ nextTodo = | |
s.nextTodo | |
{ id = nextTodoId s.nextTodo.id | |
, text = "" | |
} | |
, todos = snoc s.todos s.nextTodo | |
} | |
update (ToggleTodo x) s = s { todos = map (toggleTodo x) s.todos } | |
update (SetVisible v) s = s { visible = v } | |
toggleTodo :: TodoId -> Todo -> Todo | |
toggleTodo x t = if eq t.id x then t { isDone = toggleIsDone t.isDone } else t | |
getTodosFilter :: Visible -> Todo -> Boolean | |
getTodosFilter AllVisible _ = true | |
getTodosFilter DoneVisible x = eq x.isDone Done | |
getTodosFilter NotDoneVisible x = eq x.isDone NotDone | |
view :: State -> Html Action | |
view s = | |
div | |
[] | |
[ addTodo s.nextTodo | |
, ul [] $ map todo (filter (getTodosFilter s.visible) s.todos) | |
, visibleOptions s.visible | |
] | |
visibleOptions :: Visible -> Html Action | |
visibleOptions v = | |
div | |
[] | |
[ p [] | |
[ text "Show: " | |
, visibleOption AllVisible "All" v | |
, text ", " | |
, visibleOption DoneVisible "Done" v | |
, text ", " | |
, visibleOption NotDoneVisible "Not Done" v | |
] | |
] | |
visibleOption :: Visible -> String -> Visible -> Html Action | |
visibleOption v t x = | |
a | |
[ onClick (const (SetVisible v)) | |
, style $ do | |
color (if eq v x then rgb 200 200 200 else rgb 0 0 0) | |
] | |
[ text t ] | |
isDoneTextDecoration :: IsDone -> TextDecoration | |
isDoneTextDecoration Done = lineThrough | |
isDoneTextDecoration NotDone = noneTextDecoration | |
todo :: Todo -> Html Action | |
todo x = | |
li | |
[ key (show x.id) | |
, onClick (const (ToggleTodo x.id)) | |
, style $ do | |
textDecoration (isDoneTextDecoration x.isDone) | |
] | |
[ text x.text ] | |
addTodo :: Todo -> Html Action | |
addTodo x = | |
div | |
[] | |
[ input | |
[ type_ "text" | |
, value x.text | |
, onChange (\x -> SetTodoText x.target.value) | |
] | |
[] | |
, button | |
[ onClick (const AddTodo) ] | |
[ text "Add Todo" ] | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment