import React from 'react'; import { Link } from 'react-router-dom'; import type { ISetupProgress } from '../../service/setup-progress/setup-progress.interface'; import type { StepperStep } from '../../service/setup-progress/setup-progress.constants'; import InfoTooltip from './InfoTooltip'; interface SetupProgressStepperProps { progress: ISetupProgress | null; steps: ReadonlyArray; estimatedMinutesLeft?: number; } /** * Horizontal stepper rendered on the Dashboard. A step is "effectively * complete" only when itself and every earlier step is marked done in * setup_progress, so out-of-order completions don't paint later steps * green prematurely. * * @param {SetupProgressStepperProps} props * @return {React.ReactElement} */ export function SetupProgressStepper({ progress, steps, estimatedMinutesLeft, }: SetupProgressStepperProps) { let priorComplete: boolean = true; const effectivelyComplete: boolean[] = steps.map(stepDefinition => { const stored: boolean = progress?.steps?.[stepDefinition.key]?.completed ?? false; const isDone: boolean = priorComplete && stored; priorComplete = isDone; return isDone; }); const completedCount: number = effectivelyComplete.filter(Boolean).length; const totalCount: number = steps.length; const currentIndex: number = effectivelyComplete.findIndex(done => !done); const nextStep: StepperStep | null = currentIndex >= 0 ? steps[currentIndex] : null; return (

Setup progress

{completedCount} of {totalCount} complete {typeof estimatedMinutesLeft === 'number' && estimatedMinutesLeft > 0 ? ` · ~${estimatedMinutesLeft} min left` : ''}

{nextStep && ( Continue setup → )}
    {steps.map((stepDefinition, stepIndex) => { const done: boolean = effectivelyComplete[stepIndex]; const isCurrent: boolean = stepIndex === currentIndex; const leftConnectorDone: boolean = stepIndex > 0 && effectivelyComplete[stepIndex - 1]; const rightConnectorDone: boolean = done; return (
  1. {done ? ( ) : ( {stepIndex + 1} )}
    {stepDefinition.label} {stepDefinition.tooltip && ( )}
  2. ); })}
); }