Skip to content

Instantly share code, notes, and snippets.

@tmikeschu
Created February 4, 2020 22:09
Show Gist options
  • Save tmikeschu/8397ee95510ff87d4877dcdb50277eb1 to your computer and use it in GitHub Desktop.
Save tmikeschu/8397ee95510ff87d4877dcdb50277eb1 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
const BOOK_OR_REVIEW = { BOOK: '#schedule', DATES: '#dates' };
const machine = Machine({
id: 'app',
initial: 'fetchAttendee',
context: {
lastScreen: 'schedule',
friendId: undefined,
friendTimeId: undefined,
someoneNewTimes: new Set(),
someoneNewInterests: new Set(),
attendee: null,
meetings: [],
apiBaseUrl: '',
token: '',
pendingMatchesCount: 0,
meetingId: undefined,
attendees: [],
newMeetings: false,
meetingTimes: [],
graphqlClient: {},
topics: [],
markMeetingsAsSeen: false,
},
entry: ['setBaseUrl', 'setToken'],
states: {
fetchAttendee: {
invoke: {
id: 'fetchAttendee',
src: 'fetchAttendee',
onDone: { target: 'fetchMeetings', actions: ['setAttendee'] },
onError: {
actions: () => {
throw new Error('Unable to fetch attendee');
},
},
},
},
fetchMeetings: {
on: { CONCAT_MEETINGS: { actions: ['concatMeetings'] } },
invoke: {
id: 'meetingsApiMachine',
src: 'meetingsApiMachine',
data: ({ attendee, graphqlClient }) => ({
attendee,
graphqlClient,
}),
onDone: { target: 'codeOfConduct' },
},
},
codeOfConduct: {
on: {
'': { target: 'schedule', cond: 'hasAcceptedCodeOfConduct' },
SCHEDULE: { target: 'schedule', cond: 'hasAcceptedCodeOfConduct' },
},
},
schedule: {
id: 'schedule',
initial: 'home',
entry: 'setLastToSchedule',
on: {
DATES: 'dates',
SCHEDULE: 'schedule',
SETTINGS: 'settings',
},
states: {
hist: { type: 'history', history: 'deep' },
home: {
entry: ['clearState'],
on: { FRIEND: 'friend', SOMEONE_NEW: 'someoneNew' },
},
friend: {
initial: 'fetchAttendees',
states: {
fetchAttendees: {
invoke: {
id: 'fetchAttendees',
src: 'fetchAttendees',
onDone: {
target: 'person',
actions: assign({ attendees: (_, event) => event.data }),
},
},
},
person: {
on: {
SELECT_FRIEND: { actions: ['setSelectedFriend'] },
TIME: {
target: 'fetchTimes',
cond: 'friendSelected',
},
},
},
fetchTimes: {
invoke: {
id: 'fetchTimes',
src: 'fetchTimes',
onDone: { target: 'time', actions: ['setMeetingTimes'] },
},
},
time: {
on: {
SELECT_TIME: { actions: ['setSelectedFriendTime'] },
RESERVE_FRIEND: {
target: 'reserve',
cond: 'friendTimeSelected',
},
},
},
reserve: {
invoke: {
id: 'reserveFriend',
src: 'reserveFriend',
onDone: { target: 'reserved', actions: 'addMeeting' },
},
},
reserved: { on: BOOK_OR_REVIEW },
},
},
someoneNew: {
initial: 'fetchTimes',
states: {
fetchTimes: {
invoke: {
id: 'fetchTimes',
src: 'fetchTimes',
onDone: { target: 'times', actions: ['setMeetingTimes'] },
},
},
times: {
on: {
INTERESTS: {
target: 'fetchTopics',
cond: 'someoneNewTimesSelected',
},
SELECT_SOMEONE_NEW_TIME: {
actions: ['setSelectedSomeoneNewTimes'],
},
},
},
fetchTopics: {
invoke: {
id: 'fetchTopics',
src: 'fetchTopics',
onDone: { target: 'interests', actions: ['setTopics'] },
},
},
interests: {
on: {
RESERVE_SOMEONE_NEW: 'reserve',
SELECT_SOMEONE_NEW_INTEREST: {
actions: ['setSelectedSomeoneNewInterests'],
},
},
},
reserve: {
invoke: {
id: 'reserveSomeoneNew',
src: 'reserveSomeoneNew',
onDone: [
{
target: 'reserved.instant',
actions: ['addMeeting', 'setSelectedFriend'],
cond: 'instantMatch',
},
{ target: 'reserved.magic', actions: ['addMeeting'] },
],
},
},
reserved: {
initial: 'magic',
states: {
magic: { on: BOOK_OR_REVIEW },
instant: { on: BOOK_OR_REVIEW },
},
},
},
},
},
},
dates: {
id: 'dates',
initial: 'home',
entry: ['setLastToDates'],
on: {
CONCAT_MEETINGS: { actions: ['concatMeetings'] },
SET_PENDING_MATCHES: {
actions: assign({
pendingMatchesCount: ({ pendingMatchesCount }, event) =>
event.type === 'SET_PENDING_MATCHES'
? event.data
: pendingMatchesCount,
}),
},
SCHEDULE: 'schedule.hist',
DATES: 'dates',
SETTINGS: 'settings',
SET_MEETING_ID: {
actions: assign({
meetingId: ({ meetingId }, event) =>
event.type === 'SET_MEETING_ID' ? event.data : meetingId,
}),
},
},
states: {
hist: { type: 'history', history: 'deep' },
home: {
initial: 'init',
on: {
DECLINE: 'decline',
CANCEL: 'cancel',
DISMISS: 'dismissMeeting',
},
invoke: {
id: 'meetingsApiMachine',
src: 'meetingsApiMachine',
data: ({ attendee, graphqlClient }) => ({
attendee,
graphqlClient,
}),
},
states: {
init: {
after: {
2000: 'seen',
},
},
seen: {
exit: ['setMeetingsSeen'],
invoke: {
id: 'markMeetingsSeen',
src: 'markMeetingsSeen',
onDone: { actions: ['queueMeetingsForMarkedAsSeen'] },
},
},
},
},
dismissMeeting: {
invoke: {
id: 'dismissMeeting',
src: 'dismissMeeting',
onDone: {
target: 'home',
actions: assign({
meetings: ({ meetings }, event) => {
return meetings.filter(m => m.uuid !== event.data.uuid);
},
}),
},
},
},
decline: {
initial: 'confirm',
states: {
confirm: {
on: { DECLINE_CONFIRM: 'declineMeeting', CANCEL: '#dates' },
},
declineMeeting: {
invoke: {
id: 'declineMeeting',
src: 'declineMeeting',
onDone: { target: 'reason', actions: ['setMeeting'] },
},
},
reason: {
on: {
NOT_AVAILABLE: 'becauseNotAvailable',
NOT_INTERESTED: 'becauseNotInterested',
},
},
becauseNotAvailable: {
invoke: {
id: 'becauseNotInterested',
src: 'updateRejection',
onDone: {
target: 'notAvailable',
actions: ['setMeeting'],
},
},
},
becauseNotInterested: {
invoke: {
id: 'becauseNotInterested',
src: 'updateRejection',
onDone: {
target: 'notInterested',
actions: ['setMeeting'],
},
},
},
notAvailable: { on: BOOK_OR_REVIEW },
notInterested: { on: BOOK_OR_REVIEW },
},
},
cancel: {
initial: 'confirm',
states: {
confirm: {
on: { DECLINE_CONFIRM: 'declineMeeting', CANCEL: '#dates' },
},
declineMeeting: {
invoke: {
id: 'declineMeeting',
src: 'declineMeeting',
onDone: { target: 'declined', actions: ['setMeeting'] },
},
},
declined: { on: { BOOK: '#schedule', DATES: '#dates' } },
},
},
},
},
settings: {
initial: 'home',
on: {
CLOSE: [
{ target: 'schedule..hist', cond: 'wasSchedule' },
{ target: 'dates.hist', cond: 'wasDates' },
{ target: 'schedule' },
],
},
states: {
home: { on: { TOGGLE_ALLOW_MEETINGS: 'toggleAllowMeetings' } },
toggleAllowMeetings: {
invoke: {
id: 'toggleAllowMeetings',
src: 'toggleAllowMeetings',
onDone: { target: 'home', actions: ['toggleAllowMeetings'] },
},
},
},
},
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment