doglinks/client/src/Main.elm

209 lines
5.1 KiB
Elm

module Main exposing (..)
import Browser exposing (Document)
import Browser.Navigation as Nav
import CreatePage
import Css
import Css.Media as Media
import Html
import Html.Styled exposing (..)
import Html.Styled.Attributes exposing (css, href, src)
import ShowPage
import Url exposing (Url)
import Url.Parser as Parser exposing (Parser)
type alias Model =
{ origin : String
, key : Nav.Key
, page : Page
}
type Route
= Create
| Show String
type Page
= CreatePage CreatePage.Model
| ShowPage ShowPage.Model
sharedStyles : Css.Style
sharedStyles =
Css.batch
[ Css.margin Css.auto
, Css.maxWidth (Css.px 500)
, Css.width (Css.pct 100)
]
headerSectionStyles : Css.Style
headerSectionStyles =
Css.batch
[ Media.withMedia
[ Media.only Media.screen [ Media.maxWidth (Css.px 500) ] ]
[ Css.padding2 (Css.px 0) (Css.px 16) ]
, sharedStyles
]
sectionStyles : Css.Style
sectionStyles =
Css.batch
[ Css.backgroundColor (Css.hex "fff")
, Css.borderRadius (Css.px 4)
, Css.color (Css.hex "222")
, Css.padding (Css.px 16)
, Media.withMedia
[ Media.only Media.screen [ Media.maxWidth (Css.px 500) ] ]
[ Css.borderRadius (Css.px 0) ]
, sharedStyles
]
headerStyles : Css.Style
headerStyles =
Css.marginBottom (Css.px 0)
subHeaderStyles : Css.Style
subHeaderStyles =
Css.batch
[ Css.fontStyle Css.italic
, Css.marginTop (Css.px 0)
]
view : Model -> Document Msg
view model =
{ title = "Doglinks"
, body =
List.map toUnstyled
[ section [ css [ headerSectionStyles ] ]
[ h1 [ css [ headerStyles ] ] [ text "Doglinks" ]
, p [ css [ subHeaderStyles ] ] [ text "Create your doglinks here" ]
]
, section
[ css [ sectionStyles ] ]
[ case model.page of
CreatePage page ->
CreatePage.view page
|> Html.Styled.map CreateMsg
ShowPage page ->
ShowPage.view model.origin page
|> Html.Styled.map ShowMsg
]
]
}
init : String -> Url -> Nav.Key -> ( Model, Cmd Msg )
init origin url key =
let
initialModel =
{ origin = origin, key = key, page = CreatePage CreatePage.init }
in
updateUrl url initialModel
type Msg
= ClickedLink Browser.UrlRequest
| ChangedUrl Url
| CreateMsg CreatePage.Msg
| ShowMsg ShowPage.Msg
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ClickedLink (Browser.Internal url) ->
( model, Nav.pushUrl model.key <| Url.toString url )
ClickedLink _ ->
( model, Cmd.none )
ChangedUrl url ->
updateUrl url model
CreateMsg createMsg ->
case model.page of
CreatePage page ->
let
( pageModel, pageMsg ) =
CreatePage.update model.origin model.key createMsg page
in
( { model | page = CreatePage pageModel }, Cmd.map CreateMsg pageMsg )
_ ->
( model, Cmd.none )
ShowMsg showMsg ->
case model.page of
ShowPage page ->
let
( pageModel, pageMsg ) =
ShowPage.update showMsg page
in
( { model | page = ShowPage pageModel }, Cmd.map ShowMsg pageMsg )
_ ->
( model, Cmd.none )
updateUrl : Url -> Model -> ( Model, Cmd Msg )
updateUrl url model =
case Parser.parse routeParser url of
Just (Show uuid) ->
toShow model ( ShowPage.init uuid, Cmd.none )
_ ->
toCreate model ( CreatePage.init, Cmd.none )
toShow : Model -> ( ShowPage.Model, Cmd ShowPage.Msg ) -> ( Model, Cmd Msg )
toShow model ( showModel, showMsg ) =
case model.page of
ShowPage _ ->
( model, Cmd.none )
_ ->
( { model | page = ShowPage showModel }, Cmd.map ShowMsg showMsg )
toCreate : Model -> ( CreatePage.Model, Cmd CreatePage.Msg ) -> ( Model, Cmd Msg )
toCreate model ( createModel, createMsg ) =
case model.page of
CreatePage _ ->
( model, Cmd.none )
_ ->
( { model | page = CreatePage createModel }, Cmd.map CreateMsg createMsg )
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.map ShowMsg ShowPage.subscriptions
main : Program String Model Msg
main =
Browser.application
{ init = init
, subscriptions = subscriptions
, update = update
, view = view
, onUrlRequest = ClickedLink
, onUrlChange = ChangedUrl
}
routeParser : Parser (Route -> a) a
routeParser =
Parser.oneOf
[ Parser.map Create Parser.top
, Parser.map Show Parser.string
]