Frontend update

This commit is contained in:
2026-06-26 21:51:27 -05:00
parent eef79e2403
commit 6dba6a017c
48 changed files with 5004 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
import { useEffect, useState } from 'react'
import { Link, useNavigate, useLocation } from 'react-router-dom'
import MoonDot from '../../components/MoonDot.jsx'
import { useAuth } from '../../contexts/AuthContext.jsx'
const BG =
"linear-gradient(180deg,rgba(11,15,20,0.72),rgba(11,15,20,0.9)),url('/assets/img/uomysticmoon-main-hero.png')"
export default function AdminLogin() {
const { user, login } = useAuth()
const navigate = useNavigate()
const location = useLocation()
const dest = location.state?.from?.pathname || '/admin'
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState('')
const [busy, setBusy] = useState(false)
// Already signed in → go straight to the panel.
useEffect(() => {
if (user) navigate(dest, { replace: true })
}, [user, dest, navigate])
async function onSubmit(e) {
e.preventDefault()
setError('')
setBusy(true)
try {
await login(username, password)
navigate(dest, { replace: true })
} catch (err) {
setError(err.status === 401 ? 'Incorrect username or password.' : 'Could not sign in right now.')
setBusy(false)
}
}
return (
<main
style={{
minHeight: '100vh',
display: 'grid',
placeItems: 'center',
padding: '40px 18px',
overflow: 'hidden',
backgroundColor: 'var(--bg-deep)',
backgroundImage: BG,
backgroundPosition: 'center',
backgroundSize: 'cover',
}}
>
<div style={{ width: '100%', maxWidth: 400 }}>
<div style={{ textAlign: 'center', marginBottom: 26 }}>
<div style={{ marginBottom: 14 }}>
<MoonDot size={15} glow={0.55} />
</div>
<h1 className="display" style={{ margin: 0, fontSize: '1.7rem', letterSpacing: '0.04em', color: 'var(--head)' }}>
UOMysticmoon
</h1>
<p className="sans" style={{ margin: '6px 0 0', color: '#9aa6b4', fontSize: '0.8rem', letterSpacing: '0.16em', textTransform: 'uppercase' }}>
Admin Panel
</p>
</div>
<form
onSubmit={onSubmit}
style={{
border: '1px solid var(--line)',
borderRadius: 12,
padding: 28,
background: 'linear-gradient(180deg,rgba(25,34,49,0.92),rgba(20,26,33,0.92))',
backdropFilter: 'blur(6px)',
boxShadow: '0 24px 60px rgba(0,0,0,0.5)',
}}
>
<label style={{ display: 'block', marginBottom: 16 }}>
<span className="field-label">Username</span>
<input
type="text"
autoComplete="username"
autoFocus
value={username}
onChange={(e) => setUsername(e.target.value)}
className="input"
/>
</label>
<label style={{ display: 'block', marginBottom: 22 }}>
<span className="field-label">Password</span>
<input
type="password"
autoComplete="current-password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="input"
/>
</label>
{error && (
<p className="sans" style={{ margin: '0 0 14px', color: '#d98b84', fontSize: '0.85rem', textAlign: 'center' }}>
{error}
</p>
)}
<button
type="submit"
disabled={busy}
className="btn btn-primary"
style={{ display: 'block', width: '100%', borderRadius: 8, padding: 12, textAlign: 'center' }}
>
{busy ? 'Signing in…' : 'Sign in'}
</button>
<p className="sans" style={{ margin: '16px 0 0', textAlign: 'center', color: 'var(--dim)', fontSize: '0.76rem' }}>
Protected area not indexed. Sessions expire after 1 day.
</p>
</form>
<p style={{ textAlign: 'center', margin: '20px 0 0' }}>
<Link to="/" className="sans" style={{ color: 'var(--accent)', fontSize: '0.84rem', textDecoration: 'none' }}>
Back to site
</Link>
</p>
</div>
</main>
)
}