feat: frontend auth — login/register modal + user badge

- API service (api.js): fetch wrapper with JWT, auto-refresh on 401
- AuthContext: user state, login/register/logout, loading, roles
- AuthModal: tabbed login/register form matching .pen design
- User badge in toolbar (Sandbox + WorldMap) with initial avatar
- "Entrar" button when not logged in
- CSS: auth overlay, card, tabs, inputs, error state, user badge
- Auth is opt-in: app works fully without login

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jose Luis
2026-03-21 20:22:43 +01:00
parent e129fd3739
commit 3523111019
7 changed files with 399 additions and 5 deletions

View File

@@ -2,16 +2,22 @@ import React, { useState } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import GameApp from './game/GameApp.jsx';
import { AuthProvider } from './services/AuthContext.jsx';
import AuthModal from './components/AuthModal.jsx';
import './index.css';
function Root() {
const [mode, setMode] = useState('game'); // 'game' | 'sandbox'
if (mode === 'sandbox') {
return <App onSwitchToGame={() => setMode('game')} />;
}
return <GameApp onSwitchToSandbox={() => setMode('sandbox')} />;
return (
<AuthProvider>
{mode === 'sandbox'
? <App onSwitchToGame={() => setMode('game')} />
: <GameApp onSwitchToSandbox={() => setMode('sandbox')} />
}
<AuthModal />
</AuthProvider>
);
}
createRoot(document.getElementById('root')).render(<Root />);