Skip to content

Instantly share code, notes, and snippets.

@WinstonFassett
Created June 21, 2023 21:32
Show Gist options
  • Save WinstonFassett/8fba85662a4cc4dde9fcdb78b661cd2d to your computer and use it in GitHub Desktop.
Save WinstonFassett/8fba85662a4cc4dde9fcdb78b661cd2d to your computer and use it in GitHub Desktop.
Checkout V2
Checkout V2
Completing Checkout Requirements&
Checkout Mode
Checking out as Guest*
got new Email -> Trying One-Click Auth
is Guest Initially
Initializing Possible User
no valid Session -> Awaiting Email
valid Session -> Started with Valid Session
Awaiting Email
got new Email -> Trying One-Click Auth
Trying One-Click Auth
Submitting Email for One Click
sent OTP -> Awaiting OTP
email unrecognized -> Continuing as Guest
Showing Overlay
continueAsGuest -> Continuing as Guest
Awaiting OTP
submit OTP -> Submitting OTP
Submitting OTP
valid OTP -> Continuing as User via One-Click
invalid OTP -> Notifying OTP Failure
Notifying OTP Failure
ok -> Continuing as Guest
retry if allowed -> Requesting Another OTP
Requesting Another OTP
sent OTP -> Awaiting OTP
Continuing as Guest
Checking out as User
continue as Guest -> Continuing as Guest
Started with Valid Session
Continuing as User via One-Click
Contact
backfill Contact -> Got Valid Contact
Awaiting Contact&
valid Contact -> Got Valid Contact
Email
Awaiting Contact Email
got new Email -> Got Contact Email
Got Contact Email
Full Name
Awaiting Full Name
got Full Name -> Got Full Name
Got Full Name
Got Valid Contact
Shipping
backfill Shipping -> Got Valid Shipping
Awaiting Shipping
valid Shipping -> Got Valid Shipping
Got Valid Shipping
all done -> Final Review
Billing
backfill Billing -> Got Valid Billing
Awaiting Billing
valid Billing -> Got Valid Billing
Got Valid Billing
all done -> Final Review
Payment
Awaiting Valid Payment
No Payment Methods
Awaiting Payment Method
Showing Payment Methods
select Payment Method -> Validating Selected Payment
Validating Selected Payment
valid Payment -> Got Valid Payment
invalid Payment -> Awaiting Valid Payment
entered Payment Method -> Validating Selected Payment
backfill Payment Methods -> Showing Payment Methods
select Payment Method -> Validating Selected Payment
Got Valid Payment
all done -> Final Review
Final Review
finalize Purchase -> Submitting Purchase
Submitting Purchase
purchase Complete -> Checkout Complete
purchase Failed -> Notifying Purchase Failed
Notifying Purchase Failed
retry -> Completing Checkout Requirements
Checkout Complete
function getActiveStateTree (model) {
// return tree of active states
return { name: model.name, children: model.children && model.children
.filter(child => child.is_active)
.map((child) => (getActiveStateTree(child)))
}
}
function renderStateTree (tree) {
// console.log({tree})
return $('div', {}, [
$('p', {}, tree.name),
tree.children && $('ul', {}, tree.children.map(renderStateTree))
])
}
function getRootState(state) {
while (state.parent && state.parent.name !== 'Completing Checkout Requirements') { state = state.parent }
return state
}
function renderOverlay (model) {
return model.states['Showing Overlay'].is_active && $('div', {
style: {
position: 'absolute',
top: 0, left: 0, right: 0, bottom: 0,
backgroundColor: 'rgba(0,0,0)',
color: 'white',
display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
}
}, [
'Overlay!',
model.states['Awaiting OTP'].is_active && $('div', {}, [
$('input', { placeholder: 'Enter OTP'}),
$('button', { onClick: () => { model.emit("submit OTP") }}, 'submit otp')
]),
model.states['Submitting OTP'].is_active && $('div', {}, 'submitting OTP...'),
model.states['Notifying OTP Failure'].is_active && $('div', {}, [
'error!!',
$('button', { onClick: () => { model.emit('retry if allowed') } }, 'retry'),
]),
model.states['Requesting Another OTP'].is_active && $('div', {}, 'requesting another OTP...'),
$('button', { onClick: () => model.emit('continueAsGuest')}, 'continue as guest'),
])
}
function render(model){
globalThis.model = model
console.log({ model })
if (model.states['Validating Selected Payment'].is_active) {
setTimeout(() => { model.emit('valid Payment') }, 1000)
} else if (model.states['Submitting Purchase'].is_active) {
setTimeout(() => { model.emit('purchase Complete') }, 1000)
} else if (model.states['Submitting Email for One Click'].is_active) {
setTimeout(() => { model.emit('sent OTP') }, 1000)
} else if (model.states['Submitting OTP'].is_active) {
setTimeout(() => { model.emit('valid OTP') }, 1000)
}
if (
model.states['Awaiting Contact'].is_active &&
model.states['Got Contact Email'].is_active &&
model.states['Got Full Name'].is_active
) {
model.emit('valid Contact')
}
const tree = getActiveStateTree(model.root.children[0])
return $('div', { }, [
$('div', {style: { position: 'relative' }}, [
$('h2', 'Checkout UX'),
model.states['Completing Checkout Requirements'].is_active && $('div', {}, [
$('h3', model.states['Checkout Mode'].children.find(it => it.is_active).name),
model.states['Awaiting Contact'].is_active && $('div', {}, [
$('input', { placeholder: 'Enter Email'}),
$('button', { onClick: () => { model.emit("got new Email") }}, 'submit email'),
model.states['Got Contact Email'].is_active && ' ✅'
]),
model.states['Got Valid Contact'].is_active ?
$('div', '✅ Got Valid Contact') :
$('div', {}, [
$('input', { placeholder: 'Enter Full Name'}),
$('button', { onClick: () => { model.emit("got Full Name") }}, 'submit full name'),
model.states['Got Full Name'].is_active && ' ✅'
]),
model.states['Awaiting Shipping'].is_active ? $('div', {}, [
$('input', { placeholder: 'Enter Shipping Details'}),
$('button', { onClick: () => { model.emit("valid Shipping") }}, 'submit contact')
]) : $('div', '✅ Shipping Ready'),
model.states['Awaiting Billing'].is_active ? $('div', {}, [
$('input', { placeholder: 'Enter Billing Details'}),
$('button', { onClick: () => { model.emit("valid Billing") }}, 'submit billing')
]): $('div', '✅ Billing Ready'),
model.states['Awaiting Valid Payment'].is_active &&
(model.states['No Payment Methods'].is_active ||
model.states['Showing Payment Methods'].is_active) && $('div', {}, [
$('input', { placeholder: 'Add Payment Method'}),
$('button', { onClick: () => { model.emit("entered Payment Method") }}, 'submit new payment method')
]),
model.states['Validating Selected Payment'].is_active && $('div', {}, [
'Validating Selected Payment...'
]),
model.states['Got Valid Payment'].is_active && $('div', {}, [
'✅ Payment Ready'
]),
!model.states['Awaiting Billing'].is_active &&
!model.states['Awaiting Shipping'].is_active &&
!model.states['Awaiting Contact'].is_active &&
!model.states['Awaiting Valid Payment'].is_active &&
$('button', { onClick: () => model.emit('all done')}, 'Check Out!'),
]),
model.states['Final Review'].is_active && $('div', {}, [
$('h3', 'Final Review'),
$('button', { onClick: () => model. emit('finalize Purchase')}, 'Confirm Checkout!')
]),
renderOverlay(model),
]),
model.states['Submitting Purchase'].is_active && $('div', {}, [
'Submitting Purchase....'
]),
model.states['Checkout Complete'].is_active && $('h3', {}, [
'✅ All Done!!'
]),
<hr />,
$('div', {}, [
$('h2', 'process state'),
$('h3', 'Active Checkout Area(s)'),
$('ul', {}, model.active_states.map(state => $('li', {}, [getRootState(state).name, '? ', state.name]))),
]),
...[],
// ...tree.children.map(renderStateTree)
])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment