import Html exposing (Html, Attribute, div, h1, input, p, text)
import Html.Attributes exposing (checked, style, type_)
import Html.Events exposing (onClick)
import Html.Lazy exposing (lazy)
import Table exposing (defaultCustomizations)
import Time exposing (Time)
main =
Html.program
{ init = init missionSights
, update = update
, view = view
, subscriptions = \_ -> Sub.none
}
-- MODEL
type alias Model =
{ sights : List Sight
, tableState : Table.State
}
init : List Sight -> ( Model, Cmd Msg )
init sights =
let
model =
{ sights = sights
, tableState = Table.initialSort "Year"
}
in
( model, Cmd.none )
-- UPDATE
type Msg
= ToggleSelected String
| SetTableState Table.State
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ToggleSelected name ->
( { model | sights = List.map (toggle name) model.sights }
, Cmd.none
)
SetTableState newState ->
( { model | tableState = newState }
, Cmd.none
)
toggle : String -> Sight -> Sight
toggle name sight =
if sight.name == name then
{ sight | selected = not sight.selected }
else
sight
-- VIEW
view : Model -> Html Msg
view { sights, tableState } =
div []
[ h1 [] [ text "Trip Planner" ]
, lazy viewSummary sights
, Table.view config tableState sights
]
viewSummary : List Sight -> Html msg
viewSummary allSights =
case List.filter .selected allSights of
[] ->
p [] [ text "Click the sights you want to see on your trip!" ]
sights ->
let
time =
List.sum (List.map .time sights)
price =
List.sum (List.map .price sights)
summary =
"That is " ++ timeToString time ++ " of fun, costing $" ++ toString price
in
p [] [ text summary ]
timeToString : Time -> String
timeToString time =
let
hours =
case floor (Time.inHours time) of
0 -> ""
1 -> "1 hour"
n -> toString n ++ " hours"
minutes =
case rem (round (Time.inMinutes time)) 60 of
0 -> ""
1 -> "1 minute"
n -> toString n ++ " minutes"
in
hours ++ " " ++ minutes
-- TABLE CONFIGURATION
config : Table.Config Sight Msg
config =
Table.customConfig
{ toId = .name
, toMsg = SetTableState
, columns =
[ checkboxColumn
, Table.stringColumn "Name" .name
, timeColumn
, Table.floatColumn "Price" .price
, Table.floatColumn "Rating" .rating
]
, customizations =
{ defaultCustomizations | rowAttrs = toRowAttrs }
}
toRowAttrs : Sight -> List (Attribute Msg)
toRowAttrs sight =
[ onClick (ToggleSelected sight.name)
, style [ ("background", if sight.selected then "#CEFAF8" else "white") ]
]
timeColumn : Table.Column Sight Msg
timeColumn =
Table.customColumn
{ name = "Time"
, viewData = timeToString << .time
, sorter = Table.increasingOrDecreasingBy .time
}
checkboxColumn : Table.Column Sight Msg
checkboxColumn =
Table.veryCustomColumn
{ name = ""
, viewData = viewCheckbox
, sorter = Table.unsortable
}
viewCheckbox : Sight -> Table.HtmlDetails Msg
viewCheckbox {selected} =
Table.HtmlDetails []
[ input [ type_ "checkbox", checked selected ] []
]
-- SIGHTS
type alias Sight =
{ name : String
, time : Time
, price : Float
, rating : Float
, selected : Bool
}
missionSights : List Sight
missionSights =
[ Sight "Eat a Burrito" (30 * Time.minute) 7 4.6 False
, Sight "Buy drugs in Dolores park" Time.hour 20 4.8 False
, Sight "Armory Tour" (1.5 * Time.hour) 27 4.5 False
, Sight "Tartine Bakery" Time.hour 10 4.1 False
, Sight "Have Brunch" (2 * Time.hour) 25 4.2 False
, Sight "Get catcalled at BART" (5 * Time.minute) 0 1.6 False
, Sight "Buy a painting at \"Stuff\"" (45 * Time.minute) 400 4.7 False
, Sight "McDonalds at 24th" (20 * Time.minute) 5 2.8 False
]