diff --git a/frontend/Calculator.elm b/frontend/Calculator.elm index 4d6bcbd..7d1e355 100644 --- a/frontend/Calculator.elm +++ b/frontend/Calculator.elm @@ -9,7 +9,15 @@ import Select type Tax = Net | Gross -ctShow ct = case ct of +-- Duplicated from Entry.elm but too lazy to sandwich this out +type alias TaxGroup = + { id : Int + , description : String + , percentage : Float + } + +showTax : Tax -> String +showTax tax = case tax of Gross -> "Brutto" Net -> "Netto" @@ -19,11 +27,13 @@ type alias Model = , bundleSize : NumberInput.Model Int } +init : Float -> Model init bundlePrice = Model - (Select.init ctShow ctShow Net [Net, Gross]) + (Select.init showTax showTax Net [Net, Gross]) (NumberInput.fromFloat bundlePrice) (NumberInput.fromInt 1) +getResult : Model -> TaxGroup -> Maybe Float getResult model taxGroup = case (NumberInput.get model.bundlePrice, NumberInput.get model.bundleSize) of (Just bundlePrice, Just bundleSize) -> @@ -41,6 +51,7 @@ type Msg | SetBundlePrice String | SetBundleSize String +update : Msg -> Model -> Model update msg model = case msg of SetTax key -> { model | tax = Select.update key model.tax } @@ -49,6 +60,7 @@ update msg model = case msg of SetBundleSize str -> { model | bundleSize = NumberInput.update str model.bundleSize } +view : Model -> TaxGroup -> Html Msg view model taxGroup = let mainPart = @@ -112,4 +124,5 @@ view model taxGroup = ] ] -roundTo places x = toFloat (round <| x * 10 ^ places) / 10 ^ places +roundTo : Int -> Float -> Float +roundTo places x = toFloat (round <| x * 10 ^ toFloat places) / 10 ^ toFloat places diff --git a/frontend/Entry.elm b/frontend/Entry.elm index 434f09b..55b7355 100644 --- a/frontend/Entry.elm +++ b/frontend/Entry.elm @@ -14,6 +14,50 @@ import Calculator import NumberInput import Select +{- +Elm forces us to use the Elm architecture: + + ┌──────┐ + ┌─────Model──► view ├──Html───────┐ + │ └──────┘ │ + │ │ +┌┴─────────────────────────────────▼┐ +│ Elm runtime │ +└▲─────────────────────────────────┬┘ + │ │ + │ ┌──────┐ │ + └─Model+Cmd──┤update◄──Msg+Model──┘ + └──────┘ + +This architecture is similar to what React does but its implementation +in Elm is a bit special since it's purely functional and side effects +are isolated into the runtime system. + +An Elm component is usually centered around two types, Model and Msg. +Model contains all data the application is concerned with, including the state +of UI elements. Msg encodes all updates to Model that the application supports. + +In addition to Msg and Model, we have to provide two functions, view and update. + +view : Model -> Html Msg +update : Msg -> Model -> (Model, Cmd Msg) + +view maps a Model to a DOM tree. Events in this DOM tree create Msg values. +update maps a Msg and a Model to a new Model. In addition, update can create +a command. Commands are used to make the runtime do side effects, which in +turn create new Msg values. + +For example, we have a SetSearchTerm message which simply updates the searchTerm +property in the model. This message is triggered every time the search box input +is changed. Submitting the search box form triggers a SubmitSearch event. +This event leaves the model unchanged but issues a command that sends the search +term to a JSON endpoint. When the request successfully resolves, the runtime +triggers a ReceiveSearchResults messages which updates the list of search results +in the model. + +See Calculator.elm for a simpler example of this architecture. +-} + main = Browser.element { init = \globals -> ( Context globals <| ItemSearch { searchTerm = "", searchResults = [] }