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.
This commit is contained in:
1 parent
5a5587c2a1
commit
183f22e922
7 files changed
+23
-9
No files matched your search
@@ -3,6 +3,7 @@ import { Buildings, FolderOpen } from "@phosphor-icons/react";
|
|||||||
import type { ConnectorId, ProfileSnapshot } from "@shared/types";
|
import type { ConnectorId, ProfileSnapshot } from "@shared/types";
|
||||||
import type { AppLocale } from "@shared/locale";
|
import type { AppLocale } from "@shared/locale";
|
||||||
import { ActionButton, Input, TextArea, Select } from "../ui";
|
import { ActionButton, Input, TextArea, Select } from "../ui";
|
||||||
|
import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero";
|
||||||
|
|
||||||
interface CompanyStepProps {
|
interface CompanyStepProps {
|
||||||
companyName: string;
|
companyName: string;
|
||||||
@@ -57,7 +58,7 @@ export function CompanyStep({
|
|||||||
className="bg-card border border-border shadow-sm w-full rounded-lg p-7"
|
className="bg-card border border-border shadow-sm w-full rounded-lg p-7"
|
||||||
>
|
>
|
||||||
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
||||||
{t("onboarding.stepLabelCompany")} 3 / 6
|
{t("onboarding.stepLabelCompany")} {getStepNumber("company")} / {TOTAL_STEPS}
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
||||||
{t("onboarding.step1Title")}
|
{t("onboarding.step1Title")}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { ArrowRight, Brain, UserCircle, type Icon } from "@phosphor-icons/react";
|
import { ArrowRight, Brain, UserCircle, type Icon } from "@phosphor-icons/react";
|
||||||
import type { ExecutionMode } from "@shared/types";
|
import type { ExecutionMode } from "@shared/types";
|
||||||
|
import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero";
|
||||||
|
|
||||||
interface ExecutionModeStepProps {
|
interface ExecutionModeStepProps {
|
||||||
executionMode: ExecutionMode;
|
executionMode: ExecutionMode;
|
||||||
@@ -27,7 +28,7 @@ export function ExecutionModeStep({
|
|||||||
className="bg-card border border-border shadow-sm w-full rounded-lg p-7"
|
className="bg-card border border-border shadow-sm w-full rounded-lg p-7"
|
||||||
>
|
>
|
||||||
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
||||||
{t("onboarding.stepLabelMode")} 5 / 6
|
{t("onboarding.stepLabelMode")} {getStepNumber("executionmode")} / {TOTAL_STEPS}
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
||||||
{t("onboarding.modeStepTitle")}
|
{t("onboarding.modeStepTitle")}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { Cpu, Lightning } from "@phosphor-icons/react";
|
import { Cpu, Lightning } from "@phosphor-icons/react";
|
||||||
import { ActionButton, Input, TextArea } from "../ui";
|
import { ActionButton, Input, TextArea } from "../ui";
|
||||||
|
import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero";
|
||||||
|
|
||||||
interface MissionStepProps {
|
interface MissionStepProps {
|
||||||
goalTitle: string;
|
goalTitle: string;
|
||||||
@@ -35,7 +36,7 @@ export function MissionStep({
|
|||||||
className="bg-card border border-border shadow-sm w-full rounded-lg p-7"
|
className="bg-card border border-border shadow-sm w-full rounded-lg p-7"
|
||||||
>
|
>
|
||||||
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
||||||
{t("onboarding.stepLabelMission")} 6 / 6
|
{t("onboarding.stepLabelMission")} {getStepNumber("mission")} / {TOTAL_STEPS}
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
||||||
{t("onboarding.step2Title")}
|
{t("onboarding.step2Title")}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { ConnectorId, ProfileSnapshot } from "@shared/types";
|
|||||||
import type { AppLocale } from "@shared/locale";
|
import type { AppLocale } from "@shared/locale";
|
||||||
import { ActionButton } from "../ui";
|
import { ActionButton } from "../ui";
|
||||||
import { ModelToggleList, StatusBadge } from "../execution/ModelManagementShared";
|
import { ModelToggleList, StatusBadge } from "../execution/ModelManagementShared";
|
||||||
|
import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero";
|
||||||
|
|
||||||
interface ModelPoolStepProps {
|
interface ModelPoolStepProps {
|
||||||
currentLocale: AppLocale;
|
currentLocale: AppLocale;
|
||||||
@@ -52,7 +53,7 @@ export function ModelPoolStep({
|
|||||||
className="w-full rounded-lg border border-border bg-card p-7 shadow-sm"
|
className="w-full rounded-lg border border-border bg-card p-7 shadow-sm"
|
||||||
>
|
>
|
||||||
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
||||||
{t("onboarding.stepLabelModelPool")} 4 / 6
|
{t("onboarding.stepLabelModelPool")} {getStepNumber("modelpool")} / {TOTAL_STEPS}
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
||||||
{t("onboarding.modelPoolStepTitle")}
|
{t("onboarding.modelPoolStepTitle")}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
} from "@phosphor-icons/react";
|
} from "@phosphor-icons/react";
|
||||||
import { ActionButton } from "../ui";
|
import { ActionButton } from "../ui";
|
||||||
import type { TerminalCommandKey } from "@shared/contracts";
|
import type { TerminalCommandKey } from "@shared/contracts";
|
||||||
|
import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero";
|
||||||
|
|
||||||
interface NodeCheckStepProps {
|
interface NodeCheckStepProps {
|
||||||
nodeStatus: { installed: boolean; version: string | null } | null;
|
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"
|
className="bg-card border border-border shadow-sm w-full rounded-lg p-7"
|
||||||
>
|
>
|
||||||
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
||||||
{t("onboarding.stepLabel1")} 1 / 5 — {t("onboarding.nodeCheckStep")}
|
{t("onboarding.stepLabel1")} {getStepNumber("nodecheck")} / {TOTAL_STEPS} — {t("onboarding.nodeCheckStep")}
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
||||||
{t("onboarding.nodeCheckTitle")}
|
{t("onboarding.nodeCheckTitle")}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ const STEP_LABELS_CONFIG = [
|
|||||||
{ key: "onboarding.stepLabelLaunch", icon: Rocket, step: "launch" as const },
|
{ key: "onboarding.stepLabelLaunch", icon: Rocket, step: "launch" as const },
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
const STEP_ORDER: OnboardingStep[] = [
|
export const STEP_ORDER = [
|
||||||
"nodecheck",
|
"nodecheck",
|
||||||
"providers",
|
"providers",
|
||||||
"company",
|
"company",
|
||||||
@@ -39,7 +39,15 @@ const STEP_ORDER: OnboardingStep[] = [
|
|||||||
"executionmode",
|
"executionmode",
|
||||||
"mission",
|
"mission",
|
||||||
"launch",
|
"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 {
|
interface OnboardingHeroProps {
|
||||||
step: OnboardingStep;
|
step: OnboardingStep;
|
||||||
@@ -52,7 +60,7 @@ export function OnboardingHero({
|
|||||||
currentLocale: _currentLocale,
|
currentLocale: _currentLocale,
|
||||||
t,
|
t,
|
||||||
}: OnboardingHeroProps) {
|
}: OnboardingHeroProps) {
|
||||||
const stepIndex = STEP_ORDER.indexOf(step);
|
const stepIndex = (STEP_ORDER as readonly OnboardingStep[]).indexOf(step);
|
||||||
|
|
||||||
const stepLabels = STEP_LABELS_CONFIG.map((cfg) => ({
|
const stepLabels = STEP_LABELS_CONFIG.map((cfg) => ({
|
||||||
label: t(cfg.key),
|
label: t(cfg.key),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
StatusBadge,
|
StatusBadge,
|
||||||
INPUT_CLS,
|
INPUT_CLS,
|
||||||
} from "./ProvidersStepShared";
|
} from "./ProvidersStepShared";
|
||||||
|
import { getStepNumber, TOTAL_STEPS } from "./OnboardingHero";
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Props */
|
/* Props */
|
||||||
@@ -104,7 +105,7 @@ export function ProvidersStep({
|
|||||||
className="w-full rounded-lg border border-border bg-card p-7 shadow-sm"
|
className="w-full rounded-lg border border-border bg-card p-7 shadow-sm"
|
||||||
>
|
>
|
||||||
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
||||||
{t("onboarding.stepLabelProviders")} 2 / 6
|
{t("onboarding.stepLabelProviders")} {getStepNumber("providers")} / {TOTAL_STEPS}
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
<div className="mb-1 text-[18px] font-semibold tracking-[-0.01em] text-foreground">
|
||||||
{t("onboarding.providersTitle")}
|
{t("onboarding.providersTitle")}
|
||||||
|
|||||||
Reference in new issue
Block a user