Package

purescript-oak

Repository
ehrenmurdick/purescript-oak
License
MIT
Uploaded by
ehrenmurdick
Published on
2018-04-16

Oak is an implementation of the Elm architecture in Purescript.

module Main (main) where

import Prelude
  ( Unit
  , bind
  , (<>)
  , (#)
  )

import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Exception (EXCEPTION)
import Data.Either

import Data.Generic.Rep (class Generic)
import Data.Foreign.Class (class Decode)

import Oak
  ( runApp
  , createApp
  , App
  )
import Oak.Html
  ( Html
  , button
  , div
  , text
  , input
  , p
  )
import Oak.Html.Attribute ( value )
import Oak.Html.Events
  ( onClick
  , onInput
  )
import Oak.Document
  ( getElementById
  , appendChildNode
  , DOM
  )

import Oak.Cmd.Time (TIME, delay, seconds)
import Oak.Cmd.Http (HTTP, get, defaultDecode)
import Oak.Cmd (Cmd , none)

data User =
  User
    { name :: String
    , id :: Int
    }

derive instance genericUser :: Generic User _

instance decodeUser :: Decode User where
  decode = defaultDecode


type Model =
  { response :: String
  , pending :: Boolean
  , user :: User
  , userId :: String
  }


data Msg
  = Go
  | SetUser (Either String User)
  | GoLater
  | SetId String


showUser :: User -> Html Msg
showUser (User { id, name }) =
  div []
    [ text id
    , text " "
    , text name
    ]


view :: Model -> Html Msg
view model =
  div []
    [ p [] [ text model.response ]
    , p [] [ text "request pending: ", text model.pending ]
    , p [] [ showUser model.user ]
    , button [ onClick Go ] [ text "request" ]
    , button [ onClick GoLater ] [ text "delayed request" ]
    , input  [ onInput SetId, value model.userId ] []
    ]


next :: Msg -> Model -> Cmd (http :: HTTP, time :: TIME) Msg
next Go { userId } =
  get ("http://localhost:3000/users/" <> userId) SetUser
next GoLater _ =
  delay (2 # seconds) Go
next _ _ = none


update :: Msg -> Model -> Model
update Go model =
  model { pending = true }

update GoLater model =
  model

update (SetId id) model =
  model { userId = id }


update (SetUser result) model =
  case result of
    Left err ->
      model { response = err, pending = false }
    Right user ->
      model { user = user, response = "success", pending = false }


init :: Model
init =
  { response: "pending"
  , pending: false
  , user: User { name: "", id: 0 }
  , userId: "1"
  }

app :: App (http :: HTTP, time :: TIME) Model Msg
app = createApp
  { init: init
  , view: view
  , update: update
  , next: next
  }

main :: Eff (exception :: EXCEPTION, dom :: DOM) Unit
main = do
  rootNode <- runApp app
  container <- getElementById "app"
  appendChildNode container rootNode