Skip to content

Instantly share code, notes, and snippets.

@ZucchiniZe
Last active June 4, 2018 04:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZucchiniZe/5d60acf52c24d082e4648564e7df74a8 to your computer and use it in GitHub Desktop.
Save ZucchiniZe/5d60acf52c24d082e4648564e7df74a8 to your computer and use it in GitHub Desktop.
module Todo exposing (main)
import Css exposing (..)
import Css.Colors exposing (..)
import Html
import Html.Styled exposing (..)
import Html.Styled.Events exposing (..)
import Html.Styled.Attributes exposing (..)
main : Program Never Model Msg
main =
Html.program
{ init = init
, view = view >> toUnstyled
, update = update
, subscriptions = \_ -> Sub.none
}
-- MODEL
type alias ID =
Int
type Visibility
= All
| Active
| Completed
type alias Todo =
{ id : ID
, title : String
, completed : Bool
}
type alias Model =
{ todos : List Todo
, lastID : ID
, visibility : Visibility
, inputText : String
}
init : ( Model, Cmd Msg )
init =
( Model [] 0 All "", Cmd.none )
-- UPDATE
type Msg
= AddNewTodo
| ToggleComplete ID
| ChangeInput String
| ChangeVisibility Visibility
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
let
addTodo =
addNewTodo model.lastID
markCompleted =
markTodoAsCompleted model.todos
in
case msg of
AddNewTodo ->
if not (model.inputText == "") then
( { model
| todos = model.todos ++ [ (addTodo model.inputText) ]
, inputText = ""
, lastID = model.lastID + 1
}
, Cmd.none
)
else
( model, Cmd.none )
ToggleComplete id ->
( { model | todos = markCompleted id }, Cmd.none )
ChangeInput text ->
( { model | inputText = text }, Cmd.none )
ChangeVisibility visibility ->
( { model | visibility = visibility }, Cmd.none )
addNewTodo : ID -> String -> Todo
addNewTodo lastId title =
Todo (lastId + 1) title False
markTodoAsCompleted : List Todo -> ID -> List Todo
markTodoAsCompleted todos id =
let
updateTodo todo =
if todo.id == id then
{ todo | completed = not todo.completed }
else
todo
in
List.map updateTodo todos
-- VIEW
visibileTodos : List Todo -> Visibility -> List Todo
visibileTodos todos visibility =
case visibility of
All ->
todos
Active ->
todos |> List.filter (not << .completed)
Completed ->
todos |> List.filter .completed
view : Model -> Html Msg
view model =
let
todos =
visibileTodos model.todos model.visibility
numVisibileTodos =
todos |> List.length |> toString
numTodos =
model.todos |> List.filter (not << .completed) |> List.length |> toString
in
div
[ css
[ margin2 (px 0) (px 400)
, fontFamilies [ "sans-serif" ]
]
]
[ h1 []
[ text (numTodos ++ " Todos")
, span [ css [ color silver, padding2 (px 0) (px 10) ] ] [ text "|" ]
, text (numVisibileTodos ++ " Visible Todos")
]
, div [ css [ paddingBottom (px 5) ] ]
[ visibilityOption model.visibility All
, visibilityOption model.visibility Active
, visibilityOption model.visibility Completed
]
, div [ css [ paddingBottom (px 5) ] ]
[ input
[ css
[ marginRight (px 10)
]
, type_ "text"
, placeholder "New Todo"
, onInput ChangeInput
, value model.inputText
]
[]
, button [ onClick AddNewTodo ] [ text "Add New Todo" ]
]
, div [] (List.map todoView todos)
]
visibilityOption : Visibility -> Visibility -> Html Msg
visibilityOption current visibility =
span [ css [ paddingRight (px 10) ] ]
[ a
[ css
[ if current == visibility then
fontWeight bold
else
fontWeight normal
]
, onClick (ChangeVisibility visibility)
]
[ text (toString visibility) ]
]
todoView : Todo -> Html Msg
todoView todo =
div [ css [ margin2 (px 5) (px 0) ] ]
[ input
[ type_ "checkbox"
, Html.Styled.Attributes.checked todo.completed
, onClick (ToggleComplete todo.id)
]
[]
, p
[ css
[ display inline
, paddingRight (px 5)
, (if todo.completed then
textDecoration lineThrough
else
textDecoration none
)
]
]
[ text todo.title ]
, span [ css [ color silver ] ] [ text ("(" ++ (toString todo.id) ++ ")") ]
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment