{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE OverloadedStrings #-} module Main where import Control.Lens ((^.)) import Data.Generics.Labels () import Data.Maybe (fromMaybe) import Data.Text (Text, pack, unpack) import GHC.Generics (Generic) import Safe (readMay) import Shpadoinkle (Html, JSM, runJSorWarp, simple, text) import Shpadoinkle.Backend.ParDiff (runParDiff) import Shpadoinkle.Html (button, div_, for', getBody, id', input', label, onClick, onInput, value) import Shpadoinkle.Lens (onRecord, onSum) data Form = Form { name :: Text , age :: Int } deriving (Eq, Show, Generic) form :: Functor m => Form -> Html m Form form f = div_ [ label [ for' "name" ] [ "Name" ] , onRecord #name $ input' [ id' "name" , value $ f ^. #name , onInput id ] , label [ for' "age" ] [ "Age" ] , onRecord #age $ input' [ id' "age" , value . pack . show $ f ^. #age , onInput $ fromMaybe 0 . readMay . unpack ] ] newtype Counter = Counter Int deriving (Eq, Ord, Num, Show, Generic) counter :: Counter -> Html m Counter counter c = div_ [ label [ for' "counter" ] [ text . pack $ show c ] , button [ id' "counter", onClick $ c + 1 ] [ "Increment" ] ] data Model = MCounter Counter | MForm Form deriving (Eq, Show, Generic) view :: Applicative m => Model -> Html m Model view = \case MCounter c -> div_ [ onSum #_MCounter $ counter c , button [ onClick . MForm $ Form "" 18 ] [ "Go to Form" ] ] MForm f -> div_ [ onSum #_MForm $ form f , button [ onClick $ MCounter 0 ] [ "Go to Counter" ] ] app :: JSM () app = simple runParDiff (MCounter 0) view getBody main :: IO () main = runJSorWarp 8080 app