works on ViewMode concept

This commit is contained in:
2019-11-03 16:03:44 +01:00
parent e8d19c5deb
commit d415a92d41
3 changed files with 540 additions and 302 deletions

View File

@@ -7,6 +7,7 @@ import Url
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Svg.Attributes
import Http
import Json.Decode exposing (Decoder, field, list, string, int)
import Url.Parser as P exposing (Parser, (</>), oneOf, s)
@@ -35,7 +36,8 @@ type alias State =
, route : Route
, error : String
, menuOpen : Bool
, selectedItems : Maybe Selection
, selection : Maybe Selection
, activeMode : Maybe ViewMode
}
type alias Model =
@@ -53,7 +55,7 @@ init flags url key =
Just r -> r
Nothing -> PlayerChest
in
( Model (State key route "" False Nothing) blankPlayer Nothing Nothing Nothing, fetchInitialData 0)
( Model (State key route "" False Nothing Nothing) blankPlayer Nothing Nothing Nothing, fetchInitialData 0)
fetchInitialData : Int -> Cmd Msg
@@ -160,6 +162,7 @@ type Msg
| GotPlayer (Result Http.Error Player)
| GotLoot ToChest (Result Http.Error Loot)
| LootViewItemSwitched Int
| ModeSwitched (Maybe ViewMode)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
@@ -177,19 +180,16 @@ update msg model =
UrlChanged url ->
let
route = P.parse routeParser url
state = model.state
in
case route of
Just page ->
( let
state = model.state
in
{ model | state =
{ state | route = page , selectedItems = Just Set.empty}
}
, case page of
GroupLoot -> Cmd.none
a -> Cmd.none
)
{ model | state = { state | route = page }}
|> update (case page of
-- Directly enter add mode on NewLoot view
NewLoot -> ModeSwitched (Just Add)
other -> ModeSwitched Nothing
)
Nothing ->
( setError "Invalid route" model, Cmd.none )
@@ -227,9 +227,35 @@ update msg model =
state = model.state
in
( { model | state =
{ state | selectedItems = Debug.log "new selection" (switchSelectionState id state.selectedItems) }}
{ state | selection = Debug.log "new selection" (switchSelectionState id state.selection) }}
, Cmd.none )
ModeSwitched newMode ->
let
state = model.state
(nextMode, cmd) =
case newMode of
Nothing -> -- Cancel action
(Nothing, Cmd.none)
new ->
case new of
Just Confirm ->
-- Confirm action and exit
(Nothing, Cmd.none)
other ->
-- Enter mode
(new, Cmd.none)
in
( { model | state =
{ state | activeMode = nextMode
, selection = case nextMode of
Nothing -> Nothing
Just _ -> Just Set.empty
}}
, cmd)
-- ERRORS
setError : String -> Model -> Model
@@ -269,33 +295,56 @@ subscriptions _ =
-- VIEWS
---
type ViewMode
= Sell
| Buy
| Grab
| Add
| Confirm -- Confirm action and exit mode
actionButton mode t icon color =
button [ class <| "button is-rounded is-" ++ color
, onClick (ModeSwitched mode) ]
[ span [ class "icon" ] [ i [ Svg.Attributes.class <| "fas fa-" ++ icon ] [] ]
]
view : Model -> Browser.Document Msg
view model =
let
(header, shownLoot) =
case model.state.route of
PlayerChest ->
("Mon coffre", Maybe.withDefault [] model.loot)
GroupLoot ->
("Coffre de groupe", Maybe.withDefault [] model.groupLoot)
Merchant ->
("Marchand", Maybe.withDefault [] model.merchantItems)
NewLoot ->
("Nouveau trésor :)", [] )
actionControls =
case model.state.activeMode of
Just mode -> -- When a mode is active
[ div [class "buttons"]
[actionButton (Just Confirm) "Valider" "plus" "primary"
, actionButton Nothing "Annuler" "coins" "danger"]
]
Nothing -> -- Buttons to enter mode
case model.state.route of
PlayerChest -> [actionButton (Just Sell) "" "coins" "danger"]
GroupLoot -> [actionButton (Just Grab) "Demander" "coins" "primary"]
Merchant -> [actionButton (Just Buy) "" "coins" "success"]
NewLoot -> []
in
{ title = "Loot-a-lot in ELM"
, body =
[ viewHeaderBar model
, viewPlayerBar model.player model.state.route
, viewPlayerBar model.player actionControls
, article [class "section container"]
(case model.state.route of
PlayerChest ->
[ p [class "heading"] [text "Mon Coffre"]
, viewSearchBar
, viewLoot (Maybe.withDefault [] model.loot) model.state.selectedItems
]
GroupLoot ->
[ p [] [text "Coffre de groupe"]
, viewLoot (Maybe.withDefault [] model.groupLoot) model.state.selectedItems
]
Merchant ->
[ p [] [text "Acheter des objets"]
, viewLoot (Maybe.withDefault [] model.merchantItems) model.state.selectedItems
]
NewLoot ->
[ p [] [text "Nouveau trésor :) "] ]
)
[ p [class "heading"] [text header]
, viewSearchBar
, viewLoot shownLoot model.state.selection model.state.activeMode
]
, hr [] []
, section [class "container"] [viewDebugSection model]
]
@@ -306,36 +355,55 @@ view model =
isSelected id selection =
Set.member id selection
viewLoot : Loot -> Maybe Selection -> Html Msg
viewLoot items selection =
table [ class "table is-fullwidth is-striped"]
viewLoot : Loot -> Maybe Selection -> Maybe ViewMode -> Html Msg
viewLoot items selection activeMode =
table [ class "table is-fullwidth is-striped is-light"]
([ thead [class "table-header"]
[ th [] [text "Nom"] ]
]
++ List.map (viewItemTableRow selection) items
++ List.map (viewItemTableRow selection activeMode) items
)
controlsRenderer : ViewMode -> Item -> Html Msg
controlsRenderer mode item =
case mode of
Buy -> p [class "level-item"] [ text (String.fromInt item.base_price ++ "po")]
Sell -> p [class "level-item"] [ text (String.fromFloat (toFloat item.base_price / 2) ++ "po")]
Grab -> p [class "level-item"] [ text "Grab" ]
Add -> p [class "level-item"] [ text "New !" ]
Confirm -> text ""
viewItemTableRow selection item =
viewItemTableRow : Maybe Selection -> Maybe ViewMode -> Item -> Html Msg
viewItemTableRow selection activeMode item =
let
(canSelect, selected) =
selected =
case selection of
Just s ->
(True, isSelected item.id s)
isSelected item.id s
Nothing ->
(False, False)
False
levelRight =
case activeMode of
Nothing -> []
Just mode -> List.singleton (
div [ class "level-right" ]
[ controlsRenderer mode item
, input [ class "checkbox level-item"
, type_ "checkbox"
, onCheck (\v -> LootViewItemSwitched item.id)
] []
])
in
tr [ classList [ ("is-selected", selected) ] ]
[ td []
[ label [ class "level checkbox" ]
[ div [ class "level-left" ]
[ p [class "level-item"] [ text item.name ]
]
, div [ classList [("level-right", True), ("is-hidden", not canSelect)]]
[ p [class "level-item"] [ text (String.fromInt item.base_price ++ "po") ]
, input [class "checkbox level-item", type_ "checkbox", onCheck (\v -> LootViewItemSwitched item.id)] []
]
]
(List.concat [[
div [ class "level-left" ]
[ p [class "level-item"] [ text item.name ]]
]
, levelRight
])
]
]
@@ -348,9 +416,34 @@ viewDebugSection model =
, debugSwitchPlayers
, p [class "panel-block has-text-danger"] [text model.state.error]
, p [class "panel-block"] [text ("Route : " ++ Debug.toString model.state.route)]
, p [class "panel-block"] [text ("Selection : " ++ Debug.toString model.state.selectedItems)]
, p [class "panel-block"] [text ("Active Mode : " ++ Debug.toString model.state.activeMode)]
, p [class "panel-block"] [text ("Selection : " ++ Debug.toString model.state.selection)]
, p [] debugSandbox
]
stackedIcon name =
span [class "icon is-large has-text-dark"]
[ span [ class "fa-stack" ]
[ i [ class "fas fa-circle fa-stack-2x" ] []
, i [ class (name ++ " fa-inverse fa-stack-1x") ] []
, text name ]
]
debugSandbox =
[ stackedIcon "fas fa-coins"
, stackedIcon "fab fa-d-and-d"
, stackedIcon "fas fa-praying-hands"
, stackedIcon "fas fa-gem"
, stackedIcon "fas fa-pen"
, stackedIcon "fas fa-percentage"
, stackedIcon "fas fa-store-alt"
, stackedIcon "fas fa-cart-plus"
, stackedIcon "fas fa-angry"
, stackedIcon "fas fa-plus"
, stackedIcon "fas fa-tools"
, stackedIcon "fas fa-search"
]
debugSwitchPlayers : Html Msg
debugSwitchPlayers =
div [ class "panel-tabs" ]
@@ -392,8 +485,8 @@ viewHeaderBar model =
-- PLAYER BAR
viewPlayerBar : Player -> Route -> Html Msg
viewPlayerBar player route =
viewPlayerBar : Player -> List (Html Msg)-> Html Msg
viewPlayerBar player actionControls =
section [ class "level container is-mobile box" ]
[ div [class "level-left"]
([div [ class "level-item" ]
@@ -410,22 +503,9 @@ viewPlayerBar player route =
[]
)
)
, div [class "level-right"] (viewPlayerAction player route)
, div [class "level-right"] actionControls
]
actionButton t n c = button [ class ("button is-rounded is-" ++ c) ]
[ span [ class "icon" ] [ i [ class ("fas fa-" ++ n) ] [] ]
, span [] [ text t ]
]
viewPlayerAction : Player -> Route -> List (Html Msg)
viewPlayerAction player route =
case route of
PlayerChest -> [actionButton "Vendre" "coins" "danger"]
GroupLoot -> [actionButton "Demander" "coins" "primary"]
Merchant -> [actionButton "Acheter" "coins" "success"]
NewLoot -> [actionButton "Valider" "coins" "primary", actionButton "Annuler" "coins" "danger"]
showWealth : Wealth -> List (Html Msg)
showWealth wealth =