Skip to content

Instantly share code, notes, and snippets.

@scott-fleischman
Last active April 27, 2016 16:27
Show Gist options
  • Save scott-fleischman/4a9dcf7cdf1645daa1b2803054bc15a1 to your computer and use it in GitHub Desktop.
Save scott-fleischman/4a9dcf7cdf1645daa1b2803054bc15a1 to your computer and use it in GitHub Desktop.
PureScript Todo app
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