Last active
August 29, 2015 14:12
-
-
Save mrange/fda18d102dd2da752f9b to your computer and use it in GitHub Desktop.
Flowlet gist
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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