Spaces:
Running
Running
File size: 4,071 Bytes
d660fa9 f4542ce | 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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | /**
* LoginButton — auth entry point for admin controls.
*
* Shows a LOGIN pill when unauthenticated (opens LoginModal) and a user
* dropdown with logout when a session is active.
*
* Architecture: rendered by App.jsx; uses the useAuth context shared with
* InfoBar and RosterManager.
*
* Design: anonymous users can watch; only admins get controls.
*/
import { useState } from "react";
import { useAuth } from "../hooks/useAuth";
import LoginModal from "./LoginModal";
export default function LoginButton() {
const { user, isAuthenticated, loading, login, logout } = useAuth();
const [showModal, setShowModal] = useState(false);
const [showDropdown, setShowDropdown] = useState(false);
if (loading) return null;
const basePill = {
position: "fixed",
bottom: 16,
right: 16,
zIndex: 1500,
fontFamily: "'Space Mono', monospace",
fontSize: 11,
fontWeight: 600,
letterSpacing: "0.08em",
borderRadius: 6,
padding: "7px 16px",
cursor: "pointer",
display: "flex",
alignItems: "center",
gap: 7,
textTransform: "uppercase",
transition: "all 0.15s",
};
if (!isAuthenticated) {
return (
<>
<button
style={{
...basePill,
background: "#1a1a28",
border: "1px solid rgba(212,160,74,0.45)",
color: "#e7bd70",
boxShadow: "0 2px 12px rgba(0,0,0,0.5), inset 0 1px 0 rgba(212,160,74,0.15)",
}}
onClick={() => setShowModal(true)}
title="Admin login"
>
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M15 3h4a2 2 0 012 2v14a2 2 0 01-2 2h-4" />
<polyline points="10 17 15 12 10 7" />
<line x1="15" y1="12" x2="3" y2="12" />
</svg>
LOGIN
</button>
{showModal && <LoginModal onClose={() => setShowModal(false)} onLogin={login} />}
</>
);
}
return (
<div style={{ position: "fixed", bottom: 16, right: 16, zIndex: 1500 }}>
<button
style={{
...basePill,
background: "rgba(212,160,74,0.12)",
border: "1px solid rgba(212,160,74,0.35)",
color: "#e7bd70",
boxShadow: "0 2px 10px rgba(0,0,0,0.4)",
}}
onClick={() => setShowDropdown((v) => !v)}
title="Logged in — click to logout"
>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="8" r="5" />
<path d="M20 21a8 8 0 00-16 0" />
</svg>
{user?.name || user?.email}
</button>
{showDropdown && (
<div
style={{
position: "absolute",
bottom: 42,
right: 0,
background: "#111118",
border: "1px solid rgba(212,160,74,0.25)",
borderRadius: 6,
padding: "8px 0",
minWidth: 170,
boxShadow: "0 8px 30px rgba(0,0,0,0.6)",
}}
onMouseLeave={() => setShowDropdown(false)}
>
<div style={{ padding: "6px 14px", fontSize: 10, color: "#888", fontFamily: "'Space Mono', monospace" }}>
{user?.email}
</div>
<div style={{ height: 1, background: "rgba(255,255,255,0.08)", margin: "2px 0" }} />
<button
onClick={() => {
setShowDropdown(false);
logout();
}}
style={{
display: "block",
width: "100%",
textAlign: "left",
padding: "8px 14px",
background: "none",
border: "none",
color: "#ff9494",
cursor: "pointer",
fontSize: 11,
fontFamily: "'Space Mono', monospace",
}}
>
LOGOUT
</button>
</div>
)}
</div>
);
}
|