Overview
The Reports component (reports.js) provides sales analytics and reporting functionality. It allows users to view sales data within date ranges, export reports as CSV files, and print reports as PDF documents.
Responsibilities
- Filter sales by date range
- Display sales summary (count and total)
- Render sales data in tabular format
- Export sales data as CSV
- Print sales reports as PDF
- Calculate grand totals
DOM Elements
#fromDate - Date input for start date
#toDate - Date input for end date
#exportCsv - Button to export CSV
#printPdf - Button to print PDF
#reportSummary - Summary text showing count and total
#reportTable - Container for sales table
#print-area - Hidden print area for PDF generation
Functions
setDefaultDates()
Sets both date inputs to today’s date as the default filter.
function setDefaultDates() {
const today = new Date().toISOString().slice(0, 10);
fromDate.value = today;
toDate.value = today;
}
tableHTML(rows)
Generates HTML table markup for sales data with grand total row.
Array of sale objects to display
Returns: string - HTML table markup or empty state message
Empty State:
if (rows.length === 0) {
return '<div class="text-center text-gray-500 py-8">No sales in selected range</div>';
}
Table Structure:
return `
<table class="min-w-full border-collapse border border-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="border border-gray-200 px-4 py-2 text-left font-semibold">ID</th>
<th class="border border-gray-200 px-4 py-2 text-left font-semibold">Date</th>
<th class="border border-gray-200 px-4 py-2 text-right font-semibold">Items</th>
<th class="border border-gray-200 px-4 py-2 text-right font-semibold">Total</th>
</tr>
</thead>
<tbody>
${rows.map(r => `
<tr class="hover:bg-gray-50">
<td class="border border-gray-200 px-4 py-2">${r.id}</td>
<td class="border border-gray-200 px-4 py-2">${new Date(r.date).toLocaleString()}</td>
<td class="border border-gray-200 px-4 py-2 text-right">${r.items.reduce((a, b) => a + b.qty, 0)}</td>
<td class="border border-gray-200 px-4 py-2 text-right font-semibold">₹${money(r.total)}</td>
</tr>
`).join('')}
<tr class="bg-gray-50 font-bold">
<td colspan="3" class="border border-gray-200 px-4 py-2 text-right">Grand Total:</td>
<td class="border border-gray-200 px-4 py-2 text-right">₹${money(rows.reduce((a, r) => a + r.total, 0))}</td>
</tr>
</tbody>
</table>
`;
Table Columns:
- ID: Sale transaction ID
- Date: Transaction date and time (localized)
- Items: Total quantity of items in the sale
- Total: Sale total amount in rupees
loadReport()
Fetches and displays sales data for the selected date range.
Returns: Promise<Array<Sale>> - Array of sales in range
async function loadReport() {
const from = new Date(fromDate.value || '1970-01-01');
const to = new Date(toDate.value || '2999-12-31');
to.setHours(23, 59, 59, 999);
const rows = await getSalesInRange(from.toISOString(), to.toISOString());
const total = rows.reduce((a, r) => a + r.total, 0);
reportSummary.textContent = `${rows.length} transactions, total ₹${money(total)}`;
reportTable.innerHTML = tableHTML(rows);
return rows;
}
Behavior:
- Reads date range from input fields (with fallback defaults)
- Adjusts end date to include full day (23:59:59.999)
- Fetches sales within range from database
- Calculates grand total
- Updates summary text
- Renders table with sales data
- Returns sales array for export functions
Export Functions
CSV Export
Generates and downloads a CSV file with sales data.
exportCsvBtn.addEventListener('click', async () => {
const rows = await loadReport();
if (rows.length === 0) return;
const header = ['ID', 'Date', 'Items', 'Total'];
const lines = [header.join(',')];
rows.forEach(r => {
const items = r.items.reduce((a, b) => a + b.qty, 0);
lines.push([r.id, r.date, items, money(r.total)].join(','));
});
const csv = lines.join('\n');
const blob = new Blob([csv], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `sales-report-${fromDate.value}-to-${toDate.value}.csv`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
});
CSV Format:
ID,Date,Items,Total
1,2024-03-15T10:30:00.000Z,5,450.00
2,2024-03-15T14:20:00.000Z,3,280.00
Filename Format: sales-report-YYYY-MM-DD-to-YYYY-MM-DD.csv
PDF Print
Generates a printable report and opens the browser print dialog.
printPdfBtn.addEventListener('click', async () => {
const rows = await loadReport();
if (rows.length === 0) return;
printArea.style.display = 'block';
printArea.innerHTML = `
<div>
<h1 class="text-2xl font-bold mb-2">Sales Report</h1>
<p class="text-sm mb-4">Period: ${fromDate.value} to ${toDate.value}</p>
${tableHTML(rows)}
</div>
`;
window.print();
setTimeout(() => { printArea.style.display = 'none'; }, 100);
});
Behavior:
- Loads report data
- Shows hidden print area
- Injects report HTML with header and table
- Triggers browser print dialog
- Hides print area after 100ms
Print Layout:
- Report title: “Sales Report”
- Date range: “Period: YYYY-MM-DD to YYYY-MM-DD”
- Full sales table with grand total
Event Handlers
Auto-reload on Date Change
Automatically refreshes the report when date inputs change:
fromDate.addEventListener('change', loadReport);
toDate.addEventListener('change', loadReport);
Dependencies
Database module providing getSalesInRange(from, to) function
Shared utilities providing money(n) formatting function
Data Structure
Sale Object:
{
id: number,
date: string, // ISO format timestamp
items: Array<{
id: number,
name: string,
price: number,
qty: number
}>,
subtotal: number,
discount: number,
total: number
}
Auto-Execution
On module load:
setDefaultDates();
loadReport();
User Workflows
View Today’s Sales
- Component loads with today’s date pre-filled
- Report automatically displays today’s transactions
- Summary shows transaction count and total revenue
View Custom Date Range
- User selects start date in “From” field
- User selects end date in “To” field
- Report automatically updates on each change
- Table shows all sales within the range
- Grand total row sums all visible transactions
Export to CSV
- User sets desired date range
- User clicks “Export CSV” button
- If sales exist, CSV file downloads automatically
- Filename includes date range
- CSV can be opened in Excel or Google Sheets
Print to PDF
- User sets desired date range
- User clicks “Print PDF” button
- If sales exist, print dialog opens
- User can save as PDF or print to printer
- Report includes header with date range and full table
Date Range Handling
Default Range:
- Both dates set to today
- Shows only today’s sales
Missing Dates:
- Missing “From” defaults to
1970-01-01
- Missing “To” defaults to
2999-12-31
- Ensures report still runs if dates are cleared
Time Adjustment:
to.setHours(23, 59, 59, 999);
End date is extended to end of day to include all transactions on that date.