feat(38-03): insert TelegramStep as step 5 in NexusOnboardingWizard

- Import TelegramStep component
- Insert Telegram step at position 5 (between Voice and Root Directory)
- Shift Root Directory from step 5 → step 6
- Shift Summary from step 6 → step 7
- Update step indicator from 'of 5' to 'of 6'
- Update summary indicator from step===6 to step===7
- Update all setStep() navigation callbacks accordingly
- Update error message referencing step 6 for root directory
This commit is contained in:
Nexus Dev 2026-04-04 03:13:57 +00:00
parent 69269fea14
commit ed21eb339c

View file

@ -23,6 +23,7 @@ import { HardwareSummaryStep } from "./onboarding/HardwareSummaryStep";
import { ProviderSelectionStep } from "./onboarding/ProviderSelectionStep"; import { ProviderSelectionStep } from "./onboarding/ProviderSelectionStep";
import { OnboardingSummaryStep } from "./onboarding/OnboardingSummaryStep"; import { OnboardingSummaryStep } from "./onboarding/OnboardingSummaryStep";
import { VoiceStep } from "./onboarding/VoiceStep"; import { VoiceStep } from "./onboarding/VoiceStep";
import { TelegramStep } from "./onboarding/TelegramStep";
import { useHardwareInfo } from "../hooks/useHardwareInfo"; import { useHardwareInfo } from "../hooks/useHardwareInfo";
import { updateNexusSettings, type NexusMode } from "../api/hardware"; import { updateNexusSettings, type NexusMode } from "../api/hardware";
import { useChatPanel } from "../context/ChatPanelContext"; import { useChatPanel } from "../context/ChatPanelContext";
@ -38,7 +39,7 @@ function deriveProviderLabel(
return "None selected"; return "None selected";
} }
// [nexus] 6-step onboarding wizard: hardware detection → mode selection → provider selection → voice → root directory → summary // [nexus] 7-step onboarding wizard: hardware detection → mode selection → provider selection → voice → telegram → root directory → summary
export function OnboardingWizard() { export function OnboardingWizard() {
const { onboardingOpen, onboardingOptions, closeOnboarding } = useDialog(); const { onboardingOpen, onboardingOptions, closeOnboarding } = useDialog();
const { companies, setSelectedCompanyId, loading: companiesLoading } = useCompany(); const { companies, setSelectedCompanyId, loading: companiesLoading } = useCompany();
@ -66,7 +67,7 @@ export function OnboardingWizard() {
setRouteDismissed(false); setRouteDismissed(false);
}, [location.pathname]); }, [location.pathname]);
// Step state: 1 = hardware detection, 2 = mode selection, 3 = provider selection, 4 = voice, 5 = root directory, 6 = summary // Step state: 1 = hardware detection, 2 = mode selection, 3 = provider selection, 4 = voice, 5 = telegram, 6 = root directory, 7 = summary
const [step, setStep] = useState(1); const [step, setStep] = useState(1);
// Mode state: "both" pre-selected per UI-SPEC // Mode state: "both" pre-selected per UI-SPEC
@ -135,7 +136,7 @@ export function OnboardingWizard() {
closeOnboarding(); closeOnboarding();
} }
// [nexus] Shared workspace creation logic used by both handleSubmit (step 4 direct) and handleStartChat (step 5) // [nexus] Shared workspace creation logic used by both handleSubmit (step 4 direct) and handleStartChat (step 6)
async function createWorkspace() { async function createWorkspace() {
// Step 1: Create workspace (company) named after VOCAB.appName // Step 1: Create workspace (company) named after VOCAB.appName
const company = await companiesApi.create({ name: VOCAB.appName }); const company = await companiesApi.create({ name: VOCAB.appName });
@ -262,7 +263,7 @@ export function OnboardingWizard() {
async function handleStartChat() { async function handleStartChat() {
// Guard: claude_local requires rootDir // Guard: claude_local requires rootDir
if (defaultAdapter === "claude_local" && !rootDir.trim()) { if (defaultAdapter === "claude_local" && !rootDir.trim()) {
setError("Root directory is required for Claude Code. Go back to step 5 to set it."); setError("Root directory is required for Claude Code. Go back to step 6 to set it.");
return; return;
} }
@ -302,7 +303,7 @@ export function OnboardingWizard() {
> >
{/* Step indicator */} {/* Step indicator */}
<p className="text-xs text-muted-foreground text-center"> <p className="text-xs text-muted-foreground text-center">
{step === 6 ? "Summary" : `Step ${step} of 5`} {step === 7 ? "Summary" : `Step ${step} of 6`}
</p> </p>
{/* Step 1 — Hardware Detection */} {/* Step 1 — Hardware Detection */}
@ -442,8 +443,16 @@ export function OnboardingWizard() {
</> </>
)} )}
{/* Step 5 — Root Directory (was step 4) */} {/* Step 5 — Telegram Bridge */}
{step === 5 && ( {step === 5 && (
<TelegramStep
onNext={() => setStep(6)}
onBack={() => setStep(4)}
/>
)}
{/* Step 6 — Root Directory (was step 5, now step 6) */}
{step === 6 && (
<> <>
{/* Header */} {/* Header */}
<div className="flex flex-col gap-2 text-center"> <div className="flex flex-col gap-2 text-center">
@ -487,7 +496,7 @@ export function OnboardingWizard() {
<Button <Button
type="button" type="button"
onClick={() => setStep(6)} onClick={() => setStep(7)}
disabled={loading || probing} disabled={loading || probing}
className="w-full" className="w-full"
> >
@ -497,7 +506,7 @@ export function OnboardingWizard() {
<Button <Button
type="button" type="button"
variant="ghost" variant="ghost"
onClick={() => setStep(4)} onClick={() => setStep(5)}
className="w-full" className="w-full"
disabled={loading} disabled={loading}
> >
@ -507,7 +516,7 @@ export function OnboardingWizard() {
<Button <Button
type="button" type="button"
variant="ghost" variant="ghost"
onClick={() => setStep(6)} onClick={() => setStep(7)}
className="w-full" className="w-full"
disabled={loading} disabled={loading}
> >
@ -517,8 +526,8 @@ export function OnboardingWizard() {
</> </>
)} )}
{/* Step 6 — Summary (was step 5) */} {/* Step 7 — Summary (was step 6) */}
{step === 6 && ( {step === 7 && (
<OnboardingSummaryStep <OnboardingSummaryStep
hardwareInfo={hardwareInfo} hardwareInfo={hardwareInfo}
selectedMode={selectedMode} selectedMode={selectedMode}
@ -527,7 +536,7 @@ export function OnboardingWizard() {
loading={loading} loading={loading}
error={error} error={error}
onStartChat={handleStartChat} onStartChat={handleStartChat}
onBack={() => setStep(5)} onBack={() => setStep(6)}
/> />
)} )}
</div> </div>