219 lines
5.6 KiB
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
|
|
}
|