Restructure client code

This commit is contained in:
Paul Brinkmeier 2022-12-08 22:42:10 +01:00
parent 9ce0f974fb
commit 05724dbaab
2 changed files with 97 additions and 67 deletions

View File

@ -95,14 +95,14 @@ decodeOI = Dec.succeed OverviewItem
|> requiredAt ["item", "bought"] Dec.string |> requiredAt ["item", "bought"] Dec.string
|> requiredAt ["overview", "activeMappings"] Dec.int |> requiredAt ["overview", "activeMappings"] Dec.int
getSnacksByItemId : Int -> Cmd Msg getSnacksByItem : OverviewItem -> Cmd Msg
getSnacksByItemId itemId = rpc getSnacksByItem item = rpc
{ func = "getSnacksByItemId" { func = "getSnacksByItemId"
, args = Enc.object , args = Enc.object
[ ("item", Enc.int itemId) [ ("item", Enc.int item.id)
] ]
, expect = Dec.list decodeSnack , expect = Dec.list decodeSnack
} RcvSnacks } (RcvSnacks item)
type alias Snack = type alias Snack =
{ id : Int { id : Int
@ -136,82 +136,85 @@ type alias Location =
, name : String , name : String
} }
type alias Model = type OuterState
{ state : State
}
type State
= LoadingLocations = LoadingLocations
| LocationSelector (List Location) | LocationSelector (List Location)
| Overview | Initialized { locations : List Location, location : Location } State
{ location : Location
, selectedItems : Set Int type State
= Overview
{ selectedItems : Set Int
, desiredInventory : Dict Int Int , desiredInventory : Dict Int Int
, overviewItems : List OverviewItem , overviewItems : List OverviewItem
} }
| SnacksEditor | SnacksEditor
{ snacks : List Snack { item : OverviewItem
, snacks : List Snack
} }
type Msg type Msg
= SelectItem Int Bool = SelectLocation Location
| SelectItem Int Bool
| ChangeLocation
| SetDesiredInventory Int String | SetDesiredInventory Int String
| SelectLocation Location
| TransferInventory Int | TransferInventory Int
| GoBack
-- RPC calls -- RPC calls
| CallDisableItems (List Int) | CallDisableItems (List Int)
| CallAdjustInventory Int Int String | CallAdjustInventory Int Int String
| CallGetSnacksById Int | CallGetSnacksById OverviewItem
-- Responses -- Responses
| RcvLocations (Result Http.Error (List Location)) | RcvLocations (Result Http.Error (List Location))
| RcvOverview (Result Http.Error (List OverviewItem)) | RcvOverview (Result Http.Error (List OverviewItem))
| RcvSnacks (Result Http.Error (List Snack)) | RcvSnacks OverviewItem (Result Http.Error (List Snack))
| RcvOther | RcvOther
init = ({ state = LoadingLocations }, getLocations) init = (LoadingLocations, getLocations)
update msg global = case msg of update msg outerState = case msg of
CallAdjustInventory item amount desc -> (global, adjustInventory item amount desc) CallAdjustInventory item amount desc -> (outerState, adjustInventory item amount desc)
CallDisableItems items -> (global, disableItems items) CallDisableItems items -> (outerState, disableItems items)
CallGetSnacksById itemId -> (global, getSnacksByItemId itemId) CallGetSnacksById item -> (outerState, getSnacksByItem item)
_ -> _ -> case outerState of
let
(newState, cmd) = stateMachine msg global global.state
in
({ global | state = newState }, cmd)
stateMachine msg global state = case state of
LoadingLocations -> case msg of LoadingLocations -> case msg of
RcvLocations (Ok locations) -> RcvLocations (Ok locations) ->
(LocationSelector locations, Cmd.none) (LocationSelector locations, Cmd.none)
_ -> _ ->
(state, Cmd.none) (outerState, Cmd.none)
LocationSelector locations -> case msg of LocationSelector locations -> case msg of
SelectLocation location -> SelectLocation location ->
(Overview (Initialized { locations = locations, location = location } <| Overview
{ location = location { selectedItems = Set.empty
, selectedItems = Set.empty
, desiredInventory = Dict.empty , desiredInventory = Dict.empty
, overviewItems = [] , overviewItems = []
} }
, getOverviewItems location.id , getOverviewItems location.id
) )
_ -> _ ->
(state, Cmd.none) (outerState, Cmd.none)
Initialized global state -> case msg of
ChangeLocation ->
(LocationSelector global.locations, Cmd.none)
_ ->
let
(newState, cmd) = stateMachine msg global state
in
(Initialized global newState, cmd)
stateMachine msg global state = case state of
Overview model -> case msg of Overview model -> case msg of
RcvOverview (Ok overviewItems) -> RcvOverview (Ok overviewItems) ->
(Overview (Overview
{ location = model.location { selectedItems = Set.empty
, selectedItems = Set.empty
, desiredInventory = Dict.empty , desiredInventory = Dict.empty
, overviewItems = overviewItems , overviewItems = overviewItems
} }
, Cmd.none , Cmd.none
) )
RcvSnacks (Ok snacks) -> RcvSnacks item (Ok snacks) ->
(SnacksEditor { snacks = snacks }, Cmd.none) (SnacksEditor { item = item, snacks = snacks }, Cmd.none)
RcvOther -> RcvOther ->
(state, getOverviewItems model.location.id) (state, getOverviewItems global.location.id)
SelectItem itemId selected -> SelectItem itemId selected ->
(Overview { model | selectedItems = setSelect itemId selected model.selectedItems }, Cmd.none) (Overview { model | selectedItems = setSelect itemId selected model.selectedItems }, Cmd.none)
SetDesiredInventory itemId invStr -> case String.toInt invStr of SetDesiredInventory itemId invStr -> case String.toInt invStr of
@ -231,10 +234,13 @@ stateMachine msg global state = case state of
(state, transferInventory transfers) (state, transferInventory transfers)
_ -> _ ->
(state, Cmd.none) (state, Cmd.none)
SnacksEditor { snacks } -> SnacksEditor { snacks } -> case msg of
GoBack ->
(Overview { selectedItems = Set.empty, desiredInventory = Dict.empty, overviewItems = [] }, getOverviewItems global.location.id)
_ ->
(state, Cmd.none) (state, Cmd.none)
view { state } = case state of view outerState = case outerState of
LoadingLocations -> progress [] [] LoadingLocations -> progress [] []
LocationSelector locations -> LocationSelector locations ->
let let
@ -245,7 +251,17 @@ view { state } = case state of
[ p [] [ text "Raum auswählen:" ] [ p [] [ text "Raum auswählen:" ]
, div [] <| List.map viewLocationButton locations , div [] <| List.map viewLocationButton locations
] ]
Overview { location, selectedItems, desiredInventory, overviewItems } -> Initialized global state ->
div []
[ h2 []
[ text <| "Inventar " ++ global.location.name ++ " "
, button [ onClick ChangeLocation ] [ text "Raum ändern" ]
]
, viewState global state
]
viewState global state = case state of
Overview { selectedItems, desiredInventory, overviewItems } ->
let let
header = tableCells th <| List.map text [ "", "ID", "Artikel", "Barcode", "Preis", "Kaufdatum", "Snackeinträge", "Soll-Inv.", "Ist-Inv.", "Aktionen" ] header = tableCells th <| List.map text [ "", "ID", "Artikel", "Barcode", "Preis", "Kaufdatum", "Snackeinträge", "Soll-Inv.", "Ist-Inv.", "Aktionen" ]
viewOverviewItem oi = viewOverviewItem oi =
@ -277,7 +293,7 @@ view { state } = case state of
, text <| String.fromInt oi.id , text <| String.fromInt oi.id
, text oi.name , text oi.name
, code [] [ text oi.barcode ] , code [] [ text oi.barcode ]
, text <| String.fromFloat oi.price , text <| showEuros oi.price
, text <| Tuple.first <| splitAt 'T' oi.bought , text <| Tuple.first <| splitAt 'T' oi.bought
, text <| String.fromInt oi.activeMappings , text <| String.fromInt oi.activeMappings
, text <| String.fromInt oi.unitsLeft , text <| String.fromInt oi.unitsLeft
@ -303,32 +319,31 @@ view { state } = case state of
then [ disabled True ] then [ disabled True ]
else [ onClick <| TransferInventory oi.id ]) else [ onClick <| TransferInventory oi.id ])
[ text <| String.fromInt sumSelected ++ " Einheiten umbuchen" ] [ text <| String.fromInt sumSelected ++ " Einheiten umbuchen" ]
, button , button [ onClick <| CallGetSnacksById oi ] [ text "Snackeinträge bearbeiten" ]
(if oi.activeMappings == 0
then [ disabled True ]
else [ onClick <| CallGetSnacksById oi.id ])
[ text "Snackeinträge bearbeiten" ]
] ]
] ]
in in
div [] div []
[ h2 [] [ text <| "Inventar " ++ location.name ] [ table [] <| [header] ++ List.map viewOverviewItem overviewItems
, table [] <| [header] ++ List.map viewOverviewItem overviewItems
] ]
SnacksEditor { snacks } -> SnacksEditor { item, snacks } ->
let let
header = tableCells th <| List.map text [ "ID", "Artikel", "Barcode", "Brutto" ] header = tableCells th <| List.map text [ "ID", "Artikel", "Barcode", "Brutto" ]
viewSnack snack = tableCells td viewSnack snack = tableCells td
[ text <| String.fromInt snack.id [ text <| String.fromInt snack.id
, text snack.name , text snack.name
, text snack.barcode , text snack.barcode
, text <| String.fromFloat snack.price , text <| showEuros snack.price
] ]
in in
table [] div []
[ button [ onClick GoBack ] [ text "Zurück" ]
, p [] [ text <| "Snackeinträge für Inventareintrag " ++ String.fromInt item.id ++ " (" ++ showEuros item.price ++ " Netto)" ]
, table []
[ thead [] [ header ] [ thead [] [ header ]
, tbody [] <| List.map viewSnack snacks , tbody [] <| List.map viewSnack snacks
] ]
]
-- utils -- utils
@ -354,4 +369,11 @@ splitAt delim str =
firstOcc = locate delim str firstOcc = locate delim str
in in
(String.slice 0 firstOcc str, String.slice firstOcc (String.length str) str) (String.slice 0 firstOcc str, String.slice (firstOcc + 1) (String.length str) str)
showEuros : Float -> String
showEuros x =
let
(whole, fractional) = splitAt '.' (String.fromFloat x)
in
whole ++ "," ++ String.slice 0 2 (fractional ++ "00") ++ ""

View File

@ -1,3 +1,11 @@
html {
font-size: 12px;
}
button, input {
font-size: 0.8rem;
}
body { body {
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
} }