elm-sortable-table/examples/2-travel.elm

201 lines
3.9 KiB
Elm

import Html exposing (Html, Attribute, div, h1, input, p, text)
import Html.App as App
import Html.Attributes exposing (checked, style, type')
import Html.Events exposing (onClick)
import Html.Lazy exposing (lazy)
import String
import Table exposing (defaultCustomizations)
import Time exposing (Time)
main =
App.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
]