302 lines
7.4 KiB
Elm
302 lines
7.4 KiB
Elm
module Main exposing (..)
|
|
|
|
import Api exposing (Claim, Claims, Item, Loot, Player, Wealth)
|
|
import Browser
|
|
import Browser.Navigation as Nav
|
|
import Html exposing (..)
|
|
import Html.Attributes exposing (..)
|
|
import Html.Events exposing (..)
|
|
import Json.Encode as E
|
|
import Page.Admin as Admin
|
|
import Page.Chest as Chest exposing (Msg)
|
|
import Route exposing (..)
|
|
import Session exposing (..)
|
|
import Set exposing (Set)
|
|
import Svg.Attributes
|
|
import Url
|
|
import Utils exposing (..)
|
|
|
|
|
|
|
|
-- Main
|
|
|
|
|
|
main : Program () Model Msg
|
|
main =
|
|
Browser.application
|
|
{ init = init
|
|
, view = view
|
|
, update = update
|
|
, subscriptions = subscriptions
|
|
, onUrlChange = UrlChanged
|
|
, onUrlRequest = LinkClicked
|
|
}
|
|
|
|
|
|
|
|
-- Model
|
|
|
|
|
|
type alias Model =
|
|
{ navbar : Navbar
|
|
, page : Page
|
|
}
|
|
|
|
|
|
type alias Navbar =
|
|
{ menuOpen : Bool
|
|
, navKey : Nav.Key
|
|
}
|
|
|
|
|
|
initNavbar key =
|
|
Navbar False key
|
|
|
|
|
|
type Page
|
|
= Chest Chest.Model
|
|
| Admin Admin.Model
|
|
| About
|
|
| Loading
|
|
|
|
|
|
type alias HasPage r =
|
|
{ r | page : Page }
|
|
|
|
|
|
setPage : Page -> HasPage r -> HasPage r
|
|
setPage page model =
|
|
{ model | page = page }
|
|
|
|
|
|
|
|
-- This is not what we really want.
|
|
-- The flags will be a Maybe Int (id of logged in player), so
|
|
-- in case there is no player logged in, we need to display
|
|
-- a "Home" page
|
|
-- This mean Chest cannot be initiated right away, and many model
|
|
-- fields are useless.
|
|
--
|
|
-- A User can :
|
|
-- - not be logged in -> See About page
|
|
-- - just loggend in -> See Loading page then Chest
|
|
-- - coming back being still logged in -> See Chest (or same as above)
|
|
|
|
|
|
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
|
|
init _ _ key =
|
|
( { navbar = initNavbar key
|
|
, page = Loading
|
|
}
|
|
, Session.init SessionLoaded key
|
|
)
|
|
|
|
|
|
|
|
-- VIEW
|
|
|
|
|
|
view : Model -> Browser.Document Msg
|
|
view model =
|
|
let
|
|
( title, header, content ) =
|
|
viewPage model.page
|
|
in
|
|
{ title = title
|
|
, body =
|
|
viewHeaderBar header.title header.links model.navbar
|
|
:: content
|
|
}
|
|
|
|
|
|
viewPage page =
|
|
let
|
|
( title, content ) =
|
|
case page of
|
|
Chest chest ->
|
|
( "Loot-a-lot", List.map (Html.map GotChestMsg) (Chest.view chest) )
|
|
|
|
Admin admin ->
|
|
( "Administration", Admin.view admin )
|
|
|
|
About ->
|
|
( "A propos", [ p [] [ text "A propos" ] ] )
|
|
|
|
Loading ->
|
|
( "Veuillez patienter...", [ p [] [ text "Chargement" ] ] )
|
|
|
|
navbarTitle =
|
|
case page of
|
|
Chest chest ->
|
|
chest.state.player.name
|
|
|
|
Admin _ ->
|
|
"Administration"
|
|
|
|
About ->
|
|
"Loot-a-lot"
|
|
|
|
Loading ->
|
|
"Loot-a-(...)"
|
|
|
|
navbarLinks =
|
|
case page of
|
|
Chest chest ->
|
|
let
|
|
linkWithGem =
|
|
navLink "fas fa-gem"
|
|
in
|
|
[ navLink "fas fa-store-alt" "Marchand" "/marchand"
|
|
, if chest.state.player.id == 0 then
|
|
linkWithGem "Nouveau loot" "/nouveau-tresor"
|
|
|
|
else
|
|
linkWithGem "Coffre de groupe" "/coffre"
|
|
]
|
|
|
|
_ ->
|
|
[]
|
|
in
|
|
( title, { title = navbarTitle, links = navbarLinks }, content )
|
|
|
|
|
|
|
|
-- HEADER SECTION
|
|
|
|
|
|
navLink icon linkText url =
|
|
a [ class "navbar-item", href url ]
|
|
[ renderIcon { icon = icon, ratio = "1x", size = "medium" }
|
|
, span [] [ text linkText ]
|
|
]
|
|
|
|
|
|
viewHeaderBar : String -> List (Html Msg) -> Navbar -> Html Msg
|
|
viewHeaderBar navbarTitle navbarLinks navbar =
|
|
nav [ class "navbar", class "is-transparent" ]
|
|
[ div [ class "navbar-brand" ]
|
|
[ a [ class "navbar-item", href "/" ]
|
|
[ renderIcon { icon = "fab fa-d-and-d", size = "medium", ratio = "2x" }
|
|
, span [ class "title is-4", style "padding-left" "0.4em" ] [ text navbarTitle ]
|
|
]
|
|
, a
|
|
[ class "navbar-burger"
|
|
, classList [ ( "is-active", navbar.menuOpen ) ]
|
|
, onClick SwitchMenuOpen
|
|
]
|
|
[ span [ attribute "aria-hidden" "true" ] []
|
|
, span [ attribute "aria-hidden" "true" ] []
|
|
, span [ attribute "aria-hidden" "true" ] []
|
|
]
|
|
]
|
|
, div [ class "navbar-menu", classList [ ( "is-active", navbar.menuOpen ) ] ]
|
|
[ div [ class "navbar-end" ] navbarLinks
|
|
]
|
|
]
|
|
|
|
|
|
|
|
-- UPDATE
|
|
|
|
|
|
type Msg
|
|
= UrlChanged Url.Url
|
|
| LinkClicked Browser.UrlRequest
|
|
| SessionLoaded (Maybe Session)
|
|
| SwitchMenuOpen
|
|
| GotChestMsg Chest.Msg
|
|
| GotAdminMsg Admin.Msg
|
|
|
|
|
|
|
|
-- | GotAdminMsg Admin.Msg
|
|
|
|
|
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
|
update msg model =
|
|
let
|
|
updateChest chestMsg =
|
|
case model.page of
|
|
Chest chest ->
|
|
let
|
|
( newChest, cmd ) =
|
|
Chest.update chestMsg chest
|
|
in
|
|
( setPage (Chest newChest) model, Cmd.map GotChestMsg cmd )
|
|
|
|
_ ->
|
|
( model |> setPage About, Cmd.none )
|
|
in
|
|
case msg of
|
|
SessionLoaded session ->
|
|
case session of
|
|
Just logged ->
|
|
let
|
|
navKey =
|
|
Session.key logged
|
|
|
|
user =
|
|
Session.user logged
|
|
in
|
|
case user of
|
|
Session.Player playerId ->
|
|
let
|
|
( chest, cmd ) =
|
|
Chest.init navKey playerId
|
|
in
|
|
( model |> setPage (Chest chest), Cmd.map GotChestMsg cmd )
|
|
|
|
Session.Admin ->
|
|
let
|
|
( admin, cmd ) =
|
|
Admin.init navKey
|
|
in
|
|
( model |> setPage (Admin admin), Cmd.map GotAdminMsg cmd )
|
|
|
|
Nothing ->
|
|
( model |> setPage About, Cmd.none )
|
|
|
|
LinkClicked urlRequest ->
|
|
case model.page of
|
|
Chest chestModel ->
|
|
case urlRequest of
|
|
Browser.Internal url ->
|
|
( model, Nav.pushUrl model.navbar.navKey (Url.toString url) )
|
|
|
|
Browser.External href ->
|
|
( model, Cmd.none )
|
|
|
|
_ ->
|
|
( model, Cmd.none )
|
|
|
|
UrlChanged url ->
|
|
let
|
|
route =
|
|
Route.fromUrl url
|
|
in
|
|
case route of
|
|
Just (Route.Home content) ->
|
|
updateChest (Chest.SetContent content)
|
|
|
|
_ ->
|
|
( model |> setPage About, Cmd.none )
|
|
|
|
GotChestMsg chestMsg ->
|
|
updateChest chestMsg
|
|
|
|
GotAdminMsg adminMsg ->
|
|
( model, Cmd.none )
|
|
|
|
SwitchMenuOpen ->
|
|
( { model | navbar = Navbar (not model.navbar.menuOpen) model.navbar.navKey }, Cmd.none )
|
|
|
|
|
|
|
|
-- SUBSCRIPTIONS
|
|
--
|
|
|
|
|
|
subscriptions : Model -> Sub Msg
|
|
subscriptions _ =
|
|
Sub.none
|