1
Fork 0

elm(todolist): feat: basic todo operations

Signed-off-by: prescientmoon <git@moonythm.dev>
This commit is contained in:
Matei Adriel 2019-11-28 16:57:45 +02:00 committed by prescientmoon
parent 8cd06f56bd
commit 5278cf694d
Signed by: prescientmoon
SSH key fingerprint: SHA256:UUF9JT2s8Xfyv76b8ZuVL7XrmimH4o49p4b+iexbVH4
3 changed files with 223 additions and 21 deletions

View file

@ -0,0 +1,6 @@
{
"checks": {
"ExposeAll": false,
"ImportAll": false
}
}

View file

@ -1,20 +1,36 @@
module Main exposing (..)
import Browser
import Html exposing (Html, text, div, h1, img)
import Html.Attributes exposing (src)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
-- HELPER TYPES
type alias Todo =
{ done : Bool
, text : String
, id : Int
}
---- MODEL ----
type alias Model =
{}
{ todos : List Todo
, lastId : Int
, nextTodoText : String
}
init : ( Model, Cmd Msg )
init : Model
init =
( {}, Cmd.none )
Model [] 0 ""
@ -22,12 +38,48 @@ init =
type Msg
= NoOp
= AddTodo
| DeleteTodo Int
| ToggleTodoCompletion Int
| SetNextTodoText String
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
( model, Cmd.none )
update : Msg -> Model -> Model
update message model =
case message of
AddTodo ->
if model.nextTodoText == "" then
model
else
let
id =
model.lastId + 1
text =
model.nextTodoText
in
{ model | lastId = id, todos = Todo False text id :: model.todos }
DeleteTodo id ->
{ model | todos = List.filter ((/=) id << .id) model.todos }
ToggleTodoCompletion id ->
{ model
| todos =
List.map
(\todo ->
if todo.id == id then
{ todo | done = not todo.done }
else
todo
)
model.todos
}
SetNextTodoText text ->
{ model | nextTodoText = text }
@ -36,9 +88,69 @@ update msg model =
view : Model -> Html Msg
view model =
div []
[ img [ src "/logo.svg" ] []
, h1 [] [ text "Your Elm App is working!" ]
div [ class "container" ]
[ header model
, div [ class "todos" ] <|
List.map
todoView
model.todos
]
-- HEADER
header : Model -> Html Msg
header _ =
div [ class "header" ]
[ button
[ class "btn"
, onClick AddTodo
]
[ text "add todo" ]
, input
[ placeholder "todo text"
, onInput SetNextTodoText
, class "todoTextInput"
]
[]
]
-- _TODO VIEW
todoClasses : Todo -> String
todoClasses todo =
"todo"
++ (if todo.done then
" completed"
else
""
)
todoView : Todo -> Html Msg
todoView todo =
div [ class <| todoClasses todo ]
[ div [ class "todoCompleted" ]
[ input
[ checked todo.done
, type_ "checkbox"
, class "todoCheckbox"
, onCheck <| \_ -> ToggleTodoCompletion todo.id
]
[]
]
, div [ class "todoText" ] [ text todo.text ]
, button
[ class "btn"
, onClick <| DeleteTodo todo.id
]
[ text "Delete todo" ]
]
@ -48,9 +160,8 @@ view model =
main : Program () Model Msg
main =
Browser.element
Browser.sandbox
{ view = view
, init = \_ -> init
, init = init
, update = update
, subscriptions = always Sub.none
}

View file

@ -9,18 +9,103 @@
height: inherit;
}
:root {
--secondary: #009fb7;
--primary: #1a213b;
--on-secondary: #eff1f4;
--disabled: #555555;
}
body {
font-family: 'Source Sans Pro', 'Trebuchet MS', 'Lucida Grande', 'Bitstream Vera Sans', 'Helvetica Neue', sans-serif;
font-family: "Source Sans Pro", "Trebuchet MS", "Lucida Grande",
"Bitstream Vera Sans", "Helvetica Neue", sans-serif;
margin: 0;
text-align: center;
color: #293c4b;
background: var(--primary);
color: var(--on-secondary);
}
h1 {
font-size: 30px;
}
img {
margin: 20px 0;
max-width: 200px;
.header {
display: flex;
}
.btn {
background-color: var(--secondary);
color: var(--on-secondary);
padding: 1rem;
margin: 1rem;
border: none;
}
input {
outline: none;
}
.todos {
display: flex;
flex-direction: column;
min-height: 67vh;
border: 1px solid var(--secondary);
}
.todo {
transition: filter 0.5s;
background: var(--primary);
display: flex;
}
.todo:hover {
filter: brightness(1.4);
}
.todo.completed {
color: var(--disabled);
text-decoration: line-through;
}
.todo.completed > .btn {
color: var(--disabled);
}
.todo > * {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.todoText {
justify-content: flex-start;
flex-direction: row;
flex-grow: 1;
}
.todoCompleted {
margin: 1rem;
}
.todoTextInput {
background: var(--primary);
border: 1px var(--secondary) solid;
margin: 1rem;
padding: 2px;
box-sizing: border-box;
color: var(--on-secondary);
font-size: 1.5rem;
transition: filter 0.5s;
}
.todoTextInput:focus {
filter: brightness(1.4);
}
.todoCheckbox {
width: 1rem;
height: 1rem;
background: var(--secondary);
}