Created
February 6, 2020 04:49
-
-
Save flybayer/7d335c34294f9cda5b4784409daeaa4f to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
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
| const checkoutAppMachine = Machine( | |
| { | |
| id: "checkoutApp", | |
| initial: "studentEntry", | |
| strict: true, | |
| context: { | |
| currentStepNumber: 0, | |
| account: { | |
| authenticated: false, | |
| }, | |
| customer: { | |
| first_name: "", | |
| last_name: "", | |
| timezone: "", | |
| email: "", | |
| phone: "", | |
| address1: "", | |
| city: "", | |
| state: "", | |
| zip_code: "", | |
| agree_to_terms: false, | |
| }, | |
| students: [], | |
| bookings: { | |
| reading: undefined, | |
| math: undefined, | |
| language: undefined, | |
| science: undefined, | |
| screening: undefined, | |
| }, | |
| existingOrders: [], | |
| someoneTakingLanguage: false, | |
| someoneTakingScience: false, | |
| editingExistingOrder: undefined, | |
| isScreeningMode: false, | |
| addons: { | |
| resultsConsultation: false, | |
| }, | |
| }, | |
| states: { | |
| studentEntry: { | |
| type: "atomic", | |
| entry: assign({ currentStepNumber: 0 }), | |
| on: { | |
| CHANGE_STUDENTS: { | |
| actions: assign((context, event) => { | |
| const students = event.value | |
| const someoneTakingLanguage = | |
| students.some(student => student.tests.language) && !context.isScreeningMode | |
| const someoneTakingScience = | |
| students.some(student => student.tests.science) && !context.isScreeningMode | |
| const newBookings = {} | |
| // This ensures bookings are cleared if someone | |
| // selected one of these tests and later remove it | |
| // But only if not joining a group which already has bookings | |
| if (!context.joinGroup) { | |
| if (!someoneTakingLanguage) newBookings.language = undefined | |
| if (!someoneTakingScience) newBookings.science = undefined | |
| } | |
| return { | |
| students, | |
| someoneTakingLanguage, | |
| someoneTakingScience, | |
| bookings: { | |
| ...context.bookings, | |
| ...newBookings, | |
| }, | |
| } | |
| }), | |
| }, | |
| CHANGE_ACCOUNT: { | |
| actions: assign((context, event) => { | |
| return { | |
| account: { | |
| ...context.account, | |
| ...event.value, | |
| }, | |
| } | |
| }), | |
| }, | |
| CHANGE_CUSTOMER: { | |
| actions: assign((context, event) => { | |
| return { | |
| customer: { | |
| ...context.customer, | |
| ...event.value, | |
| }, | |
| } | |
| }), | |
| }, | |
| CHANGE_ORDERS: { | |
| actions: assign((context, event) => { | |
| return { | |
| existingOrders: event.value, | |
| } | |
| }), | |
| }, | |
| CHANGE_BOOKINGS: { | |
| actions: assign((context, event) => { | |
| return { | |
| bookings: { ...context.bookings, ...event.bookings }, | |
| } | |
| }), | |
| }, | |
| EDIT_EXISTING_ORDER: { | |
| actions: assign((context, event) => { | |
| return { | |
| editingExistingOrder: event.value, | |
| isScreeningMode: !!event.value.bookings.screening, | |
| addons: event.value.addons, | |
| } | |
| }), | |
| }, | |
| CHANGE_BOOK_GROUP: { | |
| target: "scheduling", | |
| actions: assign((context, event) => { | |
| return { bookGroup: event.value, students: [] } | |
| }), | |
| }, | |
| CHANGE_JOIN_GROUP: { | |
| actions: assign((context, event) => { | |
| return { joinGroup: event.value } | |
| }), | |
| }, | |
| CHANGE_SCREENING_MODE: { | |
| actions: assign((context, event) => { | |
| return { isScreeningMode: event.value } | |
| }), | |
| }, | |
| CHANGE_CONSULTATION_ADDON: { | |
| actions: assign((context, event) => { | |
| return { addons: { ...context.addons, resultsConsultation: event.value } } | |
| }), | |
| }, | |
| NEXT: "scheduling", | |
| }, | |
| }, | |
| scheduling: { | |
| type: "compound", | |
| entry: assign({ currentStepNumber: 1 }), | |
| on: { | |
| CHANGE_BOOKINGS: { | |
| actions: assign({ | |
| bookings: (context, event) => ({ ...context.bookings, ...event.bookings }), | |
| }), | |
| }, | |
| CHANGE_NEED_LANGUAGE: { | |
| target: ".default", | |
| actions: assign((context, event) => { | |
| return { | |
| someoneTakingLanguage: event.value, | |
| bookings: { ...context.bookings, language: undefined }, | |
| } | |
| }), | |
| }, | |
| CHANGE_NEED_SCIENCE: { | |
| target: ".default", | |
| actions: assign((context, event) => { | |
| return { | |
| someoneTakingScience: event.value, | |
| bookings: { ...context.bookings, science: undefined }, | |
| } | |
| }), | |
| }, | |
| NEXT: "checkout", | |
| "SCHEDULE.READING": "scheduling.reading", | |
| "SCHEDULE.MATH": "scheduling.math", | |
| "SCHEDULE.LANGUAGE": "scheduling.language", | |
| "SCHEDULE.SCIENCE": "scheduling.science", | |
| "NAVIGATE.STUDENT_ENTRY": { target: "studentEntry", cond: "notBookingGroup" }, | |
| }, | |
| initial: "default", | |
| states: { | |
| default: { | |
| on: { | |
| "": [ | |
| { target: "review", cond: "bookingComplete" }, | |
| { | |
| target: "screening", | |
| cond: { | |
| type: "needTestAndNeedScheduled", | |
| testName: "screening", | |
| }, | |
| }, | |
| { | |
| target: "reading", | |
| cond: { | |
| type: "needTestAndNeedScheduled", | |
| testName: "reading", | |
| }, | |
| }, | |
| { | |
| target: "math", | |
| cond: { | |
| type: "needTestAndNeedScheduled", | |
| testName: "math", | |
| }, | |
| }, | |
| { | |
| target: "language", | |
| cond: { | |
| type: "needTestAndNeedScheduled", | |
| testName: "language", | |
| }, | |
| }, | |
| { | |
| target: "science", | |
| cond: { | |
| type: "needTestAndNeedScheduled", | |
| testName: "science", | |
| }, | |
| }, | |
| ], | |
| }, | |
| }, | |
| screening: { | |
| entry: assign({ | |
| bookings: (context, event) => | |
| context.editingExistingOrder | |
| ? context.bookings | |
| : ({ | |
| ...context.bookings, | |
| screening: undefined, | |
| }), | |
| }), | |
| on: { | |
| NEXT: "review", | |
| }, | |
| }, | |
| reading: { | |
| entry: assign({ | |
| bookings: (context, event) => | |
| context.editingExistingOrder | |
| ? context.bookings | |
| : ({ | |
| ...context.bookings, | |
| math: undefined, | |
| language: undefined, | |
| science: undefined, | |
| screening: undefined, | |
| }), | |
| }), | |
| on: { | |
| NEXT: [{ target: "review", cond: "bookingComplete" }, { target: "math" }], | |
| }, | |
| }, | |
| math: { | |
| entry: assign({ | |
| bookings: (context, event) => | |
| context.editingExistingOrder | |
| ? context.bookings | |
| : ({ | |
| ...context.bookings, | |
| language: undefined, | |
| science: undefined, | |
| }), | |
| }), | |
| on: { | |
| NEXT: [ | |
| { target: "review", cond: "bookingComplete" }, | |
| { | |
| target: "language", | |
| cond: { | |
| type: "needTest", | |
| testName: "language", | |
| }, | |
| }, | |
| { | |
| target: "science", | |
| cond: { | |
| type: "needTest", | |
| testName: "science", | |
| }, | |
| }, | |
| ], | |
| }, | |
| }, | |
| language: { | |
| entry: assign({ | |
| bookings: (context, event) => | |
| context.editingExistingOrder | |
| ? context.bookings | |
| : ({ | |
| ...context.bookings, | |
| science: undefined, | |
| }), | |
| }), | |
| on: { | |
| NEXT: [ | |
| { target: "review", cond: "bookingComplete" }, | |
| { | |
| target: "science", | |
| cond: { | |
| type: "needTest", | |
| testName: "science", | |
| }, | |
| }, | |
| ], | |
| }, | |
| }, | |
| science: { | |
| on: { | |
| NEXT: "review", | |
| }, | |
| }, | |
| review: {}, | |
| }, | |
| }, | |
| checkout: { | |
| type: "atomic", | |
| entry: assign({ currentStepNumber: 2 }), | |
| on: { | |
| CHANGE_CONSULTATION_ADDON: { | |
| actions: assign((context, event) => { | |
| return { addons: { ...context.addons, resultsConsultation: event.value } } | |
| }), | |
| }, | |
| "NAVIGATE.STUDENT_ENTRY": { target: "studentEntry", cond: "notBookingGroup" }, | |
| "NAVIGATE.SCHEDULING": "scheduling.review", | |
| SUCCESS: "checkoutSuccess", | |
| }, | |
| }, | |
| checkoutSuccess: { | |
| type: "final", | |
| }, | |
| }, | |
| }, | |
| { | |
| actions: {}, | |
| guards: { | |
| needTest: (context, event, { cond }) => { | |
| switch (cond.testName) { | |
| case "screening": | |
| if (context.isScreeningMode) { | |
| return true | |
| } | |
| return false | |
| case "language": | |
| return context.someoneTakingLanguage | |
| case "science": | |
| return context.someoneTakingScience | |
| default: | |
| return true | |
| } | |
| }, | |
| needTestAndNeedScheduled: (context, event, { cond }) => { | |
| let needTest | |
| switch (cond.testName) { | |
| case "screening": | |
| if (context.isScreeningMode) { | |
| needTest = true | |
| } | |
| break | |
| case "language": | |
| needTest = context.someoneTakingLanguage | |
| break | |
| case "science": | |
| needTest = context.someoneTakingScience | |
| break | |
| default: | |
| needTest = true | |
| } | |
| return needTest && !context.bookings[cond.testName] | |
| }, | |
| bookingComplete: (context, event) => { | |
| if (context.isScreeningMode && context.bookings.screening) return true | |
| if (!context.bookings.reading) return false | |
| if (!context.bookings.math) return false | |
| if (context.someoneTakingLanguage && !context.bookings.language) return false | |
| if (context.someoneTakingScience && !context.bookings.science) return false | |
| return true | |
| }, | |
| isBookingGroup: (context, event) => { | |
| return !!context.bookGroup | |
| }, | |
| notBookingGroup: (context, event) => { | |
| return !context.bookGroup | |
| }, | |
| isJoiningGroup: (context, event) => { | |
| return !!context.joinGroup | |
| }, | |
| }, | |
| } | |
| ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment