Bot-Man-Toe/elm/GameList.elm

239 lines
6.1 KiB
Elm

module GameList exposing (..)
import Dict exposing (Dict)
import Duration
import Element exposing (Element)
import Element.Background
import Element.Events
import Games.TicTacToe as TicTacToe exposing (TicTacToe)
import Layout
import Match exposing (Match)
import Material.Icons as Icons
import Pixels exposing (Pixels)
import Quantity exposing (Quantity)
import Theme
-- MODEL
type CreateGameType
= CreateTicTacToe
type Game
= GameTicTacToe String (Match TicTacToe)
type GameList
= GameList
{ ticTacToe : Dict String (Match TicTacToe)
}
type Msg
= AddTicTacToe { baseUrl : String, matchId : String }
| OnTicTacToe String (Match.Msg TicTacToe)
init : {} -> ( GameList, Cmd Msg )
init _ =
( GameList
{ ticTacToe = Dict.empty
}
, Cmd.none
)
-- UPDATE
update : Msg -> GameList -> ( GameList, Cmd Msg )
update msg ((GameList data) as model) =
case msg of
AddTicTacToe newGame ->
let
( newMdl, newM ) =
Match.init
{ autoScroll = Just (Duration.seconds 0.75)
, baseUrl = newGame.baseUrl
, decoder = TicTacToe.decoder
, empty = TicTacToe.empty
, matchId = newGame.matchId
}
in
( GameList { data | ticTacToe = Dict.insert newGame.matchId newMdl data.ticTacToe }
, Cmd.map (OnTicTacToe newGame.matchId) newM
)
OnTicTacToe key m ->
case Dict.get key data.ticTacToe of
Nothing ->
( model, Cmd.none )
Just mdl ->
case Match.update m mdl of
( newMdl, newM ) ->
( GameList { data | ticTacToe = Dict.insert key newMdl data.ticTacToe }
, Cmd.map (OnTicTacToe key) newM
)
-- SUBSCRIPTIONS
subscriptions : GameList -> Sub Msg
subscriptions (GameList data) =
Sub.batch
[ Dict.toList data.ticTacToe
|> List.map
(\( key, mdl ) ->
Sub.map (OnTicTacToe key) (Match.subscriptions mdl)
)
|> Sub.batch
]
-- VIEW
createGameToString : CreateGameType -> String
createGameToString cg =
case cg of
CreateTicTacToe ->
"tic-tac-toe"
viewCreateGame :
{ baseUrl : String
, flavor : Theme.Flavor
, height : Quantity Int Pixels
, onBaseUrl : String -> msg
, onPlayers : List String -> msg
, players : List String
, width : Quantity Int Pixels
}
-> Element msg
viewCreateGame data =
Element.none
viewGame :
{ flavor : Theme.Flavor
, game : Game
, height : Quantity Int Pixels
, onNavigateBack : msg
, toMsg : Msg -> msg
, width : Quantity Int Pixels
}
-> Element msg
viewGame data =
let
navBarHeight =
Pixels.pixels 200
showNavBar =
Quantity.ratio (Quantity.toFloatQuantity data.height) navBarHeight <= 3
gameHeight =
if showNavBar then
data.height |> Quantity.minus navBarHeight
else
data.height
in
Element.column
[ Element.height <| Element.px <| Pixels.inPixels data.height
, Element.width <| Element.px <| Pixels.inPixels data.width
]
[ if showNavBar then
Element.row
[ Element.Background.color (Theme.blueUI data.flavor)
, Element.height <| Element.px <| Pixels.inPixels navBarHeight
, Element.width <| Element.px <| Pixels.inPixels data.width
]
[ Layout.iconAsElement
{ color = Theme.blue data.flavor
, height = Pixels.inPixels navBarHeight
, icon = Icons.arrow_back
, width = Pixels.inPixels data.width
}
|> Element.el [ Element.Events.onClick data.onNavigateBack ]
]
else
Element.none
, viewMatch
{ flavor = data.flavor
, game = data.game
, height = gameHeight
, width = data.width
}
|> Element.map data.toMsg
]
viewMatch :
{ flavor : Theme.Flavor
, game : Game
, height : Quantity Int Pixels
, width : Quantity Int Pixels
}
-> Element Msg
viewMatch data =
case data.game of
GameTicTacToe key match ->
Match.view
{ flavor = data.flavor
, height = data.height
, match = match
, toMsg = OnTicTacToe key
, viewGame = TicTacToe.view
, width = data.width
}
viewSelection :
{ flavor : Theme.Flavor
, height : Quantity Int Pixels
, model : GameList
, onCreateGame : msg
, onNavigateToGame : Game -> msg
, width : Quantity Int Pixels
}
-> Element msg
viewSelection data =
case data.model of
GameList model ->
[ Layout.itemWithSubtext
{ color = Theme.mantle data.flavor
, leftIcon = always Element.none
, onPress = Just data.onCreateGame
, rightIcon = always Element.none
, text = "Create new game"
, title = "CREATE"
}
[]
|> List.singleton
, model.ticTacToe
|> Dict.toList
|> List.map
(\( key, match ) ->
Match.viewListItem
{ flavor = data.flavor
, height = Pixels.pixels 80
, match = match
, onPress = Just <| data.onNavigateToGame <| GameTicTacToe key match
, width = data.width
}
)
]
|> List.concat
|> Element.column
[ Element.centerX
]