Files
reaktor/src/game/AdminPanel.jsx
Jose Luis be66d9a7cf 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>
2026-03-21 03:15:31 +01:00

125 lines
4.5 KiB
JavaScript

/**
* AdminPanel.jsx — Debug/admin panel for SynthQuest
* Allows adding/removing stars and unlocking levels for testing
*/
import React, { useState } from 'react';
import { loadProgress, saveProgress, resetProgress } from './gameState.js';
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);
const setStars = (levelId, stars) => {
if (stars <= 0) {
delete p.completedLevels[levelId];
} else {
p.completedLevels[levelId] = { stars: Math.min(3, stars), completedAt: Date.now() };
}
saveProgress();
refresh(n => n + 1);
};
const unlockWorld = (world) => {
// Give 1 star to each level in all previous worlds up to the requirement
let needed = world.unlockStars || 0;
for (const w of worlds) {
if (w.id === world.id) break;
for (const level of w.levels) {
if (needed <= 0) break;
const existing = p.completedLevels[level.id]?.stars || 0;
if (existing < 1) {
p.completedLevels[level.id] = { stars: 1, completedAt: Date.now() };
needed -= 1;
}
}
}
saveProgress();
refresh(n => n + 1);
};
const giveAllStars = () => {
for (const w of worlds) {
for (const level of w.levels) {
p.completedLevels[level.id] = { stars: 3, completedAt: Date.now() };
}
}
saveProgress();
refresh(n => n + 1);
};
const handleReset = () => {
resetProgress();
refresh(n => n + 1);
};
return (
<div className="admin-overlay" onClick={onClose}>
<div className="admin-panel" onClick={e => e.stopPropagation()}>
<div className="admin-header">
<h2>🛠 Admin Mode</h2>
<span className="admin-total">Total: {totalStars}</span>
<button className="admin-close" onClick={onClose}></button>
</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>
<div className="admin-worlds">
{worlds.map((world, wi) => {
const worldStars = world.levels.reduce((s, l) => {
return s + (p.completedLevels[l.id]?.stars || 0);
}, 0);
const isUnlocked = !world.unlockStars || totalStars >= world.unlockStars;
return (
<div key={world.id} className="admin-world">
<div className="admin-world-header">
<span className="admin-world-icon" style={{ color: world.color }}>{world.icon}</span>
<span className="admin-world-name">M{wi + 1}: {world.name}</span>
<span className="admin-world-stars"> {worldStars}/{world.levels.length * 3}</span>
{!isUnlocked && (
<button className="admin-unlock-btn" onClick={() => unlockWorld(world)}>
🔓 Desbloquear
</button>
)}
</div>
<div className="admin-levels">
{world.levels.map((level, li) => {
const stars = p.completedLevels[level.id]?.stars || 0;
return (
<div key={level.id} className="admin-level">
<span className="admin-level-num">{wi + 1}.{li + 1}</span>
<span className="admin-level-name">{level.title}</span>
<div className="admin-star-btns">
{[0, 1, 2, 3].map(s => (
<button
key={s}
className={`admin-star-btn ${stars >= s && s > 0 ? 'active' : ''} ${s === 0 ? 'zero' : ''}`}
onClick={() => setStars(level.id, s)}
>
{s === 0 ? '✕' : '★'.repeat(s)}
</button>
))}
</div>
</div>
);
})}
</div>
</div>
);
})}
</div>
</div>
</div>
);
}