From 4715a758a3c3d7305ea411ece68d1f8592a7e2e0 Mon Sep 17 00:00:00 2001 From: Paul Brinkmeier Date: Sat, 19 Aug 2023 05:55:27 +0200 Subject: [PATCH] Refactor fronted somewhat --- frontend/Entry.elm | 203 ++++---- frontend/NumberInput.elm | 25 + frontend/Select.elm | 36 ++ jon/static/entry.js | 1031 ++++++++++++++++++++------------------ 4 files changed, 711 insertions(+), 584 deletions(-) create mode 100644 frontend/NumberInput.elm create mode 100644 frontend/Select.elm diff --git a/frontend/Entry.elm b/frontend/Entry.elm index 300da94..34358b2 100644 --- a/frontend/Entry.elm +++ b/frontend/Entry.elm @@ -10,6 +10,9 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (..) +import NumberInput +import Select + main = Browser.element { init = \globals -> ( Context globals <| ItemSearch { searchTerm = "", searchResults = [] } @@ -85,11 +88,12 @@ type State | ItemEditor { barcode : String , name : String - , salesUnits : Int - , netUnitPrice : Float - , groupId : Int - , locationId : Int - , taxGroupId : Int + , salesUnits : NumberInput.Model Int + , netUnitPrice : NumberInput.Model Float + , grossUnitPrice : NumberInput.Model Float + , group : Select.Model Group + , location : Select.Model Location + , taxGroup : Select.Model TaxGroup } type Msg @@ -97,13 +101,14 @@ type Msg | SubmitSearch | ReceiveSearchResults (Result Http.Error (List SearchResult)) | GotoItemEditor SearchResult - | SetNetUnitPrice String - | SetGroupId String - | SetLocationId String - | SetTaxGroupId String | SetBarcode String | SetName String | SetSalesUnits String + | SetNetUnitPrice String + | SetGrossUnitPrice String + | SetGroup String + | SetLocation String + | SetTaxGroup String -- Update logic: State machine etc. @@ -127,42 +132,52 @@ updateState msg globals state = case state of ReceiveSearchResults (Ok searchResults) -> (ItemSearch { model | searchResults = searchResults }, Cmd.none) GotoItemEditor searchResult -> - ( ItemEditor - { barcode = searchResult.barcode - , groupId = searchResult.groupId - , locationId = searchResult.locationId - , name = searchResult.name - , netUnitPrice = searchResult.netUnitPrice - , salesUnits = searchResult.salesUnits - , taxGroupId = searchResult.taxGroupId - } - , Cmd.none - ) + case find (\tg -> tg.id == searchResult.taxGroupId) globals.taxGroups of + Nothing -> (state, Cmd.none) + Just taxGroup -> + ( ItemEditor + { barcode = searchResult.barcode + , name = searchResult.name + , netUnitPrice = NumberInput.fromFloat searchResult.netUnitPrice + , grossUnitPrice = NumberInput.fromFloat <| calculateGarfieldPrice searchResult.netUnitPrice taxGroup.percentage + , salesUnits = NumberInput.fromInt searchResult.salesUnits + , group = Select.init (.id >> String.fromInt) (.name) { id = searchResult.groupId, name = searchResult.groupName } globals.groups + , location = Select.init (.id >> String.fromInt) (.name) { id = searchResult.locationId, name = searchResult.locationName } globals.locations + , taxGroup = Select.init (.id >> String.fromInt) (.description) taxGroup globals.taxGroups + } + , Cmd.none + ) _ -> (state, Cmd.none) ItemEditor model -> case msg of - SetNetUnitPrice netUnitPriceStr -> case String.toFloat netUnitPriceStr of - Nothing -> (state, Cmd.none) - Just netUnitPrice -> (ItemEditor { model | netUnitPrice = netUnitPrice }, Cmd.none) - SetGroupId groupIdStr -> case String.toInt groupIdStr of - Nothing -> (state, Cmd.none) - Just groupId -> (ItemEditor { model | groupId = groupId }, Cmd.none) - SetLocationId locationIdStr -> case String.toInt locationIdStr of - Nothing -> (state, Cmd.none) - Just locationId -> (ItemEditor { model | locationId = locationId }, Cmd.none) - SetTaxGroupId taxGroupIdStr -> case String.toInt taxGroupIdStr of - Nothing -> (state, Cmd.none) - Just taxGroupId -> (ItemEditor { model | taxGroupId = taxGroupId }, Cmd.none) SetBarcode barcode -> (ItemEditor { model | barcode = barcode }, Cmd.none) SetName name -> (ItemEditor { model | name = name }, Cmd.none) - SetSalesUnits salesUnitsStr -> case String.toInt salesUnitsStr of - Nothing -> (state, Cmd.none) - Just salesUnits -> (ItemEditor { model | salesUnits = salesUnits }, Cmd.none) + SetSalesUnits str -> + (ItemEditor { model | salesUnits = NumberInput.update str model.salesUnits }, Cmd.none) + SetNetUnitPrice str -> + ( ItemEditor <| updateGrossUnitPrice { model | netUnitPrice = NumberInput.update str model.netUnitPrice } + , Cmd.none + ) + SetGrossUnitPrice str -> + (ItemEditor { model | grossUnitPrice = NumberInput.update str model.grossUnitPrice }, Cmd.none) + SetGroup key -> + (ItemEditor { model | group = Select.update key model.group }, Cmd.none) + SetLocation key -> + (ItemEditor { model | location = Select.update key model.location }, Cmd.none) + SetTaxGroup key -> + ( ItemEditor <| updateGrossUnitPrice { model | taxGroup = Select.update key model.taxGroup } + , Cmd.none + ) _ -> (state, Cmd.none) +updateGrossUnitPrice model = + { model + | grossUnitPrice = NumberInput.fromFloat <| calculateGarfieldPrice (NumberInput.get model.netUnitPrice) (Select.get model.taxGroup).percentage + } + -- View stuff view { globals, state } = case state of @@ -177,80 +192,60 @@ view { globals, state } = case state of , table [] <| searchResultHeaders :: List.map viewSearchResult model.searchResults ] ] - ItemEditor model -> case find (\tg -> tg.id == model.taxGroupId) globals.taxGroups of - Nothing -> div [] [ text "index error, this should never happen" ] - Just selectedTaxGroup -> - Html.form [] - [ fieldset [] - [ legend [] [ text "Neuer Inventareintrag" ] - , div [ class "form-input" ] - [ label [ for "barcode" ] [ text "Barcode" ] - , input [ onInput SetBarcode, value model.barcode, disabled True, id "barcode" ] [] - ] - , div [ class "form-input" ] - [ label [ for "name" ] [ text "Name" ] - , input [ onInput SetName, value model.name, id "name" ] [] - ] - , div [ class "form-input" ] - [ label [ for "sales-units" ] [ text "Stückzahl" ] - , input [ onInput SetSalesUnits, value <| String.fromInt model.salesUnits, id "sales-units", type_ "number" ] [] - ] - , div [ class "form-input" ] - [ label [ for "group" ] [ text "Gruppe" ] - , viewSelect - [ onInput SetGroupId, id "group" ] - String.fromInt .id .name model.groupId globals.groups - ] - , div [ class "form-input" ] - [ label [ for "location" ] [ text "Raum" ] - , viewSelect - [ onInput SetLocationId, id "location" ] - String.fromInt .id .name model.locationId globals.locations - ] - , div [ class "form-input" ] - [ label [ for "net-unit-price" ] [ text "Stückpreis (Netto)" ] - , input - [ value <| String.fromFloat model.netUnitPrice - , onInput SetNetUnitPrice - , type_ "number" - , id "net-unit-price" - , step "0.01" - ] - [] - ] - , div [ class "form-input" ] - [ label [ for "tax-group" ] [ text "Steuergruppe" ] - , viewSelect - [ onInput SetTaxGroupId, id "tax-group" ] - String.fromInt .id .description model.taxGroupId globals.taxGroups - ] + ItemEditor model -> + Html.form [] + [ fieldset [] + [ legend [] [ text "Neuer Inventareintrag" ] + , div [ class "form-input" ] + [ label [ for "barcode" ] [ text "Barcode" ] + , input [ onInput SetBarcode, value model.barcode, disabled True, id "barcode" ] [] ] - , fieldset [] - [ legend [] [ text "Neuer Snackeintrag" ] - , div [ class "form-input" ] - [ label [ for "snack-name" ] [ text "Name" ] - , input [ value model.name, disabled True, id "snack-name" ] [] - ] - , div [ class "form-input" ] - [ label [ for "gross-unit-price" ] - [ text <| "Stückpreis (Brutto), Vorschlag: " ++ String.fromFloat (calculateGarfieldPrice model.netUnitPrice selectedTaxGroup.percentage) - ] - , input [ value <| String.fromFloat <| Maybe.withDefault (calculateGarfieldPrice model.netUnitPrice selectedTaxGroup.percentage) Nothing, id "gross-unit-price", type_ "number", step "0.01" ] [] + , div [ class "form-input" ] + [ label [ for "name" ] [ text "Name" ] + , input [ onInput SetName, value model.name, id "name" ] [] + ] + , div [ class "form-input" ] + [ label [ for "sales-units" ] [ text "Stückzahl" ] + , input [ onInput SetSalesUnits, value <| NumberInput.show model.salesUnits, id "sales-units", type_ "number" ] [] + ] + , div [ class "form-input" ] + [ label [ for "group" ] [ text "Gruppe" ] + , Select.view SetGroup model.group + ] + , div [ class "form-input" ] + [ label [ for "location" ] [ text "Raum" ] + , Select.view SetLocation model.location + ] + , div [ class "form-input" ] + [ label [ for "net-unit-price" ] [ text "Stückpreis (Netto)" ] + , input + [ value <| NumberInput.show model.netUnitPrice + , onInput SetNetUnitPrice + , type_ "number" + , id "net-unit-price" + , step "0.01" ] + [] + ] + , div [ class "form-input" ] + [ label [ for "tax-group" ] [ text "Steuergruppe" ] + , Select.view SetTaxGroup model.taxGroup ] ] - -viewSelect selectAttributes showValue getValue getLabel selectedValue xs = - let - viewOption x = - option - [ value <| showValue <| getValue x - , selected <| getValue x == selectedValue + , fieldset [] + [ legend [] [ text "Neuer Snackeintrag" ] + , div [ class "form-input" ] + [ label [ for "snack-name" ] [ text "Name" ] + , input [ value model.name, disabled True, id "snack-name" ] [] + ] + , div [ class "form-input" ] + [ label [ for "gross-unit-price" ] + [ text <| "Stückpreis (Brutto), Vorschlag: " ++ String.fromFloat (calculateGarfieldPrice (NumberInput.get model.netUnitPrice) (Select.get model.taxGroup).percentage) + ] + , input [ onInput SetGrossUnitPrice, value <| NumberInput.show model.grossUnitPrice, id "gross-unit-price", type_ "number", step "0.01" ] [] + ] ] - [ text <| getLabel x - ] - in - select selectAttributes <| List.map viewOption xs + ] searchResultHeaders = tr [] diff --git a/frontend/NumberInput.elm b/frontend/NumberInput.elm new file mode 100644 index 0000000..6ffab83 --- /dev/null +++ b/frontend/NumberInput.elm @@ -0,0 +1,25 @@ +module NumberInput exposing (..) + +type alias Model a = + { value : a + , original : String + , convert : String -> Maybe a + } + +fromFloat : Float -> Model Float +fromFloat x = Model x (String.fromFloat x) String.toFloat + +fromInt : Int -> Model Int +fromInt x = Model x (String.fromInt x) String.toInt + +get : Model a -> a +get = .value + +update : String -> Model a -> Model a +update str model = + case model.convert str of + Nothing -> model + Just value -> { model | value = value, original = str } + +show : Model a -> String +show = .original diff --git a/frontend/Select.elm b/frontend/Select.elm new file mode 100644 index 0000000..495f86d --- /dev/null +++ b/frontend/Select.elm @@ -0,0 +1,36 @@ +module Select exposing (..) + +import Html exposing (Html, option, select, text) +import Html.Attributes exposing (selected, value) +import Html.Events exposing (onInput) + +type alias Model a = + { identify : a -> String + , show : a -> String + , selected : a + , options : List a + } + +init : (a -> String) -> (a -> String) -> a -> List a -> Model a +init = Model + +update : String -> Model a -> Model a +update key model = + case find (\x -> key == model.identify x) model.options of + Nothing -> model + Just x -> { model | selected = x } + +view : (String -> m) -> Model a -> Html m +view msg model = + let + viewOption x = + option + [ selected <| model.identify model.selected == model.identify x, value <| model.identify x ] + [ text <| model.show x ] + in + select [ onInput msg ] <| List.map viewOption model.options + +get : Model a -> a +get = .selected + +find pred xs = List.head <| List.filter pred xs diff --git a/jon/static/entry.js b/jon/static/entry.js index 3538c73..696f436 100644 --- a/jon/static/entry.js +++ b/jon/static/entry.js @@ -10745,6 +10745,17 @@ var $author$project$Entry$ItemEditor = function (a) { var $author$project$Entry$ReceiveSearchResults = function (a) { return {$: 'ReceiveSearchResults', a: a}; }; +var $elm$core$Basics$pow = _Basics_pow; +var $elm$core$Basics$round = _Basics_round; +var $author$project$Entry$roundTo = F2( + function (places, x) { + return $elm$core$Basics$round( + x * A2($elm$core$Basics$pow, 10, places)) / A2($elm$core$Basics$pow, 10, places); + }); +var $author$project$Entry$calculateGarfieldPrice = F2( + function (netUnitPrice, taxPercentage) { + return A2($author$project$Entry$roundTo, 2, (netUnitPrice * (1 + taxPercentage)) + 0.01); + }); var $elm$http$Http$BadStatus_ = F2( function (a, b) { return {$: 'BadStatus_', a: a, b: b}; @@ -10838,6 +10849,50 @@ var $elm$http$Http$expectJson = F2( A2($elm$json$Json$Decode$decodeString, decoder, string)); })); }); +var $elm$core$List$filter = F2( + function (isGood, list) { + return A3( + $elm$core$List$foldr, + F2( + function (x, xs) { + return isGood(x) ? A2($elm$core$List$cons, x, xs) : xs; + }), + _List_Nil, + list); + }); +var $elm$core$List$head = function (list) { + if (list.b) { + var x = list.a; + var xs = list.b; + return $elm$core$Maybe$Just(x); + } else { + return $elm$core$Maybe$Nothing; + } +}; +var $author$project$Entry$find = F2( + function (pred, xs) { + return $elm$core$List$head( + A2($elm$core$List$filter, pred, xs)); + }); +var $author$project$NumberInput$Model = F3( + function (value, original, convert) { + return {convert: convert, original: original, value: value}; + }); +var $elm$core$String$toFloat = _String_toFloat; +var $author$project$NumberInput$fromFloat = function (x) { + return A3( + $author$project$NumberInput$Model, + x, + $elm$core$String$fromFloat(x), + $elm$core$String$toFloat); +}; +var $author$project$NumberInput$fromInt = function (x) { + return A3( + $author$project$NumberInput$Model, + x, + $elm$core$String$fromInt(x), + $elm$core$String$toInt); +}; var $elm$http$Http$emptyBody = _Http_emptyBody; var $elm$http$Http$Request = function (a) { return {$: 'Request', a: a}; @@ -10993,6 +11048,11 @@ var $elm$http$Http$get = function (r) { return $elm$http$Http$request( {body: $elm$http$Http$emptyBody, expect: r.expect, headers: _List_Nil, method: 'GET', timeout: $elm$core$Maybe$Nothing, tracker: $elm$core$Maybe$Nothing, url: r.url}); }; +var $author$project$Select$Model = F4( + function (identify, show, selected, options) { + return {identify: identify, options: options, selected: selected, show: show}; + }); +var $author$project$Select$init = $author$project$Select$Model; var $author$project$Entry$SearchResult = function (barcode) { return function (name) { return function (netUnitPrice) { @@ -11070,7 +11130,59 @@ var $author$project$Entry$searchResultDecoder = A3( 'item_barcode', $elm$json$Json$Decode$string, $elm$json$Json$Decode$succeed($author$project$Entry$SearchResult)))))))))))); -var $elm$core$String$toFloat = _String_toFloat; +var $author$project$NumberInput$update = F2( + function (str, model) { + var _v0 = model.convert(str); + if (_v0.$ === 'Nothing') { + return model; + } else { + var value = _v0.a; + return _Utils_update( + model, + {original: str, value: value}); + } + }); +var $author$project$Select$find = F2( + function (pred, xs) { + return $elm$core$List$head( + A2($elm$core$List$filter, pred, xs)); + }); +var $author$project$Select$update = F2( + function (key, model) { + var _v0 = A2( + $author$project$Select$find, + function (x) { + return _Utils_eq( + key, + model.identify(x)); + }, + model.options); + if (_v0.$ === 'Nothing') { + return model; + } else { + var x = _v0.a; + return _Utils_update( + model, + {selected: x}); + } + }); +var $author$project$NumberInput$get = function ($) { + return $.value; +}; +var $author$project$Select$get = function ($) { + return $.selected; +}; +var $author$project$Entry$updateGrossUnitPrice = function (model) { + return _Utils_update( + model, + { + grossUnitPrice: $author$project$NumberInput$fromFloat( + A2( + $author$project$Entry$calculateGarfieldPrice, + $author$project$NumberInput$get(model.netUnitPrice), + $author$project$Select$get(model.taxGroup).percentage)) + }); +}; var $author$project$Entry$updateState = F3( function (msg, globals, state) { if (state.$ === 'ItemSearch') { @@ -11111,10 +11223,67 @@ var $author$project$Entry$updateState = F3( } case 'GotoItemEditor': var searchResult = msg.a; - return _Utils_Tuple2( - $author$project$Entry$ItemEditor( - {barcode: searchResult.barcode, groupId: searchResult.groupId, locationId: searchResult.locationId, name: searchResult.name, netUnitPrice: searchResult.netUnitPrice, salesUnits: searchResult.salesUnits, taxGroupId: searchResult.taxGroupId}), - $elm$core$Platform$Cmd$none); + var _v2 = A2( + $author$project$Entry$find, + function (tg) { + return _Utils_eq(tg.id, searchResult.taxGroupId); + }, + globals.taxGroups); + if (_v2.$ === 'Nothing') { + return _Utils_Tuple2(state, $elm$core$Platform$Cmd$none); + } else { + var taxGroup = _v2.a; + return _Utils_Tuple2( + $author$project$Entry$ItemEditor( + { + barcode: searchResult.barcode, + grossUnitPrice: $author$project$NumberInput$fromFloat( + A2($author$project$Entry$calculateGarfieldPrice, searchResult.netUnitPrice, taxGroup.percentage)), + group: A4( + $author$project$Select$init, + A2( + $elm$core$Basics$composeR, + function ($) { + return $.id; + }, + $elm$core$String$fromInt), + function ($) { + return $.name; + }, + {id: searchResult.groupId, name: searchResult.groupName}, + globals.groups), + location: A4( + $author$project$Select$init, + A2( + $elm$core$Basics$composeR, + function ($) { + return $.id; + }, + $elm$core$String$fromInt), + function ($) { + return $.name; + }, + {id: searchResult.locationId, name: searchResult.locationName}, + globals.locations), + name: searchResult.name, + netUnitPrice: $author$project$NumberInput$fromFloat(searchResult.netUnitPrice), + salesUnits: $author$project$NumberInput$fromInt(searchResult.salesUnits), + taxGroup: A4( + $author$project$Select$init, + A2( + $elm$core$Basics$composeR, + function ($) { + return $.id; + }, + $elm$core$String$fromInt), + function ($) { + return $.description; + }, + taxGroup, + globals.taxGroups) + }), + $elm$core$Platform$Cmd$none); + } default: break _v1$4; } @@ -11123,62 +11292,6 @@ var $author$project$Entry$updateState = F3( } else { var model = state.a; switch (msg.$) { - case 'SetNetUnitPrice': - var netUnitPriceStr = msg.a; - var _v3 = $elm$core$String$toFloat(netUnitPriceStr); - if (_v3.$ === 'Nothing') { - return _Utils_Tuple2(state, $elm$core$Platform$Cmd$none); - } else { - var netUnitPrice = _v3.a; - return _Utils_Tuple2( - $author$project$Entry$ItemEditor( - _Utils_update( - model, - {netUnitPrice: netUnitPrice})), - $elm$core$Platform$Cmd$none); - } - case 'SetGroupId': - var groupIdStr = msg.a; - var _v4 = $elm$core$String$toInt(groupIdStr); - if (_v4.$ === 'Nothing') { - return _Utils_Tuple2(state, $elm$core$Platform$Cmd$none); - } else { - var groupId = _v4.a; - return _Utils_Tuple2( - $author$project$Entry$ItemEditor( - _Utils_update( - model, - {groupId: groupId})), - $elm$core$Platform$Cmd$none); - } - case 'SetLocationId': - var locationIdStr = msg.a; - var _v5 = $elm$core$String$toInt(locationIdStr); - if (_v5.$ === 'Nothing') { - return _Utils_Tuple2(state, $elm$core$Platform$Cmd$none); - } else { - var locationId = _v5.a; - return _Utils_Tuple2( - $author$project$Entry$ItemEditor( - _Utils_update( - model, - {locationId: locationId})), - $elm$core$Platform$Cmd$none); - } - case 'SetTaxGroupId': - var taxGroupIdStr = msg.a; - var _v6 = $elm$core$String$toInt(taxGroupIdStr); - if (_v6.$ === 'Nothing') { - return _Utils_Tuple2(state, $elm$core$Platform$Cmd$none); - } else { - var taxGroupId = _v6.a; - return _Utils_Tuple2( - $author$project$Entry$ItemEditor( - _Utils_update( - model, - {taxGroupId: taxGroupId})), - $elm$core$Platform$Cmd$none); - } case 'SetBarcode': var barcode = msg.a; return _Utils_Tuple2( @@ -11196,19 +11309,67 @@ var $author$project$Entry$updateState = F3( {name: name})), $elm$core$Platform$Cmd$none); case 'SetSalesUnits': - var salesUnitsStr = msg.a; - var _v7 = $elm$core$String$toInt(salesUnitsStr); - if (_v7.$ === 'Nothing') { - return _Utils_Tuple2(state, $elm$core$Platform$Cmd$none); - } else { - var salesUnits = _v7.a; - return _Utils_Tuple2( - $author$project$Entry$ItemEditor( + var str = msg.a; + return _Utils_Tuple2( + $author$project$Entry$ItemEditor( + _Utils_update( + model, + { + salesUnits: A2($author$project$NumberInput$update, str, model.salesUnits) + })), + $elm$core$Platform$Cmd$none); + case 'SetNetUnitPrice': + var str = msg.a; + return _Utils_Tuple2( + $author$project$Entry$ItemEditor( + $author$project$Entry$updateGrossUnitPrice( _Utils_update( model, - {salesUnits: salesUnits})), - $elm$core$Platform$Cmd$none); - } + { + netUnitPrice: A2($author$project$NumberInput$update, str, model.netUnitPrice) + }))), + $elm$core$Platform$Cmd$none); + case 'SetGrossUnitPrice': + var str = msg.a; + return _Utils_Tuple2( + $author$project$Entry$ItemEditor( + _Utils_update( + model, + { + grossUnitPrice: A2($author$project$NumberInput$update, str, model.grossUnitPrice) + })), + $elm$core$Platform$Cmd$none); + case 'SetGroup': + var key = msg.a; + return _Utils_Tuple2( + $author$project$Entry$ItemEditor( + _Utils_update( + model, + { + group: A2($author$project$Select$update, key, model.group) + })), + $elm$core$Platform$Cmd$none); + case 'SetLocation': + var key = msg.a; + return _Utils_Tuple2( + $author$project$Entry$ItemEditor( + _Utils_update( + model, + { + location: A2($author$project$Select$update, key, model.location) + })), + $elm$core$Platform$Cmd$none); + case 'SetTaxGroup': + var key = msg.a; + return _Utils_Tuple2( + $author$project$Entry$ItemEditor( + $author$project$Entry$updateGrossUnitPrice( + _Utils_update( + model, + { + taxGroup: A2($author$project$Select$update, key, model.taxGroup) + }))), + $elm$core$Platform$Cmd$none); default: return _Utils_Tuple2(state, $elm$core$Platform$Cmd$none); } @@ -11228,11 +11389,14 @@ var $author$project$Entry$update = F2( var $author$project$Entry$SetBarcode = function (a) { return {$: 'SetBarcode', a: a}; }; -var $author$project$Entry$SetGroupId = function (a) { - return {$: 'SetGroupId', a: a}; +var $author$project$Entry$SetGrossUnitPrice = function (a) { + return {$: 'SetGrossUnitPrice', a: a}; }; -var $author$project$Entry$SetLocationId = function (a) { - return {$: 'SetLocationId', a: a}; +var $author$project$Entry$SetGroup = function (a) { + return {$: 'SetGroup', a: a}; +}; +var $author$project$Entry$SetLocation = function (a) { + return {$: 'SetLocation', a: a}; }; var $author$project$Entry$SetName = function (a) { return {$: 'SetName', a: a}; @@ -11246,21 +11410,10 @@ var $author$project$Entry$SetSalesUnits = function (a) { var $author$project$Entry$SetSearchTerm = function (a) { return {$: 'SetSearchTerm', a: a}; }; -var $author$project$Entry$SetTaxGroupId = function (a) { - return {$: 'SetTaxGroupId', a: a}; +var $author$project$Entry$SetTaxGroup = function (a) { + return {$: 'SetTaxGroup', a: a}; }; var $author$project$Entry$SubmitSearch = {$: 'SubmitSearch'}; -var $elm$core$Basics$pow = _Basics_pow; -var $elm$core$Basics$round = _Basics_round; -var $author$project$Entry$roundTo = F2( - function (places, x) { - return $elm$core$Basics$round( - x * A2($elm$core$Basics$pow, 10, places)) / A2($elm$core$Basics$pow, 10, places); - }); -var $author$project$Entry$calculateGarfieldPrice = F2( - function (netUnitPrice, taxPercentage) { - return A2($author$project$Entry$roundTo, 2, (netUnitPrice * (1 + taxPercentage)) + 0.01); - }); var $elm$json$Json$Encode$bool = _Json_wrap; var $elm$html$Html$Attributes$boolProperty = F2( function (key, bool) { @@ -11271,31 +11424,6 @@ var $elm$html$Html$Attributes$boolProperty = F2( }); var $elm$html$Html$Attributes$disabled = $elm$html$Html$Attributes$boolProperty('disabled'); var $elm$html$Html$fieldset = _VirtualDom_node('fieldset'); -var $elm$core$List$filter = F2( - function (isGood, list) { - return A3( - $elm$core$List$foldr, - F2( - function (x, xs) { - return isGood(x) ? A2($elm$core$List$cons, x, xs) : xs; - }), - _List_Nil, - list); - }); -var $elm$core$List$head = function (list) { - if (list.b) { - var x = list.a; - var xs = list.b; - return $elm$core$Maybe$Just(x); - } else { - return $elm$core$Maybe$Nothing; - } -}; -var $author$project$Entry$find = F2( - function (pred, xs) { - return $elm$core$List$head( - A2($elm$core$List$filter, pred, xs)); - }); var $elm$html$Html$Attributes$for = $elm$html$Html$Attributes$stringProperty('htmlFor'); var $elm$html$Html$form = _VirtualDom_node('form'); var $elm$html$Html$label = _VirtualDom_node('label'); @@ -11387,10 +11515,44 @@ var $author$project$Entry$searchResultHeaders = A2( ])), A2($elm$html$Html$th, _List_Nil, _List_Nil) ])); +var $author$project$NumberInput$show = function ($) { + return $.original; +}; var $elm$html$Html$Attributes$step = function (n) { return A2($elm$html$Html$Attributes$stringProperty, 'step', n); }; var $elm$html$Html$table = _VirtualDom_node('table'); +var $elm$html$Html$option = _VirtualDom_node('option'); +var $elm$html$Html$select = _VirtualDom_node('select'); +var $elm$html$Html$Attributes$selected = $elm$html$Html$Attributes$boolProperty('selected'); +var $author$project$Select$view = F2( + function (msg, model) { + var viewOption = function (x) { + return A2( + $elm$html$Html$option, + _List_fromArray( + [ + $elm$html$Html$Attributes$selected( + _Utils_eq( + model.identify(model.selected), + model.identify(x))), + $elm$html$Html$Attributes$value( + model.identify(x)) + ]), + _List_fromArray( + [ + $elm$html$Html$text( + model.show(x)) + ])); + }; + return A2( + $elm$html$Html$select, + _List_fromArray( + [ + $elm$html$Html$Events$onInput(msg) + ]), + A2($elm$core$List$map, viewOption, model.options)); + }); var $author$project$Entry$GotoItemEditor = function (a) { return {$: 'GotoItemEditor', a: a}; }; @@ -11492,35 +11654,6 @@ var $author$project$Entry$viewSearchResult = function (model) { ])) ])); }; -var $elm$html$Html$option = _VirtualDom_node('option'); -var $elm$html$Html$select = _VirtualDom_node('select'); -var $elm$html$Html$Attributes$selected = $elm$html$Html$Attributes$boolProperty('selected'); -var $author$project$Entry$viewSelect = F6( - function (selectAttributes, showValue, getValue, getLabel, selectedValue, xs) { - var viewOption = function (x) { - return A2( - $elm$html$Html$option, - _List_fromArray( - [ - $elm$html$Html$Attributes$value( - showValue( - getValue(x))), - $elm$html$Html$Attributes$selected( - _Utils_eq( - getValue(x), - selectedValue)) - ]), - _List_fromArray( - [ - $elm$html$Html$text( - getLabel(x)) - ])); - }; - return A2( - $elm$html$Html$select, - selectAttributes, - A2($elm$core$List$map, viewOption, xs)); - }); var $author$project$Entry$view = function (_v0) { var globals = _v0.globals; var state = _v0.state; @@ -11586,342 +11719,280 @@ var $author$project$Entry$view = function (_v0) { ])); } else { var model = state.a; - var _v2 = A2( - $author$project$Entry$find, - function (tg) { - return _Utils_eq(tg.id, model.taxGroupId); - }, - globals.taxGroups); - if (_v2.$ === 'Nothing') { - return A2( - $elm$html$Html$div, - _List_Nil, - _List_fromArray( - [ - $elm$html$Html$text('index error, this should never happen') - ])); - } else { - var selectedTaxGroup = _v2.a; - return A2( - $elm$html$Html$form, - _List_Nil, - _List_fromArray( - [ - A2( - $elm$html$Html$fieldset, - _List_Nil, - _List_fromArray( - [ - A2( - $elm$html$Html$legend, - _List_Nil, - _List_fromArray( - [ - $elm$html$Html$text('Neuer Inventareintrag') - ])), - A2( - $elm$html$Html$div, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('form-input') - ]), - _List_fromArray( - [ - A2( - $elm$html$Html$label, - _List_fromArray( - [ - $elm$html$Html$Attributes$for('barcode') - ]), - _List_fromArray( - [ - $elm$html$Html$text('Barcode') - ])), - A2( - $elm$html$Html$input, - _List_fromArray( - [ - $elm$html$Html$Events$onInput($author$project$Entry$SetBarcode), - $elm$html$Html$Attributes$value(model.barcode), - $elm$html$Html$Attributes$disabled(true), - $elm$html$Html$Attributes$id('barcode') - ]), - _List_Nil) - ])), - A2( - $elm$html$Html$div, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('form-input') - ]), - _List_fromArray( - [ - A2( - $elm$html$Html$label, - _List_fromArray( - [ - $elm$html$Html$Attributes$for('name') - ]), - _List_fromArray( - [ - $elm$html$Html$text('Name') - ])), - A2( - $elm$html$Html$input, - _List_fromArray( - [ - $elm$html$Html$Events$onInput($author$project$Entry$SetName), - $elm$html$Html$Attributes$value(model.name), - $elm$html$Html$Attributes$id('name') - ]), - _List_Nil) - ])), - A2( - $elm$html$Html$div, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('form-input') - ]), - _List_fromArray( - [ - A2( - $elm$html$Html$label, - _List_fromArray( - [ - $elm$html$Html$Attributes$for('sales-units') - ]), - _List_fromArray( - [ - $elm$html$Html$text('Stückzahl') - ])), - A2( - $elm$html$Html$input, - _List_fromArray( - [ - $elm$html$Html$Events$onInput($author$project$Entry$SetSalesUnits), - $elm$html$Html$Attributes$value( - $elm$core$String$fromInt(model.salesUnits)), - $elm$html$Html$Attributes$id('sales-units'), - $elm$html$Html$Attributes$type_('number') - ]), - _List_Nil) - ])), - A2( - $elm$html$Html$div, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('form-input') - ]), - _List_fromArray( - [ - A2( - $elm$html$Html$label, - _List_fromArray( - [ - $elm$html$Html$Attributes$for('group') - ]), - _List_fromArray( - [ - $elm$html$Html$text('Gruppe') - ])), - A6( - $author$project$Entry$viewSelect, - _List_fromArray( - [ - $elm$html$Html$Events$onInput($author$project$Entry$SetGroupId), - $elm$html$Html$Attributes$id('group') - ]), - $elm$core$String$fromInt, - function ($) { - return $.id; - }, - function ($) { - return $.name; - }, - model.groupId, - globals.groups) - ])), - A2( - $elm$html$Html$div, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('form-input') - ]), - _List_fromArray( - [ - A2( - $elm$html$Html$label, - _List_fromArray( - [ - $elm$html$Html$Attributes$for('location') - ]), - _List_fromArray( - [ - $elm$html$Html$text('Raum') - ])), - A6( - $author$project$Entry$viewSelect, - _List_fromArray( - [ - $elm$html$Html$Events$onInput($author$project$Entry$SetLocationId), - $elm$html$Html$Attributes$id('location') - ]), - $elm$core$String$fromInt, - function ($) { - return $.id; - }, - function ($) { - return $.name; - }, - model.locationId, - globals.locations) - ])), - A2( - $elm$html$Html$div, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('form-input') - ]), - _List_fromArray( - [ - A2( - $elm$html$Html$label, - _List_fromArray( - [ - $elm$html$Html$Attributes$for('net-unit-price') - ]), - _List_fromArray( - [ - $elm$html$Html$text('Stückpreis (Netto)') - ])), - A2( - $elm$html$Html$input, - _List_fromArray( - [ - $elm$html$Html$Attributes$value( - $elm$core$String$fromFloat(model.netUnitPrice)), - $elm$html$Html$Events$onInput($author$project$Entry$SetNetUnitPrice), - $elm$html$Html$Attributes$type_('number'), - $elm$html$Html$Attributes$id('net-unit-price'), - $elm$html$Html$Attributes$step('0.01') - ]), - _List_Nil) - ])), - A2( - $elm$html$Html$div, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('form-input') - ]), - _List_fromArray( - [ - A2( - $elm$html$Html$label, - _List_fromArray( - [ - $elm$html$Html$Attributes$for('tax-group') - ]), - _List_fromArray( - [ - $elm$html$Html$text('Steuergruppe') - ])), - A6( - $author$project$Entry$viewSelect, - _List_fromArray( - [ - $elm$html$Html$Events$onInput($author$project$Entry$SetTaxGroupId), - $elm$html$Html$Attributes$id('tax-group') - ]), - $elm$core$String$fromInt, - function ($) { - return $.id; - }, - function ($) { - return $.description; - }, - model.taxGroupId, - globals.taxGroups) - ])) - ])), - A2( - $elm$html$Html$fieldset, - _List_Nil, - _List_fromArray( - [ - A2( - $elm$html$Html$legend, - _List_Nil, - _List_fromArray( - [ - $elm$html$Html$text('Neuer Snackeintrag') - ])), - A2( - $elm$html$Html$div, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('form-input') - ]), - _List_fromArray( - [ - A2( - $elm$html$Html$label, - _List_fromArray( - [ - $elm$html$Html$Attributes$for('snack-name') - ]), - _List_fromArray( - [ - $elm$html$Html$text('Name') - ])), - A2( - $elm$html$Html$input, - _List_fromArray( - [ - $elm$html$Html$Attributes$value(model.name), - $elm$html$Html$Attributes$disabled(true), - $elm$html$Html$Attributes$id('snack-name') - ]), - _List_Nil) - ])), - A2( - $elm$html$Html$div, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('form-input') - ]), - _List_fromArray( - [ - A2( - $elm$html$Html$label, - _List_fromArray( - [ - $elm$html$Html$Attributes$for('gross-unit-price') - ]), - _List_fromArray( - [ - $elm$html$Html$text( - 'Stückpreis (Brutto), Vorschlag: ' + $elm$core$String$fromFloat( - A2($author$project$Entry$calculateGarfieldPrice, model.netUnitPrice, selectedTaxGroup.percentage))) - ])), - A2( - $elm$html$Html$input, - _List_fromArray( - [ - $elm$html$Html$Attributes$value( - $elm$core$String$fromFloat( - A2( - $elm$core$Maybe$withDefault, - A2($author$project$Entry$calculateGarfieldPrice, model.netUnitPrice, selectedTaxGroup.percentage), - $elm$core$Maybe$Nothing))), - $elm$html$Html$Attributes$id('gross-unit-price'), - $elm$html$Html$Attributes$type_('number'), - $elm$html$Html$Attributes$step('0.01') - ]), - _List_Nil) - ])) - ])) - ])); - } + return A2( + $elm$html$Html$form, + _List_Nil, + _List_fromArray( + [ + A2( + $elm$html$Html$fieldset, + _List_Nil, + _List_fromArray( + [ + A2( + $elm$html$Html$legend, + _List_Nil, + _List_fromArray( + [ + $elm$html$Html$text('Neuer Inventareintrag') + ])), + A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('form-input') + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$label, + _List_fromArray( + [ + $elm$html$Html$Attributes$for('barcode') + ]), + _List_fromArray( + [ + $elm$html$Html$text('Barcode') + ])), + A2( + $elm$html$Html$input, + _List_fromArray( + [ + $elm$html$Html$Events$onInput($author$project$Entry$SetBarcode), + $elm$html$Html$Attributes$value(model.barcode), + $elm$html$Html$Attributes$disabled(true), + $elm$html$Html$Attributes$id('barcode') + ]), + _List_Nil) + ])), + A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('form-input') + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$label, + _List_fromArray( + [ + $elm$html$Html$Attributes$for('name') + ]), + _List_fromArray( + [ + $elm$html$Html$text('Name') + ])), + A2( + $elm$html$Html$input, + _List_fromArray( + [ + $elm$html$Html$Events$onInput($author$project$Entry$SetName), + $elm$html$Html$Attributes$value(model.name), + $elm$html$Html$Attributes$id('name') + ]), + _List_Nil) + ])), + A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('form-input') + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$label, + _List_fromArray( + [ + $elm$html$Html$Attributes$for('sales-units') + ]), + _List_fromArray( + [ + $elm$html$Html$text('Stückzahl') + ])), + A2( + $elm$html$Html$input, + _List_fromArray( + [ + $elm$html$Html$Events$onInput($author$project$Entry$SetSalesUnits), + $elm$html$Html$Attributes$value( + $author$project$NumberInput$show(model.salesUnits)), + $elm$html$Html$Attributes$id('sales-units'), + $elm$html$Html$Attributes$type_('number') + ]), + _List_Nil) + ])), + A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('form-input') + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$label, + _List_fromArray( + [ + $elm$html$Html$Attributes$for('group') + ]), + _List_fromArray( + [ + $elm$html$Html$text('Gruppe') + ])), + A2($author$project$Select$view, $author$project$Entry$SetGroup, model.group) + ])), + A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('form-input') + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$label, + _List_fromArray( + [ + $elm$html$Html$Attributes$for('location') + ]), + _List_fromArray( + [ + $elm$html$Html$text('Raum') + ])), + A2($author$project$Select$view, $author$project$Entry$SetLocation, model.location) + ])), + A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('form-input') + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$label, + _List_fromArray( + [ + $elm$html$Html$Attributes$for('net-unit-price') + ]), + _List_fromArray( + [ + $elm$html$Html$text('Stückpreis (Netto)') + ])), + A2( + $elm$html$Html$input, + _List_fromArray( + [ + $elm$html$Html$Attributes$value( + $author$project$NumberInput$show(model.netUnitPrice)), + $elm$html$Html$Events$onInput($author$project$Entry$SetNetUnitPrice), + $elm$html$Html$Attributes$type_('number'), + $elm$html$Html$Attributes$id('net-unit-price'), + $elm$html$Html$Attributes$step('0.01') + ]), + _List_Nil) + ])), + A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('form-input') + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$label, + _List_fromArray( + [ + $elm$html$Html$Attributes$for('tax-group') + ]), + _List_fromArray( + [ + $elm$html$Html$text('Steuergruppe') + ])), + A2($author$project$Select$view, $author$project$Entry$SetTaxGroup, model.taxGroup) + ])) + ])), + A2( + $elm$html$Html$fieldset, + _List_Nil, + _List_fromArray( + [ + A2( + $elm$html$Html$legend, + _List_Nil, + _List_fromArray( + [ + $elm$html$Html$text('Neuer Snackeintrag') + ])), + A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('form-input') + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$label, + _List_fromArray( + [ + $elm$html$Html$Attributes$for('snack-name') + ]), + _List_fromArray( + [ + $elm$html$Html$text('Name') + ])), + A2( + $elm$html$Html$input, + _List_fromArray( + [ + $elm$html$Html$Attributes$value(model.name), + $elm$html$Html$Attributes$disabled(true), + $elm$html$Html$Attributes$id('snack-name') + ]), + _List_Nil) + ])), + A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('form-input') + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$label, + _List_fromArray( + [ + $elm$html$Html$Attributes$for('gross-unit-price') + ]), + _List_fromArray( + [ + $elm$html$Html$text( + 'Stückpreis (Brutto), Vorschlag: ' + $elm$core$String$fromFloat( + A2( + $author$project$Entry$calculateGarfieldPrice, + $author$project$NumberInput$get(model.netUnitPrice), + $author$project$Select$get(model.taxGroup).percentage))) + ])), + A2( + $elm$html$Html$input, + _List_fromArray( + [ + $elm$html$Html$Events$onInput($author$project$Entry$SetGrossUnitPrice), + $elm$html$Html$Attributes$value( + $author$project$NumberInput$show(model.grossUnitPrice)), + $elm$html$Html$Attributes$id('gross-unit-price'), + $elm$html$Html$Attributes$type_('number'), + $elm$html$Html$Attributes$step('0.01') + ]), + _List_Nil) + ])) + ])) + ])); } }; var $author$project$Entry$main = $elm$browser$Browser$element( @@ -12008,4 +12079,4 @@ _Platform_export({'Entry':{'init':$author$project$Entry$main( }, A2($elm$json$Json$Decode$field, 'id', $elm$json$Json$Decode$int)); }, - A2($elm$json$Json$Decode$field, 'percentage', $elm$json$Json$Decode$float))))))({"versions":{"elm":"0.19.1"},"types":{"message":"Entry.Msg","aliases":{"Entry.SearchResult":{"args":[],"type":"{ barcode : String.String, name : String.String, netUnitPrice : Basics.Float, bought : String.String, salesUnits : Basics.Int, available : Basics.Bool, locationName : String.String, locationId : Basics.Int, groupName : String.String, groupId : Basics.Int, taxGroupId : Basics.Int }"}},"unions":{"Entry.Msg":{"args":[],"tags":{"SetSearchTerm":["String.String"],"SubmitSearch":[],"ReceiveSearchResults":["Result.Result Http.Error (List.List Entry.SearchResult)"],"GotoItemEditor":["Entry.SearchResult"],"SetNetUnitPrice":["String.String"],"SetGroupId":["String.String"],"SetLocationId":["String.String"],"SetTaxGroupId":["String.String"],"SetBarcode":["String.String"],"SetName":["String.String"],"SetSalesUnits":["String.String"]}},"Basics.Bool":{"args":[],"tags":{"True":[],"False":[]}},"Http.Error":{"args":[],"tags":{"BadUrl":["String.String"],"Timeout":[],"NetworkError":[],"BadStatus":["Basics.Int"],"BadBody":["String.String"]}},"Basics.Float":{"args":[],"tags":{"Float":[]}},"Basics.Int":{"args":[],"tags":{"Int":[]}},"List.List":{"args":["a"],"tags":{}},"Result.Result":{"args":["error","value"],"tags":{"Ok":["value"],"Err":["error"]}},"String.String":{"args":[],"tags":{"String":[]}}}}})}});}(this)); \ No newline at end of file + A2($elm$json$Json$Decode$field, 'percentage', $elm$json$Json$Decode$float))))))({"versions":{"elm":"0.19.1"},"types":{"message":"Entry.Msg","aliases":{"Entry.SearchResult":{"args":[],"type":"{ barcode : String.String, name : String.String, netUnitPrice : Basics.Float, bought : String.String, salesUnits : Basics.Int, available : Basics.Bool, locationName : String.String, locationId : Basics.Int, groupName : String.String, groupId : Basics.Int, taxGroupId : Basics.Int }"}},"unions":{"Entry.Msg":{"args":[],"tags":{"SetSearchTerm":["String.String"],"SubmitSearch":[],"ReceiveSearchResults":["Result.Result Http.Error (List.List Entry.SearchResult)"],"GotoItemEditor":["Entry.SearchResult"],"SetBarcode":["String.String"],"SetName":["String.String"],"SetSalesUnits":["String.String"],"SetNetUnitPrice":["String.String"],"SetGrossUnitPrice":["String.String"],"SetGroup":["String.String"],"SetLocation":["String.String"],"SetTaxGroup":["String.String"]}},"Basics.Bool":{"args":[],"tags":{"True":[],"False":[]}},"Http.Error":{"args":[],"tags":{"BadUrl":["String.String"],"Timeout":[],"NetworkError":[],"BadStatus":["Basics.Int"],"BadBody":["String.String"]}},"Basics.Float":{"args":[],"tags":{"Float":[]}},"Basics.Int":{"args":[],"tags":{"Int":[]}},"List.List":{"args":["a"],"tags":{}},"Result.Result":{"args":["error","value"],"tags":{"Ok":["value"],"Err":["error"]}},"String.String":{"args":[],"tags":{"String":[]}}}}})}});}(this)); \ No newline at end of file