Skip to content

Instantly share code, notes, and snippets.

@sibljon
Created February 6, 2020 15:36
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 sibljon/2d4fee5a4322c93be1fe4e60fee40090 to your computer and use it in GitHub Desktop.
Save sibljon/2d4fee5a4322c93be1fe4e60fee40090 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
// Available variables:
// - Machine
// - interpret
// - assign
// - send
// - sendParent
// - spawn
// - raise
// - actions
// - XState (all XState exports)
const mapInviteTypeToConnectionType = inviteType => {
switch (inviteType) {
case "COLLEAGUE":
return "COLLEAGUE";
case "ORGANIZATION_CODE": // Legacy type from <=3.X
case "PATIENT": // Legacy type from <=3.X
case "SECURE_MESSAGE":
return "SECURE_MESSAGE";
case "UNKNOWN":
default:
console.error(`Unexpected inviteType ${inviteType}`);
return "SECURE_MESSAGE";
}
};
const associateInvite = (
accountCreationIntent,
accountInviteClientID,
inviteCode
) =>
new Promise(resolve =>
setTimeout(() => {
resolve({
data: {
associateInvite: {
confirmationScreen: {
body: "",
buttonText: "Continue",
entityProfile: {
url: "https://invite.spruce-dev.com/e/18M23V27KJ800"
},
imageURL:
"https://msg-media.spruce-dev.com/media/e867db5a-ba30-9dba-7cc0-38cb-f9887032?mimetype=image%2Fpng",
photoStyle: "BORDERED_CIRCLE",
title: "You're joining Sara Brown, PsyD"
},
errorCode: null,
errorMessage: null,
// inviteType: "ORGANIZATION_CODE",
// inviteType: "SECURE_MESSAGE",
inviteType: "COLLEAGUE",
phoneNumberVerificationText: null,
values: [
{
key: "client_data",
value:
'{"patient_invite":{"greeting":{"title":"You\'re Joining Sara Brown, PsyD","message":"Let\'s create your account so you can start securely messaging with Sara Brown, PsyD.","button_text":"Get Started"},"org_id":"entity_18M23V27KJ800","org_name":"Sara Brown, PsyD"},"practice_invite":{"greeting":{"title":"You\'re Joining Sara Brown, PsyD","message":"Let\'s create your account so you can start securely messaging with Sara Brown, PsyD.","button_text":"Get Started"},"org_id":"entity_18M23V27KJ800","org_name":"Sara Brown, PsyD","join_as_teammate":false}}'
},
{
key: "invite_type",
value: "ORGANIZATION_CODE"
},
{
key: "$desktop_url",
value: "https://app.spruce-dev.com/?invite=sara-brown"
},
{
key: "invite_token",
value: "sara-brown"
}
],
verifyPhoneNumber: true
}
}
});
}, 1000)
);
const verifyPhoneNumber = phoneNumber =>
Promise.resolve({
data: {
verifyPhoneNumberForAccountCreation: {
errorCode: null,
errorMessage: null,
message: "A verification code has been sent to (630) 915-9986",
token: "-XPIFGaWcwroulS8i_5zqQ"
}
}
});
// const checkVerificationCode = verificationCode =>
// Promise.resolve({
// data: {
// checkVerificationCode: {
// account: null,
// errorCode: "CODE_EXPIRED",
// errorMessage:
// "The entered code has expired. Please request a new code.",
// inviteType: null,
// success: false,
// verifiedEntityInfo: null
// }
// }
// });
const checkVerificationCode = verificationCode =>
Promise.resolve({
data: {
checkVerificationCode: {
account: null,
confirmationScreen: null,
errorCode: null,
errorMessage: null,
inviteType: null,
success: true,
verifiedEntityInfo: null
}
}
});
const detectPresenceOfInviteCode = () =>
new Promise(resolve =>
setTimeout(() => {
resolve("sara-brown");
}, 200)
);
const fetchMachine = Machine({
id: "account-creation",
initial: "initialize",
context: {
inviteCode: "",
accountCreationIntent: "PROVIDER",
connectionType: "",
phoneVerificationToken: "",
inviteConfirmationScreen: null,
accountInviteClientID: "",
firstName: "",
lastName: "",
shortTitle: "",
organizationName: "",
dob: {},
gender: "",
genderDetail: "",
email: "",
password: "",
errorMessage: ""
},
states: {
initialize: {
initial: "detectPresenceOfInviteCode",
states: {
detectPresenceOfInviteCode: {
invoke: {
id: "detectPresenceOfInviteCode",
src: (context, event) => detectPresenceOfInviteCode(),
onDone: {
target: "callingAssociateInvite",
internal: true,
actions: assign({
inviteCode: (context, event) => event.data
})
},
onError: {
target: "#choosePatientOrProvider",
actions: assign({
error: (context, event) => {
// In practice, there will never be an error, since we're simply checking the query params for the token and that can't fail
console.error(event);
}
})
}
}
},
callingAssociateInvite: {
invoke: {
id: "associateInvite",
src: (context, event) =>
associateInvite(
context.accountCreationIntent,
context.accountInviteClientID,
context.inviteCode
),
onDone: [
{
target: "#choosePatientOrProvider",
actions: assign({
connectionType: (context, event) =>
mapInviteTypeToConnectionType(
event.data.data.associateInvite.inviteType
)
}),
cond: (context, event) => {
if (
!event ||
!event.data ||
!event.data.data ||
!event.data.data.associateInvite ||
!event.data.data.associateInvite.inviteType
) {
return false;
}
const connectionType = mapInviteTypeToConnectionType(
event.data.data.associateInvite.inviteType
);
switch (connectionType) {
case "SECURE_MESSAGE":
return true;
case "COLLEAGUE":
return false;
}
}
},
{
target: "#confirmPracticeBeingJoined",
actions: assign({
connectionType: (context, event) =>
mapInviteTypeToConnectionType(
event.data.data.associateInvite.inviteType
),
confirmationScreen: (context, event) =>
mapInviteTypeToConnectionType(
event.data.data.associateInvite.confirmationScreen
)
}),
cond: (context, event) => {
if (
!event ||
!event.data ||
!event.data.data ||
!event.data.data.associateInvite ||
!event.data.data.associateInvite.inviteType
) {
return false;
}
const connectionType = mapInviteTypeToConnectionType(
event.data.data.associateInvite.inviteType
);
switch (connectionType) {
case "SECURE_MESSAGE":
return false;
case "COLLEAGUE":
return true;
}
}
}
],
onError: {
target: "#choosePatientOrProvider",
actions: assign({
error: (context, event) => {
console.error(event);
}
})
}
}
}
}
},
choosePatientOrProvider: {
id: "choosePatientOrProvider",
on: {
PATIENT: {
target: "enterPhoneNumber",
actions: "markAsPatient"
},
PROVIDER: [
{
target: "enterPhoneNumber",
actions: "markAsProvider",
cond: context => context.inviteType === "COLLEAGUE"
},
{
target: "chooseJoinExistingClinicOrCreateNewClinic",
actions: "markAsProvider"
}
]
}
},
chooseJoinExistingClinicOrCreateNewClinic: {
id: "chooseJoinExistingClinicOrCreateNewClinic",
on: {
JOIN_EXISTING: {
target: "joinExistingClinic",
actions: "markAsPatient"
},
CREATE_NEW: {
target: "enterPhoneNumber",
actions: "markAsProvider"
}
}
},
// The joinExistingClinic state is just going to explain how to join an existing practice and link to the help center
joinExistingClinic: {
on: {
BACK: {
target: "chooseJoinExistingClinicOrCreateNewClinic"
}
}
},
enterPhoneNumber: {
id: "enterPhoneNumber",
initial: "awaitPhoneNumberEntry",
states: {
awaitPhoneNumberEntry: {
on: {
CHANGE: {
actions: assign({
phoneNumber: (ctx, e) => e.data
})
},
SUBMIT: { target: "sendingPhoneVerificationCode", internal: true },
BACK: "#choosePatientOrProvider"
}
},
sendingPhoneVerificationCode: {
invoke: {
id: "verifyPhoneNumber",
src: (context, event) => verifyPhoneNumber(context.phoneNumber),
onDone: {
target: "#enterPhoneVerificationCode",
internal: false
},
onError: {
target: "error",
actions: assign({
error: (context, event) => {
console.error(event);
}
})
}
}
},
error: { type: "final" }
}
},
enterPhoneVerificationCode: {
id: "enterPhoneVerificationCode",
initial: "awaitVerificationCodeEntry",
states: {
awaitVerificationCodeEntry: {
on: {
CHANGE: {
actions: assign({
verificationCode: (ctx, e) => e.data
})
},
SUBMIT: {
target: "verifyingCode",
internal: true
}
}
},
verifyingCode: {
invoke: {
id: "checkVerificationCode",
src: (context, event) =>
checkVerificationCode(context.verificationCode),
onDone: [
{
target: "awaitVerificationCodeEntry",
internal: true,
actions: assign({
errorMessage: (context, event) =>
event.data.data.checkVerificationCode.errorMessage
}),
cond: (context, event) =>
event &&
event.data &&
event.data.data &&
event.data.data.checkVerificationCode &&
event.data.data.checkVerificationCode.errorMessage
},
{
target: "#confirmPracticeBeingJoined",
internal: false,
actions: assign({
confirmationScreen: (context, event) =>
event.data.data.checkVerificationCode.confirmationScreen
}),
cond: (context, event) =>
event &&
event.data &&
event.data.data &&
event.data.data.checkVerificationCode &&
event.data.data.checkVerificationCode.confirmationScreen
},
{
target: "#enterPatientDemographics",
cond: (context, event) =>
context.accountCreationIntent === "PATIENT"
},
{
target: "#enterOrgName",
cond: (context, event) =>
context.accountCreationIntent === "PROVIDER" &&
context.connectionType === "SECURE_MESSAGE"
},
{
target: "#enterProviderDemographics",
cond: (context, event) =>
context.accountCreationIntent === "PROVIDER" &&
context.connectionType === "COLLEAGUE"
}
],
onError: {
target: "awaitVerificationCodeEntry",
internal: true,
actions: assign({
error: (context, event) => {
console.error(event);
}
})
}
}
}
}
},
confirmPracticeBeingJoined: {
id: "confirmPracticeBeingJoined",
on: {
CONFIRM: [
{
target: "enterPhoneNumber",
cond: ctx => ctx.connectionType === "COLLEAGUE"
},
{
target: "enterProviderDemographics",
cond: ctx => ctx.accountCreationIntent === "PROVIDER"
},
{
target: "enterPatientDemographics",
cond: ctx => ctx.accountCreationIntent === "PATIENT"
}
]
}
},
enterOrgName: {
id: "enterOrgName",
on: {
CHANGE: {
actions: assign({
organizationName: (ctx, e) => e.data
})
},
SUBMIT: "enterProviderDemographics",
BACK: "enterPhoneVerificationCode"
}
},
enterPatientDemographics: {
id: "enterPatientDemographics",
on: {
CHANGE_FIRST_NAME: {
actions: assign({
firstName: (ctx, e) => e.data
})
},
CHANGE_LAST_NAME: {
actions: assign({
lastName: (ctx, e) => e.data
})
},
CHANGE_DOB: {
actions: assign({
dob: (ctx, e) => e.data
})
},
CHANGE_GENDER: {
actions: assign({
gender: (ctx, e) => e.data
})
},
CHANGE_GENDER_DETAIL: {
actions: assign({
genderDetail: (ctx, e) => e.data
})
},
SUBMIT: "enterEmailAndPassword",
BACK: "enterPhoneVerificationCode"
}
},
enterProviderDemographics: {
id: "enterProviderDemographics",
on: {
CHANGE_FIRST_NAME: {
actions: assign({
firstName: (ctx, e) => e.data
})
},
CHANGE_LAST_NAME: {
actions: assign({
lastName: (ctx, e) => e.data
})
},
CHANGE_SHORT_TITLE: {
actions: assign({
shortTitle: (ctx, e) => e.data
})
},
SUBMIT: "enterEmailAndPassword",
BACK: "enterPhoneVerificationCode"
}
},
enterEmailAndPassword: {
on: {
CHANGE_EMAIL: {
actions: assign({
email: (ctx, e) => e.data
})
},
CHANGE_PASSWORD: {
actions: assign({
password: (ctx, e) => e.data
})
},
SUBMIT: [
{
target: "providerAccountCreated",
cond: ctx =>
ctx.connectionType === "COLLEAGUE" ||
ctx.accountCreationIntent === "PROVIDER"
},
{
target: "patientAccountCreated",
cond: ctx => ctx.accountCreationIntent === "PATIENT"
}
]
}
},
patientAccountCreated: {
type: "final"
},
providerAccountCreated: {
type: "final"
}
},
actions: {
markAsProvider: assign({
accountCreationIntent: "PROVIDER"
}),
markAsPatient: assign({
accountCreationIntent: "PATIENT"
})
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment