Oil & Gas Production Dashboard

Oil & Gas Production Dashboard

Monitor and analyze well production and performance.

Overall Production Summary

Production Over Time

Total Oil Production by Well

Production Log

Date Well ID Oil (bbl) Gas (MCF) Water (bbl)

Enter Daily Production Logs

${uniqueWells}

Avg. Daily Oil (bbl)

${avgOilPerDay.toLocaleString(undefined, {maximumFractionDigits: 0})}

`; }; const renderDataTable = () => { dataTableBody.innerHTML = ''; const sortedLogs = [...state.logs].sort((a, b) => new Date(b.date) - new Date(a.date)); sortedLogs.forEach(log => { const row = ` ${log.date} ${log.wellId} ${log.oil.toLocaleString()} ${log.gas.toLocaleString()} ${log.water.toLocaleString()} `; dataTableBody.innerHTML += row; }); }; const renderCharts = () => { const productionByDate = state.logs.reduce((acc, log) => { if (!acc[log.date]) { acc[log.date] = { oil: 0, gas: 0 }; } acc[log.date].oil += log.oil; acc[log.date].gas += log.gas; return acc; }, {}); const sortedDates = Object.keys(productionByDate).sort((a, b) => new Date(a) - new Date(b)); if (trendChart) trendChart.destroy(); trendChart = new Chart(trendCanvas.getContext('2d'), { type: 'line', data: { labels: sortedDates, datasets: [ { label: 'Oil (bbl)', data: sortedDates.map(date => productionByDate[date].oil), borderColor: '#166534', backgroundColor: 'rgba(22, 101, 52, 0.1)', fill: true, yAxisID: 'yOil' }, { label: 'Gas (MCF)', data: sortedDates.map(date => productionByDate[date].gas), borderColor: '#f97316', backgroundColor: 'rgba(249, 115, 22, 0.1)', fill: true, yAxisID: 'yGas' } ] }, options: { responsive: true, maintainAspectRatio: false, scales: { x: { type: 'time', time: { unit: 'day' } }, yOil: { type: 'linear', position: 'left', title: { display: true, text: 'Oil (bbl)' } }, yGas: { type: 'linear', position: 'right', title: { display: true, text: 'Gas (MCF)' }, grid: { drawOnChartArea: false } } } } }); const productionByWell = state.logs.reduce((acc, log) => { acc[log.wellId] = (acc[log.wellId] || 0) + log.oil; return acc; }, {}); const wellLabels = Object.keys(productionByWell); const wellData = wellLabels.map(label => productionByWell[label]); if (wellChart) wellChart.destroy(); wellChart = new Chart(wellCanvas.getContext('2d'), { type: 'bar', data: { labels: wellLabels, datasets: [{ label: 'Total Oil (bbl)', data: wellData, backgroundColor: 'rgba(202, 138, 4, 0.7)' }] }, options: { indexAxis: 'y', responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } } } }); }; const renderConfigRows = () => { configRowsContainer.innerHTML = ''; const sortedLogs = [...state.logs].sort((a, b) => new Date(b.date) - new Date(a.date)); sortedLogs.forEach(log => { const row = `
`; configRowsContainer.innerHTML += row; }); addConfigEventListeners(); }; // --- EVENT HANDLERS --- const handleConfigChange = (e) => { const id = parseInt(e.target.dataset.id); const field = e.target.dataset.field; const value = (e.target.type === 'number') ? parseInt(e.target.value, 10) || 0 : e.target.value; const log = state.logs.find(l => l.id === id); if (log) log[field] = value; renderAll(); }; const handleAddLog = () => { const newId = state.logs.length > 0 ? Math.max(...state.logs.map(l => l.id)) + 1 : 1; const today = new Date().toISOString().split('T')[0]; state.logs.push({ id: newId, date: today, wellId: "New Well", oil: 0, gas: 0, water: 0 }); renderAll(); }; const handleRemoveLog = (e) => { const id = parseInt(e.target.dataset.id); state.logs = state.logs.filter(l => l.id !== id); renderAll(); }; const addConfigEventListeners = () => { document.querySelectorAll('.config-input').forEach(input => input.addEventListener('change', handleConfigChange)); document.querySelectorAll('.remove-log-btn').forEach(button => button.addEventListener('click', handleRemoveLog)); }; const handleDownloadPdf = () => { const { jsPDF } = window.jspdf; const pdfContent = document.getElementById('pdf-content'); document.querySelectorAll('.no-print').forEach(el => el.style.visibility = 'hidden'); Chart.defaults.animation = false; html2canvas(pdfContent, { scale: 2, useCORS: true, backgroundColor: '#ffffff' }).then(canvas => { document.querySelectorAll('.no-print').forEach(el => el.style.visibility = 'visible'); Chart.defaults.animation = true; const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const imgWidth = pdfWidth - 20; const imgHeight = canvas.height * imgWidth / canvas.width; pdf.addImage(imgData, 'PNG', 10, 10, imgWidth, imgHeight); pdf.save('Oil-Gas-Production-Dashboard.pdf'); }); }; // --- TABBING LOGIC --- let currentTabIndex = 0; const updateTabButtons = () => { prevTabBtn.disabled = currentTabIndex === 0; nextTabBtn.disabled = currentTabIndex === tabContents.length - 1; }; const switchTab = (index) => { tabButtons.forEach(btn => btn.classList.remove('active')); tabContents.forEach(content => content.classList.remove('active')); tabButtons[index].classList.add('active'); tabContents[index].classList.add('active'); currentTabIndex = index; updateTabButtons(); }; tabButtons.forEach((button, index) => button.addEventListener('click', () => switchTab(index))); prevTabBtn.addEventListener('click', () => { if (currentTabIndex > 0) switchTab(currentTabIndex - 1); }); nextTabBtn.addEventListener('click', () => { if (currentTabIndex < tabContents.length - 1) switchTab(currentTabIndex + 1); }); // --- INITIALIZATION --- if (kpiCardsContainer && addLogBtn && downloadPdfBtn) { addLogBtn.addEventListener('click', handleAddLog); downloadPdfBtn.addEventListener('click', handleDownloadPdf); renderAll(); updateTabButtons(); } else { console.error("Essential dashboard elements could not be found."); } });
Scroll to Top