"use client" import { useEffect, useState, useTransition } from "react" import { toast } from "sonner" import { PenLine, Link2, CheckCircle2, AlertTriangle, KeyRound, ChevronDown, ExternalLink, Loader2, } from "lucide-react" import { connectDropboxSign, disconnectEsignAction } from "@/app/actions/esign" type Adapter = { id: string; label: string; kind: "oauth" | "apikey"; available: boolean } type Conn = { provider: string; accountName: string | null; status: string; lastError: string | null } const ERR_MSG: Record = { connect_failed: "Connection failed — please try again.", invalid_state: "The connection link expired or was invalid. Please retry.", owner_only: "Only the account owner can manage integrations.", not_configured: "E-signature isn't enabled on this server yet.", unknown_provider: "Unknown provider.", use_api_key: "That provider connects with an API key, not a redirect.", } const LABEL: Record = { docusign: "DocuSign", dropbox_sign: "Dropbox Sign" } function StatusPill({ status }: { status: string }) { const error = status === "error" return ( {error ? : } {error ? "Error" : "Connected"} ) } export function EsignIntegrations({ adapters, connections, isOwner, flash, webhookUrl, }: { adapters: Adapter[] connections: Conn[] isOwner: boolean flash: { connected?: string; error?: string } webhookUrl: string }) { const connByProvider: Record = Object.fromEntries(connections.map((c) => [c.provider, c])) const [pending, start] = useTransition() const [busy, setBusy] = useState(null) const [open, setOpen] = useState(null) // which provider's instructions are expanded const [apiKey, setApiKey] = useState("") const [showKeyForm, setShowKeyForm] = useState(false) useEffect(() => { if (flash.connected) toast.success(`Connected to ${LABEL[flash.connected] ?? flash.connected}`) if (flash.error) toast.error(ERR_MSG[flash.error] ?? "Something went wrong") // eslint-disable-next-line react-hooks/exhaustive-deps }, []) function connectDbx() { const key = apiKey.trim() if (!key) return setBusy("dropbox_sign") start(async () => { try { const r = await connectDropboxSign(key) toast.success(`Connected ${r.accountName ?? "Dropbox Sign"}`) setApiKey("") setShowKeyForm(false) } catch (e) { toast.error((e as Error).message || "Couldn't connect") } finally { setBusy(null) } }) } function remove(id: string) { if (!confirm(`Disconnect ${LABEL[id] ?? id}? You won't be able to send leases through it until you reconnect.`)) return setBusy(id) start(async () => { try { await disconnectEsignAction(id) toast.success("Disconnected") } catch { toast.error("Couldn't disconnect") } finally { setBusy(null) } }) } if (!isOwner) { return (
Only the account owner can connect e-signature providers.
) } return (
{/* Intro / how it works */}

Send leases for e-signature

Connect your own DocuSign or Dropbox Sign account so signed leases carry your brand and audit trail — and the signing costs stay on your provider plan, not ours. Once connected, a “Send for signature” button appears on every lease that has a document and a tenant email.

  1. 1. Connect your provider below (one-time).
  2. 2. Open a lease → upload the lease PDF.
  3. 3. Click “Send via DocuSign / Dropbox Sign.” The tenant signs; the status updates here automatically and the signed copy is saved back to the lease.
{adapters.map((a) => { const conn = connByProvider[a.id] const isBusy = pending && busy === a.id const instructionsOpen = open === a.id return (

{a.label}

{conn ? (

{conn.accountName ?? "Connected"}

) : (

{a.kind === "oauth" ? "Connect with your DocuSign login" : "Connect with your API key"}

)}
{conn ? ( ) : !a.available ? ( Not available ) : null}
{conn?.status === "error" && conn.lastError && (

{conn.lastError}

)} {/* Actions */}
{conn ? ( ) : !a.available ? (

Ask your administrator to enable {a.label} (server credentials aren't configured).

) : a.kind === "oauth" ? ( Connect {a.label} ) : showKeyForm ? (
setApiKey(e.target.value)} placeholder="Paste your Dropbox Sign API key" className="flex-1 rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-xs text-white placeholder-white/30 outline-none focus:border-indigo-500/50" />
) : ( )} {a.available && ( )}
{/* Instructions */} {instructionsOpen && (
{a.id === "docusign" ? (
  1. 1. You need an active{" "} DocuSign eSignature plan .
  2. 2. Click Connect DocuSign above.
  3. 3. Log in to your DocuSign account and click Allow to grant access.
  4. 4. You'll return here connected — no webhook setup needed. Signed-status updates and the completed PDF flow back automatically.
) : (
  1. 1. In Dropbox Sign, open{" "} Settings → API {" "} and copy your API key.
  2. 2. Paste it above and click Connect.
  3. 3. In the same API settings, set your account callback URL to: {webhookUrl} This lets us receive signed-status updates.
)}
)}
) })}

Your credentials are encrypted at rest and never leave the server. We only send the leases you explicitly submit.

) }