Last active
April 17, 2020 20:09
-
-
Save tchardin/cb158662bf229ba5a69ccd1bc9a8c4e9 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
This file contains 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
const CHART = 'cic'; | |
const HISTORY = 'backToPrevStep'; | |
// states | |
const LIFE_CHANGE_INTRO = 'lifeChangeIntro'; | |
const MANAGE_COVERAGE_INTRO = 'manageCoverageIntro'; | |
const ADD_MEMBER_REASON = 'addMemberReason'; | |
const REMOVE_MEMBER_REASON = 'removeMemberReason'; | |
const CHANGE_SELECTION = 'changeSelection'; | |
const ADDRESS_ENTRY = 'addressEntry'; | |
const ADDRESS_NO_CHANGE = 'addressNoChange'; | |
const INCOME_ENTRY = 'incomeEntry'; | |
const BASICS_ENTRY = 'basicsEntry'; | |
const INCOME_NO_CHANGE = 'incomeNoChange'; | |
const GOV_HANDOFF = 'govHandoff'; | |
const GOV_PICKUP = 'govPickup'; | |
const STATE_HANDOFF = 'stateHandoff'; | |
const STATE_PICKUP = 'statePickup'; | |
const APP_REVIEW_INTRO = 'appReviewIntro'; | |
const MEMBER_MARRIAGE = 'memberMarriage'; | |
const DIVORCE_INTRO = 'divorceIntro'; | |
const DEATH_INTRO = 'deathIntro'; | |
const CUSTODY_INTRO = 'custodyIntro'; | |
const COVERAGE_OPTIONS_INTRO = 'coverageOptionsIntro'; | |
const POLICY_CANCEL_PROMPT = 'policyCancelPrompt'; | |
const MOVE_DATE_ENTRY = 'moveDateEntry'; | |
const MEMBER_DIVORCE = 'memberDivorce'; | |
const MEMBER_DEATH = 'memberDeath'; | |
const NEW_PLAN_INTRO = 'newPlanIntro'; | |
const MEMBER_CUSTODY = 'memberCustody'; | |
const MEMBER_JOB_COVERAGE = 'memberJobCoverage'; | |
const MEMBER_COVERAGE_LOSS = 'memberCoverageLoss'; | |
const MEMBER_FUTURE_COVERAGE_LOSS = 'memberFutureCoverageLoss'; | |
const MEMBER_STATUS_CHANGE = 'memberStatusChange'; | |
const SEP_OUTDATED = 'sepOutdated'; | |
const REMOVING_MEMBERS = 'removingMembers'; | |
const SEP_MOVE_OUTDATED = 'sepMoveOutdated'; | |
const SEP_MOVE_OUTDATED_POLICY_VALID = 'sepMoveOutdatedPolicyValid'; | |
const POLICY_INVALID = 'policyInvalid'; | |
const SEP_KEEP_OR_APPLY = 'sepKeepOrApply'; | |
const SEP_MUST_APPLY = 'sepMustApply'; | |
const FINANCIAL_ASSISTANCE = 'financialAssistance'; | |
const MEMBER_CUT = 'memberCut'; | |
// enrollment flow | |
const ENROLLMENT_FLOW = '/health/household'; | |
const INCOME_FLOW = '/health/member-income-list'; | |
const PLAN_DETAIL = 'planDetail'; | |
// events | |
const START = 'START'; | |
const APPROVE = 'APPROVE'; | |
const DISMISS = 'DISMISS'; | |
const SUBMIT = 'SUBMIT'; | |
const DONE = 'DONE'; | |
const NEXT = 'NEXT'; | |
const OPEN_URL = 'OPEN_URL'; | |
const CANCEL_POLICY = 'CANCEL_POLICY'; | |
const APPLY = 'APPLY'; | |
// Combine multiple guards while keeping a | |
// proper key for debugging | |
const applyAny = (ctx, event, { guard }) => { | |
const gList = guard.guards.split('|'); | |
return gList.some(guardKey => guards[guardKey](ctx, event)); | |
}; | |
const applyEvery = (ctx, event, { guard }) => { | |
const gList = guard.guards.split('&'); | |
return gList.every(guardKey => guards[guardKey](ctx, event)); | |
}; | |
// conditions | |
const guards = { | |
incomeChanged: (ctx, evt) => { | |
return evt.change === 'INCOME'; | |
}, | |
addressChanged: (ctx, evt) => { | |
return evt.change === 'ADDRESS'; | |
}, | |
gotPregnant: (ctx, evt) => { | |
return evt.change === 'PREGNANCY'; | |
}, | |
memberMarried: (ctx, evt) => { | |
return evt.change === 'MARRIAGE'; | |
}, | |
isBirth: (ctx, evt) => { | |
return evt.change === 'BIRTH'; | |
}, | |
isAdoption: (ctx, evt) => { | |
return evt.change === 'ADOPTION'; | |
}, | |
childTurned26: (ctx, evt) => { | |
return evt.change === 'CHILD_26'; | |
}, | |
isDivorce: (ctx, evt) => { | |
return evt.change === 'DIVORCE'; | |
}, | |
isDeath: (ctx, evt) => { | |
return evt.change === 'DEATH'; | |
}, | |
coverageChanged: (ctx, evt) => { | |
return evt.change === 'COVERAGE'; | |
}, | |
custodyChanged: (ctx, evt) => { | |
return evt.change === 'CUSTODY'; | |
}, | |
offeredJobCoverage: (ctx, evt) => { | |
return evt.change === 'COVERAGE_GAIN_JOB'; | |
}, | |
gainedCoverage: (ctx, evt) => { | |
return evt.change === 'COVERAGE_GAIN'; | |
}, | |
lostCoverage: (ctx, evt) => { | |
return evt.change === 'COVERAGE_LOSS'; | |
}, | |
willLoseCoverage: (ctx, evt) => { | |
return evt.change === 'FUTURE_COVERAGE_LOSS'; | |
}, | |
filingStatusChanged: (ctx, evt) => { | |
return evt.change === 'FILING_STATUS'; | |
}, | |
citizenshipChanged: (ctx, evt) => { | |
return evt.change === 'CITIZENSHIP'; | |
}, | |
incarcerationChanged: (ctx, evt) => { | |
return evt.change === 'INCARCERATION'; | |
}, | |
tribeMembershipChanged: (ctx, evt) => { | |
return evt.change === 'TRIBE_MEMBERSHIP'; | |
}, | |
disabilityChanged: (ctx, evt) => { | |
return evt.change === 'DISABILITY'; | |
}, | |
legalNameChanged: (ctx, evt) => { | |
return evt.change === 'LEGAL_NAME'; | |
}, | |
dobChanged: (ctx, evt) => { | |
return evt.change === 'DOB'; | |
}, | |
ssnChanged: (ctx, evt) => { | |
return evt.change === 'SSN'; | |
}, | |
isAddMember: (ctx, evt) => { | |
return evt.change === 'ADD_MEMBER'; | |
}, | |
isRemoveMember: (ctx, evt) => { | |
return evt.change === 'REMOVE_MEMBER'; | |
}, | |
isCancelPolicy: (ctx, evt) => { | |
return evt.change === 'CANCEL_POLICY'; | |
}, | |
isOther: (ctx, evt) => { | |
return evt.change === 'OTHER'; | |
}, | |
'isBirth|isAdoption|disabilityChanged': applyAny, | |
'childTurned26|isDivorce|isDeath|custodyChanged': applyAny, | |
'filingStatusChanged|citizenshipChanged|incarcerationChanged|tribeMembershipChanged': applyAny, | |
'legalNameChanged|ssnChanged|dobChanged': applyAny, | |
'citizenshipChanged|incarcerationChanged': applyAny, | |
'childTurned26|isOther': applyAny, | |
'gainedCoverage|disabilityChanged': applyAny, | |
'filingStatusChanged|incarcerationChanged': applyAny, | |
// household basics conditions WIP | |
updatedTaxHousehold: (ctx, evt) => { | |
return evt.dirty; | |
}, | |
prelimEligUnchanged: (ctx, evt) => { | |
// TODO compare all results with current app | |
return false; | |
}, | |
// Location change | |
'movedToFedMarketplace|movedCurrentPolicyValid|movedCurrentPolicyInvalid': applyAny, | |
movedToStateMarketplace: (ctx, evt) => { | |
return false; | |
}, | |
movedParamsUnchanged: (ctx, evt) => { | |
// TODO: backend feat | |
return false; | |
}, | |
isWithin60Days: (ctx, evt) => { | |
return true; | |
}, | |
isWithinNext60Days: (ctx, evt) => { | |
return true; | |
}, | |
isPolicyValid: (ctx, evt) => { | |
return evt.policyValid; | |
}, | |
'isWithin60Days&isPolicyValid': applyEvery, | |
'isWithin60Days&isPolicyInvalid': applyEvery, | |
isPolicyInvalid: (ctx, evt) => { | |
return !evt.policyValid; | |
}, | |
isFiler: (ctx, evt) => { | |
return evt.relation === 'SELF'; | |
}, | |
isSpouse: (ctx, evt) => { | |
return evt.relation === 'SPOUSE'; | |
}, | |
isMultiMembers: (ctx, evt) => { | |
return evt.members?.length > 1; | |
}, | |
isFilerOrSpouse: (ctx, evt) => { | |
return evt.relation === 'SELF' || evt.relation === 'SPOUSE'; | |
}, | |
isOtherRelative: (ctx, evt) => { | |
return evt.relation !== 'SELF' && evt.relation !== 'SPOUSE'; | |
}, | |
gotDMI: (ctx, evt) => { | |
return evt.dmis && evt.dmis.length > 0; | |
}, | |
shouldKeepMember: (ctx, evt) => { | |
return evt.relation !== 'SELF' && !evt.removeMember; | |
}, | |
'isFiler&isMultiMembers': applyEvery, | |
'isFilerOrSpouse|shouldKeepMember': applyAny, | |
}; | |
const combine = type => ({ | |
type, | |
guards: type, | |
}); | |
const chart = Machine({ | |
id: CHART, | |
initial: LIFE_CHANGE_INTRO, | |
context: {}, | |
states: { | |
[LIFE_CHANGE_INTRO]: { | |
on: { | |
[START]: CHANGE_SELECTION, | |
}, | |
}, | |
[MANAGE_COVERAGE_INTRO]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: ADD_MEMBER_REASON, cond: 'isAddMember' }, | |
{ target: REMOVE_MEMBER_REASON, cond: 'isRemoveMember' }, | |
{ target: POLICY_CANCEL_PROMPT, cond: 'isCancelPolicy' }, | |
{ target: ENROLLMENT_FLOW }, | |
], | |
}, | |
}, | |
[CHANGE_SELECTION]: { | |
on: { | |
[SUBMIT]: [ | |
{ | |
target: BASICS_ENTRY, | |
cond: 'incomeChanged', | |
}, | |
{ | |
target: APP_REVIEW_INTRO, | |
cond: combine('isBirth|isAdoption|disabilityChanged'), | |
}, | |
{ target: ADDRESS_ENTRY, cond: 'addressChanged' }, | |
{ target: MEMBER_MARRIAGE, cond: 'memberMarried' }, | |
{ target: GOV_HANDOFF, cond: 'gotPregnant' }, | |
{ | |
target: DIVORCE_INTRO, | |
cond: 'isDivorce', | |
}, | |
{ target: DEATH_INTRO, cond: 'isDeath' }, | |
{ target: CUSTODY_INTRO, cond: 'custodyChanged' }, | |
{ target: COVERAGE_OPTIONS_INTRO, cond: 'coverageChanged' }, | |
{ | |
target: MEMBER_STATUS_CHANGE, | |
cond: combine( | |
'filingStatusChanged|citizenshipChanged|incarcerationChanged|tribeMembershipChanged', | |
), | |
}, | |
], | |
}, | |
}, | |
[BASICS_ENTRY]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: APP_REVIEW_INTRO, cond: 'updatedTaxHousehold' }, | |
{ target: INCOME_ENTRY }, | |
], | |
}, | |
}, | |
[INCOME_ENTRY]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: INCOME_NO_CHANGE, cond: 'prelimEligUnchanged' }, | |
{ | |
target: FINANCIAL_ASSISTANCE, | |
}, | |
], | |
[APPLY]: ENROLLMENT_FLOW, | |
}, | |
}, | |
[INCOME_NO_CHANGE]: { | |
on: { | |
[DONE]: PLAN_DETAIL, | |
[APPLY]: ENROLLMENT_FLOW, | |
}, | |
}, | |
[APP_REVIEW_INTRO]: { | |
on: { | |
[NEXT]: ENROLLMENT_FLOW, | |
[DISMISS]: PLAN_DETAIL, | |
}, | |
}, | |
[DIVORCE_INTRO]: { | |
on: { | |
[NEXT]: MEMBER_DIVORCE, | |
}, | |
}, | |
[MEMBER_DIVORCE]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: GOV_HANDOFF, cond: 'isOtherRelative' }, | |
{ target: REMOVING_MEMBERS, cond: 'isSpouse' }, | |
{ target: APP_REVIEW_INTRO }, | |
], | |
}, | |
}, | |
[DEATH_INTRO]: { | |
on: { | |
[NEXT]: MEMBER_DEATH, | |
}, | |
}, | |
[MEMBER_DEATH]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: NEW_PLAN_INTRO, cond: combine('isFiler&isMultiMembers') }, | |
{ target: POLICY_CANCEL_PROMPT, cond: 'isFiler' }, | |
{ target: REMOVING_MEMBERS }, | |
], | |
}, | |
}, | |
[CUSTODY_INTRO]: { | |
on: { | |
[NEXT]: MEMBER_CUSTODY, | |
}, | |
}, | |
[MEMBER_CUSTODY]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: GOV_HANDOFF, cond: 'shouldKeepMember' }, | |
{ target: REMOVING_MEMBERS }, | |
], | |
}, | |
}, | |
[COVERAGE_OPTIONS_INTRO]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: MEMBER_JOB_COVERAGE, cond: 'offeredJobCoverage' }, | |
{ target: APP_REVIEW_INTRO, cond: 'gainedCoverage' }, | |
{ target: MEMBER_COVERAGE_LOSS, cond: 'lostCoverage' }, | |
{ target: MEMBER_FUTURE_COVERAGE_LOSS, cond: 'willLoseCoverage' }, | |
], | |
}, | |
}, | |
[ADDRESS_ENTRY]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: ADDRESS_NO_CHANGE, cond: 'movedParamsUnchanged' }, | |
{ target: STATE_HANDOFF, cond: 'movedToStateMarketplace' }, | |
{ | |
target: MOVE_DATE_ENTRY, | |
}, | |
], | |
}, | |
}, | |
[MOVE_DATE_ENTRY]: { | |
on: { | |
[SUBMIT]: [ | |
{ | |
target: SEP_KEEP_OR_APPLY, | |
cond: combine('isWithin60Days&isPolicyValid'), | |
}, | |
{ | |
target: SEP_MUST_APPLY, | |
cond: combine('isWithin60Days&isPolicyInvalid'), | |
}, | |
{ | |
target: SEP_MOVE_OUTDATED_POLICY_VALID, | |
cond: 'isPolicyValid', | |
}, | |
{ | |
target: SEP_MOVE_OUTDATED, | |
}, | |
], | |
}, | |
}, | |
[STATE_HANDOFF]: { | |
on: { | |
[OPEN_URL]: STATE_PICKUP, | |
}, | |
}, | |
[STATE_PICKUP]: { | |
on: { | |
[DONE]: PLAN_DETAIL, | |
[CANCEL_POLICY]: POLICY_CANCEL_PROMPT, | |
}, | |
}, | |
[POLICY_CANCEL_PROMPT]: { | |
on: { | |
[DISMISS]: HISTORY, | |
}, | |
}, | |
[ADDRESS_NO_CHANGE]: { | |
on: { | |
[DONE]: PLAN_DETAIL, | |
}, | |
}, | |
[SEP_MOVE_OUTDATED]: { | |
on: { | |
[NEXT]: POLICY_INVALID, | |
[APPLY]: ENROLLMENT_FLOW, | |
}, | |
}, | |
[SEP_OUTDATED]: { | |
on: {}, | |
}, | |
[POLICY_INVALID]: { | |
on: { | |
[CANCEL_POLICY]: POLICY_CANCEL_PROMPT, | |
[DISMISS]: PLAN_DETAIL, | |
}, | |
}, | |
[SEP_KEEP_OR_APPLY]: { | |
on: { | |
[APPLY]: ENROLLMENT_FLOW, | |
[DISMISS]: PLAN_DETAIL, | |
}, | |
}, | |
[SEP_MUST_APPLY]: { | |
on: { | |
[DISMISS]: PLAN_DETAIL, | |
[APPLY]: ENROLLMENT_FLOW, | |
}, | |
}, | |
[SEP_MOVE_OUTDATED_POLICY_VALID]: { | |
on: { | |
[DONE]: PLAN_DETAIL, | |
[APPLY]: ENROLLMENT_FLOW, | |
}, | |
}, | |
[GOV_HANDOFF]: { | |
on: { | |
[OPEN_URL]: GOV_PICKUP, | |
}, | |
}, | |
[GOV_PICKUP]: { | |
on: { | |
[DONE]: PLAN_DETAIL, | |
}, | |
}, | |
[MEMBER_MARRIAGE]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: GOV_HANDOFF, cond: 'shouldKeepMember' }, | |
{ target: APP_REVIEW_INTRO, cond: 'isFiler' }, | |
{ target: REMOVING_MEMBERS }, | |
], | |
}, | |
}, | |
[MEMBER_JOB_COVERAGE]: { | |
on: { | |
[SUBMIT]: [ | |
{ | |
target: GOV_HANDOFF, | |
cond: combine('isFilerOrSpouse|shouldKeepMember'), | |
}, | |
{ target: REMOVING_MEMBERS }, | |
], | |
}, | |
}, | |
[MEMBER_COVERAGE_LOSS]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: APP_REVIEW_INTRO, cond: 'isWithin60Days' }, | |
{ target: SEP_OUTDATED }, | |
], | |
}, | |
}, | |
[MEMBER_FUTURE_COVERAGE_LOSS]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: APP_REVIEW_INTRO, cond: 'isWithinNext60Days' }, | |
{ target: SEP_OUTDATED }, | |
], | |
}, | |
}, | |
[MEMBER_STATUS_CHANGE]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: APP_REVIEW_INTRO, cond: 'isWithin60Days' }, | |
{ target: GOV_HANDOFF, cond: 'isNotPhase1' }, | |
{ target: SEP_OUTDATED }, | |
], | |
}, | |
}, | |
[REMOVING_MEMBERS]: { | |
on: { | |
[DONE]: APP_REVIEW_INTRO, | |
}, | |
}, | |
[FINANCIAL_ASSISTANCE]: { | |
on: { | |
[NEXT]: INCOME_FLOW, | |
}, | |
}, | |
[NEW_PLAN_INTRO]: { | |
on: { | |
[NEXT]: ENROLLMENT_FLOW, | |
}, | |
}, | |
[ADD_MEMBER_REASON]: { | |
on: { | |
[SUBMIT]: [ | |
{ | |
target: APP_REVIEW_INTRO, | |
cond: combine('isBirth|isAdoption|disabilityChanged'), | |
}, | |
{ | |
target: MEMBER_STATUS_CHANGE, | |
cond: combine('citizenshipChanged|incarcerationChanged'), | |
}, | |
{ target: MEMBER_COVERAGE_LOSS, cond: 'lostCoverage' }, | |
{ target: MEMBER_MARRIAGE, cond: 'memberMarried' }, | |
], | |
}, | |
}, | |
[REMOVE_MEMBER_REASON]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: MEMBER_CUT, cond: combine('childTurned26|isOther') }, | |
{ target: MEMBER_JOB_COVERAGE, cond: 'offeredJobCoverage' }, | |
{ | |
target: APP_REVIEW_INTRO, | |
cond: combine('gainedCoverage|disabilityChanged'), | |
}, | |
{ | |
target: DIVORCE_INTRO, | |
cond: 'isDivorce', | |
}, | |
{ target: DEATH_INTRO, cond: 'isDeath' }, | |
{ target: CUSTODY_INTRO, cond: 'custodyChanged' }, | |
{ | |
target: MEMBER_STATUS_CHANGE, | |
cond: combine('filingStatusChanged|incarcerationChanged'), | |
}, | |
], | |
}, | |
}, | |
[MEMBER_CUT]: { | |
on: { | |
[SUBMIT]: [ | |
{ target: GOV_HANDOFF, cond: 'shouldKeepMember' }, | |
{ target: REMOVING_MEMBERS }, | |
], | |
}, | |
}, | |
[INCOME_FLOW]: { | |
type: 'redirect', | |
}, | |
[ENROLLMENT_FLOW]: { | |
type: 'redirect', | |
}, | |
[PLAN_DETAIL]: { | |
type: 'exit', | |
}, | |
[HISTORY]: { | |
type: 'history', | |
}, | |
}, | |
}, | |
{ | |
guards, | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment