// Production - The Idle Game: Production Floor View // Clean modular orchestrator connecting sector toolbar, facility cards, and fine-grained DOM updating import { PRODUCTS } from '../data/products.js'; import { renderSectorBarHtml, renderSectorSummariesHtml, updateSectorBarDom } from './production/sectorBar.js'; import { renderFacilityCardHtml, updateFacilityCardDom } from './production/facilityCard.js'; export { calculateMultiCost, getProductOutputRates } from './production/ratesCalculator.js'; /** * Mounts the production floor DOM structure ONCE */ export function mountProductionFloor(container, state, onAction, engine) { const selectedSector = state.selectedSector || 'all'; const buyMode = state.buyMode || '1'; const filteredProducts = PRODUCTS.filter(p => { if (selectedSector === 'all') return true; return p.sector === selectedSector; }); let html = renderSectorSummariesHtml(selectedSector, engine); html += `
`; for (const p of filteredProducts) { const pState = state.products[p.id] || { unlocked: false, lines: 0, stock: 0, cycleProgress: 0, isBottlenecked: false }; html += renderFacilityCardHtml(p, pState, state, buyMode); } html += `
`; container.innerHTML = html; // Attach event listeners ONCE container.querySelectorAll('.sector-pill').forEach(btn => { btn.onclick = () => onAction({ type: 'SELECT_SECTOR', sector: btn.dataset.sector }); }); container.querySelectorAll('.sector-mini-card').forEach(card => { card.onclick = () => onAction({ type: 'SELECT_SECTOR', sector: card.dataset.sector }); }); container.querySelectorAll('.facility-card').forEach(card => { card.onclick = (e) => { if (e.target.closest('button')) return; onAction({ type: 'SELECT_PRODUCT', productId: card.dataset.product }); }; }); container.querySelectorAll('.btn-unlock').forEach(btn => { btn.onclick = () => onAction({ type: 'UNLOCK_PRODUCT', productId: btn.dataset.product }); }); container.querySelectorAll('.btn-cycle').forEach(btn => { btn.onclick = () => onAction({ type: 'MANUAL_CYCLE', productId: btn.dataset.product }); }); container.querySelectorAll('.btn-expand').forEach(btn => { btn.onclick = () => onAction({ type: 'BUY_LINES', productId: btn.dataset.product }); }); container.querySelectorAll('.btn-hire-mgr').forEach(btn => { btn.onclick = () => onAction({ type: 'HIRE_MANAGER', productId: btn.dataset.product }); }); container.querySelectorAll('.btn-expand-logistics').forEach(btn => { btn.onclick = () => onAction({ type: 'BUY_LOGISTICS', productId: btn.dataset.product }); }); container.querySelectorAll('.btn-toggle-logistics').forEach(btn => { btn.onclick = () => onAction({ type: 'TOGGLE_LOGISTICS', productId: btn.dataset.product }); }); container.querySelectorAll('.btn-toggle-downstream').forEach(btn => { btn.onclick = () => onAction({ type: 'TOGGLE_DOWNSTREAM_SUPPLY', productId: btn.dataset.product }); }); container.querySelectorAll('.btn-throttle-pill').forEach(btn => { btn.onclick = () => onAction({ type: 'SET_PRODUCTION_TARGET', productId: btn.dataset.product, target: parseFloat(btn.dataset.target) }); }); } /** * Fine-grained in-place DOM updates (0% layout thrashing, 0% DOM teardown) */ export function updateProductionFloor(container, state, engine) { const buyMode = state.buyMode || '1'; const selectedSector = state.selectedSector || 'all'; // 1. Update Sector Navigation Pills & Summaries updateSectorBarDom(selectedSector, engine); // 2. Update Facility Cards for (const p of PRODUCTS) { const pState = state.products[p.id]; if (!pState) continue; updateFacilityCardDom(p, pState, state, buyMode); } }