tutor/www/src/UI.elm

273 lines
7 KiB
Elm
Raw Normal View History

module UI exposing
( Dimensions
, cardRow
, colors
, getViewport
, isMobile
, manaSpinner
, priceBadge
, subtitle
2023-01-09 20:00:37 +00:00
, text
, title
)
import Browser.Dom
import Card
import Color
import Element as E
import Element.Background as Background
import Element.Border as Border
2023-01-09 20:00:37 +00:00
import Element.Font as Font
import Maybe.Extra
import Spinner
import Task
import Url.Builder
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
}
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
subtitle : String -> E.Element msg
subtitle string =
E.el [ Font.size 16, Font.italic, Font.color colors.subtitle ] <| E.text string
priceBadge : { currency : String, amount : String } -> E.Element msg
priceBadge { currency, amount } =
E.el
[ Border.rounded 5
, Border.color colors.text
, E.width <| E.px 60
, 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
]
cardRow : { foil : Bool, subtitle : String } -> List (E.Attribute msg) -> Card.Card -> E.Element msg
cardRow options attributes card =
let
badge color foil string =
E.el
([ Border.rounded 5
, Border.color color
, Border.width 1
, E.width <| E.px 60
, Font.family [ Font.typeface "sans" ]
, Font.size 10
, Font.color colors.title
, E.mouseOver [ Background.color colors.hover ]
]
++ attributes
)
<|
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
[ E.width E.fill
, E.spacing 10
, E.padding 3
]
[ 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
}
, E.column [ E.centerY, E.height E.fill, E.width E.fill, E.clipX ]
[ E.el [ Font.color colors.title ] <| E.text card.name
, E.el [ Font.size 16, Font.italic, Font.color colors.subtitle ] <| E.text options.subtitle
]
, E.column [ E.alignRight, E.height E.fill ] <|
setBadge options.foil
:: List.map priceBadge prices
]