- amerc-api: GET /docs + /docs/:id are public (reads); writes still require auth - DocsApp/ConsoleShell: publicView mode renders docs read-only when logged out, with a 'Log in to edit' header CTA; edit/new/delete hidden for anonymous - Docs nav link now shown to everyone - seeded 5 quality guides: Quickstart, Publish an agent, Embed a chatbox, Showcase, API reference
77 lines
4.0 KiB
JavaScript
77 lines
4.0 KiB
JavaScript
import React, { useState } from 'react';
|
|
import { useAuth } from './Auth.jsx';
|
|
|
|
const APPS = [
|
|
{ label: 'Tavern', href: 'https://amerc.ai/' },
|
|
{ label: 'Docs', href: 'https://docs.amerc.ai/' },
|
|
{ label: 'PM', href: 'https://pm.amerc.ai/' },
|
|
{ label: 'Git', href: 'https://git.amerc.ai/' },
|
|
];
|
|
|
|
function ConsoleLogin({ auth }) {
|
|
const [mode, setMode] = useState('login');
|
|
const [email, setEmail] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [handle, setHandle] = useState('');
|
|
const [err, setErr] = useState('');
|
|
const [busy, setBusy] = useState(false);
|
|
const submit = async (e) => {
|
|
e.preventDefault(); setErr(''); setBusy(true);
|
|
try {
|
|
const { api } = await import('./api.js');
|
|
const d = await api(mode === 'login' ? '/auth/login' : '/auth/signup', { method: 'POST', body: { email, password, handle } });
|
|
auth.setUser(d.user);
|
|
} catch (e2) { setErr(e2.message); } finally { setBusy(false); }
|
|
};
|
|
return (
|
|
<div className="cs-login-wrap">
|
|
<form className="cs-login" onSubmit={submit}>
|
|
<div className="cs-brand"><span className="cs-gem" />amerc</div>
|
|
<div className="cs-tabs">
|
|
<button type="button" className={mode === 'login' ? 'on' : ''} onClick={() => setMode('login')}>Login</button>
|
|
<button type="button" className={mode === 'signup' ? 'on' : ''} onClick={() => setMode('signup')}>Sign Up</button>
|
|
</div>
|
|
<input type="email" placeholder="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
|
|
{mode === 'signup' && <input placeholder="display name" value={handle} onChange={(e) => setHandle(e.target.value)} />}
|
|
<input type="password" placeholder="password (min 6)" value={password} onChange={(e) => setPassword(e.target.value)} required minLength={6} />
|
|
{err && <p className="cs-err">{err}</p>}
|
|
<button type="submit" className="cs-btn cs-primary" disabled={busy}>{busy ? '…' : mode === 'login' ? 'Enter' : 'Create account'}</button>
|
|
<p className="cs-hint">One amerc account across tavern, docs, PM and git.</p>
|
|
</form>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function ConsoleShell({ title, accent = '#27d8ff', current, requireRole, publicView, children }) {
|
|
const auth = useAuth();
|
|
if (!auth.ready) return <div className="cs-app"><div className="cs-loading">Loading…</div></div>;
|
|
if (!auth.user && !publicView) return <div className="cs-app" style={{ '--accent': accent }}><ConsoleLogin auth={auth} /></div>;
|
|
if (requireRole && auth.user && auth.user.role !== requireRole) return (
|
|
<div className="cs-app" style={{ '--accent': accent }}>
|
|
<div className="cs-login-wrap"><div className="cs-login" style={{ textAlign: 'center' }}>
|
|
<div className="cs-brand"><span className="cs-gem" />amerc</div>
|
|
<p style={{ color: '#ff9f9f', fontSize: 11, lineHeight: 1.8 }}>This space is for <b>{requireRole}s</b> only.</p>
|
|
<p className="cs-hint">Signed in as {auth.user.handle} ({auth.user.role}). Ask an admin for access.</p>
|
|
<a className="cs-btn cs-primary" href="https://amerc.ai/">← Back to tavern</a>
|
|
<button className="cs-btn" onClick={() => auth.logout()}>Log out</button>
|
|
</div></div>
|
|
</div>
|
|
);
|
|
return (
|
|
<div className="cs-app" style={{ '--accent': accent }}>
|
|
<header className="cs-top">
|
|
<div className="cs-brand"><span className="cs-gem" />amerc<small>{title}</small></div>
|
|
<nav className="cs-appnav">
|
|
{APPS.map((a) => <a key={a.label} href={a.href} className={a.label.toLowerCase() === current ? 'on' : ''}>{a.label}</a>)}
|
|
</nav>
|
|
<div className="cs-user">
|
|
{auth.user
|
|
? <><span>{auth.user.handle}{auth.user.role === 'admin' ? ' · admin' : ''}</span><button type="button" onClick={() => auth.logout()}>Log out</button></>
|
|
: <a className="cs-btn cs-primary" href="https://amerc.ai/#/signin">Log in to edit</a>}
|
|
</div>
|
|
</header>
|
|
<main className="cs-main">{typeof children === 'function' ? children(auth) : children}</main>
|
|
</div>
|
|
);
|
|
}
|