File size: 2,712 Bytes
c52f47a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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>
  );
}