SPB Git

Repository Public

ApiTokenCard.tsx 2.4 KB 91 lines tsx

1"use client";2// Auteur : Simon-Pierre Boucher — contact@spboucher.ai3// Jeton API personnel (API·Ka) — affichage masqué, copie, régénération.4import { useState } from "react";56export default function ApiTokenCard({7  token: initialToken,8  created: initialCreated,9}: {10  token: string;11  created: string;12}) {13  const [token, setToken] = useState(initialToken);14  const [created, setCreated] = useState(initialCreated);15  const [shown, setShown] = useState(false);16  const [copied, setCopied] = useState(false);17  const [busy, setBusy] = useState(false);1819  const masked = token.slice(0, 10) + "…" + token.slice(-4);2021  async function copy() {22    try {23      await navigator.clipboard.writeText(token);24      setCopied(true);25      setTimeout(() => setCopied(false), 1800);26    } catch {27      /* presse-papiers indisponible */28    }29  }3031  async function regenerate() {32    if (33      !confirm(34        "Régénérer votre jeton API ? L'ancien jeton cessera de fonctionner immédiatement.",35      )36    )37      return;38    setBusy(true);39    try {40      const r = await fetch("/api/account/token", { method: "POST" });41      const j = (await r.json()) as { token?: string; created?: string };42      if (j.token) {43        setToken(j.token);44        setCreated(j.created ?? "");45        setShown(true);46      }47    } finally {48      setBusy(false);49    }50  }5152  return (53    <div>54      <div className="mt-3 flex flex-wrap items-center gap-2">55        <code className="min-w-0 flex-1 rounded-md border-2 border-ink bg-[#faf9f5] px-3 py-2 font-mono text-[13px] break-all select-all">56          {shown ? token : masked}57        </code>58      </div>59      <div className="mt-3 flex flex-wrap gap-2">60        <button61          type="button"62          onClick={() => setShown((s) => !s)}63          className="btn btn-ghost text-[13px]"64        >65          {shown ? "Masquer" : "Afficher"}66        </button>67        <button68          type="button"69          onClick={copy}70          className="btn btn-ghost text-[13px]"71        >72          {copied ? "Copié ✓" : "Copier"}73        </button>74        <button75          type="button"76          onClick={regenerate}77          disabled={busy}78          className="btn btn-ghost text-[13px]"79        >80          {busy ? "…" : "↻ Régénérer"}81        </button>82      </div>83      {created ? (84        <p className="mt-3 text-[12px] text-ink-2">85          Généré le {created.slice(0, 10)} (UTC).86        </p>87      ) : null}88    </div>89  );90}91
Files main
Menu

Theme