- Pool preset checkboxes with failover in Calibrate and Forge - Tier 1/2 UX: setup banner, forge next worker, LAN defaults, blueprint prompt - USB: auto-install forge tools, seed config.json, sync LAUNCH.bat
85 lines
2.7 KiB
TypeScript
85 lines
2.7 KiB
TypeScript
import { useEffect, useState, type ReactNode } from 'react';
|
|
import { getStoredAuth, setStoredAuth } from '../api/auth';
|
|
|
|
export default function SessionGate({ children }: { children: ReactNode }) {
|
|
const [ready, setReady] = useState(false);
|
|
const [authed, setAuthed] = useState(!!getStoredAuth());
|
|
const [user, setUser] = useState('');
|
|
const [pass, setPass] = useState('');
|
|
const [err, setErr] = useState('');
|
|
|
|
useEffect(() => {
|
|
const token = getStoredAuth();
|
|
if (!token) {
|
|
setAuthed(false);
|
|
setReady(true);
|
|
return;
|
|
}
|
|
fetch('/api/v1/config', { headers: { Authorization: `Basic ${token}` } })
|
|
.then((r) => {
|
|
setAuthed(r.ok);
|
|
setReady(true);
|
|
})
|
|
.catch(() => {
|
|
setAuthed(false);
|
|
setReady(true);
|
|
});
|
|
}, []);
|
|
|
|
const handleLogin = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setErr('');
|
|
const token = btoa(`${user}:${pass}`);
|
|
try {
|
|
const res = await fetch('/api/v1/config', { headers: { Authorization: `Basic ${token}` } });
|
|
if (!res.ok) {
|
|
setErr('Login failed — check username and password.');
|
|
return;
|
|
}
|
|
setStoredAuth(user, pass);
|
|
setAuthed(true);
|
|
} catch {
|
|
setErr('Cannot reach server — check that miner-server is running.');
|
|
}
|
|
};
|
|
|
|
if (!ready) {
|
|
return (
|
|
<div className="session-gate">
|
|
<p className="font-tech">Starting AetherForge…</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!authed) {
|
|
return (
|
|
<div className="session-gate">
|
|
<form className="session-gate-card card" onSubmit={handleLogin}>
|
|
<h1 className="font-display">AetherForge</h1>
|
|
<p className="form-hint">Sign in to open the command deck.</p>
|
|
<p className="form-hint" style={{ marginTop: '0.5rem' }}>
|
|
First run: password is in the LAUNCH console or <code className="mono-sm">data\login-credentials.json</code> next to the server data folder.
|
|
</p>
|
|
<label className="label" htmlFor="session-user">Username</label>
|
|
<input id="session-user" className="input" value={user} onChange={(e) => setUser(e.target.value)} autoComplete="username" />
|
|
<label className="label" htmlFor="session-pass">Password</label>
|
|
<input
|
|
id="session-pass"
|
|
className="input"
|
|
type="password"
|
|
value={pass}
|
|
onChange={(e) => setPass(e.target.value)}
|
|
autoComplete="current-password"
|
|
/>
|
|
{err && <p className="form-hint" style={{ color: 'var(--accent-red)' }}>{err}</p>}
|
|
<button type="submit" className="btn btn-primary btn-lg">
|
|
Enter Command Deck
|
|
</button>
|
|
</form>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return <>{children}</>;
|
|
}
|