summaryrefslogtreecommitdiffstats
path: root/src/Main.elm
diff options
context:
space:
mode:
Diffstat (limited to 'src/Main.elm')
-rw-r--r--src/Main.elm136
1 files changed, 114 insertions, 22 deletions
diff --git a/src/Main.elm b/src/Main.elm
index 54352d6..d359eaa 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -2,8 +2,15 @@ module Main exposing (..)
import Browser exposing (Document)
import Browser.Navigation exposing (Key)
+import Config exposing (makeApiUrl)
import Html.Styled exposing (..)
-import Types exposing (DisplayableError(..), Model, Msg(..))
+import Http
+import Json.Decode exposing (Decoder, field, int, list, map2, map5, string)
+import Json.Encode
+import Pages.Feed exposing (feedView)
+import Task
+import Time
+import Types exposing (Author, DisplayableError(..), Model, Msg(..), Post)
import Url exposing (Url)
@@ -13,7 +20,7 @@ main =
{ init = init
, view = view
, update = update
- , subscriptions = \_ -> Sub.none
+ , subscriptions = subscriptions
, onUrlRequest = \_ -> NoOp
, onUrlChange = \_ -> NoOp
}
@@ -25,18 +32,11 @@ main =
init : () -> Url -> Key -> ( Model, Cmd Msg )
init _ _ _ =
- ( { posts =
- [ { id = "123"
- , content = "foobar"
- , author =
- { id = "456"
- , name = "George Technoman"
- }
- }
- ]
- , displayError = NoError
+ ( { posts = []
+ , displayError = DNoError
+ , now = Time.millisToPosix 0
}
- , Cmd.none
+ , Cmd.batch [ getPosts, Task.perform SetNowPosix Time.now ]
)
@@ -50,11 +50,108 @@ update msg model =
NoOp ->
( model, Cmd.none )
- FetchPostsSuccess posts ->
+ SetNowPosix now ->
+ ( { model | now = now }, Cmd.none )
+
+ GetPosts ->
+ ( model, getPosts )
+
+ GotPosts (Result.Ok posts) ->
( { model | posts = posts }, Cmd.none )
- FetchPostsFailure error ->
- ( { model | displayError = error }, Cmd.none )
+ GotPosts (Result.Err httpErr) ->
+ ( { model | displayError = DHttpError httpErr }
+ , Cmd.none
+ )
+
+ LikePost post ->
+ ( model, likePost post )
+
+ LikedPost (Result.Ok post) ->
+ ( { model | posts = replaceMatchingPost post model.posts }
+ , Cmd.none
+ )
+
+ LikedPost (Result.Err httpErr) ->
+ ( { model | displayError = DHttpError httpErr }
+ , Cmd.none
+ )
+
+
+replaceMatchingPost : Post -> List Post -> List Post
+replaceMatchingPost post posts =
+ List.map
+ (\p ->
+ if p.id == post.id then
+ post
+
+ else
+ p
+ )
+ posts
+
+
+getPosts : Cmd Msg
+getPosts =
+ Http.get
+ { url = makeApiUrl Config.ApiPosts
+ , expect = Http.expectJson GotPosts postsDecoder
+ }
+
+
+likePost : Post -> Cmd Msg
+likePost post =
+ Http.request
+ { method = "PATCH"
+ , headers = []
+ , url = makeApiUrl (Config.ApiLikePost post.id)
+ , body =
+ Http.jsonBody
+ (Json.Encode.object
+ [ ( "likes", Json.Encode.int (post.likes + 1) ) ]
+ )
+ , expect = Http.expectJson LikedPost postDecoder
+ , timeout = Nothing
+ , tracker = Nothing
+ }
+
+
+subscriptions : Model -> Sub Msg
+subscriptions _ =
+ Time.every 5000 SetNowPosix
+
+
+
+-- JSON
+
+
+decodeTime : Decoder Time.Posix
+decodeTime =
+ int
+ |> Json.Decode.andThen
+ (\ms ->
+ Json.Decode.succeed <| Time.millisToPosix (ms * 1000)
+ )
+
+
+postsDecoder : Decoder (List Post)
+postsDecoder =
+ list postDecoder
+
+
+postDecoder : Decoder Post
+postDecoder =
+ map5 Post
+ (field "id" string)
+ (field "content" string)
+ (field "author"
+ (map2 Author
+ (field "id" string)
+ (field "name" string)
+ )
+ )
+ (field "createdAt" decodeTime)
+ (field "likes" int)
@@ -64,10 +161,5 @@ update msg model =
view : Model -> Document Msg
view model =
{ title = "Shoob book"
- , body = [ body model ] |> List.map toUnstyled
+ , body = feedView model |> List.map toUnstyled
}
-
-
-body : Model -> Html Msg
-body model =
- main_ [] (List.map (\post -> div [] [ text post.id ]) model.posts)