summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Config.elm6
-rw-r--r--src/Main.elm72
-rw-r--r--src/Pages/Feed.elm57
-rw-r--r--src/Types.elm13
-rw-r--r--src/index.html22
5 files changed, 131 insertions, 39 deletions
diff --git a/src/Config.elm b/src/Config.elm
index c3df2b0..ecd263b 100644
--- a/src/Config.elm
+++ b/src/Config.elm
@@ -9,6 +9,7 @@ baseUrl =
type ApiResource
= ApiPosts
| ApiLikePost String
+ | ApiCompose
makeApiUrl : ApiResource -> String
@@ -16,8 +17,11 @@ makeApiUrl res =
String.replace "{baseUrl}" baseUrl <|
case res of
ApiPosts ->
- "{baseUrl}/posts"
+ "{baseUrl}/posts?_sort=createdAt&_order=desc"
ApiLikePost postId ->
"{baseUrl}/posts/{postId}"
|> String.replace "{postId}" postId
+
+ ApiCompose ->
+ "{baseUrl}/posts"
diff --git a/src/Main.elm b/src/Main.elm
index d359eaa..bd145e0 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -1,4 +1,4 @@
-module Main exposing (..)
+port module Main exposing (..)
import Browser exposing (Document)
import Browser.Navigation exposing (Key)
@@ -10,7 +10,7 @@ import Json.Encode
import Pages.Feed exposing (feedView)
import Task
import Time
-import Types exposing (Author, DisplayableError(..), Model, Msg(..), Post)
+import Types exposing (Author, Model, Msg(..), Post)
import Url exposing (Url)
@@ -27,14 +27,21 @@ main =
+-- PORTS
+
+
+port showAlert : String -> Cmd msg
+
+
+
-- INIT
init : () -> Url -> Key -> ( Model, Cmd Msg )
init _ _ _ =
- ( { posts = []
- , displayError = DNoError
+ ( { posts = Nothing
, now = Time.millisToPosix 0
+ , composeInputValue = ""
}
, Cmd.batch [ getPosts, Task.perform SetNowPosix Time.now ]
)
@@ -57,26 +64,51 @@ update msg model =
( model, getPosts )
GotPosts (Result.Ok posts) ->
- ( { model | posts = posts }, Cmd.none )
+ ( { model | posts = Just posts }, Cmd.none )
GotPosts (Result.Err httpErr) ->
- ( { model | displayError = DHttpError httpErr }
- , Cmd.none
+ ( model
+ , showAlert (Debug.toString httpErr)
)
LikePost post ->
( model, likePost post )
LikedPost (Result.Ok post) ->
- ( { model | posts = replaceMatchingPost post model.posts }
+ ( { model | posts = Just <| replaceMatchingPost post (Maybe.withDefault [] model.posts) }
, Cmd.none
)
LikedPost (Result.Err httpErr) ->
- ( { model | displayError = DHttpError httpErr }
+ ( model
+ , showAlert (Debug.toString httpErr)
+ )
+
+ ComposeInputChanged value ->
+ ( { model | composeInputValue = value }, Cmd.none )
+
+ ComposePost ->
+ ( model
+ , if String.length model.composeInputValue > 0 then
+ composePost model
+
+ else
+ Cmd.none
+ )
+
+ ComposedPost (Result.Ok post) ->
+ ( { model
+ | posts = Maybe.map (\posts -> post :: posts) model.posts
+ , composeInputValue = ""
+ }
, Cmd.none
)
+ ComposedPost (Result.Err httpErr) ->
+ ( model
+ , showAlert (Debug.toString httpErr)
+ )
+
replaceMatchingPost : Post -> List Post -> List Post
replaceMatchingPost post posts =
@@ -116,6 +148,28 @@ likePost post =
}
+composePost : Model -> Cmd Msg
+composePost model =
+ Http.post
+ { url = makeApiUrl Config.ApiCompose
+ , expect = Http.expectJson ComposedPost postDecoder
+ , body =
+ Http.jsonBody
+ (Json.Encode.object
+ [ ( "content", Json.Encode.string model.composeInputValue )
+ , ( "createdAt", Json.Encode.int <| Time.posixToMillis model.now // 1000 )
+ , ( "likes", Json.Encode.int 0 )
+ , ( "author"
+ , Json.Encode.object
+ [ ( "id", Json.Encode.string "logged-in-user-id" )
+ , ( "name", Json.Encode.string "Logged in user" )
+ ]
+ )
+ ]
+ )
+ }
+
+
subscriptions : Model -> Sub Msg
subscriptions _ =
Time.every 5000 SetNowPosix
diff --git a/src/Pages/Feed.elm b/src/Pages/Feed.elm
index a848200..583c097 100644
--- a/src/Pages/Feed.elm
+++ b/src/Pages/Feed.elm
@@ -3,10 +3,10 @@ module Pages.Feed exposing (..)
import Css exposing (..)
import DateFormat.Relative exposing (relativeTime)
import Html.Styled exposing (..)
-import Html.Styled.Attributes exposing (css)
-import Html.Styled.Events exposing (onClick)
+import Html.Styled.Attributes exposing (css, placeholder, type_, value)
+import Html.Styled.Events exposing (onClick, onInput, onSubmit)
import Time exposing (now)
-import Types exposing (DisplayableError(..), Model, Msg(..), Post)
+import Types exposing (Model, Msg(..), Post)
styles =
@@ -19,6 +19,7 @@ styles =
css
[ padding2 (px 15) (px 20)
, backgroundColor (hex "#eee")
+ , marginBottom (px 10)
]
, postTitle =
css
@@ -28,25 +29,18 @@ styles =
[ marginRight (px 5)
, cursor pointer
]
+ , composeForm =
+ css
+ [ displayFlex
+ , flexFlow2 row wrap
+ ]
+ , composeInput =
+ css
+ [ flex (int 1)
+ ]
}
-derrorToHtml : DisplayableError -> Html Msg
-derrorToHtml derror =
- case derror of
- DNoError ->
- text ""
-
- DHttpError httpErr ->
- text <| Debug.toString httpErr
-
-
-derrorDiv : Model -> Html Msg
-derrorDiv model =
- div []
- [ derrorToHtml model.displayError ]
-
-
postDiv : Time.Posix -> Post -> Html Msg
postDiv now post =
div [ styles.post ]
@@ -64,7 +58,26 @@ postDiv now post =
postsDiv : Model -> Html Msg
postsDiv model =
- div [] <| List.map (postDiv model.now) model.posts
+ case model.posts of
+ Just posts ->
+ div [] <| List.map (postDiv model.now) posts
+
+ Nothing ->
+ div [] [ text "Loading posts..." ]
+
+
+composeDiv : Model -> Html Msg
+composeDiv model =
+ form [ styles.composeForm, onSubmit ComposePost ]
+ [ input
+ [ styles.composeInput
+ , placeholder "Type a new post..."
+ , onInput ComposeInputChanged
+ , value model.composeInputValue
+ ]
+ []
+ , button [ type_ "submit" ] [ text "➡️" ]
+ ]
headerSection : Model -> Html msg
@@ -77,8 +90,8 @@ headerSection _ =
mainSection : Model -> Html Msg
mainSection model =
main_ [] <|
- [ derrorDiv model
- , postsDiv model
+ [ postsDiv model
+ , composeDiv model
]
diff --git a/src/Types.elm b/src/Types.elm
index 02e1257..3736bbf 100644
--- a/src/Types.elm
+++ b/src/Types.elm
@@ -5,8 +5,8 @@ import Time
type alias Model =
- { posts : List Post
- , displayError : DisplayableError
+ { posts : Maybe (List Post)
+ , composeInputValue : String
, now : Time.Posix
}
@@ -20,11 +20,10 @@ type Msg
| GotPosts (Result Http.Error (List Post))
| LikePost Post
| LikedPost (Result Http.Error Post)
-
-
-type DisplayableError
- = DHttpError Http.Error
- | DNoError
+ -- COMPOSE POST
+ | ComposeInputChanged String
+ | ComposePost
+ | ComposedPost (Result Http.Error Post)
type alias Author =
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 0000000..ccf508a
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,22 @@
+<html>
+
+<head>
+ <meta charset="UTF-8">
+ <title>Main</title>
+ <link rel="stylesheet" href="main.css">
+ </link>
+ <script src="main.js"></script>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script>
+ var app = Elm.Main.init({
+ node: document.getElementById("app")
+ });
+
+ app.ports.showAlert.subscribe((message) => window.alert(message));
+ </script>
+</body>
+
+</html> \ No newline at end of file