934 lines
39 KiB
JavaScript
934 lines
39 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
|
const reportButtons = document.querySelectorAll('.report-btn');
|
|
const reportTitle = document.getElementById('report-title');
|
|
const reportTable = document.getElementById('report-table');
|
|
const exportCsvButton = document.getElementById('export-csv');
|
|
const exportPdfButton = document.getElementById('export-pdf');
|
|
const themeToggleButton = document.getElementById('theme-toggle');
|
|
const body = document.body;
|
|
|
|
// Helper function to update the theme toggle button text
|
|
function updateThemeToggleButtonText() {
|
|
if (body.classList.contains('dark-mode')) {
|
|
themeToggleButton.textContent = 'Change to Light Mode';
|
|
} else {
|
|
themeToggleButton.textContent = 'Change to Dark Mode';
|
|
}
|
|
}
|
|
|
|
// Check and apply the saved theme from localStorage
|
|
const savedTheme = localStorage.getItem('theme');
|
|
if (savedTheme) {
|
|
body.classList.toggle('dark-mode', savedTheme === 'dark');
|
|
}
|
|
|
|
// Update the button text based on the current theme
|
|
updateThemeToggleButtonText();
|
|
|
|
// Toggle the theme on button click
|
|
themeToggleButton.addEventListener('click', () => {
|
|
const isDarkMode = body.classList.toggle('dark-mode');
|
|
localStorage.setItem('theme', isDarkMode ? 'dark' : 'light');
|
|
updateThemeToggleButtonText(); // Update the button text after toggling
|
|
});
|
|
|
|
// Date formatting is now handled consistently on the backend
|
|
|
|
// Function to populate the table with data
|
|
function populateTable(data) {
|
|
const tableHead = reportTable.querySelector('thead tr');
|
|
const tableBody = reportTable.querySelector('tbody');
|
|
|
|
// Clear existing table content
|
|
tableHead.innerHTML = '';
|
|
tableBody.innerHTML = '';
|
|
|
|
if (data.headers && data.rows && data.rows.length > 0) {
|
|
// Populate table headers
|
|
data.headers.forEach((header) => {
|
|
const th = document.createElement('th');
|
|
th.textContent = header;
|
|
tableHead.appendChild(th);
|
|
});
|
|
|
|
// Populate table rows
|
|
data.rows.forEach((row) => {
|
|
const tr = document.createElement('tr');
|
|
row.forEach((cell, index) => {
|
|
const td = document.createElement('td');
|
|
|
|
// Use the cell data as-is since backend now handles formatting
|
|
td.textContent = cell;
|
|
|
|
tr.appendChild(td);
|
|
});
|
|
tableBody.appendChild(tr);
|
|
});
|
|
} else {
|
|
// Handle no data scenarios
|
|
const tr = document.createElement('tr');
|
|
const td = document.createElement('td');
|
|
|
|
// Use custom message if provided, otherwise use default
|
|
if (data.message) {
|
|
td.textContent = data.message;
|
|
} else if (data.error) {
|
|
td.textContent = `Error: ${data.error}`;
|
|
} else {
|
|
td.textContent = 'No data available.';
|
|
}
|
|
|
|
td.colSpan = data.headers ? data.headers.length || 1 : 1;
|
|
td.style.textAlign = 'center';
|
|
td.style.padding = '20px';
|
|
td.style.fontStyle = 'italic';
|
|
td.style.color = '#666';
|
|
tr.appendChild(td);
|
|
tableBody.appendChild(tr);
|
|
}
|
|
}
|
|
|
|
// Function to export table data as CSV
|
|
function exportTableToCSV(filename) {
|
|
let csv = [];
|
|
const rows = reportTable.querySelectorAll('tr');
|
|
|
|
// Loop through each row in the table
|
|
rows.forEach((row) => {
|
|
const cells = row.querySelectorAll('th, td');
|
|
const rowData = Array.from(cells).map((cell) => `"${cell.textContent.trim()}"`);
|
|
csv.push(rowData.join(','));
|
|
});
|
|
|
|
// Create a Blob from the CSV data
|
|
const csvBlob = new Blob([csv.join('\n')], { type: 'text/csv' });
|
|
|
|
// Create a link element to trigger the download
|
|
const downloadLink = document.createElement('a');
|
|
downloadLink.href = URL.createObjectURL(csvBlob);
|
|
downloadLink.download = filename;
|
|
|
|
// Append the link to the document, trigger the download, and remove the link
|
|
document.body.appendChild(downloadLink);
|
|
downloadLink.click();
|
|
document.body.removeChild(downloadLink);
|
|
}
|
|
|
|
// Handle report button clicks
|
|
reportButtons.forEach((button) => {
|
|
button.addEventListener('click', () => {
|
|
// Skip buttons that have their own handlers
|
|
if (button.id === 'select-day-report' || button.id === 'date-range-report' || button.id === 'select-day-defects-report') {
|
|
return;
|
|
}
|
|
|
|
const reportNumber = button.dataset.report;
|
|
const reportLabel = button.textContent.trim();
|
|
|
|
// Check if reportNumber exists
|
|
if (!reportNumber) {
|
|
console.warn('Report button clicked but no data-report attribute found:', button);
|
|
return;
|
|
}
|
|
|
|
// Update the title dynamically
|
|
reportTitle.textContent = `Data for "${reportLabel}"`;
|
|
|
|
// Fetch data for the selected report
|
|
fetch(`/get_report_data?report=${reportNumber}`)
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then((data) => {
|
|
console.log("Fetched data:", data); // Debugging
|
|
|
|
// Update title with additional info
|
|
if (data.message) {
|
|
reportTitle.textContent = data.message;
|
|
} else if (data.rows && data.rows.length > 0) {
|
|
reportTitle.textContent = `${reportLabel} (${data.rows.length} records)`;
|
|
} else {
|
|
reportTitle.textContent = `${reportLabel} - No data found`;
|
|
}
|
|
|
|
populateTable(data);
|
|
})
|
|
.catch((error) => {
|
|
console.error('Error fetching report data:', error);
|
|
reportTitle.textContent = 'Error loading data.';
|
|
});
|
|
});
|
|
});
|
|
|
|
// Bind the export functionality to the CSV button
|
|
exportCsvButton.addEventListener('click', () => {
|
|
const rows = reportTable.querySelectorAll('tr');
|
|
if (rows.length === 0) {
|
|
alert('No data available to export.');
|
|
return;
|
|
}
|
|
|
|
const reportTitleText = reportTitle.textContent.trim();
|
|
const filename = `${reportTitleText.replace(/\s+/g, '_')}.csv`; // Generate a filename based on the report title
|
|
exportTableToCSV(filename);
|
|
});
|
|
|
|
// Test Database Button
|
|
const testDatabaseBtn = document.getElementById('test-database');
|
|
if (testDatabaseBtn) {
|
|
testDatabaseBtn.addEventListener('click', () => {
|
|
console.log('Testing database connection...');
|
|
reportTitle.textContent = 'Testing Database Connection...';
|
|
|
|
fetch('/test_database')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
console.log('Database test results:', data);
|
|
|
|
if (data.success) {
|
|
reportTitle.textContent = `Database Test Results - ${data.total_records} records found`;
|
|
|
|
// Create a detailed results table
|
|
const thead = reportTable.querySelector('thead tr');
|
|
const tbody = reportTable.querySelector('tbody');
|
|
|
|
// Clear existing content
|
|
thead.innerHTML = '';
|
|
tbody.innerHTML = '';
|
|
|
|
// Add headers
|
|
const headers = ['Test Item', 'Result', 'Details'];
|
|
headers.forEach(header => {
|
|
const th = document.createElement('th');
|
|
th.textContent = header;
|
|
thead.appendChild(th);
|
|
});
|
|
|
|
// Add test results
|
|
const results = [
|
|
['Database Connection', data.database_connection, 'Connection successful'],
|
|
['Table Exists', data.table_exists ? 'YES' : 'NO', 'scan1_orders table check'],
|
|
['Total Records', data.total_records, 'Number of rows in table'],
|
|
['Table Structure', `${data.table_structure.length} columns`, data.table_structure.map(col => `${col.field} (${col.type})`).join(', ')],
|
|
['Available Dates', data.available_dates.length, data.available_dates.join(', ') || 'No dates found'],
|
|
['Sample Data', data.sample_data.length > 0 ? 'Available' : 'Empty', `${data.sample_data.length} sample rows`]
|
|
];
|
|
|
|
results.forEach(result => {
|
|
const row = document.createElement('tr');
|
|
result.forEach(cell => {
|
|
const td = document.createElement('td');
|
|
td.textContent = cell;
|
|
row.appendChild(td);
|
|
});
|
|
tbody.appendChild(row);
|
|
});
|
|
|
|
// Show alert with summary
|
|
alert(`Database Test Complete!\n\nConnection: ${data.database_connection}\nTable exists: ${data.table_exists}\nTotal records: ${data.total_records}\nMessage: ${data.message}`);
|
|
|
|
} else {
|
|
reportTitle.textContent = 'Database Test Failed';
|
|
alert(`Database test failed: ${data.message}`);
|
|
|
|
// Show error in table
|
|
const thead = reportTable.querySelector('thead tr');
|
|
const tbody = reportTable.querySelector('tbody');
|
|
thead.innerHTML = '<th>Error</th>';
|
|
tbody.innerHTML = `<tr><td>${data.message}</td></tr>`;
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Database test error:', error);
|
|
reportTitle.textContent = 'Database Test Error';
|
|
alert(`Error testing database: ${error.message}`);
|
|
});
|
|
});
|
|
}
|
|
|
|
// Placeholder for PDF export functionality
|
|
exportPdfButton.addEventListener('click', () => {
|
|
alert('Exporting current report as PDF...');
|
|
// Add logic to export the current report as PDF
|
|
});
|
|
|
|
});
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const templateList = document.getElementById('template-list');
|
|
const createTemplateBtn = document.getElementById('create-template-btn');
|
|
|
|
// Example: Handle the "Create New Template" button click
|
|
createTemplateBtn.addEventListener('click', () => {
|
|
window.location.href = '/create_template';
|
|
});
|
|
|
|
// Example: Handle the "Edit" and "Delete" buttons
|
|
templateList.addEventListener('click', (event) => {
|
|
if (event.target.classList.contains('edit-btn')) {
|
|
const templateId = event.target.closest('li').dataset.id;
|
|
window.location.href = `/edit_template/${templateId}`;
|
|
} else if (event.target.classList.contains('delete-btn')) {
|
|
const templateId = event.target.closest('li').dataset.id;
|
|
if (confirm('Are you sure you want to delete this template?')) {
|
|
fetch(`/delete_template/${templateId}`, { method: 'POST' })
|
|
.then(response => response.text())
|
|
.then(data => {
|
|
alert(data);
|
|
// Optionally, remove the template from the list
|
|
event.target.closest('li').remove();
|
|
});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const setDimensionsBtn = document.getElementById('set-dimensions-btn');
|
|
const labelPreview = document.getElementById('label-preview');
|
|
|
|
// Handle setting label dimensions
|
|
setDimensionsBtn.addEventListener('click', () => {
|
|
const widthInput = document.getElementById('label-width').value;
|
|
const heightInput = document.getElementById('label-height').value;
|
|
|
|
if (!widthInput || !heightInput) {
|
|
alert('Please enter valid dimensions for width and height.');
|
|
return;
|
|
}
|
|
|
|
// Convert mm to pixels (1 mm = 3.779528 pixels)
|
|
const widthPixels = parseFloat(widthInput) * 3.779528;
|
|
const heightPixels = parseFloat(heightInput) * 3.779528;
|
|
|
|
// Set the size of the label container
|
|
labelPreview.style.width = `${widthPixels}px`;
|
|
labelPreview.style.height = `${heightPixels}px`;
|
|
|
|
alert(`Label dimensions set to ${widthPixels.toFixed(2)}px x ${heightPixels.toFixed(2)}px.`);
|
|
});
|
|
});
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const labelPreview = document.getElementById('label-preview');
|
|
const addFieldButtons = document.querySelectorAll('.add-field-btn');
|
|
|
|
// Add fields dynamically
|
|
addFieldButtons.forEach(button => {
|
|
button.addEventListener('click', () => {
|
|
const fieldType = button.getAttribute('data-type');
|
|
addFieldToPreview(fieldType);
|
|
});
|
|
});
|
|
|
|
// Function to add a field to the preview
|
|
function addFieldToPreview(type) {
|
|
const field = document.createElement('div');
|
|
field.classList.add('draggable-field');
|
|
field.setAttribute('draggable', 'true');
|
|
field.style.position = 'absolute';
|
|
field.style.top = '10px';
|
|
field.style.left = '10px';
|
|
|
|
switch (type) {
|
|
case 'text-label':
|
|
field.textContent = 'Text Label';
|
|
field.style.fontSize = '14px';
|
|
break;
|
|
case 'text-input':
|
|
field.innerHTML = '<input type="text" placeholder="Input Field" style="width: 100px;">';
|
|
break;
|
|
case 'barcode':
|
|
field.textContent = 'Barcode Box';
|
|
field.style.border = '1px dashed #000';
|
|
field.style.width = '100px';
|
|
field.style.height = '50px';
|
|
break;
|
|
case 'qrcode':
|
|
field.textContent = 'QR Code Box';
|
|
field.style.border = '1px dashed #000';
|
|
field.style.width = '50px';
|
|
field.style.height = '50px';
|
|
break;
|
|
}
|
|
|
|
labelPreview.appendChild(field);
|
|
|
|
// Make the field draggable
|
|
makeFieldDraggable(field);
|
|
}
|
|
|
|
// Function to make a field draggable
|
|
function makeFieldDraggable(field) {
|
|
field.addEventListener('dragstart', (e) => {
|
|
e.dataTransfer.setData('text/plain', null);
|
|
field.classList.add('dragging');
|
|
});
|
|
|
|
field.addEventListener('dragend', () => {
|
|
field.classList.remove('dragging');
|
|
});
|
|
|
|
labelPreview.addEventListener('dragover', (e) => {
|
|
e.preventDefault();
|
|
const draggingField = document.querySelector('.dragging');
|
|
const rect = labelPreview.getBoundingClientRect();
|
|
draggingField.style.left = `${e.clientX - rect.left}px`;
|
|
draggingField.style.top = `${e.clientY - rect.top}px`;
|
|
});
|
|
}
|
|
|
|
// Calendar functionality for date selection
|
|
const selectDayReportBtn = document.getElementById('select-day-report');
|
|
const calendarModal = document.getElementById('calendar-modal');
|
|
const closeModal = document.querySelector('.close-modal');
|
|
const cancelDate = document.getElementById('cancel-date');
|
|
const confirmDate = document.getElementById('confirm-date');
|
|
const calendarDays = document.getElementById('calendar-days');
|
|
const calendarMonthYear = document.getElementById('calendar-month-year');
|
|
const prevMonth = document.getElementById('prev-month');
|
|
const nextMonth = document.getElementById('next-month');
|
|
|
|
let currentDate = new Date();
|
|
let selectedDate = null;
|
|
|
|
// Show calendar modal
|
|
if (selectDayReportBtn) {
|
|
selectDayReportBtn.addEventListener('click', () => {
|
|
calendarModal.style.display = 'block';
|
|
generateCalendar(currentDate);
|
|
});
|
|
}
|
|
|
|
// Show calendar modal for quality defects report
|
|
const selectDayDefectsReportBtn = document.getElementById('select-day-defects-report');
|
|
if (selectDayDefectsReportBtn) {
|
|
selectDayDefectsReportBtn.addEventListener('click', () => {
|
|
console.log('DEBUG: Select Day Quality Defects Report button clicked!');
|
|
calendarModal.style.display = 'block';
|
|
generateCalendar(currentDate);
|
|
|
|
// Mark this as a defects report by setting a flag
|
|
calendarModal.setAttribute('data-report-type', 'defects');
|
|
});
|
|
}
|
|
|
|
// Close modal events
|
|
if (closeModal) {
|
|
closeModal.addEventListener('click', closeCalendarModal);
|
|
}
|
|
if (cancelDate) {
|
|
cancelDate.addEventListener('click', closeCalendarModal);
|
|
}
|
|
|
|
// Click outside modal to close
|
|
window.addEventListener('click', (e) => {
|
|
if (e.target === calendarModal) {
|
|
closeCalendarModal();
|
|
}
|
|
});
|
|
|
|
// Navigation buttons
|
|
if (prevMonth) {
|
|
prevMonth.addEventListener('click', () => {
|
|
currentDate.setMonth(currentDate.getMonth() - 1);
|
|
generateCalendar(currentDate);
|
|
});
|
|
}
|
|
|
|
if (nextMonth) {
|
|
nextMonth.addEventListener('click', () => {
|
|
currentDate.setMonth(currentDate.getMonth() + 1);
|
|
generateCalendar(currentDate);
|
|
});
|
|
}
|
|
|
|
// Confirm date selection
|
|
if (confirmDate) {
|
|
confirmDate.addEventListener('click', () => {
|
|
console.log('DEBUG: Calendar Generate Report button clicked!');
|
|
if (selectedDate) {
|
|
// Format date as YYYY-MM-DD (timezone-safe)
|
|
const year = selectedDate.getFullYear();
|
|
const month = String(selectedDate.getMonth() + 1).padStart(2, '0');
|
|
const day = String(selectedDate.getDate()).padStart(2, '0');
|
|
const formattedDate = `${year}-${month}-${day}`;
|
|
console.log(`DEBUG: Selected date object:`, selectedDate);
|
|
console.log(`DEBUG: Selected date formatted as: ${formattedDate}`);
|
|
|
|
// Check if this is a defects report or regular report
|
|
const reportType = calendarModal.getAttribute('data-report-type');
|
|
console.log(`DEBUG: Report type: ${reportType}`);
|
|
|
|
closeCalendarModal();
|
|
|
|
// Fetch appropriate report data for the selected date
|
|
if (reportType === 'defects') {
|
|
console.log('DEBUG: About to call fetchCustomDefectsReport');
|
|
fetchCustomDefectsReport(formattedDate);
|
|
} else {
|
|
console.log('DEBUG: About to call fetchCustomDateReport');
|
|
fetchCustomDateReport(formattedDate);
|
|
}
|
|
} else {
|
|
console.log('DEBUG: No date selected when Generate Report clicked');
|
|
}
|
|
});
|
|
}
|
|
|
|
function closeCalendarModal() {
|
|
calendarModal.style.display = 'none';
|
|
selectedDate = null;
|
|
confirmDate.disabled = true;
|
|
|
|
// Clear report type
|
|
calendarModal.removeAttribute('data-report-type');
|
|
|
|
// Remove selected class from all days
|
|
const selectedDays = document.querySelectorAll('.calendar-day.selected');
|
|
selectedDays.forEach(day => day.classList.remove('selected'));
|
|
}
|
|
|
|
function generateCalendar(date) {
|
|
const year = date.getFullYear();
|
|
const month = date.getMonth();
|
|
|
|
// Update header
|
|
const monthNames = ['January', 'February', 'March', 'April', 'May', 'June',
|
|
'July', 'August', 'September', 'October', 'November', 'December'];
|
|
calendarMonthYear.textContent = `${monthNames[month]} ${year}`;
|
|
|
|
// Clear previous days
|
|
calendarDays.innerHTML = '';
|
|
|
|
// Get first day of month and number of days
|
|
const firstDay = new Date(year, month, 1).getDay();
|
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
const today = new Date();
|
|
|
|
// Add empty cells for days before month starts
|
|
for (let i = 0; i < firstDay; i++) {
|
|
const emptyDay = document.createElement('div');
|
|
emptyDay.classList.add('calendar-day', 'other-month');
|
|
calendarDays.appendChild(emptyDay);
|
|
}
|
|
|
|
// Add days of the month
|
|
for (let day = 1; day <= daysInMonth; day++) {
|
|
const dayElement = document.createElement('div');
|
|
dayElement.classList.add('calendar-day');
|
|
dayElement.textContent = day;
|
|
|
|
const dayDate = new Date(year, month, day);
|
|
|
|
// Highlight today
|
|
if (dayDate.toDateString() === today.toDateString()) {
|
|
dayElement.classList.add('today');
|
|
}
|
|
|
|
// Add click event
|
|
dayElement.addEventListener('click', () => {
|
|
// Remove previous selection
|
|
const previousSelected = document.querySelector('.calendar-day.selected');
|
|
if (previousSelected) {
|
|
previousSelected.classList.remove('selected');
|
|
}
|
|
|
|
// Select this day
|
|
dayElement.classList.add('selected');
|
|
selectedDate = new Date(year, month, day);
|
|
confirmDate.disabled = false;
|
|
});
|
|
|
|
calendarDays.appendChild(dayElement);
|
|
}
|
|
}
|
|
|
|
function fetchCustomDateReport(dateString) {
|
|
console.log(`DEBUG: fetchCustomDateReport called with date: ${dateString}`);
|
|
|
|
// Get elements directly to avoid scope issues
|
|
const reportTitleElement = document.getElementById('report-title');
|
|
const reportTableElement = document.getElementById('report-table');
|
|
|
|
console.log(`DEBUG: reportTitle element:`, reportTitleElement);
|
|
console.log(`DEBUG: reportTable element:`, reportTableElement);
|
|
|
|
if (!reportTitleElement) {
|
|
console.error('ERROR: report-title element not found!');
|
|
return;
|
|
}
|
|
|
|
reportTitleElement.textContent = `Loading report for ${dateString}...`;
|
|
|
|
// Local function to populate table to avoid scope issues
|
|
function localPopulateTable(data) {
|
|
const tableHead = reportTableElement.querySelector('thead tr');
|
|
const tableBody = reportTableElement.querySelector('tbody');
|
|
|
|
// Clear existing table content
|
|
tableHead.innerHTML = '';
|
|
tableBody.innerHTML = '';
|
|
|
|
if (data.headers && data.rows && data.rows.length > 0) {
|
|
// Populate table headers
|
|
data.headers.forEach((header) => {
|
|
const th = document.createElement('th');
|
|
th.textContent = header;
|
|
tableHead.appendChild(th);
|
|
});
|
|
|
|
// Populate table rows
|
|
data.rows.forEach((row) => {
|
|
const tr = document.createElement('tr');
|
|
row.forEach((cell, index) => {
|
|
const td = document.createElement('td');
|
|
// Format dates properly
|
|
if (data.headers[index].toLowerCase() === 'date' && cell) {
|
|
td.textContent = cell; // Use as-is since backend already formats it
|
|
} else {
|
|
td.textContent = cell;
|
|
}
|
|
tr.appendChild(td);
|
|
});
|
|
tableBody.appendChild(tr);
|
|
});
|
|
} else {
|
|
// Handle no data scenarios
|
|
const tr = document.createElement('tr');
|
|
const td = document.createElement('td');
|
|
td.colSpan = 10; // Span all columns
|
|
td.textContent = 'No data available.';
|
|
td.style.textAlign = 'center';
|
|
tr.appendChild(td);
|
|
tableBody.appendChild(tr);
|
|
}
|
|
}
|
|
|
|
const url = `/generate_report?report=6&date=${dateString}`;
|
|
console.log(`DEBUG: Making request to URL: ${url}`);
|
|
|
|
fetch(url)
|
|
.then(response => {
|
|
console.log(`DEBUG: Response status: ${response.status}`);
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
console.log('DEBUG: Response data:', data);
|
|
if (data.error) {
|
|
reportTitleElement.textContent = `Error: ${data.error}`;
|
|
localPopulateTable({ headers: [], rows: [] });
|
|
} else if (data.message) {
|
|
reportTitleElement.textContent = data.message;
|
|
localPopulateTable({ headers: [], rows: [] });
|
|
} else if (data.rows && data.rows.length === 0) {
|
|
reportTitleElement.textContent = `No data found for ${dateString}`;
|
|
localPopulateTable(data);
|
|
} else {
|
|
reportTitleElement.textContent = `Daily Report for ${dateString} (${data.rows ? data.rows.length : 0} records)`;
|
|
localPopulateTable(data);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching custom date report:', error);
|
|
reportTitleElement.textContent = 'Error loading report';
|
|
localPopulateTable({ headers: [], rows: [] });
|
|
});
|
|
}
|
|
|
|
// Function to fetch quality defects report for specific date
|
|
function fetchCustomDefectsReport(dateString) {
|
|
console.log(`DEBUG: fetchCustomDefectsReport called with date: ${dateString}`);
|
|
|
|
// Get elements directly to avoid scope issues
|
|
const reportTitleElement = document.getElementById('report-title');
|
|
const reportTableElement = document.getElementById('report-table');
|
|
|
|
console.log(`DEBUG: reportTitle element:`, reportTitleElement);
|
|
console.log(`DEBUG: reportTable element:`, reportTableElement);
|
|
|
|
if (!reportTitleElement) {
|
|
console.error('ERROR: report-title element not found!');
|
|
return;
|
|
}
|
|
|
|
reportTitleElement.textContent = `Loading quality defects report for ${dateString}...`;
|
|
|
|
// Local function to populate table to avoid scope issues
|
|
function localPopulateTable(data) {
|
|
const tableHead = reportTableElement.querySelector('thead tr');
|
|
const tableBody = reportTableElement.querySelector('tbody');
|
|
|
|
// Clear existing table content
|
|
tableHead.innerHTML = '';
|
|
tableBody.innerHTML = '';
|
|
|
|
if (data.headers && data.rows && data.rows.length > 0) {
|
|
// Populate table headers
|
|
data.headers.forEach((header) => {
|
|
const th = document.createElement('th');
|
|
th.textContent = header;
|
|
tableHead.appendChild(th);
|
|
});
|
|
|
|
// Populate table rows
|
|
data.rows.forEach((row) => {
|
|
const tr = document.createElement('tr');
|
|
row.forEach((cell, index) => {
|
|
const td = document.createElement('td');
|
|
// Highlight quality code column for defects
|
|
if (data.headers[index] === 'Quality Code' && cell != '0') {
|
|
td.style.backgroundColor = '#ffebee'; // Light red background
|
|
td.style.fontWeight = 'bold';
|
|
}
|
|
td.textContent = cell;
|
|
tr.appendChild(td);
|
|
});
|
|
tableBody.appendChild(tr);
|
|
});
|
|
} else {
|
|
// Handle no data scenarios
|
|
const tr = document.createElement('tr');
|
|
const td = document.createElement('td');
|
|
td.colSpan = 10; // Span all columns
|
|
td.textContent = 'No quality defects found for this date.';
|
|
td.style.textAlign = 'center';
|
|
tr.appendChild(td);
|
|
tableBody.appendChild(tr);
|
|
}
|
|
}
|
|
|
|
const url = `/generate_report?report=8&date=${dateString}`;
|
|
console.log(`DEBUG: Making request to URL: ${url}`);
|
|
|
|
fetch(url)
|
|
.then(response => {
|
|
console.log(`DEBUG: Response status: ${response.status}`);
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
console.log('DEBUG: Quality defects response data:', data);
|
|
|
|
if (data.error) {
|
|
reportTitleElement.textContent = `Error: ${data.error}`;
|
|
localPopulateTable({ headers: [], rows: [] });
|
|
} else if (data.message) {
|
|
reportTitleElement.textContent = data.message;
|
|
localPopulateTable({ headers: [], rows: [] });
|
|
} else if (data.rows && data.rows.length === 0) {
|
|
reportTitleElement.textContent = `No quality defects found for ${dateString}`;
|
|
localPopulateTable(data);
|
|
} else {
|
|
let titleText = `Quality Defects Report for ${dateString} (${data.rows ? data.rows.length : 0} defective items)`;
|
|
|
|
// Add defects summary info if available
|
|
if (data.defects_summary) {
|
|
const summary = data.defects_summary;
|
|
titleText += ` | ${summary.unique_defect_types} defect types, ${summary.total_rejected_quantity} rejected items`;
|
|
}
|
|
|
|
reportTitleElement.textContent = titleText;
|
|
localPopulateTable(data);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching quality defects report:', error);
|
|
reportTitleElement.textContent = 'Error loading quality defects report';
|
|
localPopulateTable({ headers: [], rows: [] });
|
|
});
|
|
}
|
|
|
|
// ===== DATE RANGE MODAL FUNCTIONALITY =====
|
|
|
|
const dateRangeReportBtn = document.getElementById('date-range-report');
|
|
const dateRangeModal = document.getElementById('date-range-modal');
|
|
const closeDateRange = document.getElementById('close-date-range');
|
|
const cancelDateRange = document.getElementById('cancel-date-range');
|
|
const confirmDateRange = document.getElementById('confirm-date-range');
|
|
const startDateInput = document.getElementById('start-date');
|
|
const endDateInput = document.getElementById('end-date');
|
|
|
|
if (dateRangeReportBtn && dateRangeModal) {
|
|
// Open date range modal
|
|
dateRangeReportBtn.addEventListener('click', () => {
|
|
console.log('DEBUG: Date Range Report button clicked!');
|
|
|
|
// Set default dates (last 7 days to today)
|
|
const today = new Date();
|
|
const weekAgo = new Date();
|
|
weekAgo.setDate(today.getDate() - 6); // Last 7 days including today
|
|
|
|
const todayStr = formatDateForInput(today);
|
|
const weekAgoStr = formatDateForInput(weekAgo);
|
|
|
|
startDateInput.value = weekAgoStr;
|
|
endDateInput.value = todayStr;
|
|
|
|
console.log(`DEBUG: Default date range set to ${weekAgoStr} - ${todayStr}`);
|
|
|
|
dateRangeModal.style.display = 'block';
|
|
validateDateRange(); // Enable/disable confirm button based on inputs
|
|
});
|
|
|
|
// Close modal functions
|
|
function closeDateRangeModal() {
|
|
dateRangeModal.style.display = 'none';
|
|
startDateInput.value = '';
|
|
endDateInput.value = '';
|
|
confirmDateRange.disabled = true;
|
|
}
|
|
|
|
closeDateRange.addEventListener('click', closeDateRangeModal);
|
|
cancelDateRange.addEventListener('click', closeDateRangeModal);
|
|
|
|
// Close modal when clicking outside
|
|
window.addEventListener('click', (e) => {
|
|
if (e.target === dateRangeModal) {
|
|
closeDateRangeModal();
|
|
}
|
|
});
|
|
|
|
// Validate date range and enable/disable confirm button
|
|
function validateDateRange() {
|
|
const startDate = startDateInput.value;
|
|
const endDate = endDateInput.value;
|
|
|
|
if (startDate && endDate) {
|
|
const start = new Date(startDate);
|
|
const end = new Date(endDate);
|
|
|
|
if (start <= end) {
|
|
confirmDateRange.disabled = false;
|
|
console.log(`DEBUG: Valid date range: ${startDate} to ${endDate}`);
|
|
} else {
|
|
confirmDateRange.disabled = true;
|
|
console.log('DEBUG: Invalid date range: start date is after end date');
|
|
}
|
|
} else {
|
|
confirmDateRange.disabled = true;
|
|
console.log('DEBUG: Missing start or end date');
|
|
}
|
|
}
|
|
|
|
// Validate when dates change
|
|
startDateInput.addEventListener('change', validateDateRange);
|
|
endDateInput.addEventListener('change', validateDateRange);
|
|
|
|
// Confirm date range selection
|
|
confirmDateRange.addEventListener('click', () => {
|
|
const startDate = startDateInput.value;
|
|
const endDate = endDateInput.value;
|
|
|
|
console.log(`DEBUG: Generating date range report from ${startDate} to ${endDate}`);
|
|
closeDateRangeModal();
|
|
|
|
// Fetch report data for the selected date range
|
|
fetchDateRangeReport(startDate, endDate);
|
|
});
|
|
}
|
|
|
|
// Helper function to format date for input field
|
|
function formatDateForInput(date) {
|
|
const year = date.getFullYear();
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
return `${year}-${month}-${day}`;
|
|
}
|
|
|
|
// Function to fetch date range report
|
|
function fetchDateRangeReport(startDate, endDate) {
|
|
console.log(`DEBUG: Fetching date range report from ${startDate} to ${endDate}`);
|
|
|
|
// Get elements directly to avoid scope issues
|
|
const reportTitleElement = document.getElementById('report-title');
|
|
const reportTableElement = document.getElementById('report-table');
|
|
|
|
if (!reportTitleElement) {
|
|
console.error('ERROR: report-title element not found!');
|
|
return;
|
|
}
|
|
|
|
reportTitleElement.textContent = `Loading report for ${startDate} to ${endDate}...`;
|
|
|
|
// Local function to populate table to avoid scope issues
|
|
function localPopulateTable(data) {
|
|
const tableHead = reportTableElement.querySelector('thead tr');
|
|
const tableBody = reportTableElement.querySelector('tbody');
|
|
|
|
// Clear existing table content
|
|
tableHead.innerHTML = '';
|
|
tableBody.innerHTML = '';
|
|
|
|
if (data.headers && data.rows && data.rows.length > 0) {
|
|
// Populate table headers
|
|
data.headers.forEach((header) => {
|
|
const th = document.createElement('th');
|
|
th.textContent = header;
|
|
tableHead.appendChild(th);
|
|
});
|
|
|
|
// Populate table rows
|
|
data.rows.forEach((row) => {
|
|
const tr = document.createElement('tr');
|
|
row.forEach((cell, index) => {
|
|
const td = document.createElement('td');
|
|
td.textContent = cell;
|
|
tr.appendChild(td);
|
|
});
|
|
tableBody.appendChild(tr);
|
|
});
|
|
} else {
|
|
// Handle no data scenarios
|
|
const tr = document.createElement('tr');
|
|
const td = document.createElement('td');
|
|
td.colSpan = 10; // Span all columns
|
|
td.textContent = 'No data available for the selected date range.';
|
|
td.style.textAlign = 'center';
|
|
tr.appendChild(td);
|
|
tableBody.appendChild(tr);
|
|
}
|
|
}
|
|
|
|
const url = `/generate_report?report=7&start_date=${startDate}&end_date=${endDate}`;
|
|
console.log(`DEBUG: Making date range request to URL: ${url}`);
|
|
|
|
fetch(url)
|
|
.then(response => {
|
|
console.log(`DEBUG: Response status: ${response.status}`);
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
console.log('DEBUG: Date range response data:', data);
|
|
|
|
if (data.error) {
|
|
reportTitleElement.textContent = `Error: ${data.error}`;
|
|
localPopulateTable({ headers: [], rows: [] });
|
|
} else if (data.message) {
|
|
reportTitleElement.textContent = data.message;
|
|
localPopulateTable({ headers: [], rows: [] });
|
|
} else if (data.rows && data.rows.length === 0) {
|
|
reportTitleElement.textContent = `No data found for ${startDate} to ${endDate}`;
|
|
localPopulateTable(data);
|
|
} else {
|
|
const recordCount = data.rows ? data.rows.length : 0;
|
|
let titleText = `Date Range Report: ${startDate} to ${endDate} (${recordCount} records)`;
|
|
|
|
// Add summary info if available
|
|
if (data.summary) {
|
|
titleText += ` | Approved: ${data.summary.total_approved}, Rejected: ${data.summary.total_rejected}`;
|
|
}
|
|
|
|
reportTitleElement.textContent = titleText;
|
|
localPopulateTable(data);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching date range report:', error);
|
|
reportTitleElement.textContent = 'Error loading date range report';
|
|
localPopulateTable({ headers: [], rows: [] });
|
|
});
|
|
}
|
|
}); |