xesite/frontend/src/BlogIndex.purs

85 lines
2.4 KiB
Plaintext

module App.BlogIndex where
import Control.Monad.Aff (attempt)
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Either (Either(Left, Right), either)
import DOM (DOM)
import Network.HTTP.Affjax (AJAX, get)
import Prelude (($), bind, map, const, show, (<>), pure, (<<<))
import Pux (EffModel, noEffects)
import Pux.Html (Html, br, div, h1, ol, li, button, text, span, p)
import Pux.Html.Attributes (key, className, id_)
import Pux.Html.Events (onClick)
import Pux.Router (link)
data Action = RequestPosts
| ReceivePosts (Either String Posts)
type State =
{ posts :: Posts
, status :: String }
data Post = Post
{ title :: String
, link :: String
, summary :: String
, date :: String }
type Posts = Array Post
instance decodeJsonPost :: DecodeJson Post where
decodeJson json = do
obj <- decodeJson json
title <- obj .? "title"
link <- obj .? "link"
summ <- obj .? "summary"
date <- obj .? "date"
pure $ Post { title: title, link: link, summary: summ, date: date }
init :: State
init =
{ posts: []
, status: "Loading..." }
update :: Action -> State -> EffModel State Action (ajax :: AJAX, dom :: DOM)
update (ReceivePosts (Left err)) state =
noEffects $ state { status = ("error: " <> err) }
update (ReceivePosts (Right posts)) state =
noEffects $ state { posts = posts, status = "Posts" }
update RequestPosts state =
{ state: state { status = "Fetching posts..." }
, effects: [ do
res <- attempt $ get "/api/blog/posts"
let decode r = decodeJson r.response :: Either String Posts
let posts = either (Left <<< show) decode res
pure $ ReceivePosts posts
]
}
post :: Post -> Html Action
post (Post state) =
div
[ className "col s6" ]
[ div
[ className "card pink lighten-4" ]
[ div
[ className "card-content black-text" ]
[ span [ className "card-title" ] [ text state.title ]
, br [] []
, p [] [ text ("Posted on: " <> state.date) ]
, span [] [ text state.summary ]
]
, div
[ className "card-action pink" ]
[ link state.link [] [ text "Read More" ] ]
]
]
view :: State -> Html Action
view state =
div
[]
[ h1 [] [ text state.status ]
, button [ onClick (const RequestPosts), id_ "requestbutton", className "hidden" ] [ text "Fetch posts" ]
, div [ className "row" ] $ map post state.posts ]