Files
descrybe/apps/web/src/lib/activation/workspace.ts
T

74 lines
2.1 KiB
TypeScript
Raw Normal View History

/** Live workspace signals used to advance the checklist without relying only on localStorage. */
export type ActivationWorkspaceEvidence = {
hasEnabledFields?: boolean;
hasSource?: boolean;
hasMapping?: boolean;
hasSyncedSample?: boolean;
hasProcessed?: boolean;
hasStoreConnect?: boolean;
hasExport?: boolean;
};
/** Minimal step shape for gating / workspace cursor (no i18n). */
export type ActivationStepRef = {
id: string;
optional?: boolean;
feature?: string;
};
/** Steps visible for the current plan (omit feature-gated steps the plan denies). */
export function visibleActivationSteps<T extends ActivationStepRef>(
steps: T[],
can: (featureKey: string) => boolean = () => true
): T[] {
return steps.filter((s) => !s.feature || can(s.feature));
}
const evidenceForStep: Record<
string,
(evidence: ActivationWorkspaceEvidence) => boolean | undefined
> = {
"enable-fields": (e) => e.hasEnabledFields,
"connect-source": (e) => e.hasSource,
map: (e) => e.hasMapping,
"sync-sample": (e) => e.hasSyncedSample,
process: (e) => e.hasProcessed,
"store-connect": (e) => e.hasStoreConnect,
export: (e) => e.hasExport
};
function stepEvidenceDone(step: ActivationStepRef, evidence: ActivationWorkspaceEvidence): boolean {
const getter = evidenceForStep[step.id];
return getter ? Boolean(getter(evidence)) : false;
}
/**
* Contiguous completed-step count from workspace state (stop at first incomplete).
* Optional steps do not block later required evidence (e.g. export without a store).
*/
export function activationIndexFromWorkspace(
evidence: ActivationWorkspaceEvidence | null | undefined,
steps: ActivationStepRef[]
): number {
if (!evidence) return 0;
let count = 0;
for (let i = 0; i < steps.length; i++) {
const step = steps[i];
if (stepEvidenceDone(step, evidence)) {
count += 1;
continue;
}
if (step.optional) {
const laterRequiredDone = steps
.slice(i + 1)
.some((s) => !s.optional && stepEvidenceDone(s, evidence));
if (laterRequiredDone) {
count += 1;
continue;
}
}
break;
}
return Math.min(count, steps.length);
}