Tuesday, September 16, 2025

Code only

Multiple Code Blocks

Here is the code

Click or tap to copy




<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Complete Invoice System</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.23/jspdf.plugin.autotable.min.js"></script>
  <script src="https://unpkg.com/dexie@latest/dist/dexie.min.js"></script>
  <style>
    * { box-sizing: border-box; }
    body { 
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 
      margin: 0; 
      padding: 20px; 
      background: #f5f5f5; 
      touch-action: manipulation; 
    }

    .container { max-width: 1400px; margin: auto; }

    /* Navigation Menu Styles */
    .nav-menu {
      background: linear-gradient(135deg, #007bff, #0056b3);
      padding: 15px 20px;
      margin-bottom: 20px;
      border-radius: 8px;
      box-shadow: 0 4px 6px rgba(0,0,0,0.1);
    }
    .nav-menu h2 {
      color: white;
      margin: 0 0 15px 0;
      text-align: center;
    }
    .nav-buttons {
      display: flex;
      gap: 15px;
      justify-content: center;
      flex-wrap: wrap;
    }
    .nav-btn {
      background: rgba(255,255,255,0.2);
      color: white;
      border: 2px solid rgba(255,255,255,0.3);
      padding: 12px 24px;
      border-radius: 6px;
      cursor: pointer;
      font-weight: bold;
      transition: all 0.3s;
      backdrop-filter: blur(10px);
    }
    .nav-btn:hover {
      background: rgba(255,255,255,0.3);
      transform: translateY(-2px);
    }
    .nav-btn.active {
      background: white;
      color: #007bff;
      border-color: white;
    }

    .section { display: none; }
    .section.active { display: block; }
    .input-section { 
      background: white; 
      padding: 20px; 
      margin-bottom: 20px; 
      border-radius: 8px; 
      box-shadow: 0 2px 5px rgba(0,0,0,0.1);
    }
    .invoice-preview { 
      background: white; 
      padding: 0; 
      border-radius: 8px; 
      box-shadow: 0 2px 5px rgba(0,0,0,0.1); 
    }

    h3 { margin-top: 0; color: #333; border-bottom: 2px solid #007bff; padding-bottom: 10px; }

    .form-row { display: flex; gap: 15px; margin-bottom: 15px; flex-wrap: wrap; }
    .form-group { flex: 1; min-width: 200px; position: relative; }
    .form-group label { display: block; margin-bottom: 5px; font-weight: bold; color: #555; }
    .form-group input, .form-group textarea, .form-group select { 
      width: 100%; 
      padding: 10px; 
      border: 1px solid #ddd; 
      border-radius: 4px; 
      font-size: 14px;
    }
    .form-group textarea { resize: vertical; height: 80px; }

    .auto-populated {
      background-color: #e8f5e8 !important;
      border-color: #28a745 !important;
      transition: background-color 0.5s ease;
    }

    .dropdown {
      position: absolute;
      top: 100%;
      left: 0;
      right: 0;
      background: white;
      border: 1px solid #ddd;
      border-top: none;
      max-height: 200px;
      overflow-y: auto;
      z-index: 1000;
      display: none;
      box-shadow: 0 4px 6px rgba(0,0,0,0.1);
    }
    .dropdown-item {
      padding: 10px;
      cursor: pointer;
      border-bottom: 1px solid #eee;
    }
    .dropdown-item:hover {
      background: #f5f5f5;
    }

    .items-section { margin-top: 20px; }
    .items-table { 
      width: 100%; 
      border-collapse: collapse; 
      background: #f8f9fa; 
      border-radius: 5px; 
      overflow: hidden;
    }
    .items-table th, .items-table td { 
      padding: 10px; 
      border: 1px solid #ddd; 
      text-align: left; 
      font-size: 14px;
    }
    .items-table th { 
      background: #e9ecef; 
      font-weight: bold; 
      color: #333;
    }
    .items-table input, .items-table select { 
      width: 100%; 
      padding: 8px; 
      border: 1px solid #ccc; 
      border-radius: 4px; 
      font-size: 14px;
    }
    .items-table .code-input { min-width: 100px; }
    .items-table .desc-input { min-width: 200px; }
    .items-table .qty-input, .items-table .rate-input, .items-table .sgst-input, .items-table .cgst-input, .items-table .total-input { min-width: 80px; }
    .items-table .disc-type-select { min-width: 60px; }
    .items-table .disc-input { min-width: 80px; }
    .items-table .unit-select { min-width: 80px; }
    .items-table .total-input {
      background: #f0f0f0;
      text-align: right;
      pointer-events: none;
    }
    .items-table .remove-btn { 
      background: #dc3545; 
      color: white; 
      border: none; 
      padding: 8px 12px; 
      border-radius: 4px; 
      cursor: pointer; 
      width: 100%;
    }
    .items-table .remove-btn:hover { background: #c82333; }

    .add-item-btn, .generate-btn, .browse-items-btn, .add-stock-btn, .add-customer-btn, 
    .backup-btn, .restore-btn, .save-btn, .export-csv-btn, .search-customer-btn { 
      background: #28a745; 
      color: white; 
      border: none; 
      padding: 12px 20px; 
      border-radius: 5px; 
      cursor: pointer; 
      margin-right: 10px; 
      margin-top: 10px;
      font-weight: bold;
      transition: all 0.3s;
    }
    .add-item-btn:hover, .add-stock-btn:hover, .add-customer-btn:hover, 
    .backup-btn:hover, .restore-btn:hover, .save-btn:hover, .export-csv-btn:hover, .search-customer-btn:hover { 
      background: #218838; 
      transform: translateY(-2px);
    }
    .browse-items-btn { background: #17a2b8; }
    .browse-items-btn:hover { background: #138496; }
    .generate-btn { background: #007bff; }
    .generate-btn:hover { background: #0056b3; }
    .save-btn { background: #ffc107; color: #333; }
    .save-btn:hover { background: #e0a800; }
    .export-csv-btn { background: #17a2b8; }
    .export-csv-btn:hover { background: #138496; }

    .stock-table, .customer-table, .customer-history-table {
      width: 100%;
      border-collapse: collapse;
      margin-top: 20px;
    }
    .stock-table th, .stock-table td, .customer-table th, .customer-table td, .customer-history-table th, .customer-history-table td {
      border: 1px solid #ddd;
      padding: 12px;
      text-align: left;
    }
    .stock-table th, .customer-table th, .customer-history-table th {
      background: #f8f9fa;
      font-weight: bold;
    }
    .stock-table tr:hover, .customer-table tr:hover, .customer-history-table tr:hover {
      background: #f5f5f5;
    }
    .customer-history-table .items-details {
      display: none;
      background: #f8f9fa;
    }
    .customer-history-table .items-details.active {
      display: table-row;
    }

    .edit-btn, .delete-btn, .toggle-items-btn {
      padding: 6px 12px;
      margin: 2px;
      border: none;
      border-radius: 3px;
      cursor: pointer;
      font-size: 12px;
    }
    .edit-btn { background: #ffc107; color: #333; }
    .edit-btn:hover { background: #e0a800; }
    .delete-btn { background: #dc3545; color: white; }
    .delete-btn:hover { background: #c82333; }
    .toggle-items-btn { background: #17a2b8; color: white; }
    .toggle-items-btn:hover { background: #138496; }

    .low-stock {
      color: #dc3545;
      font-weight: bold;
    }

    .quantity-error, .disc-error {
      border: 2px solid #dc3545 !important;
      background-color: #fff3f3 !important;
    }

    /* Invoice Styles */
    .invoice-box {
      max-width: 700px; 
      margin: auto; 
      padding: 20px;
      border: 1px solid #ddd; 
      border-radius: 8px; 
      background: white;
      position: relative;
    }
    .company-header {
      text-align: center; 
      margin-bottom: 20px;
    }
    .company-header h2 { margin: 0; color: #333; }
    .company-header p { margin: 2px 0; font-size: 13px; color: #666; }
    .header { display: flex; justify-content: space-between; margin-bottom: 20px; }
    .bill-to { font-size: 14px; }
    .invoice-details { text-align: right; font-size: 14px; }
    .invoice-table { 
      width: 100%; 
      border-collapse: collapse; 
      margin-top: 20px; 
    }
    .invoice-table, .invoice-table th, .invoice-table td { border: 1px solid #ccc; }
    .invoice-table th, .invoice-table td { padding: 8px; text-align: left; }
    .invoice-table th { background: #f8f9fa; }
    .total { text-align: right; font-weight: bold; margin-top: 10px; font-size: 16px; }
    .print-btn { 
      margin-top: 20px; 
      padding: 10px 20px; 
      background: #007bff; 
      color: #fff; 
      border: none; 
      cursor: pointer; 
      border-radius: 5px; 
      font-weight: bold;
    }
    .print-btn:hover { background: #0056b3; }

    /* Logo Styles */
    .invoice-logo {
      position: absolute;
      top: 20px;
      left: 20px;
      z-index: 10;
      cursor: move;
      user-select: none;
      -webkit-user-select: none;
      touch-action: none;
    }
    .invoice-logo img {
      width: 100%;
      height: 100%;
      object-fit: contain;
    }
    .invoice-logo.active {
      border: 2px dashed #007bff;
    }
    .resize-handle {
      position: absolute;
      width: 12px;
      height: 12px;
      background: #007bff;
      border-radius: 50%;
      display: none;
    }
    .invoice-logo.active .resize-handle {
      display: block;
    }
    .resize-handle.top-left {
      top: -6px;
      left: -6px;
      cursor: nwse-resize;
    }
    .resize-handle.top-right {
      top: -6px;
      right: -6px;
      cursor: nesw-resize;
    }
    .resize-handle.bottom-left {
      bottom: -6px;
      left: -6px;
      cursor: nesw-resize;
    }
    .resize-handle.bottom-right {
      bottom: -6px;
      right: -6px;
      cursor: nwse-resize;
    }
    .logo-controls {
      margin-top: 20px;
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      align-items: center;
    }
    .logo-controls input[type="number"] {
      width: 80px;
      padding: 6px;
      border: 1px solid #ddd;
      border-radius: 4px;
    }
    .logo-controls button {
      padding: 8px 16px;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      font-size: 14px;
    }
    .reset-logo-btn {
      background: #6c757d;
      color: white;
    }
    .reset-logo-btn:hover {
      background: #5a6268;
    }
    .remove-logo-btn {
      background: #dc3545;
      color: white;
    }
    .remove-logo-btn:hover {
      background: #c82333;
    }

    /* Floating Dialog Styles */
    .dialog-overlay {
      position: fixed; 
      top: 0; 
      left: 0; 
      width: 100%; 
      height: 100%;
      background: rgba(0, 0, 0, 0.5); 
      z-index: 1000; 
      display: none;
      align-items: center;
      justify-content: center;
    }
    .dialog {
      background: white; 
      border-radius: 12px; 
      padding: 0; 
      width: 90%;
      max-width: 600px; 
      min-width: 300px; 
      max-height: 80vh; 
      min-height: 200px;
      overflow: hidden; 
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
      position: relative;
    }
    .dialog-header {
      display: flex; 
      justify-content: space-between; 
      align-items: center;
      padding: 15px 20px 10px 20px; 
      border-bottom: 2px solid #e9ecef;
      background: #f8f9fa; 
      -webkit-user-select: none; 
      user-select: none;
      touch-action: none;
    }
    .dialog-controls { 
      display: flex; 
      align-items: center; 
      gap: 10px; 
      flex-wrap: wrap; 
    }
    .size-inputs { 
      display: flex; 
      gap: 5px; 
      align-items: center; 
      margin-right: 10px; 
    }
    .size-input { 
      width: 60px; 
      padding: 2px 5px; 
      border: 1px solid #ddd; 
      border-radius: 3px; 
      font-size: 0.8rem; 
      text-align: center; 
    }
    .resize-btn, .apply-btn { 
      border: none; 
      padding: 4px 8px; 
      border-radius: 4px; 
      cursor: pointer; 
      font-size: 0.8rem; 
    }
    .resize-btn { 
      background: #6c757d; 
      color: white; 
      font-weight: 600; 
    }
    .resize-btn:hover { background: #5a6268; }
    .apply-btn { background: #007bff; color: white; }
    .apply-btn:hover { background: #0056b3; }
    .dialog-header h3 { color: #495057; margin: 0; border: none; }
    .close-btn {
      background: none; 
      border: none; 
      font-size: 1.5rem; 
      cursor: pointer;
      color: #6c757d; 
      padding: 5px; 
      border-radius: 50%; 
      width: 35px; 
      height: 35px;
      display: flex; 
      align-items: center; 
      justify-content: center;
    }
    .close-btn:hover { background: #f8f9fa; color: #495057; }
    .search-section { margin-bottom: 20px; padding: 0 20px; }
    .search-input {
      width: 100%; 
      padding: 12px; 
      border: 2px solid #dee2e6; 
      border-radius: 8px; 
      font-size: 1rem;
    }
    .search-input:focus { 
      outline: none; 
      border-color: #4facfe; 
      box-shadow: 0 0 0 3px rgba(79, 172, 254, 0.1); 
    }
    .items-container {
      max-height: calc(100% - 150px); 
      overflow-y: auto; 
      border: 1px solid #dee2e6;
      border-radius: 8px; 
      margin: 0 20px 20px 20px;
    }
    .item-table { width: 100%; border-collapse: collapse; }
    .item-table th, .item-table td { 
      padding: 10px; 
      text-align: left; 
      border-bottom: 1px solid #dee2e6; 
    }
    .item-table th { 
      background: #f8f9fa; 
      position: sticky; 
      top: 0; 
      font-weight: 600; 
      color: #495057; 
    }
    .item-table tbody tr { 
      cursor: pointer; 
      transition: background-color 0.2s ease; 
    }
    .item-table tbody tr:hover { background-color: #e3f2fd; }
    .status-message {
      padding: 10px; 
      margin: 10px 20px; 
      border-radius: 6px; 
      font-size: 0.9rem; 
      display: none;
    }
    .status-success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
    .status-error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }

    @media print {
      body { background: white; }
      .input-section, .nav-menu { display: none; }
      .invoice-preview { box-shadow: none; }
      .dialog-overlay { display: none !important; }
      .invoice-logo.active { border: none !important; }
      .resize-handle { display: none !important; }
    }
    @media (max-width: 768px) {
      .form-row { flex-direction: column; }
      .items-section, .stock-table, .customer-table, .customer-history-table { 
        overflow-x: auto; 
        display: block;
      }
      .items-table th, .items-table td { min-width: 60px; }
      .items-table .desc-input { min-width: 120px; }
      .items-table .remove-btn { min-width: 80px; }
      .dialog { width: 90%; min-width: 250px; max-width: 95vw; }
      .dialog-header { padding: 10px 15px; }
      .size-input { width: 50px; font-size: 0.7rem; }
      .resize-btn, .apply-btn { padding: 3px 6px; font-size: 0.7rem; }
      .nav-buttons { flex-direction: column; align-items: center; }
      .nav-btn { width: 200px; }
      .logo-controls input[type="number"] { width: 60px; }
    }
    @media (max-width: 480px) {
      .dialog { min-height: 150px; }
      .items-container { max-height: calc(100% - 120px); }
      .items-table th, .items-table td, .stock-table th, .stock-table td, .customer-table th, .customer-table td, .customer-history-table th, .customer-history-table td { 
        font-size: 12px; 
        padding: 6px; 
      }
      .items-table input, .items-table select { font-size: 12px; padding: 4px; }
      .item-table th, .item-table td { font-size: 12px; padding: 6px; }
      .resize-handle { width: 10px; height: 10px; }
    }
    .hidden { display: none; }
    .whatsapp-section {
      background: #e8f5e8;
      padding: 15px;
      border-radius: 5px;
      margin-top: 20px;
      border-left: 4px solid #25d366;
    }
    .whatsapp-section h3 {
      color: #333;
      border-bottom: 2px solid #25d366;
    }
    .btn-whatsapp {
      background: #25d366;
      color: white;
      padding: 10px 20px;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      font-weight: bold;
      transition: all 0.3s;
    }
    .btn-whatsapp:hover {
      background: #20c360;
      transform: translateY(-2px);
    }
    .whatsapp-preview {
      max-height: 200px;
      overflow-y: auto;
      border: 1px solid #ddd;
      margin-top: 15px;
      padding: 10px;
      background: #f8f9fa;
      border-radius: 4px;
      white-space: pre-wrap;
      font-family: monospace;
      display: none;
    }
    .pdf-btn {
      background: #007bff;
      color: white;
      padding: 10px 20px;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      margin-right: 10px;
      margin-top: 10px;
    }
    .pdf-btn:hover {
      background: #0056b3;
    }
    .pdf-btn.share {
      background: linear-gradient(135deg, #17a2b8, #20c997);
    }
    /* Dashboard Styles */
    .stats-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 20px;
      margin-bottom: 20px;
    }
    .dashboard-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
      gap: 20px;
    }
    .dashboard-card {
      background: white;
      padding: 20px;
      border-radius: 8px;
      box-shadow: 0 2px 5px rgba(0,0,0,0.1);
      transition: transform 0.3s, box-shadow 0.3s;
    }
    .dashboard-card:hover {
      transform: translateY(-5px);
      box-shadow: 0 4px 10px rgba(0,0,0,0.2);
    }
    .dashboard-card h4 {
      margin: 0 0 10px;
      color: #333;
      font-size: 1.1rem;
    }
    .dashboard-card p {
      margin: 0;
      font-size: 1.5rem;
      font-weight: bold;
      color: white;
    }
    .top-products-list, .recent-orders-list {
      max-height: 200px;
      overflow-y: auto;
      margin-top: 10px;
    }
    .top-products-list div, .recent-orders-list div {
      padding: 10px;
      border-bottom: 1px solid #eee;
      display: flex;
      justify-content: space-between;
      align-items: center;
      cursor: pointer;
      transition: background 0.2s;
    }
    .top-products-list div:hover, .recent-orders-list div:hover {
      background: #f5f5f5;
    }
    .refresh-btn {
      background: #007bff;
      color: white;
      border: none;
      padding: 10px 20px;
      border-radius: 5px;
      cursor: pointer;
      margin-top: 10px;
    }
    .refresh-btn:hover {
      background: #0056b3;
    }
    @media (max-width: 768px) {
      .stats-grid, .dashboard-grid {
        grid-template-columns: 1fr;
      }
    }
  </style>
</head>
<body>
<div class="container">
  <!-- Navigation Menu -->
  <div class="nav-menu">
    <h2>🇮🇳 Enhanced Indian Invoice System</h2>
    <div class="nav-buttons">
      <button class="nav-btn active" data-section="invoice">📋 Invoice Generator</button>
      <button class="nav-btn" data-section="dashboard">📊 Sales Dashboard</button>
      <button class="nav-btn" data-section="stock">📦 Stock Management</button>
      <button class="nav-btn" data-section="customers">👥 Customer Database</button>
      <button class="nav-btn" data-section="customer-history">📜 Customer History</button>
      <button class="nav-btn" data-section="backup-restore">💾 Backup & Restore</button>
    </div>
  </div>

  <!-- Sales Dashboard Section -->
  <div class="section" id="dashboard">
    <div class="input-section">
      <h3>📊 Sales Dashboard</h3>
      <div class="form-row">
        <div class="form-group">
          <label>Date Range</label>
          <select id="dateRangeFilter" onchange="toggleCustomDateRange()">
            <option value="7">Last 7 days</option>
            <option value="30">Last 30 days</option>
            <option value="90">Last 90 days</option>
            <option value="365">Last 365 days</option>
            <option value="custom">Custom Range</option>
          </select>
        </div>
        <div class="form-group hidden" id="customDateRange">
          <label>From</label>
          <input type="date" id="fromDate">
          <label>To</label>
          <input type="date" id="toDate">
        </div>
        <div class="form-group">
          <button class="refresh-btn" onclick="updateDashboard()">Refresh</button>
          <button class="refresh-btn" onclick="clearInvoices()">Clear Invoices</button>
        </div>
      </div>
      <div class="stats-grid">
        <div class="dashboard-card" style="background: linear-gradient(135deg, #28a745, #218838);">
          <h4>Total Revenue</h4>
          <p id="totalRevenue">₹0.00</p>
        </div>
        <div class="dashboard-card" style="background: linear-gradient(135deg, #007bff, #0056b3);">
          <h4>Total Orders</h4>
          <p id="totalOrders">0</p>
        </div>
        <div class="dashboard-card" style="background: linear-gradient(135deg, #ff4d4f, #cf1322);">
          <h4>Active Customers</h4>
          <p id="totalCustomers">0</p>
        </div>
        <div class="dashboard-card" style="background: linear-gradient(135deg, #17a2b8, #117a8b);">
          <h4>Products Sold</h4>
          <p id="totalProducts">0</p>
        </div>
        <div class="dashboard-card" style="background: linear-gradient(135deg, #ffc107, #e0a800);">
          <h4>Total Discounts</h4>
          <p id="totalDiscount">₹0.00</p>
        </div>
      </div>
      <div class="dashboard-grid">
        <div class="dashboard-card">
          <h4>Top Selling Products</h4>
          <div class="top-products-list" id="topProductsList"></div>
        </div>
        <div class="dashboard-card">
          <h4>Recent Orders</h4>
          <div class="recent-orders-list" id="recentOrdersList"></div>
        </div>
      </div>
    </div>
  </div>

  <!-- Invoice Generator Section -->
  <div class="section active" id="invoice">
    <div class="input-section">
      <h3>📝 Invoice Generator</h3>
      <!-- Company Info -->
      <div class="form-row">
        <div class="form-group">
          <label>Company Name</label>
          <input type="text" id="companyName" value="Your Company Name">
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label>Company Address</label>
          <textarea id="companyAddress">123 Business Street, City, State - ZIP</textarea>
        </div>
        <div class="form-group">
          <label>Contact Info</label>
          <textarea id="companyContact">Email: info@company.com
Phone: +91 9037393709</textarea>
        </div>
      </div>
      <!-- Logo Upload -->
      <h3>🖼️ Logo</h3>
      <div class="form-row">
        <div class="form-group">
          <label>Upload Logo</label>
          <input type="file" id="logoUpload" accept="image/*">
        </div>
        <div class="form-group logo-controls">
          <label>Width (px)</label>
          <input type="number" id="logoWidth" min="20" max="300" placeholder="Width">
          <label>Height (px)</label>
          <input type="number" id="logoHeight" min="20" max="300" placeholder="Height">
          <label><input type="checkbox" id="lockAspectRatio" checked> Lock Aspect Ratio</label>
          <button class="reset-logo-btn" onclick="resetLogoPosition()">Reset Position</button>
          <button class="remove-logo-btn" onclick="removeLogo()">Remove Logo</button>
        </div>
      </div>
      <p style="font-size: 12px; color: #666;">Tip: Tap logo to show handles, drag to move, or tap handles to resize. Double-tap logo to hide handles.</p>
      <!-- Bill To -->
      <h3>👤 Bill To</h3>
      <div class="form-row">
        <div class="form-group">
          <label>Client Contact Number</label>
          <input type="text" id="clientContact" placeholder="Enter contact number">
          <div class="dropdown" id="contactDropdown"></div>
        </div>
        <div class="form-group">
          <label>Client Name</label>
          <input type="text" id="clientName" placeholder="Name will auto-populate">
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label>Client Email</label>
          <input type="email" id="clientEmail" placeholder="Email will auto-populate">
        </div>
        <div class="form-group">
          <label>Client Address</label>
          <textarea id="clientAddress" placeholder="Address will auto-populate"></textarea>
        </div>
      </div>
      <!-- Invoice Details -->
      <h3>📋 Invoice Details</h3>
      <div class="form-row">
        <div class="form-group">
          <label>Invoice Number</label>
          <input type="text" id="invoiceNumber" value="INV-001">
        </div>
        <div class="form-group">
          <label>Invoice Date</label>
          <input type="date" id="invoiceDate">
        </div>
        <div class="form-group">
          <label>Due Date</label>
          <input type="date" id="dueDate">
        </div>
      </div>
      <!-- Items Section -->
      <h3>📦 Items</h3>
      <div class="items-section">
        <table class="items-table" id="itemsList">
          <thead>
            <tr>
              <th>HSN/SAC Code</th>
              <th>Description</th>
              <th>Unit</th>
              <th>Qty</th>
              <th>Rate (₹)</th>
              <th>Disc Type</th>
              <th>Discount</th>
              <th>SGST %</th>
              <th>CGST %</th>
              <th>Total (₹)</th>
              <th>Action</th>
            </tr>
          </thead>
          <tbody>
            <tr class="item-row">
              <td><input type="text" class="item-code code-input" placeholder="Enter HSN/SAC code..."><div class="dropdown item-dropdown"></div></td>
              <td><input type="text" class="item-desc desc-input" placeholder="Service or product description"></td>
              <td><select class="item-unit unit-select"><option value="PCS">PCS</option><option value="KG">KG</option><option value="LTR">LTR</option><option value="MTR">MTR</option><option value="BOX">BOX</option><option value="SET">SET</option></select></td>
              <td><input type="number" class="item-qty qty-input" value="1" min="1"></td>
              <td><input type="number" class="item-rate rate-input" value="0" step="0.01" min="0"></td>
              <td>
                <select class="disc-type-select">
                  <option value="percent">%</option>
                  <option value="amount">₹</option>
                </select>
              </td>
              <td><input type="number" class="item-disc disc-input" value="0" step="0.01" min="0"></td>
              <td><input type="number" class="item-sgst sgst-input" value="0" step="0.01" min="0"></td>
              <td><input type="number" class="item-cgst cgst-input" value="0" step="0.01" min="0"></td>
              <td><input type="text" class="item-total total-input" value="0.00" readonly></td>
              <td><button class="remove-btn" onclick="removeItem(this)">Remove</button></td>
            </tr>
          </tbody>
        </table>
        <button class="add-item-btn" onclick="addItem()">+ Add Item</button>
        <button class="browse-items-btn" onclick="openItemDialog()">📋 Browse Items</button>
        <button class="generate-btn" onclick="updateItemTotals()">Generate Invoice</button>
        <button class="save-btn" onclick="saveInvoice()">Save Invoice</button>
      </div>
      <!-- WhatsApp Section -->
      <div class="whatsapp-section">
        <h3>Send Invoice via WhatsApp</h3>
        <div class="form-row">
          <div class="form-group">
            <label>WhatsApp Number</label>
            <input type="text" id="whatsappNumber" placeholder="Enter phone number (e.g., +919037393709)">
          </div>
          <div class="form-group">
            <label>Max Description Length</label>
            <input type="number" id="whatsappDescLength" value="20" min="10" max="50">
          </div>
          <div class="form-group">
            <label><input type="checkbox" id="gstEnabled" checked> Include GST in Message</label>
          </div>
        </div>
        <button class="btn-whatsapp" onclick="generateWhatsAppMessage()">Preview WhatsApp Message</button>
        <div class="whatsapp-preview" id="whatsappPreview" style="display: none;"></div>
        <button class="btn-whatsapp" style="margin-top: 10px;" onclick="sendWhatsApp()">Send via WhatsApp</button>
      </div>
      <div class="pdf-buttons">
        <button class="pdf-btn download" onclick="generatePDF()">Download PDF</button>
        <button class="pdf-btn share" onclick="sharePDF()">Share PDF via WhatsApp</button>
        <button class="pdf-btn print" onclick="printInvoice()">Print Invoice</button>
      </div>
    </div>
    <!-- Invoice Preview -->
    <div class="invoice-preview" id="invoicePreview">
      <div class="invoice-box">
        <div class="company-header">
          <h2 id="previewCompanyName">Your Company Name</h2>
          <p id="previewCompanyAddress">123 Business Street, City, State - ZIP</p>
          <p id="previewCompanyContact">Email: info@company.com | Phone: +91 9037393709</p>
        </div>
        <div class="header">
          <div class="bill-to">
            <b>Bill To</b><br>
            <span id="previewClientName">Customer Name</span><br>
            <span id="previewClientAddress">Customer Address</span><br>
            Contact: <span id="previewClientContact">Customer Contact</span><br>
            Email: <span id="previewClientEmail">Customer Email</span>
          </div>
          <div class="invoice-details">
            <b style="color:red;">INVOICE</b><br>
            Invoice #: <span id="previewInvoiceNumber">INV-001</span><br>
            Invoice Date: <span id="previewInvoiceDate">27 August 2025</span><br>
            Due Date: <span id="previewDueDate">26 September 2025</span>
          </div>
        </div>
        <table class="invoice-table">
          <thead>
            <tr>
              <th>Code</th>
              <th>Description</th>
              <th>Unit</th>
              <th>Qty</th>
              <th>Rate</th>
              <th>Discount</th>
              <th>SGST %</th>
              <th>CGST %</th>
              <th>Total</th>
            </tr>
          </thead>
          <tbody id="previewItems">
            <tr>
              <td></td>
              <td>Sample Item</td>
              <td>PCS</td>
              <td>1</td>
              <td>₹0.00</td>
              <td>0%</td>
              <td>0</td>
              <td>0</td>
              <td>₹0.00</td>
            </tr>
          </tbody>
        </table>
        <p class="total">Grand Total: <span id="previewTotal">₹0.00</span></p>
        <button class="print-btn" onclick="window.print()">Print / Save as PDF</button>
      </div>
    </div>
  </div>
  <!-- Stock Management Section -->
  <div class="section" id="stock">
    <div class="input-section">
      <h3>📦 Stock Management</h3>
      <div class="form-row">
        <div class="form-group">
          <label>Item Code</label>
          <input type="text" id="stockCode" placeholder="e.g., ITM001">
        </div>
        <div class="form-group">
          <label>HSN/SAC Code</label>
          <input type="text" id="stockHSN" placeholder="e.g., 8471">
        </div>
        <div class="form-group">
          <label>Description</label>
          <input type="text" id="stockDescription" placeholder="e.g., Ergonomic wireless mouse">
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label>Rate (₹)</label>
          <input type="number" id="stockPrice" placeholder="e.g., 25.99" step="0.01" min="0">
        </div>
        <div class="form-group">
          <label>Unit of Measurement</label>
          <select id="stockUnit">
            <option value="PCS">PCS - Pieces</option>
            <option value="KG">KG - Kilogram</option>
            <option value="LTR">LTR - Liter</option>
            <option value="MTR">MTR - Meter</option>
            <option value="BOX">BOX - Box</option>
            <option value="SET">SET - Set</option>
          </select>
        </div>
        <div class="form-group">
          <label>Quantity</label>
          <input type="number" id="stockQuantity" min="0" placeholder="Enter quantity">
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label>SGST Rate (%)</label>
          <input type="number" id="stockSGST" value="9" step="0.01" min="0">
        </div>
        <div class="form-group">
          <label>CGST Rate (%)</label>
          <input type="number" id="stockCGST" value="9" step="0.01" min="0">
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label>Discount Type</label>
          <select id="stockDiscountType">
            <option value="percent">%</option>
            <option value="amount">₹</option>
          </select>
        </div>
        <div class="form-group">
          <label>Discount</label>
          <input type="number" id="stockDiscount" value="0" step="0.01" min="0">
        </div>
      </div>
      <button class="add-stock-btn" onclick="addStockItem()">Add to Inventory</button>
      <table class="stock-table" id="stockTable">
        <thead>
          <tr>
            <th>Item Code</th>
            <th>HSN/SAC</th>
            <th>Description</th>
            <th>Rate (₹)</th>
            <th>Unit</th>
            <th>SGST %</th>
            <th>CGST %</th>
            <th>Discount</th>
            <th>Quantity</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody id="stockTableBody">
        </tbody>
      </table>
    </div>
  </div>
  <!-- Customer Database Section -->
  <div class="section" id="customers">
    <div class="input-section">
      <h3>👥 Customer Database</h3>
      <div class="form-row">
        <div class="form-group">
          <label>Contact Number</label>
          <input type="text" id="newCustomerContact" placeholder="Enter contact number">
        </div>
        <div class="form-group">
          <label>Customer Name</label>
          <input type="text" id="newCustomerName" placeholder="Enter customer name">
        </div>
        <div class="form-group">
          <label>Email</label>
          <input type="email" id="newCustomerEmail" placeholder="Enter email">
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label>Address</label>
          <textarea id="newCustomerAddress" placeholder="Enter address"></textarea>
        </div>
      </div>
      <button class="add-customer-btn" onclick="addCustomer()">+ Add Customer</button>
      <table class="customer-table" id="customerTable">
        <thead>
          <tr>
            <th>Contact</th>
            <th>Name</th>
            <th>Email</th>
            <th>Address</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody id="customerTableBody">
        </tbody>
      </table>
    </div>
  </div>
  <!-- Customer History Section -->
  <div class="section" id="customer-history">
    <div class="input-section">
      <h3>📜 Customer History</h3>
      <div class="form-row">
        <div class="form-group">
          <label>Customer Contact Number</label>
          <input type="text" id="historyContact" placeholder="Enter contact number (e.g., +919037393709)">
          <div class="dropdown" id="historyContactDropdown"></div>
        </div>
        <div class="form-group">
          <button class="search-customer-btn" onclick="loadCustomerHistory()">Search History</button>
        </div>
      </div>
      <table class="customer-history-table" id="customerHistoryTable">
        <thead>
          <tr>
            <th>Invoice Number</th>
            <th>Invoice Date</th>
            <th>Customer Name</th>
            <th>Total (₹)</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody id="customerHistoryTableBody">
        </tbody>
      </table>
      <div class="status-message" id="historyStatusMessage"></div>
    </div>
  </div>
  <!-- Backup & Restore Section -->
  <div class="section" id="backup-restore">
    <div class="input-section">
      <h3>💾 Backup & Restore</h3>
      <div class="form-row">
        <div class="form-group">
          <label>Backup All Data</label>
          <button class="backup-btn" onclick="backupData()">Backup Data to JSON</button>
        </div>
        <div class="form-group">
          <label>Restore All Data</label>
          <input type="file" id="restoreFileInput" accept=".json">
          <button class="restore-btn" onclick="restoreData()">Restore Data</button>
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label>Backup Stock Data Only</label>
          <button class="backup-btn" onclick="backupStockData()">Backup Stock to JSON</button>
        </div>
        <div class="form-group">
          <label>Restore Stock Data Only</label>
          <input type="file" id="restoreStockFileInput" accept=".json">
          <button class="restore-btn" onclick="restoreStockData()">Restore Stock Data</button>
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label>Backup Customer Data Only</label>
          <button class="backup-btn" onclick="backupCustomerData()">Backup Customers to JSON</button>
        </div>
        <div class="form-group">
          <label>Restore Customer Data Only</label>
          <input type="file" id="restoreCustomerFileInput" accept=".json">
          <button class="restore-btn" onclick="restoreCustomerData()">Restore Customer Data</button>
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label>Export Invoices</label>
          <button class="export-csv-btn" onclick="exportInvoicesToCSV()">Export Invoices to CSV</button>
        </div>
      </div>
      <div class="status-message" id="backupStatusMessage"></div>
    </div>
  </div>
</div>

<!-- Item Selection Dialog -->
<div class="dialog-overlay" id="dialogOverlay" onclick="closeDialog(event, 'dialogOverlay')">
  <div class="dialog" id="itemDialog" onclick="event.stopPropagation()">
    <div class="dialog-header">
      <h3>Select Items</h3>
      <div class="dialog-controls">
        <div class="size-inputs">
          <span style="font-size: 0.8rem;">W:</span>
          <input type="number" class="size-input" id="itemWidthInput" value="600" min="300" max="1200">
          <span style="font-size: 0.8rem;">H:</span>
          <input type="number" class="size-input" id="itemHeightInput" value="450" min="200" max="800">
          <button class="apply-btn" onclick="applyCustomSize('itemDialog', 'itemWidthInput', 'itemHeightInput')">Apply</button>
        </div>
        <div class="resize-controls">
          <button class="resize-btn" onclick="quickResize(400, 250, 'itemDialog', 'itemWidthInput', 'itemHeightInput')" title="Compact">XS</button>
          <button class="resize-btn" onclick="quickResize(500, 350, 'itemDialog', 'itemWidthInput', 'itemHeightInput')" title="Small">S</button>
          <button class="resize-btn" onclick="quickResize(700, 500, 'itemDialog', 'itemWidthInput', 'itemHeightInput')" title="Large">L</button>
        </div>
        <button class="close-btn" onclick="closeDialog(null, 'dialogOverlay')">&times;</button>
      </div>
    </div>
    <div class="search-section">
      <input type="text" class="search-input" id="searchInput" placeholder="Search items by code, name, or description..." oninput="searchItems()">
    </div>
    <div class="status-message" id="statusMessage"></div>
    <div class="items-container">
      <table class="item-table">
        <thead>
          <tr>
            <th>Code</th>
            <th>Name</th>
            <th>Description</th>
            <th>Price</th>
            <th>SGST %</th>
            <th>CGST %</th>
            <th>Discount</th>
          </tr>
        </thead>
        <tbody id="itemsList2">
        </tbody>
      </table>
    </div>
  </div>
</div>

<!-- Edit Customer Dialog -->
<div class="dialog-overlay" id="editCustomerDialogOverlay" onclick="closeDialog(event, 'editCustomerDialogOverlay')">
  <div class="dialog" id="editCustomerDialog" onclick="event.stopPropagation()">
    <div class="dialog-header">
      <h3>Edit Customer</h3>
      <button class="close-btn" onclick="closeDialog(null, 'editCustomerDialogOverlay')">&times;</button>
    </div>
    <div class="form-row" style="padding: 20px;">
      <div class="form-group">
        <label>Contact Number</label>
        <input type="text" id="editCustomerContact" placeholder="Enter contact number">
      </div>
      <div class="form-group">
        <label>Customer Name</label>
        <input type="text" id="editCustomerName" placeholder="Enter customer name">
      </div>
      <div class="form-group">
        <label>Email</label>
        <input type="email" id="editCustomerEmail" placeholder="Enter email">
      </div>
      <div class="form-group">
        <label>Address</label>
        <textarea id="editCustomerAddress" placeholder="Enter address"></textarea>
      </div>
    </div>
    <div style="padding: 0 20px 20px;">
      <button class="add-customer-btn" onclick="saveEditedCustomer()">Save Changes</button>
    </div>
  </div>
</div>

<script>
// Initialize IndexedDB with Dexie.js
const db = new Dexie('InvoiceDB');
db.version(1).stores({
  invoices: 'invoiceNumber,clientContact,timestamp',
  inventory: 'code,hsn,description',
  customers: 'contact,name'
});

// Initialize data arrays
let inventory = [];
let customerDatabase = [];
let filteredInventory = [];
let invoices = [];
let editingCustomerContact = null;

// Default inventory data
const defaultInventory = [
  { code: 'ITM001', hsn: '8471', name: 'Wireless Mouse', description: 'Ergonomic wireless mouse with USB receiver', price: 25.99, unit: 'PCS', quantity: 50, sgst: 9, cgst: 9, discountType: 'percent', discount: 5 },
  { code: 'ITM002', hsn: '8471', name: 'Keyboard', description: 'Mechanical gaming keyboard with RGB lighting', price: 89.99, unit: 'PCS', quantity: 30, sgst: 9, cgst: 9, discountType: 'amount', discount: 10 },
  { code: 'ITM003', hsn: '9403', name: 'Monitor Stand', description: 'Adjustable aluminum monitor stand', price: 45.00, unit: 'PCS', quantity: 20, sgst: 9, cgst: 9, discountType: 'percent', discount: 0 },
  { code: 'ITM004', hsn: '8544', name: 'USB Cable', description: '6ft USB-C to USB-A cable', price: 12.50, unit: 'PCS', quantity: 100, sgst: 9, cgst: 9, discountType: 'amount', discount: 2.50 },
  { code: 'ITM005', hsn: '8525', name: 'Webcam', description: '1080p HD webcam with built-in microphone', price: 67.99, unit: 'PCS', quantity: 15, sgst: 9, cgst: 9, discountType: 'percent', discount: 10 }
];

// Default customer data
const defaultCustomers = [
  { contact: "+919037393709", name: "John Doe", email: "john@example.com", address: "123 Main St, City" },
  { contact: "+919876543210", name: "Jane Smith", email: "jane@example.com", address: "456 Park Ave, City" }
];

// Migrate data from localStorage to IndexedDB
async function migrateLocalStorageToIndexedDB() {
  try {
    const invoiceCount = await db.invoices.count();
    if (invoiceCount > 0) return; // Skip migration if IndexedDB already has data

    const localInventory = JSON.parse(localStorage.getItem('inventory'));
    const localCustomers = JSON.parse(localStorage.getItem('customerDatabase'));
    const localInvoices = JSON.parse(localStorage.getItem('invoices'));

    if (localInventory && localInventory.length > 0) {
      await db.inventory.bulkPut(localInventory);
    } else {
      await db.inventory.bulkPut(defaultInventory);
    }

    if (localCustomers && localCustomers.length > 0) {
      await db.customers.bulkPut(localCustomers);
    } else {
      await db.customers.bulkPut(defaultCustomers);
    }

    if (localInvoices && localInvoices.length > 0) {
      await db.invoices.bulkPut(localInvoices);
    }

    // Clear localStorage after migration
    localStorage.removeItem('inventory');
    localStorage.removeItem('customerDatabase');
    localStorage.removeItem('invoices');
  } catch (error) {
    showStatus('Error during data migration: ' + error.message, 'error');
  }
}

// Load data from IndexedDB
async function loadDataFromIndexedDB() {
  try {
    inventory = await db.inventory.toArray();
    customerDatabase = await db.customers.toArray();
    invoices = await db.invoices.toArray();
    filteredInventory = [...inventory];
  } catch (error) {
    showStatus('Error loading data from IndexedDB: ' + error.message, 'error');
  }
}

// Input sanitization function
function sanitizeInput(input) {
  return input.replace(/[<>"'&]/g, '');
}

// Debounce function for autocomplete
function debounce(func, wait) {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

// Generate unique invoice number
async function generateInvoiceNumber() {
  try {
    const invoices = await db.invoices.toArray();
    const existingNumbers = invoices.map(inv => parseInt(inv.invoiceNumber.replace('INV-', '')));
    const nextNumber = existingNumbers.length ? Math.max(...existingNumbers) + 1 : 1;
    return `INV-${String(nextNumber).padStart(3, '0')}`;
  } catch (error) {
    showStatus('Error generating invoice number: ' + error.message, 'error');
    return 'INV-001';
  }
}

// Navigation functionality
function setupNavigation() {
  const navButtons = document.querySelectorAll('.nav-btn');
  navButtons.forEach(button => {
    button.addEventListener('click', function() {
      navButtons.forEach(btn => btn.classList.remove('active'));
      this.classList.add('active');
      document.querySelectorAll('.section').forEach(section => section.classList.remove('active'));
      document.getElementById(this.getAttribute('data-section')).classList.add('active');
    });
  });
}

// Show status message
function showStatus(message, type, elementId = 'statusMessage') {
  const statusMessage = document.getElementById(elementId);
  statusMessage.textContent = message;
  statusMessage.className = `status-message status-${type}`;
  statusMessage.style.display = 'block';
  setTimeout(() => {
    statusMessage.style.display = 'none';
  }, 3000);
}

// Add new item row
function addItem() {
  const itemsList = document.getElementById('itemsList').querySelector('tbody');
  const newRow = document.createElement('tr');
  newRow.className = 'item-row';
  newRow.innerHTML = `
    <td><input type="text" class="item-code code-input" placeholder="Enter HSN/SAC code..."><div class="dropdown item-dropdown"></div></td>
    <td><input type="text" class="item-desc desc-input" placeholder="Service or product description"></td>
    <td><select class="item-unit unit-select"><option value="PCS">PCS</option><option value="KG">KG</option><option value="LTR">LTR</option><option value="MTR">MTR</option><option value="BOX">BOX</option><option value="SET">SET</option></select></td>
    <td><input type="number" class="item-qty qty-input" value="1" min="1"></td>
    <td><input type="number" class="item-rate rate-input" value="0" step="0.01" min="0"></td>
    <td>
      <select class="disc-type-select">
        <option value="percent">%</option>
        <option value="amount">₹</option>
      </select>
    </td>
    <td><input type="number" class="item-disc disc-input" value="0" step="0.01" min="0"></td>
    <td><input type="number" class="item-sgst sgst-input" value="0" step="0.01" min="0"></td>
    <td><input type="number" class="item-cgst cgst-input" value="0" step="0.01" min="0"></td>
    <td><input type="text" class="item-total total-input" value="0.00" readonly></td>
    <td><button class="remove-btn" onclick="removeItem(this)">Remove</button></td>
  `;
  itemsList.appendChild(newRow);
  attachInputListeners(newRow);
  setupItemAutocomplete(newRow);
  updateItemTotals();
  return newRow;
}

// Remove item row
function removeItem(button) {
  const itemsList = document.getElementById('itemsList').querySelector('tbody');
  if (itemsList.children.length > 1) {
    button.closest('tr').remove();
    updateItemTotals();
  } else {
    showStatus('At least one item is required.', 'error');
  }
}

// Attach input listeners for real-time calculations
function attachInputListeners(row) {
  row.querySelectorAll('.item-qty, .item-rate, .item-disc, .item-sgst, .item-cgst, .disc-type-select').forEach(input => {
    input.addEventListener('input', () => {
      const code = row.querySelector('.item-code').value;
      const qty = parseInt(row.querySelector('.item-qty').value) || 0;
      const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
      const discType = row.querySelector('.disc-type-select').value;
      const rate = parseFloat(row.querySelector('.item-rate').value) || 0;

      // Validate quantity
      if (input.classList.contains('item-qty') && code) {
        const item = inventory.find(i => i.code === code);
        if (item && qty > item.quantity) {
          input.classList.add('quantity-error');
          showStatus(`Insufficient stock for ${item.description}. Available: ${item.quantity} units.`, 'error');
          input.value = item.quantity;
        } else {
          input.classList.remove('quantity-error');
        }
      }

      // Validate discount
      if (input.classList.contains('item-disc') || input.classList.contains('disc-type-select')) {
        if (discType === 'percent' && disc > 100) {
          input.classList.add('disc-error');
          showStatus('Discount percentage cannot exceed 100%.', 'error');
          input.value = 100;
        } else if (discType === 'amount' && disc > qty * rate) {
          input.classList.add('disc-error');
          showStatus('Discount amount cannot exceed subtotal.', 'error');
          input.value = qty * rate;
        } else {
          input.classList.remove('disc-error');
        }
      }

      updateItemTotal(row);
      updateItemTotals();
    });
  });
}

// Update individual item total
function updateItemTotal(row) {
  const qty = parseFloat(row.querySelector('.item-qty').value) || 0;
  const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
  const discType = row.querySelector('.disc-type-select').value;
  const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
  const sgst = parseFloat(row.querySelector('.item-sgst').value) || 0;
  const cgst = parseFloat(row.querySelector('.item-cgst').value) || 0;

  const subtotal = qty * rate;
  let discAmount = discType === 'percent' ? subtotal * (disc / 100) : disc;
  const afterDisc = subtotal - discAmount;
  const sgstAmount = afterDisc * (sgst / 100);
  const cgstAmount = afterDisc * (cgst / 100);
  const lineTotal = afterDisc + sgstAmount + cgstAmount;

  row.querySelector('.item-total').value = lineTotal.toFixed(2);
}

// Update all item totals and invoice preview
function updateItemTotals() {
  const rows = document.querySelectorAll('.item-row');
  let subtotal = 0, totalDiscount = 0, totalSGST = 0, totalCGST = 0, grandTotal = 0;
  let canGenerate = true;

  rows.forEach(row => {
    const code = row.querySelector('.item-code').value;
    const qty = parseInt(row.querySelector('.item-qty').value) || 0;
    const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
    const discType = row.querySelector('.disc-type-select').value;
    const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
    const item = inventory.find(i => i.code === code);

    if (item && qty > item.quantity) {
      canGenerate = false;
      row.querySelector('.item-qty').classList.add('quantity-error');
      showStatus(`Insufficient stock for ${item.description}. Available: ${item.quantity} units.`, 'error');
    } else {
      row.querySelector('.item-qty').classList.remove('quantity-error');
    }

    if (discType === 'percent' && disc > 100) {
      canGenerate = false;
      row.querySelector('.item-disc').classList.add('disc-error');
      showStatus('Discount percentage cannot exceed 100%.', 'error');
    } else if (discType === 'amount' && disc > qty * rate) {
      canGenerate = false;
      row.querySelector('.item-disc').classList.add('disc-error');
      showStatus('Discount amount cannot exceed subtotal.', 'error');
    } else {
      row.querySelector('.item-disc').classList.remove('disc-error');
    }
  });

  if (!canGenerate) return;

  rows.forEach(row => {
    const qty = parseFloat(row.querySelector('.item-qty').value) || 0;
    const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
    const discType = row.querySelector('.disc-type-select').value;
    const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
    const sgst = parseFloat(row.querySelector('.item-sgst').value) || 0;
    const cgst = parseFloat(row.querySelector('.item-cgst').value) || 0;

    const subtotalAmount = qty * rate;
    let discAmount = discType === 'percent' ? subtotalAmount * (disc / 100) : disc;
    const afterDisc = subtotalAmount - discAmount;
    const sgstAmount = afterDisc * (sgst / 100);
    const cgstAmount = afterDisc * (cgst / 100);
    const lineTotal = afterDisc + sgstAmount + cgstAmount;

    row.querySelector('.item-total').value = lineTotal.toFixed(2);
    subtotal += subtotalAmount;
    totalDiscount += discAmount;
    totalSGST += sgstAmount;
    totalCGST += cgstAmount;
    grandTotal += lineTotal;
  });

  const totalsRow = `
    <tr>
      <td colspan="4"></td>
      <td colspan="3">Subtotal</td>
      <td>₹${subtotal.toFixed(2)}</td>
    </tr>
    <tr>
      <td colspan="4"></td>
      <td colspan="3">Total Discount</td>
      <td>₹${totalDiscount.toFixed(2)}</td>
    </tr>
    <tr>
      <td colspan="4"></td>
      <td colspan="3">Total SGST</td>
      <td>₹${totalSGST.toFixed(2)}</td>
    </tr>
    <tr>
      <td colspan="4"></td>
      <td colspan="3">Total CGST</td>
      <td>₹${totalCGST.toFixed(2)}</td>
    </tr>
    <tr>
      <td colspan="4"></td>
      <td colspan="3"><strong>Grand Total</strong></td>
      <td><strong>₹${grandTotal.toFixed(2)}</strong></td>
    </tr>
  `;
  generateInvoice(totalsRow);
}

// Save invoice and update inventory
async function saveInvoice() {
  try {
    const invoice = {
      invoiceNumber: document.getElementById('invoiceNumber').value || await generateInvoiceNumber(),
      invoiceDate: document.getElementById('invoiceDate').value,
      dueDate: document.getElementById('dueDate').value,
      clientContact: sanitizeInput(document.getElementById('clientContact').value),
      clientName: sanitizeInput(document.getElementById('clientName').value),
      clientEmail: sanitizeInput(document.getElementById('clientEmail').value),
      clientAddress: sanitizeInput(document.getElementById('clientAddress').value),
      items: [],
      subtotal: 0,
      totalDiscount: 0,
      totalSGST: 0,
      totalCGST: 0,
      grandTotal: 0,
      timestamp: new Date().toISOString()
    };

    const rows = document.querySelectorAll('.item-row');
    let canSave = true;

    // Validate all rows
    rows.forEach(row => {
      const code = row.querySelector('.item-code').value;
      const qty = parseInt(row.querySelector('.item-qty').value) || 0;
      const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
      const discType = row.querySelector('.disc-type-select').value;
      const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
      const item = inventory.find(i => i.code === code);

      if (item && qty > item.quantity) {
        canSave = false;
        row.querySelector('.item-qty').classList.add('quantity-error');
        showStatus(`Insufficient stock for ${item.description}. Available: ${item.quantity} units.`, 'error');
      }
      if (discType === 'percent' && disc > 100) {
        canSave = false;
        row.querySelector('.item-disc').classList.add('disc-error');
        showStatus('Discount percentage cannot exceed 100%.', 'error');
      } else if (discType === 'amount' && disc > qty * rate) {
        canSave = false;
        row.querySelector('.item-disc').classList.add('disc-error');
        showStatus('Discount amount cannot exceed subtotal.', 'error');
      }
    });

    if (!canSave) return;

    // Build invoice items and update totals
    rows.forEach(row => {
      const code = row.querySelector('.item-code').value;
      const qty = parseFloat(row.querySelector('.item-qty').value) || 0;
      const unit = row.querySelector('.item-unit').value || 'PCS';
      const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
      const discType = row.querySelector('.disc-type-select').value;
      const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
      const sgst = parseFloat(row.querySelector('.item-sgst').value) || 0;
      const cgst = parseFloat(row.querySelector('.item-cgst').value) || 0;

      const subtotalAmount = qty * rate;
      let discAmount = discType === 'percent' ? subtotalAmount * (disc / 100) : disc;
      const afterDisc = subtotalAmount - discAmount;
      const sgstAmount = afterDisc * (sgst / 100);
      const cgstAmount = afterDisc * (cgst / 100);
      const lineTotal = afterDisc + sgstAmount + cgstAmount;

      invoice.items.push({
        code: sanitizeInput(code),
        description: sanitizeInput(row.querySelector('.item-desc').value),
        quantity: qty,
        unit: unit,
        rate: rate,
        discountType: discType,
        discount: disc,
        sgst: sgst,
        cgst: cgst,
        total: lineTotal
      });

      invoice.subtotal += subtotalAmount;
      invoice.totalDiscount += discAmount;
      invoice.totalSGST += sgstAmount;
      invoice.totalCGST += cgstAmount;
      invoice.grandTotal += lineTotal;

      const item = inventory.find(i => i.code === code);
      if (item) item.quantity -= qty;
    });

    if (!invoice.clientContact || !invoice.clientName || invoice.items.length === 0) {
      showStatus('Please fill in client details and add at least one item.', 'error');
      return;
    }

    // Save invoice and update inventory
    await db.invoices.put(invoice);
    await db.inventory.bulkPut(inventory);
    invoices = await db.invoices.toArray();
    loadStockTable();
    showStatus('Invoice saved successfully!', 'success');
    updateDashboard();

    // Reset form
    document.getElementById('invoiceNumber').value = await generateInvoiceNumber();
    document.getElementById('clientContact').value = '';
    document.getElementById('clientName').value = '';
    document.getElementById('clientEmail').value = '';
    document.getElementById('clientAddress').value = '';
    document.getElementById('whatsappNumber').value = '';
    const itemsList = document.getElementById('itemsList').querySelector('tbody');
    itemsList.innerHTML = '';
    addItem();
  } catch (error) {
    showStatus('Error saving invoice: ' + error.message, 'error');
  }
}

// Generate invoice preview
function generateInvoice(totalsRow) {
  const companyName = document.getElementById('companyName').value;
  const companyAddress = document.getElementById('companyAddress').value;
  const companyContact = document.getElementById('companyContact').value;
  const clientName = document.getElementById('clientName').value;
  const clientAddress = document.getElementById('clientAddress').value;
  const clientContact = document.getElementById('clientContact').value;
  const clientEmail = document.getElementById('clientEmail').value;
  const invoiceNumber = document.getElementById('invoiceNumber').value;
  const invoiceDate = document.getElementById('invoiceDate').value;
  const dueDate = document.getElementById('dueDate').value;

  document.getElementById('previewCompanyName').textContent = companyName || 'Your Company Name';
  document.getElementById('previewCompanyAddress').textContent = companyAddress || '123 Business Street, City, State - ZIP';
  document.getElementById('previewCompanyContact').textContent = companyContact || 'Email: info@company.com | Phone: +91 9037393709';
  document.getElementById('previewClientName').textContent = clientName || 'Customer Name';
  document.getElementById('previewClientAddress').textContent = clientAddress || 'Customer Address';
  document.getElementById('previewClientContact').textContent = clientContact || 'Customer Contact';
  document.getElementById('previewClientEmail').textContent = clientEmail || 'Customer Email';
  document.getElementById('previewInvoiceNumber').textContent = invoiceNumber || 'INV-001';
  document.getElementById('previewInvoiceDate').textContent = invoiceDate || new Date().toLocaleDateString();
  document.getElementById('previewDueDate').textContent = dueDate || new Date().toLocaleDateString();

  let itemsHtml = '';
  document.querySelectorAll('.item-row').forEach(row => {
    const code = row.querySelector('.item-code').value || '';
    const desc = row.querySelector('.item-desc').value || 'Sample Item';
    const unit = row.querySelector('.item-unit').value || 'PCS';
    const qty = row.querySelector('.item-qty').value || 1;
    const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
    const discType = row.querySelector('.disc-type-select').value;
    const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
    const sgst = parseFloat(row.querySelector('.item-sgst').value) || 0;
    const cgst = parseFloat(row.querySelector('.item-cgst').value) || 0;
    const total = parseFloat(row.querySelector('.item-total').value) || 0;
    const item = inventory.find(i => i.code === code);
const hsnCode = item ? item.hsn : code;

    const discDisplay = discType === 'percent' ? `${disc}%` : `₹${disc.toFixed(2)}`;
    itemsHtml += `
      <tr>
        <td>${sanitizeInput(hsnCode)}</td>
        <td>${sanitizeInput(desc)}</td>
        <td>${unit}</td>
        <td>${qty}</td>
        <td>₹${rate.toFixed(2)}</td>
        <td>${discDisplay}</td>
        <td>${sgst}%</td>
        <td>${cgst}%</td>
        <td>₹${total.toFixed(2)}</td>
      </tr>
    `;
  });
  itemsHtml += totalsRow;
  document.getElementById('previewItems').innerHTML = itemsHtml;
  document.getElementById('previewTotal').textContent = `₹${parseFloat(totalsRow.match(/₹([\d.]+)/)[1]).toFixed(2)}`;
}

// Generate PDF
async function generatePDF() {
  try {
    const { jsPDF } = window.jspdf;
    const doc = new jsPDF();
    const invoiceBox = document.querySelector('.invoice-box');
    const companyName = document.getElementById('previewCompanyName').textContent;
    const invoiceNumber = document.getElementById('previewInvoiceNumber').textContent;

    // Add logo if present
    const logo = document.querySelector('.invoice-logo img');
    if (logo) {
      const logoStyle = window.getComputedStyle(document.querySelector('.invoice-logo'));
      const left = parseFloat(logoStyle.left) / 3.78; // Convert px to mm
      const top = parseFloat(logoStyle.top) / 3.78;
      const width = parseFloat(logoStyle.width) / 3.78;
      const height = parseFloat(logoStyle.height) / 3.78;
      const imgData = await getImageData(logo);
      doc.addImage(imgData, 'PNG', left, top, width, height);
    }

    // Capture invoice content
    const canvas = await html2canvas(invoiceBox, { scale: 2 });
    const imgData = canvas.toDataURL('image/png');
    doc.addImage(imgData, 'PNG', 10, 30, 190, 0);
    doc.save(`${companyName}_Invoice_${invoiceNumber}.pdf`);
  } catch (error) {
    showStatus('Error generating PDF: ' + error.message, 'error');
  }
}

// Share PDF via WhatsApp
// Replace your existing sharePDF() function with this improved version
async function sharePDF() {
  try {
    const { jsPDF } = window.jspdf;
    const doc = new jsPDF();
    const invoiceBox = document.querySelector('.invoice-box');
    const companyName = document.getElementById('previewCompanyName').textContent;
    const invoiceNumber = document.getElementById('previewInvoiceNumber').textContent;
    const whatsappNumber = document.getElementById('whatsappNumber').value;

    if (!whatsappNumber) {
      showStatus('Please enter a WhatsApp number.', 'error');
      return;
    }

    // Add logo if present
    const logo = document.querySelector('.invoice-logo img');
    if (logo) {
      const logoStyle = window.getComputedStyle(document.querySelector('.invoice-logo'));
      const left = parseFloat(logoStyle.left) / 3.78;
      const top = parseFloat(logoStyle.top) / 3.78;
      const width = parseFloat(logoStyle.width) / 3.78;
      const height = parseFloat(logoStyle.height) / 3.78;
      const imgData = await getImageData(logo);
      doc.addImage(imgData, 'PNG', left, top, width, height);
    }

    // Capture the invoice with higher resolution
    const canvas = await html2canvas(invoiceBox, { 
      scale: 2,
      useCORS: true,
      allowTaint: true,
      height: invoiceBox.scrollHeight,
      width: invoiceBox.scrollWidth
    });
    
    const imgData = canvas.toDataURL('image/png');
    const imgWidth = 190; // PDF width in mm
    const pageHeight = 277; // A4 page height in mm
    const imgHeight = (canvas.height * imgWidth) / canvas.width;
    let heightLeft = imgHeight;
    let position = 30; // Start position

    // Add first page
    doc.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight);
    heightLeft -= (pageHeight - position);

    // Add additional pages if needed
    while (heightLeft >= 0) {
      position = heightLeft - imgHeight + 30;
      doc.addPage();
      doc.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight);
      heightLeft -= pageHeight;
    }

    const pdfBlob = doc.output('blob');
    const file = new File([pdfBlob], `${companyName}_Invoice_${invoiceNumber}.pdf`, { type: 'application/pdf' });

    if (navigator.canShare && navigator.canShare({ files: [file] })) {
      await navigator.share({
        files: [file],
        title: `Invoice ${invoiceNumber}`,
        text: `Invoice ${invoiceNumber} from ${companyName}`,
        url: whatsappNumber ? `https://wa.me/${whatsappNumber.replace('+', '')}?text=Invoice%20${invoiceNumber}%20from%20${encodeURIComponent(companyName)}` : ''
      });
    } else {
      // Fallback: Download the file and open WhatsApp
      const url = URL.createObjectURL(pdfBlob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `${companyName}_Invoice_${invoiceNumber}.pdf`;
      a.click();
      URL.revokeObjectURL(url);
      
      // Open WhatsApp with message
      const whatsappUrl = `https://wa.me/${whatsappNumber.replace('+', '')}?text=Please%20find%20the%20invoice%20PDF%20attached.%20Invoice%20${invoiceNumber}%20from%20${encodeURIComponent(companyName)}`;
      window.open(whatsappUrl, '_blank');
      
      showStatus('PDF downloaded. Please manually attach it to WhatsApp.', 'success');
    }
  } catch (error) {
    showStatus('Error sharing PDF: ' + error.message, 'error');
  }
}

// Print invoice
function printInvoice() {
  window.print();
}

// Get image data for PDF
function getImageData(img) {
  return new Promise((resolve) => {
    const canvas = document.createElement('canvas');
    canvas.width = img.naturalWidth;
    canvas.height = img.naturalHeight;
    const ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0);
    resolve(canvas.toDataURL('image/png'));
  });
}

// Setup item autocomplete
function setupItemAutocomplete(row) {
  const codeInput = row.querySelector('.item-code');
  const dropdown = row.querySelector('.item-dropdown');
  codeInput.addEventListener('input', debounce(async () => {
    const query = codeInput.value.toLowerCase();
    dropdown.innerHTML = '';
    if (query.length < 1) {
      dropdown.style.display = 'none';
      return;
    }
    const filtered = inventory.filter(item =>
      item.code.toLowerCase().includes(query) ||
      item.description.toLowerCase().includes(query)
    );
    filtered.forEach(item => {
      const div = document.createElement('div');
      div.className = 'dropdown-item';
      div.textContent = `${item.code} - ${item.description}`;
      div.addEventListener('click', () => {
        codeInput.value = item.code;
        row.querySelector('.item-desc').value = item.description;
        row.querySelector('.item-rate').value = item.price.toFixed(2);
        row.querySelector('.item-unit').value = item.unit;
        row.querySelector('.item-sgst').value = item.sgst;
        row.querySelector('.item-cgst').value = item.cgst;
        row.querySelector('.item-disc').value = item.discount;
        row.querySelector('.disc-type-select').value = item.discountType;
        [row.querySelector('.item-desc'), row.querySelector('.item-rate'), row.querySelector('.item-unit'),
         row.querySelector('.item-sgst'), row.querySelector('.item-cgst'), row.querySelector('.item-disc'),
         row.querySelector('.disc-type-select')].forEach(el => el.classList.add('auto-populated'));
        updateItemTotal(row);
        updateItemTotals();
        dropdown.style.display = 'none';
      });
      dropdown.appendChild(div);
    });
    dropdown.style.display = filtered.length ? 'block' : 'none';
  }, 300));
}

// Client contact autocomplete
function setupClientAutocomplete() {
  const contactInput = document.getElementById('clientContact');
  const dropdown = document.getElementById('contactDropdown');
  contactInput.addEventListener('input', debounce(async () => {
    const query = contactInput.value.toLowerCase();
    dropdown.innerHTML = '';
    if (query.length < 1) {
      dropdown.style.display = 'none';
      return;
    }
    const filtered = customerDatabase.filter(customer =>
      customer.contact.toLowerCase().includes(query) ||
      customer.name.toLowerCase().includes(query)
    );
    filtered.forEach(customer => {
      const div = document.createElement('div');
      div.className = 'dropdown-item';
      div.textContent = `${customer.contact} - ${customer.name}`;
      div.addEventListener('click', () => {
        contactInput.value = customer.contact;
        document.getElementById('clientName').value = customer.name;
        document.getElementById('clientEmail').value = customer.email;
        document.getElementById('clientAddress').value = customer.address;
        document.getElementById('whatsappNumber').value = customer.contact;
        [document.getElementById('clientName'), document.getElementById('clientEmail'),
         document.getElementById('clientAddress'), document.getElementById('whatsappNumber')]
          .forEach(el => el.classList.add('auto-populated'));
        dropdown.style.display = 'none';
      });
      dropdown.appendChild(div);
    });
    dropdown.style.display = filtered.length ? 'block' : 'none';
  }, 300));
}

// Load stock table
async function loadStockTable() {
  try {
    const stockTableBody = document.getElementById('stockTableBody');
    stockTableBody.innerHTML = '';
    inventory = await db.inventory.toArray();
    inventory.forEach((item, index) => {
      const row = document.createElement('tr');
      const discDisplay = item.discountType === 'percent' ? `${item.discount}%` : `₹${item.discount.toFixed(2)}`;
      row.innerHTML = `
        <td>${sanitizeInput(item.code)}</td>
        <td>${sanitizeInput(item.hsn)}</td>
        <td>${sanitizeInput(item.description)}</td>
        <td>₹${item.price.toFixed(2)}</td>
        <td>${item.unit}</td>
        <td>${item.sgst}%</td>
        <td>${item.cgst}%</td>
        <td>${discDisplay}</td>
        <td class="${item.quantity < 10 ? 'low-stock' : ''}">${item.quantity}</td>
        <td>
          <button class="edit-btn" onclick="editStockItem(${index})">Edit</button>
          <button class="delete-btn" onclick="deleteStockItem('${item.code}')">Delete</button>
        </td>
      `;
      stockTableBody.appendChild(row);
    });
  } catch (error) {
    showStatus('Error loading stock table: ' + error.message, 'error');
  }
}

// Add stock item
async function addStockItem() {
  try {
    const item = {
      code: sanitizeInput(document.getElementById('stockCode').value),
      hsn: sanitizeInput(document.getElementById('stockHSN').value),
      description: sanitizeInput(document.getElementById('stockDescription').value),
      price: parseFloat(document.getElementById('stockPrice').value) || 0,
      unit: document.getElementById('stockUnit').value,
      quantity: parseInt(document.getElementById('stockQuantity').value) || 0,
      sgst: parseFloat(document.getElementById('stockSGST').value) || 0,
      cgst: parseFloat(document.getElementById('stockCGST').value) || 0,
      discountType: document.getElementById('stockDiscountType').value,
      discount: parseFloat(document.getElementById('stockDiscount').value) || 0
    };

    if (!item.code || !item.description || !item.hsn) {
      showStatus('Please fill in all required fields (Code, HSN/SAC, Description).', 'error');
      return;
    }

    if (inventory.some(i => i.code === item.code)) {
      showStatus('Item code already exists.', 'error');
      return;
    }

    await db.inventory.put(item);
    inventory = await db.inventory.toArray();
    loadStockTable();
    document.getElementById('stockCode').value = '';
    document.getElementById('stockHSN').value = '';
    document.getElementById('stockDescription').value = '';
    document.getElementById('stockPrice').value = '';
    document.getElementById('stockUnit').value = 'PCS';
    document.getElementById('stockQuantity').value = '';
    document.getElementById('stockSGST').value = '9';
    document.getElementById('stockCGST').value = '9';
    document.getElementById('stockDiscountType').value = 'percent';
    document.getElementById('stockDiscount').value = '0';
    showStatus('Item added successfully!', 'success');
  } catch (error) {
    showStatus('Error adding stock item: ' + error.message, 'error');
  }
}

// Edit stock item
function editStockItem(index) {
  const item = inventory[index];
  document.getElementById('stockCode').value = item.code;
  document.getElementById('stockHSN').value = item.hsn;
  document.getElementById('stockDescription').value = item.description;
  document.getElementById('stockPrice').value = item.price;
  document.getElementById('stockUnit').value = item.unit;
  document.getElementById('stockQuantity').value = item.quantity;
  document.getElementById('stockSGST').value = item.sgst;
  document.getElementById('stockCGST').value = item.cgst;
  document.getElementById('stockDiscountType').value = item.discountType;
  document.getElementById('stockDiscount').value = item.discount;

  document.getElementById('add-stock-btn').textContent = 'Update Item';
  document.getElementById('add-stock-btn').onclick = async () => {
    try {
      const updatedItem = {
        code: sanitizeInput(document.getElementById('stockCode').value),
        hsn: sanitizeInput(document.getElementById('stockHSN').value),
        description: sanitizeInput(document.getElementById('stockDescription').value),
        price: parseFloat(document.getElementById('stockPrice').value) || 0,
        unit: document.getElementById('stockUnit').value,
        quantity: parseInt(document.getElementById('stockQuantity').value) || 0,
        sgst: parseFloat(document.getElementById('stockSGST').value) || 0,
        cgst: parseFloat(document.getElementById('stockCGST').value) || 0,
        discountType: document.getElementById('stockDiscountType').value,
        discount: parseFloat(document.getElementById('stockDiscount').value) || 0
      };

      if (!updatedItem.code || !updatedItem.description || !updatedItem.hsn) {
        showStatus('Please fill in all required fields (Code, HSN/SAC, Description).', 'error');
        return;
      }

      await db.inventory.put(updatedItem);
      inventory = await db.inventory.toArray();
      loadStockTable();
      document.getElementById('add-stock-btn').textContent = 'Add to Inventory';
      document.getElementById('add-stock-btn').onclick = addStockItem;
      document.getElementById('stockCode').value = '';
      document.getElementById('stockHSN').value = '';
      document.getElementById('stockDescription').value = '';
      document.getElementById('stockPrice').value = '';
      document.getElementById('stockUnit').value = 'PCS';
      document.getElementById('stockQuantity').value = '';
      document.getElementById('stockSGST').value = '9';
      document.getElementById('stockCGST').value = '9';
      document.getElementById('stockDiscountType').value = 'percent';
      document.getElementById('stockDiscount').value = '0';
      showStatus('Item updated successfully!', 'success');
    } catch (error) {
      showStatus('Error updating stock item: ' + error.message, 'error');
    }
  };
}

// Delete stock item
async function deleteStockItem(code) {
  if (confirm('Are you sure you want to delete this item?')) {
    try {
      await db.inventory.delete(code);
      inventory = await db.inventory.toArray();
      loadStockTable();
      showStatus('Item deleted successfully!', 'success');
    } catch (error) {
      showStatus('Error deleting stock item: ' + error.message, 'error');
    }
  }
}

// Add customer
async function addCustomer() {
  try {
    const customer = {
      contact: sanitizeInput(document.getElementById('newCustomerContact').value),
      name: sanitizeInput(document.getElementById('newCustomerName').value),
      email: sanitizeInput(document.getElementById('newCustomerEmail').value),
      address: sanitizeInput(document.getElementById('newCustomerAddress').value)
    };

    if (!customer.contact || !customer.name) {
      showStatus('Please fill in contact number and name.', 'error');
      return;
    }

    if (customerDatabase.some(c => c.contact === customer.contact)) {
      showStatus('Customer with this contact number already exists.', 'error');
      return;
    }

    await db.customers.put(customer);
    customerDatabase = await db.customers.toArray();
    loadCustomerTable();
    document.getElementById('newCustomerContact').value = '';
    document.getElementById('newCustomerName').value = '';
    document.getElementById('newCustomerEmail').value = '';
    document.getElementById('newCustomerAddress').value = '';
    showStatus('Customer added successfully!', 'success');
    updateDashboard();
  } catch (error) {
    showStatus('Error adding customer: ' + error.message, 'error');
  }
}

// Load customer table
async function loadCustomerTable() {
  try {
    const customerTableBody = document.getElementById('customerTableBody');
    customerTableBody.innerHTML = '';
    customerDatabase = await db.customers.toArray();
    customerDatabase.forEach((customer, index) => {
      const row = document.createElement('tr');
      row.innerHTML = `
        <td>${sanitizeInput(customer.contact)}</td>
        <td>${sanitizeInput(customer.name)}</td>
        <td>${sanitizeInput(customer.email)}</td>
        <td>${sanitizeInput(customer.address)}</td>
        <td>
          <button class="edit-btn" onclick="editCustomer('${customer.contact}')">Edit</button>
          <button class="delete-btn" onclick="deleteCustomer('${customer.contact}')">Delete</button>
        </td>
      `;
      customerTableBody.appendChild(row);
    });
  } catch (error) {
    showStatus('Error loading customer table: ' + error.message, 'error');
  }
}

// Edit customer
function editCustomer(contact) {
  const customer = customerDatabase.find(c => c.contact === contact);
  if (!customer) return;

  editingCustomerContact = contact;
  document.getElementById('editCustomerContact').value = customer.contact;
  document.getElementById('editCustomerName').value = customer.name;
  document.getElementById('editCustomerEmail').value = customer.email;
  document.getElementById('editCustomerAddress').value = customer.address;
  document.getElementById('editCustomerDialogOverlay').style.display = 'flex';
}

// Save edited customer
async function saveEditedCustomer() {
  try {
    const updatedCustomer = {
      contact: sanitizeInput(document.getElementById('editCustomerContact').value),
      name: sanitizeInput(document.getElementById('editCustomerName').value),
      email: sanitizeInput(document.getElementById('editCustomerEmail').value),
      address: sanitizeInput(document.getElementById('editCustomerAddress').value)
    };

    if (!updatedCustomer.contact || !updatedCustomer.name) {
      showStatus('Please fill in contact number and name.', 'error');
      return;
    }

    if (updatedCustomer.contact !== editingCustomerContact && customerDatabase.some(c => c.contact === updatedCustomer.contact)) {
      showStatus('Customer with this contact number already exists.', 'error');
      return;
    }

    await db.customers.delete(editingCustomerContact);
    await db.customers.put(updatedCustomer);
    customerDatabase = await db.customers.toArray();
    loadCustomerTable();
    document.getElementById('editCustomerDialogOverlay').style.display = 'none';
    showStatus('Customer updated successfully!', 'success');
    editingCustomerContact = null;
  } catch (error) {
    showStatus('Error updating customer: ' + error.message, 'error');
  }
}

// Delete customer
async function deleteCustomer(contact) {
  if (confirm('Are you sure you want to delete this customer?')) {
    try {
      await db.customers.delete(contact);
      customerDatabase = await db.customers.toArray();
      loadCustomerTable();
      showStatus('Customer deleted successfully!', 'success');
    } catch (error) {
      showStatus('Error deleting customer: ' + error.message, 'error');
    }
  }
}

// Load customer history
async function loadCustomerHistory() {
  try {
    const contact = document.getElementById('historyContact').value;
    const historyTableBody = document.getElementById('customerHistoryTableBody');
    historyTableBody.innerHTML = '';
    const filteredInvoices = invoices.filter(inv => inv.clientContact === contact);

    if (filteredInvoices.length === 0) {
      showStatus('No invoices found for this customer.', 'error', 'historyStatusMessage');
      return;
    }

    filteredInvoices.forEach(invoice => {
      const row = document.createElement('tr');
      row.innerHTML = `
        <td>${sanitizeInput(invoice.invoiceNumber)}</td>
        <td>${invoice.invoiceDate}</td>
        <td>${sanitizeInput(invoice.clientName)}</td>
        <td>₹${invoice.grandTotal.toFixed(2)}</td>
        <td>
          <button class="toggle-items-btn" onclick="toggleInvoiceItems(this, '${invoice.invoiceNumber}')">Show Items</button>
        </td>
      `;
      const itemsRow = document.createElement('tr');
      itemsRow.className = 'items-details';
      itemsRow.innerHTML = `
        <td colspan="5">
          <table class="item-table">
            <thead>
              <tr>
                <th>Code</th>
                <th>Description</th>
                <th>Unit</th>
                <th>Qty</th>
                <th>Rate</th>
                <th>Discount</th>
                <th>SGST %</th>
                <th>CGST %</th>
                <th>Total</th>
              </tr>
            </thead>
            <tbody>
              ${invoice.items.map(item => `
                <tr>
                  <td>${sanitizeInput(item.code)}</td>
                  <td>${sanitizeInput(item.description)}</td>
                  <td>${item.unit}</td>
                  <td>${item.quantity}</td>
                  <td>₹${item.rate.toFixed(2)}</td>
                  <td>${item.discountType === 'percent' ? `${item.discount}%` : `₹${item.discount.toFixed(2)}`}</td>
                  <td>${item.sgst}%</td>
                  <td>${item.cgst}%</td>
                  <td>₹${item.total.toFixed(2)}</td>
                </tr>
              `).join('')}
            </tbody>
          </table>
        </td>
      `;
      historyTableBody.appendChild(row);
      historyTableBody.appendChild(itemsRow);
    });
    showStatus('Customer history loaded successfully!', 'success', 'historyStatusMessage');
  } catch (error) {
    showStatus('Error loading customer history: ' + error.message, 'error', 'historyStatusMessage');
  }
}

// Toggle invoice items in customer history
function toggleInvoiceItems(button, invoiceNumber) {
  const row = button.closest('tr');
  const itemsRow = row.nextElementSibling;
  if (itemsRow.classList.contains('active')) {
    itemsRow.classList.remove('active');
    button.textContent = 'Show Items';
  } else {
    itemsRow.classList.add('active');
    button.textContent = 'Hide Items';
  }
}

// Customer history contact autocomplete
function setupHistoryContactAutocomplete() {
  const contactInput = document.getElementById('historyContact');
  const dropdown = document.getElementById('historyContactDropdown');
  contactInput.addEventListener('input', debounce(async () => {
    const query = contactInput.value.toLowerCase();
    dropdown.innerHTML = '';
    if (query.length < 1) {
      dropdown.style.display = 'none';
      return;
    }
    const filtered = customerDatabase.filter(customer =>
      customer.contact.toLowerCase().includes(query) ||
      customer.name.toLowerCase().includes(query)
    );
    filtered.forEach(customer => {
      const div = document.createElement('div');
      div.className = 'dropdown-item';
      div.textContent = `${customer.contact} - ${customer.name}`;
      div.addEventListener('click', () => {
        contactInput.value = customer.contact;
        dropdown.style.display = 'none';
        loadCustomerHistory();
      });
      dropdown.appendChild(div);
    });
    dropdown.style.display = filtered.length ? 'block' : 'none';
  }, 300));
}

// Open item dialog
async function openItemDialog() {
  try {
    const itemsList = document.getElementById('itemsList2');
    itemsList.innerHTML = '';
    filteredInventory = await db.inventory.toArray();
    filteredInventory.forEach(item => {
      const discDisplay = item.discountType === 'percent' ? `${item.discount}%` : `₹${item.discount.toFixed(2)}`;
      const row = document.createElement('tr');
      row.innerHTML = `
        <td>${sanitizeInput(item.code)}</td>
        <td>${sanitizeInput(item.name)}</td>
        <td>${sanitizeInput(item.description)}</td>
        <td>₹${item.price.toFixed(2)}</td>
        <td>${item.sgst}%</td>
        <td>${item.cgst}%</td>
        <td>${discDisplay}</td>
      `;
      row.addEventListener('click', () => {
        const newRow = addItem();
        newRow.querySelector('.item-code').value = item.code;
        newRow.querySelector('.item-desc').value = item.description;
        newRow.querySelector('.item-rate').value = item.price.toFixed(2);
        newRow.querySelector('.item-unit').value = item.unit;
        newRow.querySelector('.item-sgst').value = item.sgst;
        newRow.querySelector('.item-cgst').value = item.cgst;
        newRow.querySelector('.item-disc').value = item.discount;
        newRow.querySelector('.disc-type-select').value = item.discountType;
        [newRow.querySelector('.item-desc'), newRow.querySelector('.item-rate'), newRow.querySelector('.item-unit'),
         newRow.querySelector('.item-sgst'), newRow.querySelector('.item-cgst'), newRow.querySelector('.item-disc'),
         newRow.querySelector('.disc-type-select')].forEach(el => el.classList.add('auto-populated'));
        updateItemTotal(newRow);
        updateItemTotals();
        
      });
      itemsList.appendChild(row);
    });
    document.getElementById('dialogOverlay').style.display = 'flex';
  } catch (error) {
    showStatus('Error opening item dialog: ' + error.message, 'error');
  }
}

// Search items in dialog
async function searchItems() {
  try {
    const query = document.getElementById('searchInput').value.toLowerCase();
    const itemsList = document.getElementById('itemsList2');
    itemsList.innerHTML = '';
    filteredInventory = inventory.filter(item =>
      item.code.toLowerCase().includes(query) ||
      item.description.toLowerCase().includes(query)
    );
    filteredInventory.forEach(item => {
      const discDisplay = item.discountType === 'percent' ? `${item.discount}%` : `₹${item.discount.toFixed(2)}`;
      const row = document.createElement('tr');
      row.innerHTML = `
        <td>${sanitizeInput(item.code)}</td>
        <td>${sanitizeInput(item.name)}</td>
        <td>${sanitizeInput(item.description)}</td>
        <td>₹${item.price.toFixed(2)}</td>
        <td>${item.sgst}%</td>
        <td>${item.cgst}%</td>
        <td>${discDisplay}</td>
      `;
      row.addEventListener('click', () => {
        const newRow = addItem();
        newRow.querySelector('.item-code').value = item.code;
        newRow.querySelector('.item-desc').value = item.description;
        newRow.querySelector('.item-rate').value = item.price.toFixed(2);
        newRow.querySelector('.item-unit').value = item.unit;
        newRow.querySelector('.item-sgst').value = item.sgst;
        newRow.querySelector('.item-cgst').value = item.cgst;
        newRow.querySelector('.item-disc').value = item.discount;
        newRow.querySelector('.disc-type-select').value = item.discountType;
        [newRow.querySelector('.item-desc'), newRow.querySelector('.item-rate'), newRow.querySelector('.item-unit'),
         newRow.querySelector('.item-sgst'), newRow.querySelector('.item-cgst'), newRow.querySelector('.item-disc'),
         newRow.querySelector('.disc-type-select')].forEach(el => el.classList.add('auto-populated'));
        updateItemTotal(newRow);
        updateItemTotals();
        document.getElementById('dialogOverlay').style.display = 'none';
      });
      itemsList.appendChild(row);
    });
  } catch (error) {
    showStatus('Error searching items: ' + error.message, 'error');
  }
}

// Close dialog
function closeDialog(event, overlayId) {
  if (event && event.target.id !== overlayId) return;
  document.getElementById(overlayId).style.display = 'none';
}

// Apply custom dialog size
function applyCustomSize(dialogId, widthInputId, heightInputId) {
  const dialog = document.getElementById(dialogId);
  const width = parseInt(document.getElementById(widthInputId).value);
  const height = parseInt(document.getElementById(heightInputId).value);
  if (width >= 300 && width <= 1200 && height >= 200 && height <= 800) {
    dialog.style.width = `${width}px`;
    dialog.style.height = `${height}px`;
  } else {
    showStatus('Width must be between 300-1200px and height between 200-800px.', 'error');
  }
}

// Quick resize dialog
function quickResize(width, height, dialogId, widthInputId, heightInputId) {
  document.getElementById(dialogId).style.width = `${width}px`;
  document.getElementById(dialogId).style.height = `${height}px`;
  document.getElementById(widthInputId).value = width;
  document.getElementById(heightInputId).value = height;
}

// Backup all data
async function backupData() {
  try {
    const data = {
      inventory: await db.inventory.toArray(),
      customers: await db.customers.toArray(),
      invoices: await db.invoices.toArray()
    };
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `invoice_backup_${new Date().toISOString().split('T')[0]}.json`;
    a.click();
    URL.revokeObjectURL(url);
    showStatus('Backup created successfully!', 'success', 'backupStatusMessage');
  } catch (error) {
    showStatus('Error creating backup: ' + error.message, 'error', 'backupStatusMessage');
  }
}

// Restore all data
async function restoreData() {
  try {
    const fileInput = document.getElementById('restoreFileInput');
    const file = fileInput.files[0];
    if (!file) {
      showStatus('Please select a backup file.', 'error', 'backupStatusMessage');
      return;
    }
    const text = await file.text();
    const data = JSON.parse(text);

    await db.inventory.clear();
    await db.customers.clear();
    await db.invoices.clear();
    if (data.inventory) await db.inventory.bulkPut(data.inventory);
    if (data.customers) await db.customers.bulkPut(data.customers);
    if (data.invoices) await db.invoices.bulkPut(data.invoices);

    await loadDataFromIndexedDB();
    loadStockTable();
    loadCustomerTable();
    updateDashboard();
    showStatus('Data restored successfully!', 'success', 'backupStatusMessage');
    fileInput.value = '';
  } catch (error) {
    showStatus('Error restoring data: ' + error.message, 'error', 'backupStatusMessage');
  }
}

// Backup stock data
async function backupStockData() {
  try {
    const data = await db.inventory.toArray();
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `stock_backup_${new Date().toISOString().split('T')[0]}.json`;
    a.click();
    URL.revokeObjectURL(url);
    showStatus('Stock backup created successfully!', 'success', 'backupStatusMessage');
  } catch (error) {
    showStatus('Error creating stock backup: ' + error.message, 'error', 'backupStatusMessage');
  }
}

// Restore stock data
async function restoreStockData() {
  try {
    const fileInput = document.getElementById('restoreStockFileInput');
    const file = fileInput.files[0];
    if (!file) {
      showStatus('Please select a stock backup file.', 'error', 'backupStatusMessage');
      return;
    }
    const text = await file.text();
    const data = JSON.parse(text);

    await db.inventory.clear();
    await db.inventory.bulkPut(data);
    inventory = await db.inventory.toArray();
    loadStockTable();
    showStatus('Stock data restored successfully!', 'success', 'backupStatusMessage');
    fileInput.value = '';
  } catch (error) {
    showStatus('Error restoring stock data: ' + error.message, 'error', 'backupStatusMessage');
  }
}

// Backup customer data
async function backupCustomerData() {
  try {
    const data = await db.customers.toArray();
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `customer_backup_${new Date().toISOString().split('T')[0]}.json`;
    a.click();
    URL.revokeObjectURL(url);
    showStatus('Customer backup created successfully!', 'success', 'backupStatusMessage');
  } catch (error) {
    showStatus('Error creating customer backup: ' + error.message, 'error', 'backupStatusMessage');
  }
}

// Restore customer data
async function restoreCustomerData() {
  try {
    const fileInput = document.getElementById('restoreCustomerFileInput');
    const file = fileInput.files[0];
    if (!file) {
      showStatus('Please select a customer backup file.', 'error', 'backupStatusMessage');
      return;
    }
    const text = await file.text();
    const data = JSON.parse(text);

    await db.customers.clear();
    await db.customers.bulkPut(data);
    customerDatabase = await db.customers.toArray();
    loadCustomerTable();
    showStatus('Customer data restored successfully!', 'success', 'backupStatusMessage');
    fileInput.value = '';
  } catch (error) {
    showStatus('Error restoring customer data: ' + error.message, 'error', 'backupStatusMessage');
  }
}

// Export invoices to CSV
function exportInvoicesToCSV() {
  if (invoices.length === 0) {
    showStatus('No invoices to export.', 'error');
    return;
  }

  let csv = 'Invoice Number,Invoice Date,Due Date,Client Name,Client Contact,Client Email,Client Address,Item Code,Item Description,Item Unit,Item Quantity,Item Rate,Item Discount Type,Item Discount,Item SGST,Item CGST,Item Total,Invoice Subtotal,Invoice Total Discount,Invoice Total SGST,Invoice Total CGST,Invoice Grand Total\n';
  
  invoices.forEach(invoice => {
    invoice.items.forEach(item => {
      csv += `"${invoice.invoiceNumber}","${invoice.invoiceDate}","${invoice.dueDate}","${invoice.clientName.replace(/"/g, '""')}","${invoice.clientContact.replace(/"/g, '""')}","${invoice.clientEmail.replace(/"/g, '""')}","${invoice.clientAddress.replace(/"/g, '""')}","${item.code.replace(/"/g, '""')}","${item.description.replace(/"/g, '""')}","${item.unit}","${item.quantity}","${item.rate.toFixed(2)}","${item.discountType}","${item.discount.toFixed(2)}","${item.sgst.toFixed(2)}","${item.cgst.toFixed(2)}","${item.total.toFixed(2)}","${invoice.subtotal.toFixed(2)}","${invoice.totalDiscount.toFixed(2)}","${invoice.totalSGST.toFixed(2)}","${invoice.totalCGST.toFixed(2)}","${invoice.grandTotal.toFixed(2)}"\n`;
    });
  });

  const blob = new Blob([csv], { type: 'text/csv' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `invoices_${new Date().toISOString().slice(0, 10)}.csv`;
  a.click();
  URL.revokeObjectURL(url);
  showStatus('Invoices exported to CSV successfully!', 'success');
}
// Generate WhatsApp message
function generateWhatsAppMessage() {
  const whatsappNumber = document.getElementById('whatsappNumber').value;
  const maxDescLength = parseInt(document.getElementById('whatsappDescLength').value) || 20;
  const gstEnabled = document.getElementById('gstEnabled').checked;
  const companyName = document.getElementById('companyName').value || 'Your Company Name';
  const invoiceNumber = document.getElementById('invoiceNumber').value;
  const clientName = document.getElementById('clientName').value;
  const invoiceDate = document.getElementById('invoiceDate').value;
  let message = `Invoice from *${companyName}*\n`;
  message += `Invoice #: ${invoiceNumber}\n`;
  message += `Date: ${invoiceDate}\n`;
  message += `To: ${clientName}\n\n`;
  message += `Items:\n`;

  let grandTotal = 0;
  let totalDiscount = 0;

  document.querySelectorAll('.item-row').forEach(row => {
    const desc = row.querySelector('.item-desc').value;
    const qty = parseFloat(row.querySelector('.item-qty').value) || 0;
    const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
    const discType = row.querySelector('.disc-type-select').value;
    const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
    const sgst = parseFloat(row.querySelector('.item-sgst').value) || 0;
    const cgst = parseFloat(row.querySelector('.item-cgst').value) || 0;

    const subtotalAmount = qty * rate;
    const discAmount = discType === 'percent' ? subtotalAmount * (disc / 100) : disc;
    const afterDisc = subtotalAmount - discAmount;
    const sgstAmount = afterDisc * (sgst / 100);
    const cgstAmount = afterDisc * (cgst / 100);
    const lineTotal = afterDisc + sgstAmount + cgstAmount;

    totalDiscount += discAmount;

    const shortDesc = desc.length > maxDescLength ? desc.substring(0, maxDescLength) + '...' : desc;
    message += `- ${shortDesc} (Qty: ${qty}, Rate: ₹${rate.toFixed(2)})`;
    message += `, Discount: ${discType === 'percent' ? `${disc}%` : `₹${disc.toFixed(2)}`}`; // Add discount
    if (gstEnabled) {
      message += `, SGST: ${sgst}%, CGST: ${cgst}%`;
    }
    message += ` = ₹${lineTotal.toFixed(2)}\n`;
    grandTotal += lineTotal;
  });

  message += `\nTotal Discount: ₹${totalDiscount.toFixed(2)}\n`; // Add total discount
  message += `Grand Total: ₹${grandTotal.toFixed(2)}\n`;
  message += `Thank you for your business!`;

  const preview = document.getElementById('whatsappPreview');
  preview.textContent = message;
  preview.style.display = 'block';
}
// Send WhatsApp message
function sendWhatsApp() {
  const whatsappNumber = document.getElementById('whatsappNumber').value;
  const preview = document.getElementById('whatsappPreview').textContent;
  if (!whatsappNumber) {
    showStatus('Please enter a WhatsApp number.', 'error');
    return;
  }
  const encodedMessage = encodeURIComponent(preview);
  const url = `https://wa.me/${whatsappNumber.replace('+', '')}?text=${encodedMessage}`;
  window.open(url, '_blank');
}

// Logo handling
let isDragging = false, isResizing = false, currentHandle = null;
let startX, startY, startWidth, startHeight, startLeft, startTop;

function setupLogoHandling() {
  const logoUpload = document.getElementById('logoUpload');
  const logoWidthInput = document.getElementById('logoWidth');
  const logoHeightInput = document.getElementById('logoHeight');
  const lockAspectRatio = document.getElementById('lockAspectRatio');

  logoUpload.addEventListener('change', (e) => {
    const file = e.target.files[0];
    if (file) {
      const reader = new FileReader();
      reader.onload = (event) => {
        const img = new Image();
        img.src = event.target.result;
        img.onload = () => {
          const logoContainer = document.createElement('div');
          logoContainer.className = 'invoice-logo';
          logoContainer.style.width = '100px';
          logoContainer.style.height = '100px';
          logoContainer.style.left = '20px';
          logoContainer.style.top = '20px';
          logoContainer.innerHTML = `
            <img src="${img.src}" alt="Logo">
            <div class="resize-handle top-left"></div>
            <div class="resize-handle top-right"></div>
            <div class="resize-handle bottom-left"></div>
            <div class="resize-handle bottom-right"></div>
          `;
          document.querySelector('.invoice-box').prepend(logoContainer);
          logoWidthInput.value = 100;
          logoHeightInput.value = 100;
          setupLogoInteractions(logoContainer, img);
        };
      };
      reader.readAsDataURL(file);
    }
  });

  logoWidthInput.addEventListener('input', () => {
    const logo = document.querySelector('.invoice-logo');
    if (logo) {
      let width = parseInt(logoWidthInput.value) || 100;
      if (lockAspectRatio.checked) {
        const img = logo.querySelector('img');
        const aspectRatio = img.naturalWidth / img.naturalHeight;
        logoHeightInput.value = Math.round(width / aspectRatio);
        logo.style.height = `${logoHeightInput.value}px`;
      }
      logo.style.width = `${width}px`;
    }
  });

  logoHeightInput.addEventListener('input', () => {
    const logo = document.querySelector('.invoice-logo');
    if (logo) {
      let height = parseInt(logoHeightInput.value) || 100;
      if (lockAspectRatio.checked) {
        const img = logo.querySelector('img');
        const aspectRatio = img.naturalWidth / img.naturalHeight;
        logoWidthInput.value = Math.round(height * aspectRatio);
        logo.style.width = `${logoWidthInput.value}px`;
      }
      logo.style.height = `${height}px`;
    }
  });
}

function setupLogoInteractions(logoContainer, img) {
  const logoWidthInput = document.getElementById('logoWidth');
  const logoHeightInput = document.getElementById('logoHeight');
  const lockAspectRatio = document.getElementById('lockAspectRatio');

  logoContainer.addEventListener('mousedown', (e) => {
    if (e.target.classList.contains('resize-handle')) {
      isResizing = true;
      currentHandle = e.target.className.split(' ')[1];
      startX = e.clientX;
      startY = e.clientY;
      startWidth = parseFloat(logoContainer.style.width);
      startHeight = parseFloat(logoContainer.style.height);
      startLeft = parseFloat(logoContainer.style.left);
      startTop = parseFloat(logoContainer.style.top);
    } else {
      isDragging = true;
      startX = e.clientX - parseFloat(logoContainer.style.left);
      startY = e.clientY - parseFloat(logoContainer.style.top);
      logoContainer.classList.add('active');
    }
    e.preventDefault();
  });

  document.addEventListener('mousemove', (e) => {
    if (isDragging) {
      logoContainer.style.left = `${e.clientX - startX}px`;
      logoContainer.style.top = `${e.clientY - startY}px`;
    } else if (isResizing) {
      let newWidth, newHeight, newLeft = startLeft, newTop = startTop;
      const deltaX = e.clientX - startX;
      const deltaY = e.clientY - startY;
      const aspectRatio = img.naturalWidth / img.naturalHeight;

      if (currentHandle.includes('top-left')) {
        newWidth = startWidth - deltaX;
        newHeight = lockAspectRatio.checked ? newWidth / aspectRatio : startHeight - deltaY;
        newLeft = startLeft + deltaX;
        newTop = lockAspectRatio.checked ? startTop + deltaX / aspectRatio : startTop + deltaY;
      } else if (currentHandle.includes('top-right')) {
        newWidth = startWidth + deltaX;
        newHeight = lockAspectRatio.checked ? newWidth / aspectRatio : startHeight - deltaY;
        newTop = lockAspectRatio.checked ? startTop + deltaX / aspectRatio : startTop + deltaY;
      } else if (currentHandle.includes('bottom-left')) {
        newWidth = startWidth - deltaX;
        newHeight = lockAspectRatio.checked ? newWidth / aspectRatio : startHeight + deltaY;
        newLeft = startLeft + deltaX;
      } else if (currentHandle.includes('bottom-right')) {
        newWidth = startWidth + deltaX;
        newHeight = lockAspectRatio.checked ? newWidth / aspectRatio : startHeight + deltaY;
      }

      if (newWidth >= 20 && newWidth <= 300 && newHeight >= 20 && newHeight <= 300) {
        logoContainer.style.width = `${newWidth}px`;
        logoContainer.style.height = `${newHeight}px`;
        logoContainer.style.left = `${newLeft}px`;
        logoContainer.style.top = `${newTop}px`;
        logoWidthInput.value = Math.round(newWidth);
        logoHeightInput.value = Math.round(newHeight);
      }
    }
  });

  document.addEventListener('mouseup', () => {
    isDragging = false;
    isResizing = false;
    currentHandle = null;
  });

  logoContainer.addEventListener('dblclick', () => {
    logoContainer.classList.toggle('active');
  });

  logoContainer.addEventListener('touchstart', (e) => {
    const touch = e.touches[0];
    if (e.target.classList.contains('resize-handle')) {
      isResizing = true;
      currentHandle = e.target.className.split(' ')[1];
      startX = touch.clientX;
      startY = touch.clientY;
      startWidth = parseFloat(logoContainer.style.width);
      startHeight = parseFloat(logoContainer.style.height);
      startLeft = parseFloat(logoContainer.style.left);
      startTop = parseFloat(logoContainer.style.top);
    } else {
      isDragging = true;
      startX = touch.clientX - parseFloat(logoContainer.style.left);
      startY = touch.clientY - parseFloat(logoContainer.style.top);
      logoContainer.classList.add('active');
    }
    e.preventDefault();
  });

  document.addEventListener('touchmove', (e) => {
    const touch = e.touches[0];
    if (isDragging) {
      logoContainer.style.left = `${touch.clientX - startX}px`;
      logoContainer.style.top = `${touch.clientY - startY}px`;
    } else if (isResizing) {
      let newWidth, newHeight, newLeft = startLeft, newTop = startTop;
      const deltaX = touch.clientX - startX;
      const deltaY = touch.clientY - startY;
      const aspectRatio = img.naturalWidth / img.naturalHeight;

      if (currentHandle.includes('top-left')) {
        newWidth = startWidth - deltaX;
        newHeight = lockAspectRatio.checked ? newWidth / aspectRatio : startHeight - deltaY;
        newLeft = startLeft + deltaX;
        newTop = lockAspectRatio.checked ? startTop + deltaX / aspectRatio : startTop + deltaY;
      } else if (currentHandle.includes('top-right')) {
        newWidth = startWidth + deltaX;
        newHeight = lockAspectRatio.checked ? newWidth / aspectRatio : startHeight - deltaY;
        newTop = lockAspectRatio.checked ? startTop + deltaX / aspectRatio : startTop + deltaY;
      } else if (currentHandle.includes('bottom-left')) {
        newWidth = startWidth - deltaX;
        newHeight = lockAspectRatio.checked ? newWidth / aspectRatio : startHeight + deltaY;
        newLeft = startLeft + deltaX;
      } else if (currentHandle.includes('bottom-right')) {
        newWidth = startWidth + deltaX;
        newHeight = lockAspectRatio.checked ? newWidth / aspectRatio : startHeight + deltaY;
      }

      if (newWidth >= 20 && newWidth <= 300 && newHeight >= 20 && newHeight <= 300) {
        logoContainer.style.width = `${newWidth}px`;
        logoContainer.style.height = `${newHeight}px`;
        logoContainer.style.left = `${newLeft}px`;
        logoContainer.style.top = `${newTop}px`;
        logoWidthInput.value = Math.round(newWidth);
        logoHeightInput.value = Math.round(newHeight);
      }
    }
  });

  document.addEventListener('touchend', () => {
    isDragging = false;
    isResizing = false;
    currentHandle = null;
  });
}

function resetLogoPosition() {
  const logo = document.querySelector('.invoice-logo');
  if (logo) {
    logo.style.left = '20px';
    logo.style.top = '20px';
    logo.style.width = '100px';
    logo.style.height = '100px';
    document.getElementById('logoWidth').value = 100;
    document.getElementById('logoHeight').value = 100;
  }
}

function removeLogo() {
  const logo = document.querySelector('.invoice-logo');
  if (logo) logo.remove();
  document.getElementById('logoUpload').value = '';
  document.getElementById('logoWidth').value = '';
  document.getElementById('logoHeight').value = '';
}

// Update dashboard
async function updateDashboard() {
  try {
    const dateRange = document.getElementById('dateRangeFilter').value;
    let fromDate, toDate = new Date();

    if (dateRange === 'custom') {
      fromDate = new Date(document.getElementById('fromDate').value);
      toDate = new Date(document.getElementById('toDate').value);
    } else {
      fromDate = new Date();
      fromDate.setDate(toDate.getDate() - parseInt(dateRange));
    }

    const filteredInvoices = invoices.filter(inv => {
      const invDate = new Date(inv.timestamp);
      return invDate >= fromDate && invDate <= toDate;
    });

    let totalRevenue = 0, totalOrders = filteredInvoices.length, totalProducts = 0, totalDiscount = 0;
    const productSales = {};

    filteredInvoices.forEach(invoice => {
      totalRevenue += invoice.grandTotal;
      totalDiscount += invoice.totalDiscount;
      invoice.items.forEach(item => {
        totalProducts += item.quantity;
        productSales[item.code] = (productSales[item.code] || 0) + item.quantity;
      });
    });

    const uniqueCustomers = new Set(filteredInvoices.map(inv => inv.clientContact)).size;

    document.getElementById('totalRevenue').textContent = `₹${totalRevenue.toFixed(2)}`;
    document.getElementById('totalOrders').textContent = totalOrders;
    document.getElementById('totalCustomers').textContent = uniqueCustomers;
    document.getElementById('totalProducts').textContent = totalProducts;
    document.getElementById('totalDiscount').textContent = `₹${totalDiscount.toFixed(2)}`;

    const topProductsList = document.getElementById('topProductsList');
    topProductsList.innerHTML = '';
    const sortedProducts = Object.entries(productSales)
      .sort((a, b) => b[1] - a[1])
      .slice(0, 5);
    sortedProducts.forEach(([code, qty]) => {
      const item = inventory.find(i => i.code === code);
      const div = document.createElement('div');
      div.textContent = `${item ? item.description : code}: ${qty} units`;
      div.addEventListener('click', () => {
        document.getElementById('stockCode').value = code;
        document.getElementById('nav-btn-stock').click();
      });
      topProductsList.appendChild(div);
    });

    const recentOrdersList = document.getElementById('recentOrdersList');
    recentOrdersList.innerHTML = '';
    filteredInvoices.slice(-5).reverse().forEach(invoice => {
      const div = document.createElement('div');
      div.textContent = `${invoice.invoiceNumber} - ${invoice.clientName}: ₹${invoice.grandTotal.toFixed(2)}`;
      div.addEventListener('click', () => {
        document.getElementById('historyContact').value = invoice.clientContact;
        document.getElementById('nav-btn-customer-history').click();
        loadCustomerHistory();
      });
      recentOrdersList.appendChild(div);
    });
  } catch (error) {
    showStatus('Error updating dashboard: ' + error.message, 'error');
  }
}

// Toggle custom date range
function toggleCustomDateRange() {
  const dateRange = document.getElementById('dateRangeFilter').value;
  const customDateRange = document.getElementById('customDateRange');
  customDateRange.classList.toggle('hidden', dateRange !== 'custom');
  updateDashboard();
}

// Clear invoices
async function clearInvoices() {
  if (confirm('Are you sure you want to clear all invoices? This action cannot be undone.')) {
    try {
      await db.invoices.clear();
      invoices = [];
      updateDashboard();
      showStatus('All invoices cleared successfully!', 'success');
    } catch (error) {
      showStatus('Error clearing invoices: ' + error.message, 'error');
    }
  }
}

// Initialize application
async function init() {
  try {
    await migrateLocalStorageToIndexedDB();
    await loadDataFromIndexedDB();
    setupNavigation();
    setupClientAutocomplete();
    setupHistoryContactAutocomplete();
    setupLogoHandling();
    document.querySelectorAll('.item-row').forEach(row => {
      attachInputListeners(row);
      setupItemAutocomplete(row);
    });
    document.getElementById('invoiceDate').value = new Date().toISOString().split('T')[0];
    const dueDate = new Date();
    dueDate.setDate(dueDate.getDate() + 30);
    document.getElementById('dueDate').value = dueDate.toISOString().split('T')[0];
    document.getElementById('invoiceNumber').value = await generateInvoiceNumber();
    loadStockTable();
    loadCustomerTable();
    updateDashboard();
    updateItemTotals();
  } catch (error) {
    showStatus('Error initializing application: ' + error.message, 'error');
  }
}

document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>

No comments:

Post a Comment