import type { SequenceView } from "@fanfare-io/fanfare-sdk-core/experiences";
function renderSequence(sequence: SequenceView) {
if (sequence.phase === "scheduled") {
showUpcoming({
startsAt: sequence.startsAt,
});
// Waitlist is now a scheduled-phase attachment, not a mechanism or phase.
// See [Journey State](/sdk/core/journey-state) for the full model.
const waitlist = sequence.waitlist;
if (waitlist) {
showWaitlist({
status: waitlist.status,
onJoin: () => waitlist.join(),
onLeave: () => waitlist.leave(),
});
}
return;
}
if (sequence.phase === "enterable") {
if ("enter" in sequence) {
showEnterButton(() => sequence.enter());
} else if (sequence.mechanism === "auction") {
showBidForm((amount) => sequence.bid(amount));
} else if (sequence.mechanism === "appointment") {
showAppointmentPicker((slotId, locationId) => sequence.book(slotId, locationId));
}
return;
}
if (sequence.phase === "participating") {
// Live participating data is read from the `display$` atom, not the view itself.
const unsubscribeDisplay = sequence.display$.listen((display) => {
showLiveParticipation({ type: sequence.mechanism, display });
});
if (sequence.mechanism === "appointment") {
showAppointmentControls({
onReschedule: (slotId, locationId) => sequence.reschedule(slotId, locationId),
onCancel: (reason) => sequence.cancel(reason),
});
} else {
// queue, draw, and timed_release can leave; auction can leave and also raise its bid.
showParticipationControls({
onLeave: "leave" in sequence ? () => sequence.leave() : undefined,
onBid: sequence.mechanism === "auction" ? (amount) => sequence.bid(amount) : undefined,
});
}
return unsubscribeDisplay;
}
if (sequence.phase === "granted") {
// claim() starts checkout and stops the client-side grant-expiry countdown.
const grant = sequence.claim();
goToCheckout(grant.token);
return;
}
if (sequence.phase === "ended") {
showEnded({ reason: sequence.outcome.type });
}
}