Apply guided scheduling interface patterns

This commit is contained in:
2026-08-03 08:29:29 +02:00
parent 3e9a14a970
commit 3d8272b28e
7 changed files with 225 additions and 4 deletions
@@ -35,6 +35,21 @@ export type SchedulingRequestGroups = {
other: SchedulingRequest[];
};
export type SchedulingLifecycleStageId = "prepare" | "participate" | "decide";
export type SchedulingLifecycleStageState =
| "complete"
| "current"
| "locked"
| "stopped";
export type SchedulingLifecycleStage = {
id: SchedulingLifecycleStageId;
state: SchedulingLifecycleStageState;
current: boolean;
locked: boolean;
};
export type SchedulingSortPhase =
| "unanswered"
| "answered"
@@ -282,6 +297,37 @@ export function schedulingRequestIsPast(
return slotEnds.every((value) => Number.isFinite(value) && value < now.getTime());
}
export function schedulingLifecycleStages(
status: SchedulingRequest["status"]
): SchedulingLifecycleStage[] {
const currentIndex = status === "draft"
? 0
: status === "collecting" || status === "cancelled"
? 1
: 2;
const completedThrough = status === "draft"
? -1
: status === "collecting" || status === "cancelled"
? 0
: status === "closed"
? 1
: 2;
const stopped = status === "cancelled";
return (["prepare", "participate", "decide"] as const).map((id, index) => {
const current = index === currentIndex;
const locked = index > completedThrough + 1;
const state: SchedulingLifecycleStageState = stopped && current
? "stopped"
: index <= completedThrough
? "complete"
: current
? "current"
: "locked";
return { id, state, current, locked };
});
}
export function schedulingInvitationActionBlocks(
request: SchedulingRequest,
participant: SchedulingParticipant,