Last active
October 21, 2016 01:06
-
-
Save zwhitchcox/7fce616f55d1cdc3cc0b1fb79ee72168 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
| port module Training exposing (..) | |
| import Html exposing (..) | |
| import Html.App exposing (programWithFlags) | |
| import Html.Attributes exposing (..) | |
| import Html.Events exposing (..) | |
| import Html.Keyed as Keyed | |
| import Html.Lazy exposing (lazy, lazy2) | |
| import Json.Decode as Json | |
| import String | |
| main : Program (Maybe Model) | |
| main = | |
| programWithFlags | |
| { init = init | |
| , view = view | |
| , update = updateWithStorage | |
| , subscriptions = \_ -> Sub.none | |
| } | |
| type alias Model = | |
| { todos : List Todo | |
| , newTodo : String | |
| , visibility : String | |
| , id : Int | |
| } | |
| type alias Todo = | |
| { description : String | |
| , completed : Bool | |
| , id : Int | |
| } | |
| emptyModel : Model | |
| emptyModel = | |
| { todos = [] | |
| , newTodo = "" | |
| , visibility = "All" | |
| , id = 0 | |
| } | |
| init : Maybe Model -> ( Model, Cmd Msg ) | |
| init savedState = | |
| Maybe.withDefault emptyModel savedState ! [] | |
| port setStorage : Model -> Cmd msg | |
| updateWithStorage : Msg -> Model -> ( Model, Cmd Msg ) | |
| updateWithStorage msg model = | |
| let | |
| ( newModel, cmds ) = | |
| update msg model | |
| in | |
| ( newModel | |
| , Cmd.batch [ setStorage newModel, cmds ] | |
| ) | |
| type Msg | |
| = DeleteCompleted | |
| | ToggleAll Bool | |
| | UpdateTodo Int String | |
| | Delete Int | |
| | ChangeVisibility String | |
| | AddTodo | |
| | UpdateNewTodo String | |
| | Check Int Bool | |
| | NoOp | |
| update : Msg -> Model -> ( Model, Cmd Msg ) | |
| update msg model = | |
| case msg of | |
| Check id isCompleted -> | |
| let | |
| updateTodo todo = | |
| if todo.id == id then | |
| { todo | completed = isCompleted } | |
| else | |
| todo | |
| in | |
| { model | todos = List.map updateTodo model.todos } | |
| ! [] | |
| UpdateTodo id task -> | |
| let | |
| updateTodo t = | |
| if t.id == id then | |
| { t | description = task } | |
| else | |
| t | |
| in | |
| { model | todos = List.map updateTodo model.todos } | |
| ! [] | |
| Delete id -> | |
| { model | todos = List.filter (\t -> t.id /= id) model.todos } | |
| ! [] | |
| DeleteCompleted -> | |
| { model | todos = List.filter (not << .completed) model.todos } | |
| ! [] | |
| ToggleAll isCompleted -> | |
| let | |
| updateTodo t = | |
| { t | completed = isCompleted } | |
| in | |
| { model | todos = List.map updateTodo model.todos } | |
| ! [] | |
| ChangeVisibility visibility -> | |
| { model | visibility = visibility } | |
| ! [] | |
| AddTodo -> | |
| if (not (String.isEmpty model.newTodo)) then | |
| { model | |
| | id = model.id + 1 | |
| , todos = model.todos ++ [ newTodo model.newTodo model.id ] | |
| , newTodo = "" | |
| } | |
| ! [] | |
| else | |
| model | |
| ! [] | |
| UpdateNewTodo description -> | |
| { model | newTodo = description } | |
| ! [] | |
| NoOp -> | |
| model | |
| ! [] | |
| newTodo : String -> Int -> Todo | |
| newTodo description id = | |
| { description = description | |
| , id = id | |
| , completed = False | |
| } | |
| view : Model -> Html Msg | |
| view model = | |
| div [] | |
| [ section | |
| [] | |
| [ lazy viewNewTodo model.newTodo | |
| , lazy2 viewTodos model.visibility model.todos | |
| , lazy2 viewControls model.visibility model.todos | |
| ] | |
| ] | |
| viewNewTodo : String -> Html Msg | |
| viewNewTodo newTodo = | |
| input | |
| [ type' "text" | |
| , placeholder "What needs to be done?" | |
| , autofocus True | |
| , value newTodo | |
| , onInput UpdateNewTodo | |
| , onEnter AddTodo | |
| ] | |
| [] | |
| onEnter : Msg -> Attribute Msg | |
| onEnter msg = | |
| let | |
| tagger code = | |
| if code == 13 then | |
| msg | |
| else | |
| NoOp | |
| in | |
| on "keydown" (Json.map tagger keyCode) | |
| viewTodos : String -> List Todo -> Html Msg | |
| viewTodos visibility todos = | |
| let | |
| isVisible todo = | |
| case visibility of | |
| "Completed" -> | |
| todo.completed | |
| "Active" -> | |
| not todo.completed | |
| _ -> | |
| True | |
| cssVisibility = | |
| if List.isEmpty todos then | |
| "hidden" | |
| else | |
| "visible" | |
| allCompleted = | |
| List.all .completed todos | |
| in | |
| section | |
| [ style [ ( "visibility", cssVisibility ) ] ] | |
| [ br [] [] | |
| , button | |
| [ onClick (ToggleAll (not allCompleted)) ] | |
| [ text "Toggle all todos" ] | |
| , Keyed.ul [] <| | |
| List.map viewKeyedTodo (List.filter isVisible todos) | |
| ] | |
| viewKeyedTodo : Todo -> ( String, Html Msg ) | |
| viewKeyedTodo todo = | |
| ( toString todo.id, lazy viewTodo todo ) | |
| viewTodo : Todo -> Html Msg | |
| viewTodo todo = | |
| li [] | |
| [ input | |
| [ type' "checkbox" | |
| , checked todo.completed | |
| , onClick (Check todo.id (not todo.completed)) | |
| ] | |
| [] | |
| , input | |
| [ value todo.description | |
| , onInput (UpdateTodo todo.id) | |
| ] | |
| [] | |
| , button [ onClick (Delete todo.id) ] [ text "X" ] | |
| ] | |
| viewControls : String -> List Todo -> Html Msg | |
| viewControls visibility todos = | |
| let | |
| todosCompleted = | |
| List.length (List.filter .completed todos) | |
| todosLeft = | |
| List.length todos - todosCompleted | |
| in | |
| footer | |
| [ hidden (List.isEmpty todos) | |
| ] | |
| [ lazy viewControlsCount todosLeft | |
| , viewControlsFilters | |
| , lazy viewControlsClear todosCompleted | |
| ] | |
| viewControlsCount : Int -> Html Msg | |
| viewControlsCount left = | |
| let | |
| pluralized = | |
| if left == 1 then | |
| " todo" | |
| else | |
| " todos" | |
| in | |
| text (toString left ++ pluralized) | |
| viewControlsFilters : Html Msg | |
| viewControlsFilters = | |
| ul [] | |
| [ visibilityLi "#/" "All" | |
| , visibilityLi "#/completed" "Completed" | |
| , visibilityLi "#/active" "Active" | |
| ] | |
| visibilityLi : String -> String -> Html Msg | |
| visibilityLi uri visible = | |
| li [] | |
| [ a | |
| [ href uri | |
| , onClick (ChangeVisibility visible) | |
| ] | |
| [ text visible ] | |
| ] | |
| viewControlsClear : Int -> Html Msg | |
| viewControlsClear completed = | |
| button | |
| [ onClick DeleteCompleted ] | |
| [ text ("Delete " ++ (toString completed) ++ " completed items") ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment