Writing Flows
When you set out to write the logic for your app, what you are doing is actually laying out how the user will move through various steps towards attaining a goal. This going through steps towards a goal is what we call a flow. To write flows in Presto is very simple. Abstractions like 'Remote' and 'UI' will help you organize your code better and makes code more readable.
This app has a primary goal of Paying a Bill.
App Goal
billPayFlow :: Flow BillPayFailure StatusScreenAction
billPayFlow = do
_ <- UI.splashScreen
operators <- Remote.fetchOperators
operator <- UI.chooseOperator operators
mobileNumber <- UI.askMobileNumber
amount <- UI.askAmount
result <- Remote.payBill mobileNumber amount operator
UI.billPayStatus mobileNumber amount result
UI Flows
Choose Operator
chooseOperator :: Array Operator -> Flow BillPayFailure Operator
chooseOperator operators = do
action <- runUI' (ChooseOperatorScreen operators)
case action of
OperatorSelected operator-> pure operator
ChooseOperatorScreenAbort -> liftLeft UserAbort
Ask MobileNumber
askMobileNumber :: Flow BillPayFailure MobileNumber
askMobileNumber = do
action <- runUI' AskMobileNumberScreen
case action of
SubmitMobileNumber mobileNumber -> pure mobileNumber
AskMobileNumberScreenAbort -> liftLeft UserAbort
Ask Amount
askAmount :: Flow BillPayFailure Amount
askAmount = do
action <- runUI' AskAmountScreen
case action of
SubmitAmount amount -> pure amount
AskAmountScreenAbort -> liftLeft UserAbort
Show Status
billPayStatus :: MobileNumber -> Amount -> BillPayStatus -> Flow BillPayFailure StatusScreenAction
billPayStatus mobileNumber amount payStatus = do
action <- runUI' (StatusScreen mobileNumber amount payStatus)
case action of
SuccessResult -> pure SuccessResult
StatusScreenAbort -> liftLeft UserAbort
SplashScreen
billPayStatus :: MobileNumber -> Amount -> BillPayStatus -> Flow BillPayFailure StatusScreenAction
billPayStatus mobileNumber amount payStatus = do
action <- runUI' (StatusScreen mobileNumber amount payStatus)
case action of
SuccessResult -> pure SuccessResult
StatusScreenAbort -> liftLeft UserAbort
Api Flows
Fetch Operators Api
fetchOperators :: Flow BillPayFailure (Array Operator)
fetchOperators = do
FetchOperatorsResponse { operators } <- callApi FetchOperatorsRequest
pure operators
Bill Pay Api
payBill :: Operator -> MobileNumber -> Amount -> Flow BillPayFailure BillPayStatus
payBill operator mobileNumber amount =
BillPayResponse { status } <- callApi $ BillPayRequest { operator : operator, mobileNumber : mobileNumber, amount : amount }
pure status