1import { useAtomValue } from "@effect/atom-react";
2import type { EnvironmentId, ProviderInstanceId } from "@t3tools/contracts";
3
4import { useEnvironmentQuery } from "../../state/query";
5import { EMPTY_SERVER_PROVIDERS, serverEnvironment } from "../../state/server";
6import { Button } from "../ui/button";
7import { WizardFooter, WizardPanel } from "../ui/wizard";
8import { ProviderAuthenticationSection } from "./ProviderAuthenticationSection";
9import { SettingsGroup } from "./SettingsGroup";
10import { SettingsRow } from "./settingsLayout";
11
12/** Sign-in uses the saved instance's environment and credentials, just like chat. */
13export function ProviderWizardAuthenticationStep({
14 environmentId,
15 environmentLabel,
16 instanceId,
17 onFinish,
18}: {
19 readonly environmentId: EnvironmentId;
20 readonly environmentLabel: string;
21 readonly instanceId: ProviderInstanceId;
22 readonly onFinish: () => void;
23}) {
24 const providers =
25 useAtomValue(serverEnvironment.providersValueAtom(environmentId)) ?? EMPTY_SERVER_PROVIDERS;
26 const provider = providers.find((candidate) => candidate.instanceId === instanceId);
27 const query = useEnvironmentQuery(
28 serverEnvironment.providerAuthState({ environmentId, input: { instanceId } }),
29 );
30 const auth = query.data;
31 const active =
32 auth?.phase === "starting" || auth?.phase === "waiting" || auth?.phase === "verifying";
33 const signedIn =
34 provider?.auth.status === "authenticated" ||
35 (provider?.auth.status === "unknown" && auth?.phase === "succeeded");
36 const isDiscovering = !signedIn && !query.error && auth?.methods === undefined;
37 const canAuthenticate = (auth?.methods?.length ?? 0) > 0;
38
39 return (
40 <>
41 <WizardPanel className="min-h-72">
42 <SettingsGroup variant="plain">
43 {provider && (canAuthenticate || signedIn) ? (
44 <ProviderAuthenticationSection
45 environmentId={environmentId}
46 environmentLabel={environmentLabel}
47 instanceId={instanceId}
48 provider={{
49 ...provider,
50 setup: {
51 ...provider.setup,
52 canInstall: provider.setup?.canInstall ?? false,
53 canAuthenticate,
54 },
55 }}
56 readOnly={false}
57 />
58 ) : (
59 <SettingsRow
60 title="Account"
61 description={
62 isDiscovering
63 ? "Discovering sign-in methods…"
64 : (query.error ??
65 auth?.message ??
66 "No in-app sign-in advertised. Follow the provider's docs to finish setup.")
67 }
68 control={
69 isDiscovering ? (
70 <Button disabled size="sm" variant="outline">
71 Sign in
72 </Button>
73 ) : provider?.setup?.documentationUrl ? (
74 <Button
75 size="sm"
76 variant="outline"
77 render={
78 <a href={provider.setup.documentationUrl} target="_blank" rel="noreferrer" />
79 }
80 >
81 Open docs
82 </Button>
83 ) : undefined
84 }
85 />
86 )}
87 </SettingsGroup>
88 </WizardPanel>
89 <WizardFooter>
90 <Button
91 size="sm"
92 variant={signedIn ? "default" : "outline"}
93 disabled={active}
94 onClick={onFinish}
95 >
96 {signedIn ? "Done" : "Skip for now"}
97 </Button>
98 </WizardFooter>
99 </>
100 );
101}