"use client" import { useCallback, useEffect, useMemo, useRef, useState } from "react" import { getSetupStatus, setSetupIdentity } from "@/lib/api" import { SetupIdentityMode } from "./setup-identity-mode" import { SetupConfigure } from "./setup-configure" import { SetupAttachAuth } from "./setup-attach-auth" import { SetupVerify } from "./setup-verify" import { SetupComplete } from "./setup-complete" import { Button } from "@/components/ui/button" import { Skeleton } from "@/components/ui/skeleton" import { Stepper, StepperItem, StepperList, StepperIndicator, StepperSeparator, StepperTitle, StepperTrigger, } from "@/components/ui/stepper" type SetupStep = "mode" | "configure" | "attach-auth" | "verify" | "complete" export function SetupWizard() { const [currentStep, setCurrentStep] = useState("mode") const [identityMode, setIdentityMode] = useState(null) const [attachedDid, setAttachedDid] = useState(null) const [attachedHandle, setAttachedHandle] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const lastFailedModeRef = useRef(null) const stepContentRef = useRef(null) const initialLoadRef = useRef(true) useEffect(() => { if (initialLoadRef.current) { initialLoadRef.current = false return } stepContentRef.current?.focus() }, [currentStep]) useEffect(() => { getSetupStatus() .then((status) => { if (status.setup_complete) { setCurrentStep("complete") } else if (status.plc_verified) { setCurrentStep("complete") } else if (status.identity_configured) { setIdentityMode(status.identity_mode) setCurrentStep("verify") } else if (status.identity_mode && status.identity_mode !== "not_exposed") { setIdentityMode(status.identity_mode) const pendingAuth = localStorage.getItem("happyview_attach_auth") if (status.identity_mode === "attach_account" && pendingAuth) { try { const payload = JSON.parse(pendingAuth) as { attachedDid: string } setAttachedDid(payload.attachedDid) setCurrentStep("attach-auth") } catch { setCurrentStep("configure") } } else { setCurrentStep("configure") } } }) .catch(() => {}) .finally(() => setLoading(false)) }, []) const handleModeSelected = useCallback(async (mode: string) => { setIdentityMode(mode) setError(null) lastFailedModeRef.current = null if (mode === "not_exposed") { try { await setSetupIdentity({ mode: "not_exposed" }) setCurrentStep("complete") } catch (e) { lastFailedModeRef.current = mode setError(e instanceof Error ? e.message : "Failed to save configuration. Check that your backend is running and try again.") } } else if (mode === "attach_account") { setCurrentStep("configure") } else { try { await setSetupIdentity({ mode }) setCurrentStep("verify") } catch (e) { lastFailedModeRef.current = mode setError(e instanceof Error ? e.message : "Failed to configure identity. Check that your backend is running and try again.") } } }, []) const handleGoBack = useCallback(() => { setError(null) switch (currentStep) { case "configure": setCurrentStep("mode") break case "attach-auth": setCurrentStep("configure") break case "verify": setCurrentStep(identityMode === "attach_account" ? "configure" : "mode") break } }, [currentStep, identityMode]) const handleConfigureComplete = useCallback((opts?: { attachedDid?: string; attachedHandle?: string | null }) => { if (opts?.attachedDid) { setAttachedDid(opts.attachedDid) setAttachedHandle(opts.attachedHandle ?? null) setCurrentStep("attach-auth") } else { setCurrentStep("verify") } }, []) const handleAttachAuthComplete = useCallback(() => { setCurrentStep("verify") }, []) const handleVerifyComplete = useCallback(() => { setCurrentStep("complete") }, []) const stepOrder = useMemo(() => identityMode === "attach_account" ? ["mode", "configure", "attach-auth", "verify", "complete"] : ["mode", "verify", "complete"] , [identityMode]) const handleStepperNav = useCallback((value: string) => { const target = value as SetupStep const currentIndex = stepOrder.indexOf(currentStep) const targetIndex = stepOrder.indexOf(target) if (targetIndex < 0 || targetIndex > currentIndex) return if (target === "mode") { setIdentityMode(null) setAttachedDid(null) setAttachedHandle(null) setError(null) } setCurrentStep(target) }, [currentStep, stepOrder]) if (loading) { return (
) } return ( Identity {identityMode === "attach_account" && ( <> Account Sign In )} {identityMode === "did_plc" ? "Key Backup" : identityMode === "attach_account" ? "Verify" : "Review"} Done {error && (
{error} {lastFailedModeRef.current && ( )}
)}
{currentStep === "mode" && } {currentStep === "configure" && identityMode && ( )} {currentStep === "attach-auth" && attachedDid && ( )} {currentStep === "verify" && identityMode && ( )} {currentStep === "complete" && }
) }