Repository Public
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