@q3assets/auth 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/admin-panel.tsx +20 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q3assets/auth",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "exports": {
5
5
  ".": "./src/index.ts",
6
6
  "./login": "./src/login.tsx",
@@ -36,14 +36,20 @@ export function AdminPanel({ supabase, onClose, apiBase = "/api/admin/users" }:
36
36
  }
37
37
 
38
38
  async function loadUsers() {
39
- const headers = await getAuthHeader()
40
- const res = await fetch(apiBase, { headers })
41
- const data = await res.json()
42
- if (res.ok) {
39
+ try {
40
+ const headers = await getAuthHeader()
41
+ const res = await fetch(apiBase, { headers })
42
+ if (!res.ok) {
43
+ const text = await res.text()
44
+ try { setError(JSON.parse(text).error || `HTTP ${res.status}`) } catch { setError(`HTTP ${res.status}: ${text.slice(0, 200)}`) }
45
+ setLoading(false)
46
+ return
47
+ }
48
+ const data = await res.json()
43
49
  setUsers(data.users)
44
50
  setError("")
45
- } else {
46
- setError(data.error || "Failed to load users")
51
+ } catch (err: any) {
52
+ setError(err.message || "Failed to load users")
47
53
  }
48
54
  setLoading(false)
49
55
  }
@@ -108,18 +114,18 @@ export function AdminPanel({ supabase, onClose, apiBase = "/api/admin/users" }:
108
114
 
109
115
  return (
110
116
  <div className="fixed inset-0 z-50 flex justify-end">
111
- <div className="absolute inset-0 bg-black/50" onClick={onClose} />
112
- <div className="relative w-full max-w-lg overflow-y-auto bg-[var(--bg)] border-l border-[var(--border)] shadow-2xl">
113
- <div className="sticky top-0 z-10 flex items-center justify-between border-b border-[var(--border)] bg-[var(--bg)] px-5 py-4">
114
- <h2 className="text-lg font-semibold">Admin</h2>
117
+ <div className="absolute inset-0 bg-black/30" onClick={onClose} />
118
+ <div className="relative w-80 sm:w-96 overflow-y-auto bg-[var(--bg)] border-l border-[var(--border)] shadow-xl">
119
+ <div className="sticky top-0 z-10 flex items-center justify-between border-b border-[var(--border)] bg-[var(--bg)] px-4 py-3">
120
+ <h2 className="text-sm font-semibold">Admin</h2>
115
121
  <button onClick={onClose} className="rounded-lg p-1.5 text-[var(--text-muted)] hover:bg-[var(--bg-card)] hover:text-[var(--text)]">
116
122
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M18 6L6 18M6 6l12 12" /></svg>
117
123
  </button>
118
124
  </div>
119
125
 
120
- <div className="p-5 space-y-6">
121
- <div className="rounded-xl border border-[var(--border)] bg-[var(--bg-card)] p-4">
122
- <h3 className="text-sm font-medium mb-3">Invite User</h3>
126
+ <div className="p-4 space-y-4">
127
+ <div className="rounded-lg border border-[var(--border)] bg-[var(--bg-card)] p-3">
128
+ <h3 className="text-xs font-medium mb-2">Invite User</h3>
123
129
  <form onSubmit={handleInvite} className="space-y-3">
124
130
  <input type="text" value={inviteName} onChange={(e) => setInviteName(e.target.value)} placeholder="Name (required)" required className="w-full rounded-lg border border-[var(--border)] bg-[var(--bg)] px-3 py-2 text-sm text-[var(--text)] placeholder:text-[var(--text-muted)] focus:border-[var(--accent)] focus:outline-none focus:ring-1 focus:ring-[var(--accent)]" />
125
131
  <input type="email" value={inviteEmail} onChange={(e) => setInviteEmail(e.target.value)} placeholder="email@example.com" required className="w-full rounded-lg border border-[var(--border)] bg-[var(--bg)] px-3 py-2 text-sm text-[var(--text)] placeholder:text-[var(--text-muted)] focus:border-[var(--accent)] focus:outline-none focus:ring-1 focus:ring-[var(--accent)]" />
@@ -137,7 +143,7 @@ export function AdminPanel({ supabase, onClose, apiBase = "/api/admin/users" }:
137
143
  </div>
138
144
 
139
145
  <div>
140
- <h3 className="text-sm font-medium mb-3">Users ({users.length})</h3>
146
+ <h3 className="text-xs font-medium mb-2">Users ({users.length})</h3>
141
147
  {error && <p className="mb-3 text-sm text-[var(--danger)]">{error}</p>}
142
148
  {loading ? (
143
149
  <p className="text-sm text-[var(--text-muted)]">Loading...</p>