diff --git a/frontend/src/Dashboard.elm b/frontend/src/Dashboard.elm index 12ee2aa..27c27c1 100644 --- a/frontend/src/Dashboard.elm +++ b/frontend/src/Dashboard.elm @@ -2,9 +2,12 @@ module Dashboard exposing (Model, Msg, Task, init, update, view) import Browser exposing (Document) import Browser.Navigation as Nav -import Html exposing (Html, div, text) +import Html exposing (Html, button, div, input, text, textarea) +import Html.Attributes exposing (placeholder, value) +import Html.Events exposing (onClick, onInput) import Http import Json.Decode exposing (Decoder, field, int, list, map3, maybe, string) +import Json.Encode as Encode type alias Task = @@ -14,9 +17,22 @@ type alias Task = } +type alias CreateTaskInfo = + { title : String, description : String } + + +defaultCreateTask : CreateTaskInfo +defaultCreateTask = + { title = "" + , description = "" + } + + type alias Model = { navKey : Nav.Key , tasks : Status (List Task) + , createTaskCollapsed : Bool + , createTask : CreateTaskInfo } @@ -28,16 +44,21 @@ type Status a init : Nav.Key -> ( Model, Cmd Msg ) init navKey = - ( Model navKey Loading + ( Model navKey Loading True defaultCreateTask , Http.get { url = "http://localhost:3000/tasks" - , expect = Http.expectJson GotTasks taskDecoder + , expect = Http.expectJson GotTasks (list taskDecoder) } ) type Msg = GotTasks (Result Http.Error (List Task)) + | ToggleCreateTask + | CreateTask + | GotTaskCreated (Result Http.Error Task) + | CreateTaskUpdateTitle String + | CreateTaskUpdateDescription String update : Msg -> Model -> ( Model, Cmd Msg ) @@ -51,21 +72,68 @@ update msg model = Err _ -> ( { model | tasks = Failure }, Cmd.none ) + ToggleCreateTask -> + ( { model | createTaskCollapsed = not model.createTaskCollapsed } + , Cmd.none + ) -taskDecoder : Decoder (List Task) + CreateTask -> + ( model + , Http.post + { url = "http://localhost:3000/tasks" + , body = Http.jsonBody (taskEncoder model.createTask) + , expect = Http.expectJson GotTaskCreated taskDecoder + } + ) + + GotTaskCreated result -> + case result of + Ok task -> + case model.tasks of + Success tasks -> + ( { model | tasks = Success (task :: tasks) }, Cmd.none ) + + _ -> + ( { model | tasks = Success [ task ] }, Cmd.none ) + + Err _ -> + ( model, Cmd.none ) + + CreateTaskUpdateTitle title -> + let + createTask = + model.createTask + in + ( { model | createTask = { createTask | title = title } }, Cmd.none ) + + CreateTaskUpdateDescription description -> + let + createTask = + model.createTask + in + ( { model | createTask = { createTask | description = description } }, Cmd.none ) + + +taskDecoder : Decoder Task taskDecoder = - list - (map3 Task - (field "id" int) - (field "title" string) - (maybe - (field "description" - string - ) + map3 Task + (field "id" int) + (field "title" string) + (maybe + (field "description" + string ) ) +taskEncoder : CreateTaskInfo -> Encode.Value +taskEncoder task = + Encode.object + [ ( "title", Encode.string task.title ) + , ( "description", Encode.string task.description ) + ] + + view : Model -> Document Msg view model = { title = "Dashboard" @@ -83,4 +151,38 @@ viewBody model = div [] [ text "Loading" ] Success tasks -> - div [] [ text ("Loaded " ++ String.fromInt (List.length tasks) ++ " tasks") ] + div [] + [ text ("Loaded " ++ String.fromInt (List.length tasks) ++ "tasks") + , viewCreate model + ] + + +viewCreate : Model -> Html Msg +viewCreate model = + if model.createTaskCollapsed then + div [] [ button [ onClick ToggleCreateTask ] [ text "+ Expand" ] ] + + else + div [] + [ button [ onClick ToggleCreateTask ] [ text "- Collapse" ] + , div [] + [ input + [ placeholder "Task Title" + , value + model.createTask.title + , onInput CreateTaskUpdateTitle + ] + [] + ] + , div [] + [ textarea + [ placeholder "Task Description" + , value + model.createTask.description + , onInput CreateTaskUpdateDescription + ] + [] + ] + , div [] + [ button [ onClick CreateTask ] [ text "Create Task" ] ] + ]