2022-12-16 22:15:10 +00:00
|
|
|
module UI exposing
|
|
|
|
( Dimensions
|
2023-01-11 02:21:33 +00:00
|
|
|
, cardRow
|
2022-12-16 22:15:10 +00:00
|
|
|
, colors
|
2023-01-11 02:36:57 +00:00
|
|
|
, footer
|
2022-12-16 22:15:10 +00:00
|
|
|
, getViewport
|
|
|
|
, isMobile
|
|
|
|
, manaSpinner
|
2023-01-11 02:21:33 +00:00
|
|
|
, priceBadge
|
2023-01-10 17:31:31 +00:00
|
|
|
, subtitle
|
2023-01-09 20:00:37 +00:00
|
|
|
, text
|
|
|
|
, title
|
2022-12-16 22:15:10 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
import Browser.Dom
|
2023-01-11 02:21:33 +00:00
|
|
|
import Card
|
2022-12-16 22:15:10 +00:00
|
|
|
import Color
|
|
|
|
import Element as E
|
2023-01-11 02:21:33 +00:00
|
|
|
import Element.Background as Background
|
|
|
|
import Element.Border as Border
|
2023-01-09 20:00:37 +00:00
|
|
|
import Element.Font as Font
|
2023-01-11 02:21:33 +00:00
|
|
|
import Maybe.Extra
|
2022-12-16 22:15:10 +00:00
|
|
|
import Spinner
|
2023-01-11 22:10:48 +00:00
|
|
|
import Symbol
|
2022-12-16 22:15:10 +00:00
|
|
|
import Task
|
2023-01-11 02:21:33 +00:00
|
|
|
import Url.Builder
|
2022-12-16 22:15:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
type alias Dimensions =
|
|
|
|
{ width : Int
|
|
|
|
, height : Int
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
colors =
|
|
|
|
let
|
|
|
|
blue =
|
|
|
|
E.rgb255 100 100 255
|
|
|
|
|
|
|
|
slate =
|
|
|
|
E.rgb255 150 150 200
|
|
|
|
|
|
|
|
lighterGrey =
|
|
|
|
E.rgb255 60 60 60
|
|
|
|
|
|
|
|
lightGrey =
|
|
|
|
E.rgb255 50 50 50
|
|
|
|
|
|
|
|
grey =
|
|
|
|
E.rgb255 40 40 40
|
|
|
|
|
|
|
|
darkGrey =
|
|
|
|
E.rgb255 30 30 30
|
|
|
|
|
|
|
|
darkerGrey =
|
|
|
|
E.rgb255 20 20 20
|
|
|
|
|
|
|
|
white =
|
|
|
|
E.rgb255 255 255 255
|
|
|
|
|
|
|
|
offwhite =
|
|
|
|
E.rgb255 200 200 200
|
|
|
|
|
|
|
|
mythic =
|
|
|
|
E.rgb255 205 55 0
|
|
|
|
|
|
|
|
rare =
|
|
|
|
E.rgb255 218 165 32
|
|
|
|
|
|
|
|
uncommon =
|
|
|
|
E.rgb255 112 128 144
|
|
|
|
|
|
|
|
common =
|
|
|
|
E.rgb255 47 79 79
|
|
|
|
in
|
|
|
|
{ primary = blue
|
|
|
|
, secondary = slate
|
|
|
|
, background = lightGrey
|
|
|
|
, navBar = darkerGrey
|
|
|
|
, sidebar = lighterGrey
|
|
|
|
, selected = darkGrey
|
|
|
|
, hover = grey
|
|
|
|
, title = white
|
|
|
|
, subtitle = offwhite
|
|
|
|
, text = offwhite
|
|
|
|
, mythic = mythic
|
|
|
|
, rare = rare
|
|
|
|
, uncommon = uncommon
|
|
|
|
, common = common
|
2023-01-11 22:10:48 +00:00
|
|
|
, mana =
|
|
|
|
{ white =
|
|
|
|
{ fg = E.rgb255 249 250 244
|
|
|
|
, bg = E.rgb255 248 231 185
|
|
|
|
}
|
|
|
|
, black =
|
|
|
|
{ fg = E.rgb255 21 11 0
|
|
|
|
, bg = E.rgb255 166 159 157
|
|
|
|
}
|
|
|
|
, blue =
|
|
|
|
{ fg = E.rgb255 14 104 171
|
|
|
|
, bg = E.rgb255 179 206 234
|
|
|
|
}
|
|
|
|
, green =
|
|
|
|
{ fg = E.rgb255 0 114 62
|
|
|
|
, bg = E.rgb255 196 211 202
|
|
|
|
}
|
|
|
|
, red =
|
|
|
|
{ fg = E.rgb255 211 32 42
|
|
|
|
, bg = E.rgb255 235 159 130
|
|
|
|
}
|
|
|
|
, generic =
|
|
|
|
{ fg = E.rgb255 190 190 190
|
|
|
|
, bg = E.rgb255 250 250 250
|
|
|
|
}
|
|
|
|
}
|
2022-12-16 22:15:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
getViewport : (Dimensions -> msg) -> Cmd msg
|
|
|
|
getViewport msg =
|
|
|
|
Task.perform
|
|
|
|
(\x ->
|
|
|
|
msg
|
|
|
|
{ width = floor x.viewport.width
|
|
|
|
, height = floor x.viewport.height
|
|
|
|
}
|
|
|
|
)
|
|
|
|
Browser.Dom.getViewport
|
|
|
|
|
|
|
|
|
|
|
|
isMobile : E.Device -> Bool
|
|
|
|
isMobile device =
|
|
|
|
case device.orientation of
|
|
|
|
E.Landscape ->
|
|
|
|
False
|
|
|
|
|
|
|
|
E.Portrait ->
|
|
|
|
True
|
|
|
|
|
|
|
|
|
|
|
|
manaSpinner : Spinner.Config
|
|
|
|
manaSpinner =
|
|
|
|
let
|
|
|
|
color index =
|
|
|
|
if index < 1.0 then
|
|
|
|
Color.red
|
|
|
|
|
|
|
|
else if index < 2.0 then
|
|
|
|
Color.green
|
|
|
|
|
|
|
|
else if index < 3.0 then
|
|
|
|
Color.purple
|
|
|
|
|
|
|
|
else if index < 4.0 then
|
|
|
|
Color.blue
|
|
|
|
|
|
|
|
else
|
|
|
|
Color.white
|
|
|
|
|
|
|
|
default =
|
|
|
|
Spinner.defaultConfig
|
|
|
|
in
|
|
|
|
{ default
|
|
|
|
| lines = 5.0
|
|
|
|
, length = 0.0
|
|
|
|
, width = 20
|
|
|
|
, color = color
|
|
|
|
}
|
2023-01-09 20:00:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
text : String -> E.Element msg
|
|
|
|
text string =
|
|
|
|
E.el [ Font.color colors.text ] <| E.text string
|
|
|
|
|
|
|
|
|
|
|
|
title : String -> E.Element msg
|
|
|
|
title string =
|
|
|
|
E.el [ Font.color colors.title ] <| E.text string
|
2023-01-10 17:31:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
subtitle : String -> E.Element msg
|
|
|
|
subtitle string =
|
|
|
|
E.el [ Font.size 16, Font.italic, Font.color colors.subtitle ] <| E.text string
|
2023-01-11 02:21:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
priceBadge : { currency : String, amount : String } -> E.Element msg
|
|
|
|
priceBadge { currency, amount } =
|
|
|
|
E.el
|
|
|
|
[ Border.rounded 5
|
|
|
|
, Border.color colors.text
|
2023-01-12 01:31:35 +00:00
|
|
|
, E.width E.fill
|
2023-01-11 02:21:33 +00:00
|
|
|
, E.padding 2
|
|
|
|
, Font.family [ Font.typeface "sans" ]
|
|
|
|
, Font.size 10
|
|
|
|
]
|
|
|
|
<|
|
|
|
|
E.row [ E.width E.fill ]
|
|
|
|
[ E.el [ E.width <| E.fillPortion 1 ] <| E.text <| String.toUpper currency
|
|
|
|
, E.el [ E.width <| E.fillPortion 2, Font.alignRight ] <| E.text amount
|
|
|
|
]
|
|
|
|
|
|
|
|
|
2023-01-11 22:10:48 +00:00
|
|
|
cardRow : { foil : Bool, subtitle : String } -> List (E.Attribute msg) -> Symbol.Table -> Card.Card -> E.Element msg
|
|
|
|
cardRow options attributes symbols card =
|
2023-01-11 02:21:33 +00:00
|
|
|
let
|
|
|
|
badge color foil string =
|
|
|
|
E.el
|
2023-01-11 02:52:02 +00:00
|
|
|
[ Border.rounded 5
|
|
|
|
, Border.color color
|
|
|
|
, Border.width 1
|
2023-01-12 01:31:35 +00:00
|
|
|
, E.width E.fill
|
2023-01-11 02:52:02 +00:00
|
|
|
, Font.family [ Font.typeface "sans" ]
|
|
|
|
, Font.size 10
|
|
|
|
, Font.color colors.title
|
|
|
|
]
|
2023-01-11 02:21:33 +00:00
|
|
|
<|
|
|
|
|
E.row [ E.height E.fill, E.width E.fill ]
|
|
|
|
[ E.el [ E.padding 2, E.width E.fill ] <| E.text string
|
|
|
|
, E.row [ E.padding 1, E.height E.fill, E.width E.fill, Background.color color ]
|
|
|
|
[ if foil then
|
|
|
|
E.el
|
|
|
|
[ E.width E.fill
|
|
|
|
, E.height E.fill
|
|
|
|
, Background.gradient
|
|
|
|
{ angle = 4.0
|
|
|
|
, steps =
|
|
|
|
[ E.rgb 148 0 211
|
|
|
|
, E.rgb 75 0 130
|
|
|
|
, E.rgb 0 0 255
|
|
|
|
, E.rgb 0 255 0
|
|
|
|
, E.rgb 255 255 0
|
|
|
|
, E.rgb 255 127 0
|
|
|
|
, E.rgb 255 0 0
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
E.none
|
|
|
|
|
|
|
|
else
|
|
|
|
E.none
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
setBadge : Bool -> E.Element msg
|
|
|
|
setBadge isFoil =
|
|
|
|
let
|
|
|
|
color =
|
|
|
|
case card.rarity of
|
|
|
|
"mythic" ->
|
|
|
|
colors.mythic
|
|
|
|
|
|
|
|
"rare" ->
|
|
|
|
colors.rare
|
|
|
|
|
|
|
|
"uncommon" ->
|
|
|
|
colors.uncommon
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
colors.common
|
|
|
|
in
|
|
|
|
badge color isFoil card.setCode
|
|
|
|
|
|
|
|
prices =
|
|
|
|
Maybe.Extra.values
|
|
|
|
[ Maybe.map (\usd -> { currency = "usd", amount = usd }) <|
|
|
|
|
Maybe.Extra.or card.prices.usd card.prices.usd_foil
|
|
|
|
, Maybe.map (\eur -> { currency = "eur", amount = eur }) <|
|
|
|
|
Maybe.Extra.or card.prices.eur card.prices.eur_foil
|
|
|
|
, Maybe.map (\tix -> { currency = "tix", amount = tix }) card.prices.tix
|
|
|
|
]
|
|
|
|
in
|
|
|
|
E.row
|
2023-01-11 02:52:02 +00:00
|
|
|
(List.append
|
|
|
|
[ E.width E.fill
|
|
|
|
, E.spacing 10
|
|
|
|
, E.padding 3
|
|
|
|
, E.mouseOver [ Background.color colors.hover ]
|
|
|
|
]
|
|
|
|
attributes
|
|
|
|
)
|
2023-01-11 02:21:33 +00:00
|
|
|
[ E.el [ E.width <| E.px 100 ] <|
|
|
|
|
E.image
|
|
|
|
[ E.height <| E.px 60
|
|
|
|
, E.centerX
|
|
|
|
]
|
|
|
|
{ src =
|
|
|
|
Url.Builder.crossOrigin "https://api.scryfall.com"
|
|
|
|
[ "cards", card.scryfallId ]
|
|
|
|
[ Url.Builder.string "format" "image"
|
|
|
|
, Url.Builder.string "version" "art_crop"
|
|
|
|
]
|
|
|
|
, description = card.name
|
|
|
|
}
|
2023-01-12 01:31:35 +00:00
|
|
|
, E.column [ E.alignTop, E.width E.fill, E.clipX ]
|
2023-01-11 22:10:48 +00:00
|
|
|
[ Symbol.text symbols 12 card.manaCost
|
|
|
|
, E.el [ Font.color colors.title ] <| E.text card.name
|
2023-01-11 02:21:33 +00:00
|
|
|
, E.el [ Font.size 16, Font.italic, Font.color colors.subtitle ] <| E.text options.subtitle
|
|
|
|
]
|
2023-01-12 01:31:35 +00:00
|
|
|
, E.column [ E.width <| E.px 70, E.alignTop, E.alignRight ] <|
|
2023-01-11 02:21:33 +00:00
|
|
|
setBadge options.foil
|
|
|
|
:: List.map priceBadge prices
|
|
|
|
]
|
2023-01-11 02:36:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
footer : E.Element msg -> E.Element msg
|
|
|
|
footer element =
|
|
|
|
E.el
|
|
|
|
[ E.height (E.px 50)
|
|
|
|
, E.width E.fill
|
|
|
|
, E.padding 10
|
|
|
|
, Font.color colors.text
|
|
|
|
, Background.color colors.navBar
|
|
|
|
, E.alignBottom
|
|
|
|
]
|
|
|
|
element
|