"use client";
import type { McpAiCopy } from "./copy";
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
import { useEffect, useState } from "react";
import { type GuidedNav } from "@12-apps/onboarding";
import { Progress } from "@12-apps/ui/data-display/Progress";
import { Button } from "@12-apps/ui/form/Button";
import { Box } from "@12-apps/ui/mui/Box";
import { Stack } from "@12-apps/ui/mui/Stack";
import { Text } from "@12-apps/ui/typography/Text";
import type { AiHostConfigureStage, AiHostGuide } from "../guide";
import { activeAgo, connectionForHost, hostLabel, type AiConnection } from "./ai-connection-utils";
import {
EndpointCopyBlock,
HostConnectHeader,
HostDocsLink,
HostOpenButton,
HostStepList,
PromptCopyBlock,
} from "./host-connect-guide";
/** The host's connect steps split across the Configurar / Conectar stages. */
const CONFIGURE_STEP_COUNT = 3;
/** How often the Confirmar step re-checks the live connection while waiting. */
const POLL_INTERVAL_MS = 3000;
/** A step's continue/back controls (Voltar left, primary next right). */
function StepNav({
nav,
onNext,
nextLabel,
nextDisabled = false,
nextTestId,
copy,
}: {
nav: GuidedNav;
onNext: () => void;
nextLabel?: string;
nextDisabled?: boolean;
nextTestId?: string;
copy: McpAiCopy;
}): React.JSX.Element {
return (
);
}
/** Step 2 — copy the store URL; copying is the action that advances the wizard. */
export function CopyUrlStep({
nav,
endpointUrl,
copy,
}: {
nav: GuidedNav;
endpointUrl: string;
copy: McpAiCopy;
}): React.JSX.Element {
return (
{copy.flow.copyUrlTitle}
{copy.flow.urlCaption}
nav.next()} />
);
}
/** Step 3 — open the host's connectors and add + configure the custom connector. */
export function ConfigureStep({
nav,
host,
copy,
}: {
nav: GuidedNav;
host: AiHostGuide;
copy: McpAiCopy;
}): React.JSX.Element {
// Hosts with no direct link (e.g. Claude Desktop) have nothing to open, so
// "Próximo" is available immediately; otherwise it unlocks on the open click.
const [opened, setOpened] = useState(!host.link);
return (
setOpened(true)} />
nav.next()} nextDisabled={!opened} nextTestId="ai-configure-next" />
);
}
/**
* One stage of a host's per-stage configuration (e.g. ChatGPT's "enable
* developer mode" then "configurar"). Each stage has its OWN deep link — opening
* it unlocks "Próximo" — and its own instructions.
*/
export function ConfigureStageStep({
nav,
host,
stage,
copy,
}: {
nav: GuidedNav;
host: AiHostGuide;
stage: AiHostConfigureStage;
copy: McpAiCopy;
}): React.JSX.Element {
const [opened, setOpened] = useState(!stage.link);
return (
{stage.link && (
)}
nav.next()}
nextDisabled={!opened}
nextTestId={`ai-stage-next-${stage.id}`}
/>
);
}
/** Step 4 — connect: log in, authorize and activate the connector. */
export function ConnectStep({
nav,
host,
connectPrompt,
copy,
}: {
nav: GuidedNav;
host: AiHostGuide;
connectPrompt: string;
copy: McpAiCopy;
}): React.JSX.Element {
return (
nav.next()} nextLabel={copy.flow.advance} nextTestId="ai-connect-done" />
);
}
/**
* Simplified-flow step (host has a published `pluginUrl`): open the one-click
* plugin (install + authorize), then paste the prompt asking the assistant to
* connect. No URL to copy, no manual connector. The next step (Confirmar) waits.
*/
export function InstallStep({
nav,
host,
connectPrompt,
copy,
}: {
nav: GuidedNav;
host: AiHostGuide;
connectPrompt: string;
copy: McpAiCopy;
}): React.JSX.Element {
const [opened, setOpened] = useState(false);
return (
{copy.flow.installBody}
{host.pluginUrl && (
)}
nav.next()}
nextLabel={copy.flow.advance}
nextDisabled={!opened}
nextTestId="ai-install-done"
/>
);
}
/**
* Step 5: auto-detect the live connection. While waiting it polls the server
* (the sign-in / `announceAiConnection` tool call registers the connection
* server-side), showing a spinner — the owner never clicks "verify". Completes
* when the selected host's connection appears.
*/
export function ConfirmStep({
nav,
connections,
hosts,
onRetest,
copy,
}: {
nav: GuidedNav;
connections: readonly AiConnection[];
hosts: readonly AiHostGuide[];
onRetest: () => void;
copy: McpAiCopy;
}): React.JSX.Element {
const selectedHostId = nav.data.selectedHost as string | undefined;
const connection = connectionForHost(connections, selectedHostId);
const label = connection?.clientName ?? hostLabel(hosts, selectedHostId);
// Auto-detect: re-check on an interval until the connection shows up. The
// interval is cleared as soon as `connection` is non-null (and on unmount).
useEffect(() => {
if (connection) return undefined;
const id = setInterval(() => onRetest(), POLL_INTERVAL_MS);
return () => clearInterval(id);
}, [connection, onRetest]);
if (connection) {
return (
{copy.flow.connectedTo(label)}
{activeAgo(connection.lastActiveAt, copy.summary)}
);
}
return (
{copy.flow.waitingTitle}
{copy.flow.waitingBody(label)}
);
}