jacquardSnapshot

← snapshot

2393 bytes
"use client";

import { useRouter } from "next/navigation";
import { useState } from "react";
import { ApiError, api } from "@/lib/api";
import type { ActorView } from "@/lib/types";
import { statementStatus } from "@/lib/validate";
import { VoiceStatementInput } from "./voice-statement-input";

/**
 * The one write that matters: a human puts their name to a decision, in
 * their own words. The select offers only humans — agents are not merely
 * discouraged, they have no constructor.
 */
export function AttestForm({
  repo,
  decisionId,
  humans,
}: {
  repo: string;
  decisionId: string;
  humans: ActorView[];
}) {
  const router = useRouter();
  const [by, setBy] = useState(humans[0]?.id ?? "");
  const [statement, setStatement] = useState("");
  const [pending, setPending] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const valid = statementStatus(statement).valid && by !== "";

  async function submit() {
    setPending(true);
    setError(null);
    try {
      await api.attest(repo, decisionId, by, statement);
      router.refresh();
    } catch (e) {
      setError(e instanceof ApiError ? e.message : String(e));
    } finally {
      setPending(false);
    }
  }

  return (
    <div style={{ marginTop: 16 }}>
      <div className="jac-field">
        <label className="jac-label" htmlFor="attest-by">
          Signing as
        </label>
        <select
          id="attest-by"
          className="jac-select"
          value={by}
          onChange={(e) => setBy(e.target.value)}
        >
          {humans.map((h) => (
            <option key={h.id} value={h.id}>
              {h.display_name ?? h.id} ({h.id})
            </option>
          ))}
        </select>
      </div>
      <div className="jac-field">
        <label className="jac-label">Your statement — verbatim</label>
        <VoiceStatementInput value={statement} onChange={setStatement} />
      </div>
      {error ? <div className="jac-error-box">{error}</div> : null}
      <div className="jac-cta-row">
        <button
          type="button"
          className="jac-btn jac-btn--primary"
          disabled={!valid || pending}
          onClick={submit}
        >
          {pending ? "Signing…" : "Sign in your own words"}
        </button>
        <span className="jac-small">Recognised, never policed.</span>
      </div>
    </div>
  );
}