From 183f22e922c4e5b758d759ae6eb42baa81fef8a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Thu, 16 Apr 2026 22:03:57 -0400 Subject: [PATCH] fix(onboarding): derive step counter from STEP_ORDER All six step panels previously hard-coded "X / 5" or "X / 6" in their header captions, which drifted out of sync with the 7-step STEP_ORDER in OnboardingHero. Export STEP_ORDER / TOTAL_STEPS / getStepNumber from OnboardingHero and consume them in every step so the counter is always the single source of truth. --- .../components/company-onboarding/CompanyStep.tsx | 3 ++- .../company-onboarding/ExecutionModeStep.tsx | 3 ++- .../components/company-onboarding/MissionStep.tsx | 3 ++- .../company-onboarding/ModelPoolStep.tsx | 3 ++- .../company-onboarding/NodeCheckStep.tsx | 3 ++- .../company-onboarding/OnboardingHero.tsx | 14 +++++++++++--- .../company-onboarding/ProvidersStep.tsx | 3 ++- 7 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/renderer/components/company-onboarding/CompanyStep.tsx b/src/renderer/components/company-onboarding/CompanyStep.tsx index ab77f17a..bdb105a8 100644 --- a/src/renderer/components/company-onboarding/CompanyStep.tsx +++ b/src/renderer/components/company-onboarding/CompanyStep.tsx @@ -3,6 +3,7 @@ import { Buildings, FolderOpen } from "@phosphor-icons/react"; import type { ConnectorId, ProfileSnapshot } from "@shared/types"; import type { AppLocale } from "@shared/locale"; import { ActionButton, Input, TextArea, Select } from "../ui"; +import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero"; interface CompanyStepProps { companyName: string; @@ -57,7 +58,7 @@ export function CompanyStep({ className="bg-card border border-border shadow-sm w-full rounded-lg p-7" >
- {t("onboarding.stepLabelCompany")} 3 / 6 + {t("onboarding.stepLabelCompany")} {getStepNumber("company")} / {TOTAL_STEPS}
{t("onboarding.step1Title")} diff --git a/src/renderer/components/company-onboarding/ExecutionModeStep.tsx b/src/renderer/components/company-onboarding/ExecutionModeStep.tsx index ea9af758..9446ed62 100644 --- a/src/renderer/components/company-onboarding/ExecutionModeStep.tsx +++ b/src/renderer/components/company-onboarding/ExecutionModeStep.tsx @@ -1,6 +1,7 @@ import { motion } from "framer-motion"; import { ArrowRight, Brain, UserCircle, type Icon } from "@phosphor-icons/react"; import type { ExecutionMode } from "@shared/types"; +import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero"; interface ExecutionModeStepProps { executionMode: ExecutionMode; @@ -27,7 +28,7 @@ export function ExecutionModeStep({ className="bg-card border border-border shadow-sm w-full rounded-lg p-7" >
- {t("onboarding.stepLabelMode")} 5 / 6 + {t("onboarding.stepLabelMode")} {getStepNumber("executionmode")} / {TOTAL_STEPS}
{t("onboarding.modeStepTitle")} diff --git a/src/renderer/components/company-onboarding/MissionStep.tsx b/src/renderer/components/company-onboarding/MissionStep.tsx index ef4639d2..6d1fe2b4 100644 --- a/src/renderer/components/company-onboarding/MissionStep.tsx +++ b/src/renderer/components/company-onboarding/MissionStep.tsx @@ -1,6 +1,7 @@ import { motion } from "framer-motion"; import { Cpu, Lightning } from "@phosphor-icons/react"; import { ActionButton, Input, TextArea } from "../ui"; +import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero"; interface MissionStepProps { goalTitle: string; @@ -35,7 +36,7 @@ export function MissionStep({ className="bg-card border border-border shadow-sm w-full rounded-lg p-7" >
- {t("onboarding.stepLabelMission")} 6 / 6 + {t("onboarding.stepLabelMission")} {getStepNumber("mission")} / {TOTAL_STEPS}
{t("onboarding.step2Title")} diff --git a/src/renderer/components/company-onboarding/ModelPoolStep.tsx b/src/renderer/components/company-onboarding/ModelPoolStep.tsx index fae78aad..56e9266e 100644 --- a/src/renderer/components/company-onboarding/ModelPoolStep.tsx +++ b/src/renderer/components/company-onboarding/ModelPoolStep.tsx @@ -4,6 +4,7 @@ import type { ConnectorId, ProfileSnapshot } from "@shared/types"; import type { AppLocale } from "@shared/locale"; import { ActionButton } from "../ui"; import { ModelToggleList, StatusBadge } from "../execution/ModelManagementShared"; +import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero"; interface ModelPoolStepProps { currentLocale: AppLocale; @@ -52,7 +53,7 @@ export function ModelPoolStep({ className="w-full rounded-lg border border-border bg-card p-7 shadow-sm" >
- {t("onboarding.stepLabelModelPool")} 4 / 6 + {t("onboarding.stepLabelModelPool")} {getStepNumber("modelpool")} / {TOTAL_STEPS}
{t("onboarding.modelPoolStepTitle")} diff --git a/src/renderer/components/company-onboarding/NodeCheckStep.tsx b/src/renderer/components/company-onboarding/NodeCheckStep.tsx index e6414d4d..039a6153 100644 --- a/src/renderer/components/company-onboarding/NodeCheckStep.tsx +++ b/src/renderer/components/company-onboarding/NodeCheckStep.tsx @@ -8,6 +8,7 @@ import { } from "@phosphor-icons/react"; import { ActionButton } from "../ui"; import type { TerminalCommandKey } from "@shared/contracts"; +import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero"; interface NodeCheckStepProps { nodeStatus: { installed: boolean; version: string | null } | null; @@ -69,7 +70,7 @@ export function NodeCheckStep({ className="bg-card border border-border shadow-sm w-full rounded-lg p-7" >
- {t("onboarding.stepLabel1")} 1 / 5 — {t("onboarding.nodeCheckStep")} + {t("onboarding.stepLabel1")} {getStepNumber("nodecheck")} / {TOTAL_STEPS} — {t("onboarding.nodeCheckStep")}
{t("onboarding.nodeCheckTitle")} diff --git a/src/renderer/components/company-onboarding/OnboardingHero.tsx b/src/renderer/components/company-onboarding/OnboardingHero.tsx index 5388c49b..08e53a9e 100644 --- a/src/renderer/components/company-onboarding/OnboardingHero.tsx +++ b/src/renderer/components/company-onboarding/OnboardingHero.tsx @@ -31,7 +31,7 @@ const STEP_LABELS_CONFIG = [ { key: "onboarding.stepLabelLaunch", icon: Rocket, step: "launch" as const }, ] as const; -const STEP_ORDER: OnboardingStep[] = [ +export const STEP_ORDER = [ "nodecheck", "providers", "company", @@ -39,7 +39,15 @@ const STEP_ORDER: OnboardingStep[] = [ "executionmode", "mission", "launch", -]; +] as const satisfies readonly OnboardingStep[]; + +export type OnboardingStepName = (typeof STEP_ORDER)[number]; + +export const TOTAL_STEPS = STEP_ORDER.length; + +export function getStepNumber(step: OnboardingStepName): number { + return STEP_ORDER.indexOf(step) + 1; +} interface OnboardingHeroProps { step: OnboardingStep; @@ -52,7 +60,7 @@ export function OnboardingHero({ currentLocale: _currentLocale, t, }: OnboardingHeroProps) { - const stepIndex = STEP_ORDER.indexOf(step); + const stepIndex = (STEP_ORDER as readonly OnboardingStep[]).indexOf(step); const stepLabels = STEP_LABELS_CONFIG.map((cfg) => ({ label: t(cfg.key), diff --git a/src/renderer/components/company-onboarding/ProvidersStep.tsx b/src/renderer/components/company-onboarding/ProvidersStep.tsx index ffdee600..1f696b98 100644 --- a/src/renderer/components/company-onboarding/ProvidersStep.tsx +++ b/src/renderer/components/company-onboarding/ProvidersStep.tsx @@ -11,6 +11,7 @@ import { StatusBadge, INPUT_CLS, } from "./ProvidersStepShared"; +import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero"; /* ------------------------------------------------------------------ */ /* Props */ @@ -104,7 +105,7 @@ export function ProvidersStep({ className="w-full rounded-lg border border-border bg-card p-7 shadow-sm" >
- {t("onboarding.stepLabelProviders")} 2 / 6 + {t("onboarding.stepLabelProviders")} {getStepNumber("providers")} / {TOTAL_STEPS}
{t("onboarding.providersTitle")}