feat: admin auto-solve button for quick level testing
- Add adminMode toggle in AdminPanel (green "Admin ON/OFF" button) - Pass adminMode through GameApp → PuzzleView - Show purple "🛠 Resolver" button in puzzle toolbar when admin is active - Auto-solve gives 3 stars instantly and shows completion overlay - Lets admin skip through all 96 levels for rapid testing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { loadProgress, saveProgress, resetProgress } from './gameState.js';
|
||||
|
||||
export default function AdminPanel({ worlds, onClose }) {
|
||||
export default function AdminPanel({ worlds, onClose, adminMode, onToggleAdmin }) {
|
||||
const [, refresh] = useState(0);
|
||||
const p = loadProgress();
|
||||
const totalStars = Object.values(p.completedLevels).reduce((s, l) => s + (l.stars || 0), 0);
|
||||
@@ -63,6 +63,12 @@ export default function AdminPanel({ worlds, onClose }) {
|
||||
</div>
|
||||
|
||||
<div className="admin-actions">
|
||||
<button
|
||||
className={`admin-action-btn ${adminMode ? 'active' : ''}`}
|
||||
onClick={onToggleAdmin}
|
||||
>
|
||||
{adminMode ? '🛠 Admin ON' : '🛠 Admin OFF'}
|
||||
</button>
|
||||
<button className="admin-action-btn gold" onClick={giveAllStars}>★★★ Todo</button>
|
||||
<button className="admin-action-btn danger" onClick={handleReset}>Reset Progreso</button>
|
||||
</div>
|
||||
|
||||
@@ -23,6 +23,7 @@ export default function GameApp({ onSwitchToSandbox }) {
|
||||
const [currentLevelIndex, setCurrentLevelIndex] = useState(0);
|
||||
const [currentWorld, setCurrentWorld] = useState(null);
|
||||
const [showAdmin, setShowAdmin] = useState(false);
|
||||
const [adminMode, setAdminMode] = useState(false);
|
||||
|
||||
const handleSelectLevel = useCallback((level, world) => {
|
||||
const idx = world.levels.findIndex(l => l.id === level.id);
|
||||
@@ -67,6 +68,7 @@ export default function GameApp({ onSwitchToSandbox }) {
|
||||
worldLevels={currentWorld.levels}
|
||||
onBack={handleBack}
|
||||
onNextLevel={handleNextLevel}
|
||||
adminMode={adminMode}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -82,6 +84,8 @@ export default function GameApp({ onSwitchToSandbox }) {
|
||||
<AdminPanel
|
||||
worlds={allWorlds}
|
||||
onClose={() => setShowAdmin(false)}
|
||||
adminMode={adminMode}
|
||||
onToggleAdmin={() => setAdminMode(a => !a)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -9,7 +9,7 @@ import LevelComplete from './LevelComplete.jsx';
|
||||
import { completeLevel, saveLevelPatch, getLevelPatch, markHintUsed, wasHintUsed } from './gameState.js';
|
||||
import { playLevelComplete, playFail, playHint, playEngineStart, playEngineStop, playNav } from '../engine/uiSounds.js';
|
||||
|
||||
export default function PuzzleView({ level, levelIndex, worldLevels, onBack, onNextLevel }) {
|
||||
export default function PuzzleView({ level, levelIndex, worldLevels, onBack, onNextLevel, adminMode }) {
|
||||
const [, forceUpdate] = useState(0);
|
||||
const containerRef = useRef(null);
|
||||
const portPositions = useRef({});
|
||||
@@ -285,6 +285,17 @@ export default function PuzzleView({ level, levelIndex, worldLevels, onBack, onN
|
||||
}
|
||||
};
|
||||
|
||||
// Admin auto-solve — gives 3 stars instantly
|
||||
const handleAutoSolve = () => {
|
||||
const checks = level.checks.map(check => ({
|
||||
...check,
|
||||
passed: true,
|
||||
}));
|
||||
completeLevel(level.id, 3);
|
||||
setResult({ stars: 3, checks, hintPenalty: false });
|
||||
playLevelComplete();
|
||||
};
|
||||
|
||||
const isLastLevel = levelIndex >= worldLevels.length - 1;
|
||||
|
||||
return (
|
||||
@@ -312,6 +323,11 @@ export default function PuzzleView({ level, levelIndex, worldLevels, onBack, onN
|
||||
<button className="gm-btn check" onClick={handleCheck}>
|
||||
✓ Comprobar
|
||||
</button>
|
||||
{adminMode && (
|
||||
<button className="gm-btn admin-solve" onClick={handleAutoSolve} title="Admin: resolver nivel">
|
||||
🛠 Resolver
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -715,9 +715,17 @@ html, body, #root {
|
||||
}
|
||||
.admin-action-btn.gold { border-color: var(--yellow); color: var(--yellow); }
|
||||
.admin-action-btn.gold:hover { background: var(--yellow); color: var(--bg); }
|
||||
.admin-action-btn.active { border-color: var(--green); color: var(--green); background: rgba(68, 255, 136, 0.1); }
|
||||
.admin-action-btn.active:hover { background: var(--green); color: var(--bg); }
|
||||
.admin-action-btn.danger { border-color: var(--red); color: var(--red); }
|
||||
.admin-action-btn.danger:hover { background: var(--red); color: #fff; }
|
||||
|
||||
/* Admin auto-solve button in puzzle bar */
|
||||
.gm-btn.admin-solve {
|
||||
background: rgba(170, 85, 255, 0.15); border-color: var(--purple); color: var(--purple);
|
||||
}
|
||||
.gm-btn.admin-solve:hover { background: var(--purple); color: #fff; }
|
||||
|
||||
.admin-world { margin-bottom: 16px; }
|
||||
.admin-world-header {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
|
||||
Reference in New Issue
Block a user