Spaces:
Running
Running
| import { useState } from "react"; | |
| import type { FormEvent } from "react"; | |
| import { lockAdmin, unlockAdmin, useAdmin } from "../lib/admin"; | |
| export function AdminButton() { | |
| const { enabled } = useAdmin(); | |
| const [open, setOpen] = useState(false); | |
| const [token, setToken] = useState(""); | |
| const [error, setError] = useState<string | null>(null); | |
| const [submitting, setSubmitting] = useState(false); | |
| async function onSubmit(event: FormEvent<HTMLFormElement>) { | |
| event.preventDefault(); | |
| setSubmitting(true); | |
| setError(null); | |
| try { | |
| const ok = await unlockAdmin(token); | |
| if (!ok) { | |
| setError("Invalid token."); | |
| return; | |
| } | |
| setToken(""); | |
| setOpen(false); | |
| } finally { | |
| setSubmitting(false); | |
| } | |
| } | |
| function onLogout() { | |
| lockAdmin(); | |
| setOpen(false); | |
| } | |
| return ( | |
| <div className="admin-button-wrap"> | |
| <button | |
| type="button" | |
| className={`admin-button ${enabled ? "admin-button-on" : ""}`} | |
| onClick={() => setOpen((value) => !value)} | |
| aria-expanded={open} | |
| > | |
| {enabled ? "Admin ✓" : "Admin 🔒"} | |
| </button> | |
| {open ? ( | |
| <div className="admin-panel" role="dialog" aria-label="Admin token"> | |
| {enabled ? ( | |
| <> | |
| <div className="admin-panel-text"> | |
| Admin features are unlocked for this browser tab. | |
| </div> | |
| <button type="button" className="ghost-button" onClick={onLogout}> | |
| Log out | |
| </button> | |
| </> | |
| ) : ( | |
| <form className="admin-form" onSubmit={onSubmit}> | |
| <label htmlFor="adminToken">Admin token</label> | |
| <input | |
| id="adminToken" | |
| type="password" | |
| value={token} | |
| onChange={(event) => setToken(event.target.value)} | |
| placeholder="paste the admin token" | |
| autoComplete="off" | |
| autoFocus | |
| /> | |
| {error ? <div className="admin-panel-error">{error}</div> : null} | |
| <div className="button-row"> | |
| <button | |
| type="submit" | |
| className="primary-button" | |
| disabled={submitting || !token.trim()} | |
| > | |
| {submitting ? "Checking..." : "Unlock"} | |
| </button> | |
| <button | |
| type="button" | |
| className="ghost-button" | |
| onClick={() => setOpen(false)} | |
| > | |
| Cancel | |
| </button> | |
| </div> | |
| </form> | |
| )} | |
| </div> | |
| ) : null} | |
| </div> | |
| ); | |
| } | |