Files
Magic-Garden-Bot/extension/modules/ui/overlays/garden.js
2025-12-09 23:49:52 +00:00

106 lines
4.7 KiB
JavaScript

import { WindowManager } from './window_manager.js';
export const GardenOverlay = {
open() {
const { win, content } = WindowManager.create('window-garden', '🌻 Garden', { x: 240, y: 20, width: 600, height: 320 });
// Render happens via update()
this.update(content);
},
update(container) {
if (!container) container = document.getElementById('window-garden-content');
if (!container) return;
const MB = window.MagicBot;
if (!MB || !MB.state || !MB.state.garden || !MB.state.garden.tileObjects) {
container.innerHTML = '<div style="color:red">No Garden Data</div>';
return;
}
const now = Date.now();
// Re-render completely for simplicity (virtual DOM would be better but vanilla JS...)
// To avoid flicker, we could diff, but for now just clear and rebuild.
container.innerHTML = '';
// Harvest All Button
const btnHarvestAll = document.createElement('button');
btnHarvestAll.textContent = "Harvest All Ready";
btnHarvestAll.style.cssText = "width: 100%; margin-bottom: 10px; padding: 8px; background: #66bb6a; color: white; border: none; border-radius: 4px; font-weight: bold; cursor: pointer;";
btnHarvestAll.onclick = () => {
let count = 0;
for (let i = 0; i < 200; i++) {
const tile = MB.state.garden.tileObjects[i.toString()];
const slots = tile?.slots || [];
slots.forEach((s, idx) => {
if (Date.now() >= s.endTime) {
MB.sendMsg({ type: 'HarvestCrop', slot: i, slotsIndex: idx, scopePath: ["Room", "Quinoa"] });
count++;
}
});
}
btnHarvestAll.textContent = `Harvested ${count}!`;
setTimeout(() => btnHarvestAll.textContent = "Harvest All Ready", 1000);
};
container.appendChild(btnHarvestAll);
const gridContainer = document.createElement('div');
gridContainer.style.cssText = "display: flex; gap: 10px; justify-content: center;";
const leftGrid = document.createElement('div');
leftGrid.style.cssText = "display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px;";
const rightGrid = document.createElement('div');
rightGrid.style.cssText = "display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px;";
gridContainer.appendChild(leftGrid);
gridContainer.appendChild(rightGrid);
container.appendChild(gridContainer);
const getProgressColor = (p) => {
const hue = Math.floor(Math.max(0, Math.min(1, p)) * 120);
return `hsl(${hue}, 70%, 50%)`;
};
for (let i = 0; i < 200; i++) {
const tile = MB.state.garden.tileObjects[i.toString()];
const slots = tile?.slots || [];
const crop = slots[0];
const cell = document.createElement('div');
cell.style.cssText = "width: 25px; height: 25px; border: 1px solid #333; border-radius: 3px; background: rgba(255,255,255,0.02); position: relative; cursor: pointer;";
if (crop) {
const totalTime = crop.endTime - crop.startTime;
const progress = totalTime > 0 ? (Math.max(0, now - crop.startTime) / totalTime) : 1;
cell.style.background = getProgressColor(progress);
let anyReady = false;
let tooltip = `Slot: ${i}\nSpecies: ${tile.species}`;
slots.forEach((s, idx) => {
const isReady = now >= s.endTime;
if (isReady) anyReady = true;
const left = Math.max(0, Math.ceil((s.endTime - now) / 1000));
tooltip += `\n#${idx}: ${isReady ? 'READY' : left + 's'}`;
if (s.mutations?.length) tooltip += ` [${s.mutations.join(',')}]`;
});
cell.style.border = `1px solid ${anyReady ? '#fff' : '#555'}`;
cell.title = tooltip;
cell.innerHTML = `<span style="font-size: 10px; color: rgba(0,0,0,0.5); font-weight: bold; position: absolute; top: 1px; left: 2px;">${tile.species[0]}</span>`;
cell.onclick = () => {
slots.forEach((s, idx) => {
if (Date.now() >= s.endTime) {
MB.sendMsg({ type: 'HarvestCrop', slot: i, slotsIndex: idx, scopePath: ["Room", "Quinoa"] });
}
});
cell.style.opacity = '0.5';
};
}
if (i % 20 < 10) leftGrid.appendChild(cell);
else rightGrid.appendChild(cell);
}
}
};