552 lines
15 KiB
Elm
552 lines
15 KiB
Elm
module Page exposing (Page(..), PageMsg, gotoGroupChest, gotoHome, gotoShop, initHome, update, view)
|
|
|
|
import Api
|
|
import Api.Player
|
|
import Bulma as B
|
|
import Html exposing (..)
|
|
import Html.Attributes exposing (..)
|
|
import Html.Events exposing (..)
|
|
import Page.Dashboard as Home
|
|
import Page.GroupChest as GroupChest
|
|
import Page.Shop as Shop
|
|
import Process
|
|
import Route exposing (toHref)
|
|
import Session exposing (Session)
|
|
import Task
|
|
import Wealth
|
|
|
|
|
|
type Page
|
|
= Home Home.Model
|
|
| GroupChest GroupChest.Model
|
|
| Shop Shop.Model
|
|
| About
|
|
| Loading
|
|
|
|
|
|
init =
|
|
Loading
|
|
|
|
|
|
mapPageMsg toMsg ( controls, content ) =
|
|
( Html.map toMsg controls
|
|
, List.map (Html.map toMsg) content
|
|
)
|
|
|
|
|
|
maybeSession page =
|
|
case page of
|
|
Home model ->
|
|
Just <| Home.getSession model
|
|
|
|
GroupChest model ->
|
|
Just <| Session.getSession model
|
|
|
|
Shop model ->
|
|
Just <| Session.getSession model
|
|
|
|
_ ->
|
|
Nothing
|
|
|
|
|
|
view page =
|
|
let
|
|
( pageTitle, ( controls, content ) ) =
|
|
case page of
|
|
Home home ->
|
|
( "Loot-a-lot"
|
|
, Home.view home
|
|
|> mapPageMsg GotHomeMsg
|
|
)
|
|
|
|
GroupChest chest ->
|
|
( "Coffre de groupe"
|
|
, GroupChest.view chest
|
|
|> mapPageMsg GotGroupChestMsg
|
|
)
|
|
|
|
Shop shop ->
|
|
( "Marchand"
|
|
, Shop.view shop
|
|
|> mapPageMsg GotShopMsg
|
|
)
|
|
|
|
About ->
|
|
( "Loot-a-lot", ( text "", [ p [] [ text "A propos" ] ] ) )
|
|
|
|
Loading ->
|
|
( "Loot-a-lot"
|
|
, ( text ""
|
|
, [ div [ class "hero" ]
|
|
[ div [ class "hero-body" ]
|
|
[ p [] [ text "Chargement" ] ]
|
|
]
|
|
]
|
|
)
|
|
)
|
|
|
|
( navbarTitle, navbarLinks ) =
|
|
case maybeSession page of
|
|
Just session ->
|
|
case Session.user session of
|
|
Session.Player data ->
|
|
( data.player.name
|
|
, [ navLink "fas fa-dungeon" Route.Home page
|
|
, navLink "fas fa-store-alt" Route.Merchant page
|
|
, if data.player.id /= 0 then
|
|
navLink "fas fa-gem" Route.GroupChest page
|
|
|
|
else
|
|
text ""
|
|
]
|
|
)
|
|
|
|
Session.Admin _ ->
|
|
( "Administration"
|
|
, [ navLink "fas fa-users" Route.Home page
|
|
, navLink "fas fa-store-alt" Route.Merchant page
|
|
]
|
|
)
|
|
|
|
Nothing ->
|
|
( "Loot-a-lot"
|
|
, []
|
|
)
|
|
in
|
|
( pageTitle
|
|
, { title = navbarTitle, links = navbarLinks }
|
|
, [ div [ class "container box is-paddingless" ] <|
|
|
[ viewSessionBar (maybeSession page) pageTitle [ controls ]
|
|
, section [ class "section" ]
|
|
content
|
|
]
|
|
]
|
|
)
|
|
|
|
|
|
type NotificationKind
|
|
= NotifySuccess
|
|
| NotifyError
|
|
|
|
|
|
viewNotification kind content =
|
|
let
|
|
className =
|
|
case kind of
|
|
NotifySuccess ->
|
|
"is-success"
|
|
|
|
NotifyError ->
|
|
"is-danger"
|
|
in
|
|
div
|
|
[ class ("level-item notification " ++ className)
|
|
, style "margin-left" "1.5rem"
|
|
]
|
|
[ text content
|
|
, a [ class "delete", onClick <| CloseNotification kind ] []
|
|
]
|
|
|
|
|
|
viewSessionBar session pageTitle pageControls =
|
|
let
|
|
user =
|
|
case Maybe.map Session.user session of
|
|
Nothing ->
|
|
[]
|
|
|
|
Just (Session.Player data) ->
|
|
-- TODO: Urgh ! When will this Wealth.Model move out of session !
|
|
[ div [ class "level-item level is-mobile" ] <|
|
|
List.map (Html.map Wealth) <|
|
|
Wealth.view data.player.wealth data.wealth
|
|
++ (if data.player.debt > 0 then
|
|
[ div [ class "level-item" ]
|
|
[ p [ class "has-text-right has-text-danger" ]
|
|
[ strong [ class "heading is-marginless has-text-danger" ] [ text "Dette" ]
|
|
, span [ class <| "is-size-4" ] [ text (String.fromInt data.player.debt ++ "po") ]
|
|
]
|
|
]
|
|
]
|
|
|
|
else
|
|
[]
|
|
)
|
|
]
|
|
|
|
Just (Session.Admin _) ->
|
|
[]
|
|
|
|
notifications =
|
|
[ case Maybe.map Session.notification session of
|
|
Just (Just t) ->
|
|
viewNotification NotifySuccess t
|
|
|
|
_ ->
|
|
text ""
|
|
, case Maybe.map Session.error session of
|
|
Just (Just t) ->
|
|
viewNotification NotifyError t
|
|
|
|
_ ->
|
|
text ""
|
|
]
|
|
|
|
title =
|
|
p [ class "title" ] [ text pageTitle ]
|
|
in
|
|
section [ class "hero is-dark is-bold" ]
|
|
[ div [ class "hero-body", style "padding" "3rem 1.5rem 1.5rem 1.5rem" ]
|
|
[ renderLevel notifications user
|
|
, renderLevel [ title ] pageControls
|
|
]
|
|
]
|
|
|
|
|
|
renderLevel left right =
|
|
div [ class "level" ]
|
|
[ div [ class "level-left" ] left
|
|
, div [ class "level-right" ] right
|
|
]
|
|
|
|
|
|
|
|
-- PLAYER BAR
|
|
|
|
|
|
navLink icon route page =
|
|
let
|
|
linkText =
|
|
case route of
|
|
Route.Merchant ->
|
|
"Marchand"
|
|
|
|
Route.GroupChest ->
|
|
"Coffre de groupe"
|
|
|
|
Route.Home ->
|
|
"Accueil"
|
|
|
|
Route.About ->
|
|
"About"
|
|
|
|
isActive =
|
|
case ( route, page ) of
|
|
( Route.Merchant, Shop _ ) ->
|
|
True
|
|
|
|
( Route.GroupChest, GroupChest _ ) ->
|
|
True
|
|
|
|
( Route.Home, Home _ ) ->
|
|
True
|
|
|
|
( Route.About, About ) ->
|
|
True
|
|
|
|
_ ->
|
|
False
|
|
in
|
|
a [ class "navbar-item", classList [ ( "is-active", isActive ) ], href (toHref route) ]
|
|
[ B.icon { icon = icon, ratio = Just "fa-1x", size = Just "is-medium" }
|
|
, span [] [ text linkText ]
|
|
]
|
|
|
|
|
|
|
|
-- UPDATE
|
|
--
|
|
|
|
|
|
type PageMsg
|
|
= ApiMsg Api.Msg
|
|
| GotGroupChestMsg GroupChest.Msg
|
|
| GotHomeMsg Home.Msg
|
|
| GotShopMsg Shop.Msg
|
|
| Wealth Wealth.Msg
|
|
| CloseNotification NotificationKind
|
|
|
|
|
|
|
|
-- Restores the page after an action has be resolved (either success or error)
|
|
|
|
|
|
closeAction ( page, cmd ) =
|
|
let
|
|
( newPage, pageCmd ) =
|
|
case page of
|
|
Home from ->
|
|
gotoHome page
|
|
|
|
GroupChest from ->
|
|
gotoGroupChest page
|
|
|
|
Shop from ->
|
|
gotoShop page
|
|
|
|
_ ->
|
|
( page, Cmd.none )
|
|
in
|
|
( newPage, Cmd.batch [ cmd, pageCmd ] )
|
|
|
|
|
|
update msg page =
|
|
case ( msg, page, maybeSession page ) of
|
|
-- Home page
|
|
-- Capture API messages
|
|
( GotHomeMsg (Home.Api apiMsg), Home home, _ ) ->
|
|
update (ApiMsg apiMsg) page
|
|
|> closeAction
|
|
|
|
-- Relay others
|
|
( GotHomeMsg subMsg, Home home, _ ) ->
|
|
Home.update subMsg home
|
|
|> updatePage Home GotHomeMsg
|
|
|
|
( GotHomeMsg _, _, _ ) ->
|
|
( page, Cmd.none )
|
|
|
|
-- Group chest
|
|
( GotGroupChestMsg (GroupChest.Api apiMsg), GroupChest _, _ ) ->
|
|
update (ApiMsg apiMsg) page
|
|
|> closeAction
|
|
|
|
( GotGroupChestMsg subMsg, GroupChest chest, _ ) ->
|
|
GroupChest.update subMsg chest
|
|
|> updatePage GroupChest GotGroupChestMsg
|
|
|
|
( GotGroupChestMsg _, _, _ ) ->
|
|
( page, Cmd.none )
|
|
|
|
-- Shop page
|
|
( GotShopMsg (Shop.Api apiMsg), Shop shop, _ ) ->
|
|
update (ApiMsg apiMsg) page
|
|
|> closeAction
|
|
|
|
( GotShopMsg subMsg, Shop shop, _ ) ->
|
|
Shop.update subMsg shop
|
|
|> updatePage Shop GotShopMsg
|
|
|
|
( GotShopMsg _, _, _ ) ->
|
|
( page, Cmd.none )
|
|
|
|
-- Notifications
|
|
--
|
|
( CloseNotification kind, _, Just session ) ->
|
|
( map
|
|
(case kind of
|
|
NotifySuccess ->
|
|
Session.setNotification Nothing
|
|
|
|
NotifyError ->
|
|
Session.setError Nothing
|
|
)
|
|
page
|
|
, Cmd.none
|
|
)
|
|
|
|
( CloseNotification _, _, _ ) ->
|
|
let
|
|
_ =
|
|
Debug.log "lost close msg" 0
|
|
in
|
|
( page, Cmd.none )
|
|
|
|
-- Wealth viewer/editor
|
|
( Wealth wealthMsg, _, Just session ) ->
|
|
let
|
|
wealthModel =
|
|
Session.wealth session
|
|
in
|
|
case Session.user session of
|
|
Session.Player data ->
|
|
let
|
|
( newWealth, maybeEdit ) =
|
|
Wealth.update wealthMsg data.wealth
|
|
in
|
|
( map (Session.updateWealth newWealth) page
|
|
, case maybeEdit of
|
|
Just amount ->
|
|
Api.confirmAction
|
|
(String.fromInt (.id data.player))
|
|
(Api.WealthPayload amount)
|
|
|> Cmd.map ApiMsg
|
|
|
|
Nothing ->
|
|
Cmd.none
|
|
)
|
|
|
|
_ ->
|
|
Debug.log "not a player but updates wealth"
|
|
( page, Cmd.none )
|
|
|
|
( Wealth wealthMsg, _, Nothing ) ->
|
|
( page, Cmd.none )
|
|
|
|
-- Handle API messages
|
|
( ApiMsg (Api.GotActionResult response), _, Just session ) ->
|
|
let
|
|
_ =
|
|
Debug.log "got api response" response
|
|
in
|
|
case response of
|
|
Ok result ->
|
|
let
|
|
updates =
|
|
Maybe.withDefault [] result.updates
|
|
|
|
updatedUser =
|
|
List.foldl applyUpdate (Session.user session) updates
|
|
in
|
|
( page
|
|
|> map (Session.updateUser updatedUser)
|
|
|> map (Session.updateNotifications ( result.notification, result.errors ))
|
|
, case result.notification of
|
|
Just n ->
|
|
Task.perform
|
|
(\_ -> CloseNotification NotifySuccess)
|
|
(Process.sleep 5000.0)
|
|
|
|
Nothing ->
|
|
Cmd.none
|
|
)
|
|
|
|
Err error ->
|
|
let
|
|
_ =
|
|
Debug.log "ApiError" error
|
|
in
|
|
( page
|
|
|> map (Session.setError (Just "Oups! Cela n'a pas fonctionné"))
|
|
, Cmd.none
|
|
)
|
|
|
|
( ApiMsg apiMsg, _, Nothing ) ->
|
|
let
|
|
_ =
|
|
Debug.log "rogue api msg !" apiMsg
|
|
in
|
|
( page, Cmd.none )
|
|
|
|
|
|
updatePage toPage toMsg ( subModel, subMsg ) =
|
|
( toPage subModel
|
|
, Cmd.map toMsg subMsg
|
|
)
|
|
|
|
|
|
|
|
-- Maps the page session to a function, if any
|
|
|
|
|
|
map func page =
|
|
case maybeSession page of
|
|
Nothing ->
|
|
page
|
|
|
|
Just session ->
|
|
case page of
|
|
Home model ->
|
|
Home <| Home.updateSession model (func session)
|
|
|
|
GroupChest model ->
|
|
GroupChest { model | session = func session }
|
|
|
|
Shop model ->
|
|
Shop { model | session = func session }
|
|
|
|
_ ->
|
|
page
|
|
|
|
|
|
applyUpdate : Api.Update -> Session.User -> Session.User
|
|
applyUpdate u user =
|
|
{- Note: DbUpdates always refer to the active player -}
|
|
case user of
|
|
Session.Player data ->
|
|
case u of
|
|
Api.ItemRemoved item ->
|
|
Session.Player
|
|
{ data
|
|
| loot =
|
|
List.filter
|
|
(\i -> i.id /= item.id)
|
|
data.loot
|
|
}
|
|
|
|
Api.ItemAdded item ->
|
|
Session.Player { data | loot = item :: data.loot }
|
|
|
|
Api.WealthUpdated diff ->
|
|
let
|
|
player =
|
|
data.player
|
|
|
|
wealth =
|
|
player.wealth
|
|
in
|
|
Session.Player
|
|
{ data
|
|
| player =
|
|
{ player
|
|
| wealth =
|
|
Api.Player.Wealth
|
|
(wealth.cp + diff.cp)
|
|
(wealth.sp + diff.sp)
|
|
(wealth.gp + diff.gp)
|
|
(wealth.pp + diff.pp)
|
|
}
|
|
}
|
|
|
|
Api.ClaimAdded claim ->
|
|
Session.Player { data | claims = claim :: data.claims }
|
|
|
|
Api.ClaimRemoved claim ->
|
|
Session.Player { data | claims = List.filter (\c -> c.id /= claim.id) data.claims }
|
|
|
|
Session.Admin _ ->
|
|
user
|
|
|
|
|
|
|
|
-- CHANGE ROUTE
|
|
|
|
|
|
initHome session =
|
|
Home.init session
|
|
|> updatePage Home GotHomeMsg
|
|
|
|
|
|
gotoHome page =
|
|
case maybeSession page of
|
|
Nothing ->
|
|
( page, Cmd.none )
|
|
|
|
Just session ->
|
|
Home.init session
|
|
|> updatePage Home GotHomeMsg
|
|
|
|
|
|
gotoShop page =
|
|
case maybeSession page of
|
|
Nothing ->
|
|
( page, Cmd.none )
|
|
|
|
Just session ->
|
|
Shop.init session
|
|
|> updatePage Shop GotShopMsg
|
|
|
|
|
|
gotoGroupChest page =
|
|
case maybeSession page of
|
|
Nothing ->
|
|
( page, Cmd.none )
|
|
|
|
Just session ->
|
|
GroupChest.init session
|
|
|> updatePage GroupChest GotGroupChestMsg
|
|
|
|
|
|
gotoInventory session =
|
|
()
|