Skip to content

Instantly share code, notes, and snippets.

@mrange
Last active August 29, 2015 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrange/fda18d102dd2da752f9b to your computer and use it in GitHub Desktop.
Save mrange/fda18d102dd2da752f9b to your computer and use it in GitHub Desktop.
Flowlet gist
// A flowlet sample of simple customer registration flow
// First let's declare some types to hold the registration info
type AddressInfo =
{
FirstName : string
LastName : string
CareOf : string
AddressLine1 : string
AddressLine2 : string
AddressLine3 : string
Zip : string
City : string
Country : string
}
type GenderInfo =
| Unspecified
| Male
| Female
type PersonInfo =
{
Id : string
FirstName : string
LastName : string
Gender : GenderInfo
BirthDate : DateTime
CellPhone : string
Email : string
}
type CompanyInfo =
{
Id : string
VatId : string
Name : string
Contact : PersonInfo
}
type EntityInfo =
| Person of PersonInfo
| Company of CompanyInfo
type PaymentInfo =
| CreditCard of string*string*DateTime*string
| Invoice of AddressInfo option
type RegistrationInfo =
{
Entity : EntityInfo
DeliveryAddress : AddressInfo
Payment : PaymentInfo
}
// Then let's declare some formlets
// This will generate the forms user interface
let personForm legend firstName lastName =
formlet {
let! id = LabeledText "Social No" ""
let! firstName = LabeledText "First name" firstName
let! lastName = LabeledText "Last name" lastName
let! gender = LabeledOption "Gender" Unspecified [|"Unspecified",Unspecified; "Female",Female; "Male",Male|]
let! birthDate = LabeledBirthDate "Birth date" None
let! cellPhone = LabeledText "Cell" ""
let! email = LabeledText "Email" ""
return
{
Id = id
FirstName = firstName
LastName = lastName
Gender = gender
BirthDate = birthDate
CellPhone = cellPhone
Email = email
}
}
|> Enhance.WithLegend legend
let companyForm legend =
formlet {
let! id = LabeledText "Company No" ""
let! vatId = LabeledText "Vat No" ""
let! name = LabeledText "Company name" ""
return id, vatId, name
}
|> Enhance.WithLegend legend
let addressForm legend firstName lastName =
formlet {
let! firstName = LabeledText "First name" firstName
let! lastName = LabeledText "Last name" lastName
let! careOf = LabeledOptText "C/O" ""
let! addressLine1 = LabeledText "Address" ""
let! addressLine2 = LabeledOptText "Address" ""
let! addressLine3 = LabeledOptText "Address" ""
let! zip = LabeledText "Zip" ""
let! city = LabeledText "City" ""
let! country = LabeledText "Country" ""
return
{
FirstName = firstName
LastName = lastName
CareOf = careOf
AddressLine1 = addressLine1
AddressLine2 = addressLine2
AddressLine3 = addressLine3
Zip = zip
City = city
Country = country
}
}
|> Enhance.WithLegend legend
let creditCardForm legend firstName lastName =
formlet {
let! name = LabeledText "Name" <| firstName + " " + lastName
let! no = LabeledText "No" ""
let! expireDate = LabeledExpireDate "Expire date" None
let! cvc = LabeledText "CVC" ""
return CreditCard (name, no, expireDate, cvc)
}
let invoiceForm legend firstName lastName =
formlet {
let! useDeliveryAddress = YesNo "Invoice address is same as delivery address" <| Some true
if not useDeliveryAddress then
let! address = addressForm "Invoice address" firstName lastName
return Some address
else
return None
}
// Now define some flowlets that ties formlets together into a flow
// showPage shows a formlet as a page in the flow
let personFlow firstName lastName =
flowlet {
let! person = showPage <| personForm "Personal information" firstName lastName
return Person person
}
let companyFlow firstName lastName =
flowlet {
let! id, vatId, name= showPage <| companyForm "Company information"
let! contact = showPage <| personForm "Contact information" firstName lastName
let company =
{
Id = id
VatId = vatId
Name = name
Contact = contact
}
return Company company
}
let creditCardFlow firstName lastName =
flowlet {
let! creditCard = showPage <| creditCardForm "Credit card information" firstName lastName
return creditCard
}
let invoiceFlow firstName lastName =
flowlet {
let! invoice = showPage <| invoiceForm "Invoice information" firstName lastName
return Invoice invoice
}
// The selectForm is the first form the user sees, this allows the user to pick
// if it's for a company or person and which payment method is preferable
// Note that the result of this form is a flowlet,
// enables multi paths flowlets in functionally idiomatic way
let selectForm =
formlet {
let! entityFlow = LabeledOption "Entity" personFlow [|"Person",personFlow; "Company",companyFlow|]
let! paymentFlow = LabeledOption "Payment" creditCardFlow [|"Credit card",creditCardFlow; "Invoice",invoiceFlow|]
return entityFlow, paymentFlow
}
// Ties the flows and a formlets together
let registrationFlow =
flowlet {
let! entityFlow, paymentFlow= showPage selectForm
let! deliveryAddress = showPage <| addressForm "Delivery address" "" ""
let! entity = entityFlow deliveryAddress.FirstName deliveryAddress.LastName
let! payment = paymentFlow deliveryAddress.FirstName deliveryAddress.LastName
return
{
Entity = entity
DeliveryAddress = deliveryAddress
Payment = payment
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment