---
phase: 03-wizard-ui
plan: "05"
type: execute
wave: 4
depends_on:
- "03-03"
- "03-04"
files_modified:
- src/components/wizard/DeploymentStep.tsx
- src/components/wizard/StepIndicator.tsx
- src/App.tsx
autonomous: false
requirements:
- WIZD-02
- WIZD-03
must_haves:
truths:
- "App.tsx renders BackendSelectionStep for currentStep 0, RemoteConfigStep for step 1, DeploymentStep for step 2"
- "StepIndicator shows 3 labeled steps with checkmarks on completed steps"
- "Clicking a completed step in StepIndicator dispatches SET_STEP — clicking step 0 also dispatches SET_REMOTE_PARAMS({})"
- "DeploymentStep renders includeInstall toggle, configPath radio group, and scriptTargets checkboxes"
- "DeploymentStep dispatches SET_DEPLOYMENT on each change, keeping deployment state in sync"
- "Full forward + backward wizard navigation works without losing entered data in any step"
artifacts:
- path: "src/components/wizard/DeploymentStep.tsx"
provides: "Step 2 — deployment options (includeInstall, configPath, scriptTargets)"
exports: ["DeploymentStep"]
- path: "src/components/wizard/StepIndicator.tsx"
provides: "Breadcrumb navigation — 1.Backend > 2.Remote Config > 3.Deployment"
exports: ["StepIndicator"]
- path: "src/App.tsx"
provides: "Step router — renders correct step component by currentStep"
key_links:
- from: "src/App.tsx"
to: "src/components/wizard/BackendSelectionStep.tsx"
via: "STEPS[0] — renders when currentStep === 0"
pattern: "BackendSelectionStep"
- from: "src/App.tsx"
to: "src/components/wizard/RemoteConfigStep.tsx"
via: "STEPS[1] — renders when currentStep === 1, keyed on backendType"
pattern: "RemoteConfigStep"
- from: "src/components/wizard/StepIndicator.tsx"
to: "src/store/context.tsx"
via: "dispatches SET_STEP and conditionally SET_REMOTE_PARAMS on back-nav to step 0"
pattern: "dispatch.*SET_STEP|SET_REMOTE_PARAMS"
- from: "src/components/wizard/DeploymentStep.tsx"
to: "src/store/context.tsx"
via: "dispatches SET_DEPLOYMENT on every control change"
pattern: "dispatch.*SET_DEPLOYMENT"
---
Wire the complete wizard: implement DeploymentStep and StepIndicator, then update App.tsx to route between all three steps and render the breadcrumb navigation.
Purpose: Satisfies WIZD-02 (multi-step navigation shell) and WIZD-03 (back navigation without data loss). Closes the full wizard loop.
Output: DeploymentStep, StepIndicator, App.tsx wired — all tests GREEN.
@C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md
@C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md
@.planning/PROJECT.md
@.planning/phases/03-wizard-ui/03-CONTEXT.md
@.planning/phases/03-wizard-ui/03-RESEARCH.md
@.planning/phases/03-wizard-ui/03-03-SUMMARY.md
@.planning/phases/03-wizard-ui/03-04-SUMMARY.md
From src/store/types.ts:
```typescript
export interface WizardState {
currentStep: number; // 0=Backend, 1=RemoteConfig, 2=Deployment
remote: {
name: string;
backendType: BackendType | null;
params: Record;
};
deployment: {
includeInstall: boolean; // toggle — default: false
configPath: 'machine-wide' | 'user-profile'; // radio — default: 'machine-wide'
scriptTargets: ('intune' | 'rmm')[]; // checkboxes — default: both selected
};
}
// Deploy step actions:
dispatch({ type: 'SET_DEPLOYMENT', payload: { includeInstall: true } });
dispatch({ type: 'SET_DEPLOYMENT', payload: { configPath: 'user-profile' } });
dispatch({ type: 'SET_DEPLOYMENT', payload: { scriptTargets: ['intune'] } });
// Back-nav to step 0 (CRITICAL: clears params but NOT deployment):
dispatch({ type: 'SET_REMOTE_PARAMS', payload: {} });
dispatch({ type: 'SET_STEP', payload: 0 });
```
From src/store/context.tsx:
```typescript
export function useWizard(): { state: WizardState; dispatch: React.Dispatch }
```
Step routing pattern (from RESEARCH.md):
```tsx
// App.tsx step routing
import { BackendSelectionStep } from './components/wizard/BackendSelectionStep';
import { RemoteConfigStep } from './components/wizard/RemoteConfigStep';
import { DeploymentStep } from './components/wizard/DeploymentStep';
import { StepIndicator } from './components/wizard/StepIndicator';
// Key RemoteConfigStep on backendType to force remount on backend change (Pitfall 1 fix)
const STEPS = [
() => ,
() => ,
() => ,
];
```
StepIndicator back-nav pattern (from RESEARCH.md):
```tsx
const handleStepClick = (targetStep: number) => {
if (targetStep === 0 && state.currentStep > 0) {
dispatch({ type: 'SET_REMOTE_PARAMS', payload: {} }); // clear params (backend may change)
// Do NOT dispatch RESET — deployment options must be preserved
}
dispatch({ type: 'SET_STEP', payload: targetStep });
};
```
Task 1: Implement DeploymentStep and StepIndicatorsrc/components/wizard/DeploymentStep.tsx, src/components/wizard/StepIndicator.tsx
DeploymentStep:
- Renders an "Include rclone installation" toggle (checkbox or switch); state.deployment.includeInstall default false
- Renders a "Config deployment path" radio group: 'machine-wide' (C:\ProgramData\rclone\) and 'user-profile' (%APPDATA%\rclone\); default machine-wide
- Renders a "Script targets" checkbox group: 'intune' and 'rmm' checkboxes; both checked by default
- Each control dispatches SET_DEPLOYMENT immediately on change (live sync, no Next button needed for deployment options)
- Renders a "Back" button that dispatches SET_STEP(1) and a "Next / Review" button that dispatches SET_STEP(3) to advance to Phase 4's review step
StepIndicator:
- Renders three labeled steps: "1. Backend", "2. Remote Config", "3. Deployment"
- Current step is bold/active
- Completed steps (step index < currentStep) show a checkmark prefix and are clickable buttons
- Future steps are not clickable (non-interactive)
- Clicking a completed step that is NOT step 0 dispatches only SET_STEP(targetStep)
- Clicking step 0 dispatches SET_REMOTE_PARAMS({}) THEN SET_STEP(0) — clears params for potential backend change
- Does NOT dispatch RESET on any click
Create `src/components/wizard/DeploymentStep.tsx`:
- Uses `useWizard()` to read `state.deployment` and `dispatch`
- Does NOT use react-hook-form — deployment fields dispatch directly via onChange handlers
- `includeInstall` toggle: ` dispatch({ type: 'SET_DEPLOYMENT', payload: { includeInstall: e.target.checked } })} />`
- `configPath` radios: two `` elements for 'machine-wide' and 'user-profile'
- `scriptTargets` checkboxes: two `` for 'intune' and 'rmm' — on change, compute new array and dispatch SET_DEPLOYMENT
- Back button: `dispatch({ type: 'SET_STEP', payload: 1 })`
- Next button: `dispatch({ type: 'SET_STEP', payload: 3 })` — step 3 is Phase 4's review/download (placeholder for now)
Create `src/components/wizard/StepIndicator.tsx`:
- Uses `useWizard()` to read `state.currentStep`
- Renders a horizontal breadcrumb with separators (›)
- Step labels: `['Backend', 'Remote Config', 'Deployment']`
- For each step index i:
- If i < currentStep: completed — render as `npx vitest run src/components/wizard/StepIndicator.test.tsx --reporter=verbose 2>&1
DeploymentStep.tsx and StepIndicator.tsx exist with named exports. All StepIndicator WIZD-03 tests GREEN.
Task 2: Wire App.tsx step router and make App.test GREENsrc/App.tsx
- App renders BackendSelectionStep when state.currentStep === 0
- App renders RemoteConfigStep when state.currentStep === 1
- App renders DeploymentStep when state.currentStep === 2
- App always renders StepIndicator above the current step component
- RemoteConfigStep is keyed on state.remote.backendType to force remount on backend change
Replace the placeholder `src/App.tsx` with the step router.
```tsx
import { useWizard } from './store/context';
import { WizardProvider } from './store/context';
import { StepIndicator } from './components/wizard/StepIndicator';
import { BackendSelectionStep } from './components/wizard/BackendSelectionStep';
import { RemoteConfigStep } from './components/wizard/RemoteConfigStep';
import { DeploymentStep } from './components/wizard/DeploymentStep';
function WizardShell() {
const { state } = useWizard();
const steps = [
,
,
,
];
// Guard: clamp to valid range (phase 4 adds step 3 later)
const stepIndex = Math.min(state.currentStep, steps.length - 1);
const CurrentStep = steps[stepIndex];
return (
Ready2Blob
{CurrentStep}
);
}
export default function App() {
return (
);
}
```
Then update `src/App.test.tsx` to make all WIZD-02 tests GREEN:
- "renders BackendSelectionStep when currentStep is 0" — render App, expect to find backend card grid (e.g., text "Azure Blob Storage")
- "renders RemoteConfigStep when currentStep is 1" — render App, dispatch SET_BACKEND_TYPE + SET_STEP(1), expect backend config form to appear
- "renders DeploymentStep when currentStep is 2" — render App, navigate to step 2, expect deployment options to appear
Testing approach: `render()`, then use a dispatch helper or find elements that are only present on the target step.
npx vitest run src/App.test.tsx --reporter=verbose 2>&1
All App.test.tsx WIZD-02 tests GREEN. App.tsx wires all three steps. StepIndicator renders above each step.
Task 3: Human verification of complete wizard flow end-to-endHuman runs `npm run dev` and manually verifies the complete wizard flow in the browser. No code changes required — this task only requires visual inspection and interaction testing.Complete wizard navigation: BackendSelectionStep to RemoteConfigStep to DeploymentStep, with StepIndicator breadcrumb and full back-navigation support.
1. Run `npm run dev` and open http://localhost:5173
2. Verify the breadcrumb shows "1. Backend › 2. Remote Config › 3. Deployment"
3. Step 1 (Backend Selection):
- Remote name field is at the top
- Try clicking a card without a name — inline error should appear below the name field
- Enter "my-remote" in the name field, click "Azure Blob Storage" — should advance to step 2
4. Step 2 (Remote Config) with Azure:
- Storage Account Name field visible
- "SAS URL" is the default active auth method
- Enter a SAS URL, toggle to "Access Key", enter a key — both values should be in the form
- Click "Back" — should return to step 1 with "my-remote" still in the name field
5. Navigate back to step 1, click "Amazon S3" — should advance to step 2 with S3 fields
6. Verify S3 form: access key ID, secret access key, region fields (no provider dropdown visible)
7. Fill S3 form and click "Next" — should advance to step 3
8. Step 3 (Deployment): verify include-install toggle, config path radios, script targets checkboxes
9. Click step "1. Backend" in breadcrumb from step 3 — should navigate back to step 1 without losing deployment options
10. Select a different backend — step 2 form should be blank (not showing old S3 values)
npm run dev 2>&1 | head -5User confirms the full wizard flow works end-to-end with correct navigation, validation, and data preservation.Type "approved" if navigation works correctly end-to-end, or describe any issues found.
Full automated suite:
```bash
npx vitest run --reporter=verbose 2>&1
```
All tests GREEN: App.test.tsx (WIZD-02), BackendSelectionStep.test.tsx (WIZD-01, WIZD-04), RemoteConfigStep.test.tsx (BACK-01, BACK-02, BACK-03), StepIndicator.test.tsx (WIZD-03).
Dev server check:
```bash
npm run dev 2>&1 | head -5
```
Server starts without errors.
- All 7 requirement test suites GREEN (WIZD-01, WIZD-02, WIZD-03, WIZD-04, BACK-01, BACK-02, BACK-03)
- App.tsx routes to correct step component by currentStep
- RemoteConfigStep keyed on backendType (prevents stale form values on backend change)
- StepIndicator dispatches SET_REMOTE_PARAMS({}) when navigating back to step 0 (preserves deployment)
- DeploymentStep dispatches SET_DEPLOYMENT live on every control change
- Human verifies full wizard flow end-to-end: forward navigation, back navigation, data preservation