import { useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { type LucideIcon, X, Wallet, ShieldCheck, Music, Link2, CheckCircle2, ArrowRight, ArrowLeft } from "lucide-react"; import { type WalletState } from "@/types/wallet"; interface Props { wallet: WalletState; onClose: () => void; } type Step = "wallet" | "ipi" | "kyc" | "confirm"; const STEPS: { id: Step; label: string; icon: LucideIcon }[] = [ { id: "wallet", label: "Wallet", icon: Wallet }, { id: "ipi", label: "IPI Number", icon: Music }, { id: "kyc", label: "Verify IPI & Identity", icon: ShieldCheck }, { id: "confirm", label: "Confirm", icon: Link2 }, ]; const OnboardingWizard = ({ wallet, onClose }: Props) => { const [currentStep, setCurrentStep] = useState("wallet"); const [ipiNumber, setIpiNumber] = useState(""); const [ipiError, setIpiError] = useState(""); const [kycConsent, setKycConsent] = useState(false); const stepIndex = STEPS.findIndex((s) => s.id === currentStep); const next = () => { if (stepIndex < STEPS.length - 1) { setCurrentStep(STEPS[stepIndex + 1].id); } }; const back = () => { if (stepIndex > 0) { setCurrentStep(STEPS[stepIndex - 1].id); } }; const validateIpi = (value: string) => { const clean = value.replace(/\D/g, ""); if (clean.length < 9 || clean.length > 11) { setIpiError("IPI numbers are 9–11 digits. Check your PRO for yours."); return false; } setIpiError(""); return true; }; const [isSubmitting, setIsSubmitting] = useState(false); const [kycError, setKycError] = useState(null); const handleConfirm = async () => { if (isSubmitting) return; setIsSubmitting(true); setKycError(null); const uid = wallet.address.toLowerCase(); try { const res = await fetch(`/api/kyc/${encodeURIComponent(uid)}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ legal_name: uid, country_code: "US", id_type: "IPI", tax_form: "W9", tin_hash: null, }), }); if (!res.ok && res.status !== 409) { const text = await res.text().catch(() => ""); throw new Error(`KYC submission failed (${res.status}): ${text || res.statusText}`); } onClose(); } catch (err: unknown) { const message = err instanceof Error ? err.message : "KYC submission failed."; setKycError(message); } finally { setIsSubmitting(false); } }; return (

Verify Artist Identity

{STEPS.map((step, i) => (
{i < stepIndex ? : i + 1}
{i < STEPS.length - 1 && (
)}
))}
{currentStep === "wallet" && (

Connected Artist Wallet

Your wallet address is your unique identifier. We do not use or store artist names.

{wallet.walletType} Wallet
{wallet.address}
)} {currentStep === "ipi" && (

IPI Number

Enter your Interested Party Information (IPI) number. This links your identity to your musical works.

{ const v = e.target.value.replace(/[^0-9]/g, "").slice(0, 11); setIpiNumber(v); if (ipiError) setIpiError(""); }} placeholder="e.g. 00523879412" className="w-full px-4 py-3 rounded-lg bg-zinc-950 border border-zinc-800 text-sm font-mono placeholder:text-zinc-600 focus:outline-none focus:ring-2 focus:ring-primary" maxLength={11} /> {ipiError && (

{ipiError}

)}

Your IPI is a unique 9-11 digit number assigned to you by your Performing Rights Organization (PRO).

)} {currentStep === "kyc" && (

Verify IPI Ownership

We must verify that IPI {ipiNumber} legally belongs to the owner of this wallet.

Identity & IPI Link

This automated KYC process will verify your government ID against the IPI registration. This prevents unauthorized parties from claiming your royalties.

)} {currentStep === "confirm" && (

Final Review

Your verification is successful. Click below to finalize the link between your wallet and IPI.

Artist ID (Wallet)
{wallet.address.slice(0, 8)}…{wallet.address.slice(-6)}
IPI Number
{ipiNumber}
KYC Status
Verified
)}
{stepIndex > 0 ? ( ) : (
)} {currentStep === "confirm" ? (
{kycError && (

{kycError}

)}
) : ( )}
); }; export default OnboardingWizard;