Skip to main content

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.
rows
Array<Sale>
required
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:
  1. Reads date range from input fields (with fallback defaults)
  2. Adjusts end date to include full day (23:59:59.999)
  3. Fetches sales within range from database
  4. Calculates grand total
  5. Updates summary text
  6. Renders table with sales data
  7. 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:
  1. Loads report data
  2. Shows hidden print area
  3. Injects report HTML with header and table
  4. Triggers browser print dialog
  5. 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

db.js
module
Database module providing getSalesInRange(from, to) function
shared.js
module
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

  1. Component loads with today’s date pre-filled
  2. Report automatically displays today’s transactions
  3. Summary shows transaction count and total revenue

View Custom Date Range

  1. User selects start date in “From” field
  2. User selects end date in “To” field
  3. Report automatically updates on each change
  4. Table shows all sales within the range
  5. Grand total row sums all visible transactions

Export to CSV

  1. User sets desired date range
  2. User clicks “Export CSV” button
  3. If sales exist, CSV file downloads automatically
  4. Filename includes date range
  5. CSV can be opened in Excel or Google Sheets
  1. User sets desired date range
  2. User clicks “Print PDF” button
  3. If sales exist, print dialog opens
  4. User can save as PDF or print to printer
  5. 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.

Build docs developers (and LLMs) love