feat: Phase 4 — Admin panel (dashboard, users, moderation)

AdminPanel2 component with sidebar navigation:
- Dashboard: KPI cards (users, patches, premium, flagged)
- Users: search, filter by role, table with role dropdown to
  change user/premium/admin/banned per user
- Workshop moderation: filter flagged/deleted, approve/delete/restore
  actions per patch with status badges

Features:
- Role-protected: non-admins see 🔒 locked screen
- Sidebar nav: Dashboard / Usuarios / Workshop / Volver
- Admin button visible in Workshop nav for admin users
- Responsive: sidebar becomes horizontal tabs on mobile,
  KPIs 2x2 grid, table rows wrap

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jose Luis
2026-03-21 20:53:32 +01:00
parent c673745b09
commit e53ec600ad
4 changed files with 348 additions and 4 deletions

View File

@@ -142,8 +142,8 @@ function PatchCard({ patch, onLoad, onLike }) {
);
}
export default function Workshop({ onSwitchToSandbox, onSwitchToGame }) {
const { isLoggedIn, openAuth, logout, user } = useAuth();
export default function Workshop({ onSwitchToSandbox, onSwitchToGame, onSwitchToAdmin }) {
const { isLoggedIn, isAdmin, openAuth, logout, user } = useAuth();
const [patches, setPatches] = useState([]);
const [search, setSearch] = useState('');
const [activeTag, setActiveTag] = useState('');
@@ -209,6 +209,9 @@ export default function Workshop({ onSwitchToSandbox, onSwitchToGame }) {
<button className="ws-nav-tab active">Workshop</button>
</div>
<div style={{ flex: 1 }} />
{isAdmin && onSwitchToAdmin && (
<button className="ws-nav-tab" onClick={onSwitchToAdmin} style={{ color: 'var(--yellow)' }}>🛠 Admin</button>
)}
{isLoggedIn ? (
<div className="user-badge" onClick={logout} title="Cerrar sesion">
<div className="user-avatar">{user?.username?.[0]?.toUpperCase()}</div>