tutor/www/src/Pages/DeckEditor.elm

219 lines
5.6 KiB
Elm

module Pages.DeckEditor exposing (..)
import Browser
import Browser.Events
import Browser.Navigation
import Deck
import Element as E
import Element.Background as Background
import Element.Events as Events
import Element.Font as Font
import Http
import Paginated
import Route
import Spinner
import Symbol
import UI
import Url
import Url.Builder
type alias Model =
{ navigationKey : Browser.Navigation.Key
, url : Url.Url
, device : E.Device
, spinner : Spinner.Model
, symbols : Symbol.Table
, deck : Deck
}
type Msg
= ViewportChanged UI.Dimensions
| SpinnerMsg Spinner.Msg
| GotDeck (Result Http.Error Deck.Deck)
| GotSymbols Symbol.Table
type Deck
= Ready Deck.Deck
| Loading
| NotFound
| Failed
type alias Grouped =
{ creatures : List Deck.Card
, instants : List Deck.Card
, sorceries : List Deck.Card
, enchantments : List Deck.Card
, lands : List Deck.Card
}
type alias Group =
{ label : String, cards : List Deck.Card }
groups : List Deck.Card -> List Group
groups cards =
let
last : List a -> Maybe a
last xs =
List.reverse xs |> List.head
typeOf : Deck.Card -> String
typeOf card =
String.split "" card.card.typeLine
|> List.head
|> Maybe.andThen (\types -> String.words types |> last)
|> Maybe.withDefault ""
isA : String -> Deck.Card -> Bool
isA cardType card =
typeOf card == cardType
isEmpty : Group -> Bool
isEmpty group =
List.isEmpty group.cards
gather : String -> String -> Group
gather groupName typeName =
List.filter (isA typeName) cards
|> List.sortBy (\dc ->(dc.card.cmc, dc.card.name))
|> Group groupName
in
List.filter (\l -> not <| isEmpty l)
[ gather "Creatures" "Creature"
, gather "Planeswalkers" "Planeswalker"
, gather "Instants" "Instant"
, gather "Sorceries" "Sorcery"
, gather "Enchantments" "Enchantment"
, gather "Artifacts" "Artifact"
, gather "Lands" "Land"
]
init : Browser.Navigation.Key -> Url.Url -> E.Device -> Symbol.Table -> Int -> ( Model, Cmd Msg )
init key url device symbols deckId =
( { navigationKey = key
, url = url
, device = device
, spinner = Spinner.init
, symbols = symbols
, deck = Loading
}
, getDeck deckId
)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ViewportChanged viewport ->
( { model
| device = E.classifyDevice viewport
}
, Cmd.none
)
SpinnerMsg msg_ ->
( { model | spinner = Spinner.update msg_ model.spinner }, Cmd.none )
GotDeck (Ok deck) ->
( { model | deck = Ready deck }, Cmd.none )
GotDeck (Err _) ->
( { model | deck = Failed }, Cmd.none )
GotSymbols symbols ->
( { model | symbols = symbols }, Cmd.none )
viewDeck : Symbol.Table -> Deck.Deck -> E.Element Msg
viewDeck symbols deck =
let
viewGroup group =
E.column [ E.spacing 10 ]
[ E.paragraph [ Font.heavy ] [ UI.title group.label ]
, E.wrappedRow [ E.spacing 10 ] <|
List.map
(\dc ->
UI.cardRow
{ foil = False
, subtitle = "x" ++ String.fromInt dc.quantity
}
[ E.width <| E.px 400, E.clipX, Background.color UI.colors.background ]
symbols
dc.card
)
group.cards
]
in
E.column [ E.height E.fill, E.centerX, E.spacing 5 ] <|
[ E.paragraph [ Font.heavy, Font.size 24, Font.center ] [ UI.title deck.name ]
, E.column
[ E.height E.fill
, E.spacing 10
, Background.color UI.colors.sidebar
, E.scrollbarY
, E.clipX
]
<|
List.map viewGroup <|
groups deck.cards
]
view : Model -> E.Element Msg
view model =
E.column
[ E.width E.fill
, E.height E.fill
]
[ case model.deck of
Ready deck ->
viewDeck model.symbols deck
Failed ->
E.none
NotFound ->
E.none
Loading ->
E.el [ E.height E.fill, E.centerX ] <|
E.html <|
Spinner.view UI.manaSpinner
model.spinner
, UI.footer <|
case model.deck of
Ready deck ->
UI.text <|
String.join " "
[ String.fromInt (List.sum <| List.map .quantity deck.cards)
, "cards"
]
_ ->
E.none
]
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.batch
[ Browser.Events.onResize
(\w h -> ViewportChanged { width = w, height = h })
, Sub.map SpinnerMsg Spinner.subscription
]
getDeck : Int -> Cmd Msg
getDeck deckId =
Http.get
{ url =
Url.Builder.absolute
[ "api", "decks", String.fromInt deckId ]
[]
, expect = Http.expectJson GotDeck Deck.decode
}