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