Bot-Man-Toe/elm/Screen/Leaderboard.elm

160 lines
5.1 KiB
Elm

module Screen.Leaderboard exposing (..)
{-| Widget module for a leaderboard page.
-}
import Api.Elo exposing (EloStat, Leaderboard, Players)
import Color
import Element exposing (Element)
import Element.Background
import Element.Border
import Element.Events
import Element.Font
import Layout
import Pixels exposing (Pixels)
import Program exposing (ViewBox)
import Quantity exposing (Quantity)
import Theme
view : ViewBox { board : Leaderboard, onSelect : String -> msg, selectedName : String } -> Element msg
view data =
Element.column
[]
[ selectBoard
{ flavor = data.flavor
, leaderboard = data.model.board
, onSelect = data.model.onSelect
, selectedName = data.model.selectedName
, width = data.size.width
}
, data.model.board
|> List.map
(\l ->
if l.name == data.model.selectedName then
viewSingleBoard
{ flavor = data.flavor
, model = l
, size = data.size
}
else
Element.none
)
|> Element.column []
]
selectBoard :
{ flavor : Theme.Flavor
, leaderboard : Leaderboard
, onSelect : String -> msg
, selectedName : String
, width : Quantity Int Pixels
}
-> Element msg
selectBoard data =
data.leaderboard
|> List.map .name
|> List.map
(\s ->
Element.el
[ if data.selectedName == s then
Element.Background.color (Theme.subtext0UI data.flavor)
else
Element.Background.color (Theme.surface1UI data.flavor)
, Element.Border.rounded 25
, Element.centerX
, Element.Events.onClick (data.onSelect s)
, Element.padding 10
]
(Element.text s)
)
|> Element.wrappedRow
[ Element.padding 20
, Element.spacing 10
, Element.width <| Element.px <| Pixels.inPixels data.width
]
viewSingleBoard : ViewBox { name : String, players : Players } -> Element msg
viewSingleBoard data =
let
boardWidth =
data.size.width
|> Quantity.toFloatQuantity
|> Quantity.multiplyBy (2 / 3)
|> Quantity.floor
|> Quantity.clamp (Pixels.pixels 600) (Pixels.pixels 1800)
|> Pixels.inPixels
|> Element.px
|> Element.width
in
data.model.players
|> List.map (viewEloStat { flavor = data.flavor })
|> Element.column [ Element.centerX, boardWidth ]
|> List.singleton
|> (::)
(Element.text data.model.name
|> Element.el
[ Element.centerX, Element.Font.size 50 ]
)
|> Element.column
[ Element.padding 15
, Element.spacing 30
, Element.width <| Element.px <| Pixels.inPixels data.size.width
]
viewEloStat : { flavor : Theme.Flavor } -> EloStat -> Element msg
viewEloStat data stat =
Element.row
[ Element.Background.color (Theme.mantleUI data.flavor)
, Element.Border.rounded 5
, Element.padding 10
, Element.spacing 5
, Element.width Element.fill
]
[ Element.column
[ Element.centerY, Element.spacing 5, Element.width Element.fill ]
[ Element.text stat.name
|> Element.el [ Element.Font.size 30 ]
, Element.el
[ Element.Font.color (Theme.subtext0UI data.flavor)
, Element.Font.size 15
]
(case stat.version of
Nothing ->
Element.text stat.url
Just v ->
Element.text (stat.url ++ " | " ++ v)
)
]
-- Bar to push the rest to the right
, Element.column [ Element.width Element.fill ] []
, field { text = "ELO", value = stat.elo, color = Theme.lavenderUI data.flavor }
|> Element.el [ Element.paddingEach { top = 0, bottom = 0, left = 0, right = 15 } ]
, field { text = "WINS", value = stat.wins, color = Theme.greenUI data.flavor }
, field { text = "DRAWS", value = stat.draws, color = Theme.subtext0UI data.flavor }
, field { text = "LOSSES", value = stat.losses, color = Theme.redUI data.flavor }
]
field : { text : String, value : Int, color : Element.Color } -> Element msg
field { text, value, color } =
Element.column
[ Element.Font.color color
, Element.spacing 3
, Element.width (Element.px 70)
]
[ String.fromInt value
|> Element.text
|> Element.el [ Element.centerX, Element.Font.size 25 ]
, text
|> Element.text
|> Element.el [ Element.centerX, Element.Font.size 15 ]
]