Tuesday, September 9, 2025

๐ŸŸขTaxlessInvoiceWithLogoCopy code Enabled

Complete Guide: Enhanced Indian Invoice System (Tax-Free)

๐Ÿ‡ฎ๐Ÿ‡ณ Enhanced Indian Invoice System

Complete Business Management Solution - Tax-Free Invoicing Made Simple

๐Ÿ“‹ System Overview

The Enhanced Indian Invoice System is a comprehensive web-based solution designed specifically for Indian businesses operating with tax-free transactions. This all-in-one platform combines invoice generation, inventory management, customer database, and sales analytics in a single, user-friendly interface.

Perfect for: Small businesses, freelancers, service providers, retailers, and any business needing professional invoicing without tax calculations.

๐Ÿ’ผ Professional Invoicing

Generate clean, professional invoices with company branding, custom logos, and detailed line items.

๐Ÿ“ฆ Inventory Management

Track stock levels, manage product information, and get alerts for low inventory.

๐Ÿ‘ฅ Customer Database

Store customer information with auto-complete features for faster invoice creation.

๐Ÿ“Š Sales Dashboard

Monitor business performance with revenue tracking, order analytics, and product insights.

✨ Key Features

๐Ÿงพ Invoice Generation Features

  • Custom Company Branding: Add your company name, address, contact details, and logo
  • Flexible Logo Positioning: Drag, resize, and position your logo anywhere on the invoice
  • Smart Item Management: Add multiple line items with HSN/SAC codes, descriptions, quantities, rates, and discounts
  • Auto-calculations: Automatic subtotal, discount, and grand total calculations
  • Multiple Export Options: Print, save as PDF, or share via WhatsApp
  • Customer Auto-complete: Quick customer selection from your database

๐Ÿ“ฆ Inventory Management Features

  • Complete Product Database: Store item codes, HSN/SAC codes, descriptions, prices, and units
  • Stock Tracking: Monitor quantity levels with low-stock alerts
  • Quick Item Selection: Browse and add items directly to invoices
  • Bulk Operations: Edit, delete, and manage multiple items efficiently
  • Stock Validation: Prevents over-selling with quantity checks

๐Ÿ“Š Analytics & Reporting Features

  • Revenue Tracking: Monitor total sales across different time periods
  • Order Analytics: Track number of orders and customer activity
  • Product Performance: Identify top-selling products and trends
  • Custom Date Ranges: Filter data for specific periods
  • Visual Dashboard: Easy-to-read cards and charts

๐Ÿ’พ Data Management Features

  • Complete Backup System: Export all data for safekeeping
  • Selective Backups: Backup individual data types (stock, customers, invoices)
  • Data Restoration: Import previously backed up data
  • Cross-platform Compatibility: Works on desktop, tablet, and mobile devices

๐Ÿš€ Getting Started

System Requirements

  • Browser: Modern web browser (Chrome, Firefox, Safari, Edge)
  • Internet: Required for initial loading and WhatsApp sharing
  • Storage: Uses browser local storage for data persistence
  • Device: Works on desktop, tablet, and mobile devices

Initial Setup Steps

  1. Load the System: Open the HTML file in your web browser
  2. Configure Company Details: Enter your company name, address, and contact information
  3. Upload Company Logo: Add your business logo and position it as needed
  4. Add Initial Inventory: Input your products/services into the stock management system
  5. Import Customer Data: Add your existing customers to the database
  6. Create Your First Invoice: Test the system with a sample invoice
Important: This system stores data locally in your browser. Regular backups are essential to prevent data loss when clearing browser data or switching devices.

๐Ÿ› ️ Try Our Invoice Creation Tool

Experience our tax-free invoice system right here! Create professional invoices with custom logos, inventory management, and easy export options.

Open Tool in New Window

๐Ÿ“– How to Use Each Feature

๐Ÿงพ Creating Your First Invoice

  1. Navigate to Invoice Generator: Click the "๐Ÿ“‹ Invoice Generator" tab in the navigation menu
  2. Set Company Information: Fill in your company name, address, and contact details in the top section
  3. Add Customer Details: Enter the customer's contact number - if they exist in your database, their information will auto-populate
  4. Set Invoice Details: The system auto-generates invoice numbers, but you can customize the date and due date
  5. Add Line Items:
    • Enter HSN/SAC code (auto-complete available from inventory)
    • Add item description
    • Set quantity and rate
    • Apply discount if needed
  6. Review Totals: The system automatically calculates subtotals, discounts, and grand total
  7. Generate Invoice: Click "Generate Invoice" to see the preview
  8. Export Options: Print, save as PDF, or share via WhatsApp

๐Ÿ“ฆ Managing Your Inventory

  1. Access Stock Management: Click the "๐Ÿ“ฆ Stock Management" tab
  2. Add New Items:
    • Enter unique item code
    • Add HSN/SAC code for compliance
    • Write detailed description
    • Set price and unit of measurement
    • Enter initial quantity
  3. Edit Existing Items: Click the "Edit" button on any item to modify details
  4. Monitor Stock Levels: Items with low stock (≤10 units) appear in red
  5. Delete Items: Use the "Delete" button to remove items (with confirmation)

๐Ÿ‘ฅ Managing Customers

  1. Open Customer Database: Click the "๐Ÿ‘ฅ Customer Database" tab
  2. Add New Customers:
    • Enter contact number (primary identifier)
    • Add customer name
    • Include email address
    • Add full address
  3. Edit Customer Info: Click "Edit" to modify existing customer details
  4. Auto-complete Benefits: When creating invoices, typing a contact number will auto-fill customer details

๐Ÿ“Š Using the Sales Dashboard

  1. Access Dashboard: Click the "๐Ÿ“Š Sales Dashboard" tab
  2. Select Date Range: Choose from preset ranges (7, 30, 90, 365 days) or set custom dates
  3. View Key Metrics:
    • Total Revenue
    • Number of Orders
    • Active Customers
    • Products Sold
  4. Analyze Performance: Review top-selling products and recent orders
  5. Refresh Data: Click "Refresh" to update with latest information

⚡ Advanced Features

๐Ÿ–ผ️ Logo Management

Interactive Logo Positioning:
  • Tap/click logo to show resize handles
  • Drag logo to reposition
  • Use corner handles to resize
  • Lock aspect ratio to maintain proportions
  • Double-tap to hide handles

๐Ÿ“ฑ WhatsApp Integration

  1. Generate Message: Enter WhatsApp number and customize description length
  2. Preview Content: Click "Preview WhatsApp Message" to see formatted text
  3. Send Message: Click "Send via WhatsApp" to open WhatsApp with pre-filled message
  4. Share PDF: Use "Share PDF via WhatsApp" for direct PDF sharing (on supported devices)

๐Ÿ’พ Backup & Restore System

Complete System Backup

  • Full Backup: Exports all data (inventory, customers, invoices) in one file
  • Automatic Naming: Files named with current date for easy organization
  • JSON Format: Human-readable format that can be viewed and edited

Selective Backups

  • Stock Only: Export just inventory data for sharing with other systems
  • Customer Data: Backup customer database independently
  • Invoice History: Export all past invoices for record-keeping
Best Practices:
  • Create regular backups (weekly recommended)
  • Store backup files in multiple locations (cloud storage, USB drive)
  • Test restore functionality periodically
  • Keep backups when updating or changing devices

๐Ÿ” Smart Search & Autocomplete

  • Item Search: Search inventory by code, name, or description
  • Customer Lookup: Find customers by contact number or name
  • Instant Suggestions: Real-time suggestions as you type
  • Quick Selection: Click suggestions to auto-fill forms

๐Ÿ“ฑ Mobile Optimization

  • Responsive Design: Adapts to different screen sizes
  • Touch-Friendly: Large buttons and touch targets
  • Optimized Tables: Horizontal scrolling for data tables
  • Mobile Gestures: Supports swipe and tap interactions

๐Ÿ’ก Tips for Maximum Efficiency

๐Ÿš€ Speed Up Invoice Creation

  • Maintain updated customer database
  • Use item codes for quick product selection
  • Set up common products in inventory
  • Use "Browse Items" for visual selection

๐Ÿ“Š Better Data Management

  • Regular backups prevent data loss
  • Use consistent naming conventions
  • Keep inventory updated with current prices
  • Clean up old data periodically

๐Ÿ”ง Customization Options

  • Personalize company information
  • Position logo strategically
  • Customize invoice numbering
  • Set appropriate due dates

๐Ÿ“ˆ Business Growth

  • Monitor dashboard regularly
  • Track top-selling products
  • Identify customer patterns
  • Analyze revenue trends

❓ Troubleshooting & Support

Common Issues & Solutions

Data Not Saving:
  • Ensure browser allows local storage
  • Check if running in private/incognito mode
  • Clear browser cache and reload
  • Try a different browser
PDF Generation Issues:
  • Allow pop-ups in browser settings
  • Ensure stable internet connection
  • Try reducing logo size if PDF fails
  • Use browser's built-in print-to-PDF as alternative
WhatsApp Sharing Problems:
  • Ensure WhatsApp is installed on device
  • Check phone number format (include country code)
  • Use alternative: copy message text manually
  • For PDF sharing, check device compatibility

Performance Optimization

  • Regular Maintenance: Clear old invoices periodically using dashboard
  • Image Optimization: Use compressed logos (under 5MB)
  • Data Management: Remove unused inventory items and customers
  • Browser Performance: Close unnecessary tabs and restart browser occasionally

๐ŸŽ‰ Ready to Get Started?

Transform your business with professional invoicing and comprehensive management tools.

This system is completely self-contained and works offline after initial loading. Perfect for businesses of all sizes looking for reliable, professional invoicing solutions.

Multiple Code Blocks

Here is the code

Click or Tap Here to Copy Code

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=2.0, user-scalable=yes">
  <title>Invoice Generator (Tax-Free)</title>
  <!-- Include html2canvas and jsPDF libraries -->
  <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>
  <style>
    * { box-sizing: border-box; }
    body { 
      font-family: Arial, 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 { 
      width: 100%; 
      padding: 8px; 
      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: 8px; 
      border: 1px solid #ddd; 
      text-align: left; 
      font-size: 14px;
    }
    .items-table th { 
      background: #e9ecef; 
      font-weight: bold; 
      color: #333;
    }
    .items-table input { 
      width: 100%; 
      padding: 6px; 
      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 .disc-input, .items-table .total-input { 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: 6px 10px; 
      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 { 
      background: #28a745; 
      color: white; 
      border: none; 
      padding: 10px 20px; 
      border-radius: 5px; 
      cursor: pointer; 
      margin-right: 10px; 
      margin-top: 10px;
    }
    .add-item-btn:hover, .add-stock-btn:hover, .add-customer-btn:hover, .backup-btn:hover, .restore-btn:hover, .save-btn:hover { background: #218838; }
    .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; }

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

    .edit-btn, .delete-btn {
      padding: 5px 10px;
      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; }

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

    .quantity-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: 8px 16px; 
      background: #007bff; 
      color: #fff; 
      border: none; 
      cursor: pointer; 
      border-radius: 5px; 
    }
    .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 { 
        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 { 
        font-size: 12px; 
        padding: 6px; 
      }
      .items-table input { 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;
    }
    .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 (Tax-Free)</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="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>
      <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-004">
        </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>Qty</th>
              <th>Rate (₹)</th>
              <th>Disc %</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><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><input type="number" class="item-disc disc-input" value="0" step="0.01" min="0" max="100"></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>
        <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-004</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>Qty</th>
              <th>Rate</th>
              <th>Disc %</th>
              <th>Total</th>
            </tr>
          </thead>
          <tbody id="previewItems">
            <tr>
              <td></td><td>Sample Item</td><td>1</td><td>₹0.00</td><td>0</td><td>₹0.00</td>
            </tr>
          </tbody>
        </table>
        <p class="total">Grand Total: <span id="previewTotal">₹0.00</span></p>
        <p style="text-align: right; font-size: 12px; color: #666;">Note: All items are tax-free.</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>
      <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>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>
  <!-- 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 Data</label>
          <button class="backup-btn" onclick="backupData()">Backup Data to JSON</button>
        </div>
        <div class="form-group">
          <label>Restore Data</label>
          <input type="file" id="restoreFileInput" accept=".json">
          <button class="restore-btn" onclick="restoreData()">Restore Data</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>
          </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>
const inventory = [
  { code: 'ITM001', hsn: '8471', name: 'Wireless Mouse', description: 'Ergonomic wireless mouse with USB receiver', price: 25.99, unit: 'PCS', quantity: 50 },
  { code: 'ITM002', hsn: '8471', name: 'Keyboard', description: 'Mechanical gaming keyboard with RGB lighting', price: 89.99, unit: 'PCS', quantity: 30 },
  { code: 'ITM003', hsn: '9403', name: 'Monitor Stand', description: 'Adjustable aluminum monitor stand', price: 45.00, unit: 'PCS', quantity: 20 },
  { code: 'ITM004', hsn: '8544', name: 'USB Cable', description: '6ft USB-C to USB-A cable', price: 12.50, unit: 'PCS', quantity: 100 },
  { code: 'ITM005', hsn: '8525', name: 'Webcam', description: '1080p HD webcam with built-in microphone', price: 67.99, unit: 'PCS', quantity: 15 },
  { code: 'ITM006', hsn: '9405', name: 'Desk Lamp', description: 'LED desk lamp with touch control', price: 34.99, unit: 'PCS', quantity: 25 },
  { code: 'ITM007', hsn: '8504', name: 'Phone Charger', description: 'Fast charging wireless phone charger', price: 28.99, unit: 'PCS', quantity: 40 },
  { code: 'ITM008', hsn: '8518', name: 'Speakers', description: 'Bluetooth desktop speakers', price: 55.00, unit: 'PCS', quantity: 10 },
  { code: 'ITM009', hsn: '4016', name: 'Mouse Pad', description: 'Extra large gaming mouse pad', price: 19.99, unit: 'PCS', quantity: 60 },
  { code: 'ITM010', hsn: '8518', name: 'Headphones', description: 'Noise-canceling over-ear headphones', price: 149.99, unit: 'PCS', quantity: 5 },
  { code: 'ITM011', hsn: '8473', name: 'External Drive', description: '1TB portable external hard drive', price: 79.99, unit: 'PCS', quantity: 12 },
  { code: 'ITM012', hsn: '3926', name: 'Cable Organizer', description: 'Desktop cable management solution', price: 15.99, unit: 'PCS', quantity: 80 }
];

// Initialize customerDatabase with sample data
let customerDatabase = [
  { 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" }
];

let filteredInventory = [...inventory];
let isDragging = false;
let dragOffset = { x: 0, y: 0 };
let activeDialog = null;
let editingCustomerIndex = null;
let invoices = JSON.parse(localStorage.getItem('invoices')) || [];

// Logo variables
let logoElement = null;
let isLogoDragging = false;
let isResizing = false;
let resizeHandle = null;
let logoStartPos = { x: 0, y: 0 };
let logoStartSize = { width: 0, height: 0 };
let originalAspectRatio = 1;
let lastTapTime = 0;

// 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
function generateInvoiceNumber() {
  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')}`;
}

// Core Functions
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><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><input type="number" class="item-disc disc-input" value="0" step="0.01" min="0" max="100"></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); // This was missing!
  updateItemTotals();
}

function removeItem(button) {
  const itemsList = document.getElementById('itemsList').querySelector('tbody');
  if (itemsList.children.length > 1) {
    button.closest('tr').remove();
    updateItemTotals();
  } else {
    alert('You must have at least one item.');
  }
}

function attachInputListeners(row) {
  row.querySelectorAll('.item-qty, .item-rate, .item-disc').forEach(input => {
    input.addEventListener('input', () => {
      const code = row.querySelector('.item-code').value;
      const qty = parseInt(row.querySelector('.item-qty').value) || 0;
      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');
        }
      }
      updateItemTotal(row);
      updateItemTotals();
    });
  });
}

function updateItemTotal(row) {
  const qty = parseFloat(row.querySelector('.item-qty').value) || 0;
  const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
  const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
  const subtotal = qty * rate;
  const discAmount = subtotal * (disc / 100);
  const lineTotal = subtotal - discAmount;
  row.querySelector('.item-total').value = lineTotal.toFixed(2);
}

function updateItemTotals() {
  const rows = document.querySelectorAll('.item-row');
  let subtotal = 0;
  let totalDiscount = 0;
  let 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 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 (!canGenerate) {
    return;
  }

  rows.forEach(row => {
    const qty = parseFloat(row.querySelector('.item-qty').value) || 0;
    const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
    const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
    const subtotalAmount = qty * rate;
    const discAmount = subtotalAmount * (disc / 100);
    const lineTotal = subtotalAmount - discAmount;

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

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

function saveInvoice() {
  const invoice = {
    invoiceNumber: document.getElementById('invoiceNumber').value || 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,
    grandTotal: 0,
    timestamp: new Date().toISOString()
  };

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

  rows.forEach(row => {
    const code = row.querySelector('.item-code').value;
    const qty = parseInt(row.querySelector('.item-qty').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 (!canSave) {
    return;
  }

  rows.forEach(row => {
    const code = row.querySelector('.item-code').value;
    const qty = parseInt(row.querySelector('.item-qty').value) || 0;
    const item = inventory.find(i => i.code === code);
    if (item) {
      item.quantity -= qty;
    }
  });

  rows.forEach(row => {
    const qty = parseFloat(row.querySelector('.item-qty').value) || 0;
    const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
    const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
    const subtotalAmount = qty * rate;
    const discAmount = subtotalAmount * (disc / 100);
    const lineTotal = subtotalAmount - discAmount;

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

    invoice.subtotal += subtotalAmount;
    invoice.totalDiscount += discAmount;
    invoice.grandTotal += lineTotal;
  });

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

  invoices.push(invoice);
  localStorage.setItem('invoices', JSON.stringify(invoices));
  showStatus('Invoice saved successfully!', 'success');
  updateDashboard();

  document.getElementById('invoiceNumber').value = generateInvoiceNumber();
  document.getElementById('clientContact').value = '';
  document.getElementById('clientName').value = '';
  document.getElementById('clientEmail').value = '';
  document.getElementById('clientAddress').value = '';
  document.getElementById('itemsList').querySelector('tbody').innerHTML = `
    <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><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><input type="number" class="item-disc disc-input" value="0" step="0.01" min="0" max="100"></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>
  `;
  document.querySelectorAll('.item-row').forEach(row => {
    attachInputListeners(row);
    setupItemAutocomplete(row);
  });
  loadStockTable();
}

function formatDate(dateString) {
  if (!dateString) return '';
  const date = new Date(dateString);
  const options = { day: 'numeric', month: 'long', year: 'numeric' };
  return date.toLocaleDateString('en-GB', options);
}

function generateInvoice(totalsRow = '') {
  document.getElementById('previewCompanyName').textContent = sanitizeInput(document.getElementById('companyName').value);
  document.getElementById('previewCompanyAddress').textContent = sanitizeInput(document.getElementById('companyAddress').value);
  document.getElementById('previewCompanyContact').textContent = sanitizeInput(document.getElementById('companyContact').value.replace('\n', ' | '));
  document.getElementById('previewClientName').textContent = sanitizeInput(document.getElementById('clientName').value) || 'Customer Name';
  document.getElementById('previewClientContact').textContent = sanitizeInput(document.getElementById('clientContact').value) || 'Customer Contact';
  document.getElementById('previewClientEmail').textContent = sanitizeInput(document.getElementById('clientEmail').value) || 'Customer Email';
  document.getElementById('previewClientAddress').textContent = sanitizeInput(document.getElementById('clientAddress').value) || 'Customer Address';
  document.getElementById('previewInvoiceNumber').textContent = document.getElementById('invoiceNumber').value;
  document.getElementById('previewInvoiceDate').textContent = formatDate(document.getElementById('invoiceDate').value);
  document.getElementById('previewDueDate').textContent = formatDate(document.getElementById('dueDate').value);

  const previewItems = document.getElementById('previewItems');
  previewItems.innerHTML = '';
  const itemRows = document.querySelectorAll('.item-row');

  itemRows.forEach(row => {
    const code = sanitizeInput(row.querySelector('.item-code').value) || '';
    const desc = sanitizeInput(row.querySelector('.item-desc').value) || 'Item';
    const qty = parseFloat(row.querySelector('.item-qty').value) || 0;
    const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
    const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
    const subtotal = qty * rate;
    const discAmount = subtotal * (disc / 100);
    const lineTotal = subtotal - discAmount;

    const tr = document.createElement('tr');
    tr.innerHTML = `
      <td>${code}</td>
      <td>${desc}</td>
      <td>${qty}</td>
      <td>₹${rate.toFixed(2)}</td>
      <td>${disc}</td>
      <td>₹${lineTotal.toFixed(2)}</td>
    `;
    previewItems.appendChild(tr);
  });

  previewItems.insertAdjacentHTML('beforeend', totalsRow);
  document.getElementById('previewTotal').textContent = '₹' + (parseFloat(document.querySelector('#previewItems tr:last-child td:last-child').textContent.replace('₹', '')) || 0).toFixed(2);
}

// Logo Functions
function createLogoElement(imageSrc, width = 100, height = 100) {
  const invoiceBox = document.querySelector('.invoice-box');
  if (logoElement) {
    logoElement.remove();
  }
  logoElement = document.createElement('div');
  logoElement.className = 'invoice-logo';
  logoElement.style.width = `${width}px`;
  logoElement.style.height = `${height}px`;
  logoElement.style.top = '20px';
  logoElement.style.left = '20px';
  logoElement.innerHTML = `
    <img src="${imageSrc}" 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>
  `;
  invoiceBox.appendChild(logoElement);
  document.getElementById('logoWidth').value = width;
  document.getElementById('logoHeight').value = height;
  setupLogoDragging();
  setupLogoResizing();
  setupLogoDoubleTap();
}

function setupLogoUpload() {
  const logoUpload = document.getElementById('logoUpload');
  logoUpload.addEventListener('change', (event) => {
    const file = event.target.files[0];
    if (file && file.type.startsWith('image/')) {
      if (file.size > 5 * 1024 * 1024) {
        showStatus('Logo file size must be less than 5MB.', 'error');
        logoUpload.value = '';
        return;
      }
      const reader = new FileReader();
      reader.onload = (e) => {
        const img = new Image();
        img.onload = () => {
          originalAspectRatio = img.width / img.height;
          createLogoElement(e.target.result);
        };
        img.src = e.target.result;
      };
      reader.readAsDataURL(file);
    } else {
      showStatus('Please upload a valid image file.', 'error');
      logoUpload.value = '';
    }
  });
}

function setupLogoDragging() {
  if (!logoElement) return;
  const invoiceBox = document.querySelector('.invoice-box');
  const moveLogo = (e) => {
    if (!isLogoDragging || !logoElement) return;
    e.preventDefault();
    let clientX, clientY;
    if (e.type.includes('touch')) {
      clientX = e.touches[0].clientX;
      clientY = e.touches[0].clientY;
    } else {
      clientX = e.clientX;
      clientY = e.clientY;
    }
    const rect = invoiceBox.getBoundingClientRect();
    let newX = clientX - dragOffset.x - rect.left;
    let newY = clientY - dragOffset.y - rect.top;
    newX = Math.max(0, Math.min(newX, rect.width - logoElement.offsetWidth));
    newY = Math.max(0, Math.min(newY, rect.height - logoElement.offsetHeight));
    logoElement.style.left = `${newX}px`;
    logoElement.style.top = `${newY}px`;
  };
  logoElement.addEventListener('mousedown', (e) => {
    if (e.target.classList.contains('resize-handle')) return;
    isLogoDragging = true;
    const rect = logoElement.getBoundingClientRect();
    dragOffset.x = e.clientX - rect.left;
    dragOffset.y = e.clientY - rect.top;
  });
  logoElement.addEventListener('touchstart', (e) => {
    if (e.target.classList.contains('resize-handle')) return;
    e.preventDefault();
    isLogoDragging = true;
    const rect = logoElement.getBoundingClientRect();
    dragOffset.x = e.touches[0].clientX - rect.left;
    dragOffset.y = e.touches[0].clientY - rect.top;
  }, { passive: false });
  document.addEventListener('mousemove', moveLogo);
  document.addEventListener('touchmove', moveLogo, { passive: false });
  document.addEventListener('mouseup', () => isLogoDragging = false);
  document.addEventListener('touchend', () => isLogoDragging = false);
}

function setupLogoResizing() {
  if (!logoElement) return;
  const handles = logoElement.querySelectorAll('.resize-handle');
  const resizeLogoElement = (e) => {
    if (!logoElement || !isResizing || !resizeHandle) return;
    e.preventDefault();
    let clientX, clientY;
    if (e.type.includes('touch')) {
      clientX = e.touches[0].clientX;
      clientY = e.touches[0].clientY;
    } else {
      clientX = e.clientX;
      clientY = e.clientY;
    }
    const rect = logoElement.getBoundingClientRect();
    const invoiceBox = document.querySelector('.invoice-box').getBoundingClientRect();
    let newWidth = logoStartSize.width;
    let newHeight = logoStartSize.height;
    let newX = parseFloat(logoElement.style.left) || 0;
    let newY = parseFloat(logoElement.style.top) || 0;
    const lockAspectRatio = document.getElementById('lockAspectRatio').checked;

    if (resizeHandle.classList.contains('bottom-right')) {
      newWidth = clientX - rect.left;
      newHeight = lockAspectRatio ? newWidth / originalAspectRatio : clientY - rect.top;
    } else if (resizeHandle.classList.contains('top-left')) {
      newWidth = logoStartSize.width - (clientX - logoStartPos.x);
      newHeight = lockAspectRatio ? newWidth / originalAspectRatio : logoStartSize.height - (clientY - logoStartPos.y);
      newX = clientX - logoStartPos.x + logoStartSize.width - newWidth;
      newY = lockAspectRatio ? newY : clientY - logoStartPos.y + logoStartSize.height - newHeight;
    } else if (resizeHandle.classList.contains('top-right')) {
      newWidth = clientX - rect.left;
      newHeight = lockAspectRatio ? newWidth / originalAspectRatio : logoStartSize.height - (clientY - logoStartPos.y);
      newY = lockAspectRatio ? newY : clientY - logoStartPos.y + logoStartSize.height - newHeight;
    } else if (resizeHandle.classList.contains('bottom-left')) {
      newWidth = logoStartSize.width - (clientX - logoStartPos.x);
      newHeight = lockAspectRatio ? newWidth / originalAspectRatio : clientY - rect.top;
      newX = clientX - logoStartPos.x + logoStartSize.width - newWidth;
    }

    newWidth = Math.max(20, Math.min(300, newWidth));
    newHeight = Math.max(20, Math.min(300, newHeight));
    newX = Math.max(0, Math.min(newX, invoiceBox.width - newWidth));
    newY = Math.max(0, Math.min(newY, invoiceBox.height - newHeight));

    logoElement.style.width = `${newWidth}px`;
    logoElement.style.height = `${newHeight}px`;
    logoElement.style.left = `${newX}px`;
    logoElement.style.top = `${newY}px`;

    document.getElementById('logoWidth').value = Math.round(newWidth);
    document.getElementById('logoHeight').value = Math.round(newHeight);
  };

  handles.forEach(handle => {
    handle.addEventListener('mousedown', (e) => {
      isResizing = true;
      resizeHandle = handle;
      const rect = logoElement.getBoundingClientRect();
      logoStartPos = { x: e.clientX, y: e.clientY };
      logoStartSize = { width: rect.width, height: rect.height };
    });
    handle.addEventListener('touchstart', (e) => {
      e.preventDefault();
      isResizing = true;
      resizeHandle = handle;
      const rect = logoElement.getBoundingClientRect();
      logoStartPos = { x: e.touches[0].clientX, y: e.touches[0].clientY };
      logoStartSize = { width: rect.width, height: rect.height };
    }, { passive: false });
  });

  document.addEventListener('mousemove', resizeLogoElement);
  document.addEventListener('touchmove', resizeLogoElement, { passive: false });
  document.addEventListener('mouseup', () => {
    isResizing = false;
    resizeHandle = null;
  });
  document.addEventListener('touchend', () => {
    isResizing = false;
    resizeHandle = null;
  });
}

function setupLogoDoubleTap() {
  if (!logoElement) return;
  logoElement.addEventListener('click', () => {
    const currentTime = new Date().getTime();
    const tapInterval = currentTime - lastTapTime;
    if (tapInterval < 300 && tapInterval > 0) {
      logoElement.classList.toggle('active');
    } else {
      logoElement.classList.add('active');
    }
    lastTapTime = currentTime;
  });
  logoElement.addEventListener('touchstart', (e) => {
    e.preventDefault();
    const currentTime = new Date().getTime();
    const tapInterval = currentTime - lastTapTime;
    if (tapInterval < 300 && tapInterval > 0) {
      logoElement.classList.toggle('active');
    } else {
      logoElement.classList.add('active');
    }
    lastTapTime = currentTime;
  }, { passive: false });
}

function applyLogoSize() {
  if (!logoElement) return;
  const widthInput = document.getElementById('logoWidth');
  const heightInput = document.getElementById('logoHeight');
  const lockAspectRatio = document.getElementById('lockAspectRatio').checked;
  let newWidth = parseInt(widthInput.value) || 100;
  let newHeight = parseInt(heightInput.value) || 100;

  // Enforce minimum and maximum dimensions
  newWidth = Math.max(20, Math.min(300, newWidth));
  newHeight = Math.max(20, Math.min(300, newHeight));

  // Preserve aspect ratio if checked
  if (lockAspectRatio) {
    if (widthInput === document.activeElement) {
      newHeight = newWidth / originalAspectRatio;
    } else {
      newWidth = newHeight * originalAspectRatio;
    }
    newWidth = Math.max(20, Math.min(300, newWidth));
    newHeight = Math.max(20, Math.min(300, newHeight));
  }

  // Update logo dimensions
  logoElement.style.width = `${newWidth}px`;
  logoElement.style.height = `${newHeight}px`;
  widthInput.value = Math.round(newWidth);
  heightInput.value = Math.round(newHeight);

  // Ensure logo stays within invoice bounds
  const invoiceBox = document.querySelector('.invoice-box').getBoundingClientRect();
  let newX = parseFloat(logoElement.style.left) || 0;
  let newY = parseFloat(logoElement.style.top) || 0;
  newX = Math.max(0, Math.min(newX, invoiceBox.width - newWidth));
  newY = Math.max(0, Math.min(newY, invoiceBox.height - newHeight));
  logoElement.style.left = `${newX}px`;
  logoElement.style.top = `${newY}px`;
}

function resetLogoPosition() {
  if (!logoElement) return;
  logoElement.style.left = '20px';
  logoElement.style.top = '20px';
  logoElement.style.width = '100px';
  logoElement.style.height = '100px';
  document.getElementById('logoWidth').value = 100;
  document.getElementById('logoHeight').value = 100;
  logoElement.classList.remove('active');
}

function removeLogo() {
  if (logoElement) {
    logoElement.remove();
    logoElement = null;
    document.getElementById('logoUpload').value = '';
    document.getElementById('logoWidth').value = '';
    document.getElementById('logoHeight').value = '';
    document.getElementById('lockAspectRatio').checked = true;
  }
}

function generatePDF() {
  const invoiceBox = document.querySelector('.invoice-box');
  // Temporarily hide resize handles and border for PDF
  if (logoElement) {
    logoElement.classList.remove('active');
    logoElement.style.border = 'none';
  }

  html2canvas(invoiceBox, { scale: 2 }).then(canvas => {
    const imgData = canvas.toDataURL('image/png');
    const { jsPDF } = window.jspdf;
    const pdf = new jsPDF('p', 'mm', 'a4');
    const pdfWidth = pdf.internal.pageSize.getWidth();
    const pdfHeight = (canvas.height * pdfWidth) / canvas.width;
    pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight);
    pdf.save(`Invoice_${document.getElementById('invoiceNumber').value}.pdf`);

    // Restore logo state
    if (logoElement) {
      logoElement.style.border = logoElement.classList.contains('active') ? '2px dashed #007bff' : 'none';
    }
  });
}

function printInvoice() {
  // Hide resize handles and border for printing
  if (logoElement) {
    logoElement.classList.remove('active');
    logoElement.style.border = 'none';
  }
  window.print();
  // Restore logo state after print dialog closes
  if (logoElement) {
    logoElement.style.border = logoElement.classList.contains('active') ? '2px dashed #007bff' : 'none';
  }
}

function sharePDF() {
  const invoiceBox = document.querySelector('.invoice-box');
  if (logoElement) {
    logoElement.classList.remove('active');
    logoElement.style.border = 'none';
  }

  html2canvas(invoiceBox, { scale: 2 }).then(canvas => {
    const imgData = canvas.toDataURL('image/png');
    const { jsPDF } = window.jspdf;
    const pdf = new jsPDF('p', 'mm', 'a4');
    const pdfWidth = pdf.internal.pageSize.getWidth();
    const pdfHeight = (canvas.height * pdfWidth) / canvas.width;
    pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight);

    const pdfBlob = pdf.output('blob');
    const file = new File([pdfBlob], `Invoice_${document.getElementById('invoiceNumber').value}.pdf`, { type: 'application/pdf' });
    const whatsappNumber = document.getElementById('whatsappNumber').value.replace(/\D/g, '');

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

    const filesArray = [file];
    if (navigator.canShare && navigator.canShare({ files: filesArray })) {
      navigator.share({
        files: filesArray,
        title: `Invoice ${document.getElementById('invoiceNumber').value}`,
        text: `Here is your invoice from ${document.getElementById('companyName').value}.`
      }).catch(error => {
        showStatus('Error sharing PDF: ' + error.message, 'error');
      });
    } else {
      showStatus('Your device does not support sharing PDFs via WhatsApp.', 'error');
    }

    if (logoElement) {
      logoElement.style.border = logoElement.classList.contains('active') ? '2px dashed #007bff' : 'none';
    }
  });
}

function generateWhatsAppMessage() {
  const whatsappNumber = document.getElementById('whatsappNumber').value;
  const descLength = parseInt(document.getElementById('whatsappDescLength').value) || 20;
  if (!whatsappNumber) {
    showStatus('Please enter a WhatsApp number.', 'error');
    return;
  }

  const companyName = sanitizeInput(document.getElementById('companyName').value);
  const invoiceNumber = document.getElementById('invoiceNumber').value;
  const invoiceDate = formatDate(document.getElementById('invoiceDate').value);
  const dueDate = formatDate(document.getElementById('dueDate').value);
  const clientName = sanitizeInput(document.getElementById('clientName').value);
  let message = `Invoice from ${companyName}\n`;
  message += `Invoice #: ${invoiceNumber}\n`;
  message += `Date: ${invoiceDate}\n`;
  message += `Due Date: ${dueDate}\n`;
  message += `Bill To: ${clientName}\n\n`;
  message += `Items:\n`;

  const itemRows = document.querySelectorAll('.item-row');
  itemRows.forEach(row => {
    const desc = sanitizeInput(row.querySelector('.item-desc').value);
    const qty = parseFloat(row.querySelector('.item-qty').value) || 0;
    const rate = parseFloat(row.querySelector('.item-rate').value) || 0;
    const disc = parseFloat(row.querySelector('.item-disc').value) || 0;
    const total = (qty * rate * (1 - disc / 100)).toFixed(2);
    const shortDesc = desc.length > descLength ? desc.substring(0, descLength) + '...' : desc;
    message += `- ${shortDesc} (Qty: ${qty}, Rate: ₹${rate.toFixed(2)}, Disc: ${disc}%) = ₹${total}\n`;
  });

  const grandTotal = parseFloat(document.getElementById('previewTotal').textContent.replace('₹', '')) || 0;
  message += `\nGrand Total: ₹${grandTotal.toFixed(2)}`;

  const preview = document.getElementById('whatsappPreview');
  preview.textContent = message;
  preview.style.display = 'block';
}

function sendWhatsApp() {
  const whatsappNumber = document.getElementById('whatsappNumber').value.replace(/\D/g, '');
  const message = document.getElementById('whatsappPreview').textContent;
  if (!whatsappNumber || !message) {
    showStatus('Please generate a WhatsApp message first.', 'error');
    return;
  }
  const url = `https://wa.me/${whatsappNumber}?text=${encodeURIComponent(message)}`;
  window.open(url, '_blank');
}

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

function setupItemAutocomplete(row) {
  const codeInput = row.querySelector('.item-code');
  const dropdown = row.querySelector('.item-dropdown');
  codeInput.addEventListener('input', debounce(() => {
    const query = codeInput.value.toLowerCase();
    dropdown.innerHTML = '';
    if (query) {
      const filtered = inventory.filter(item =>
        item.code.toLowerCase().includes(query) ||
        item.hsn.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} (₹${item.price.toFixed(2)})`;
        div.addEventListener('click', () => {
          codeInput.value = item.code;
          row.querySelector('.item-desc').value = item.description;
          row.querySelector('.item-rate').value = item.price.toFixed(2);
          updateItemTotal(row);
          updateItemTotals();
          dropdown.innerHTML = '';
          dropdown.style.display = 'none';
        });
        dropdown.appendChild(div);
      });
      dropdown.style.display = filtered.length ? 'block' : 'none';
    } else {
      dropdown.style.display = 'none';
    }
  }, 300));
}

function openItemDialog() {
  const dialogOverlay = document.getElementById('dialogOverlay');
  dialogOverlay.style.display = 'flex';
  activeDialog = dialogOverlay;
  searchItems();
}

function searchItems() {
  const query = document.getElementById('searchInput').value.toLowerCase();
  filteredInventory = inventory.filter(item =>
    item.code.toLowerCase().includes(query) ||
    item.name.toLowerCase().includes(query) ||
    item.description.toLowerCase().includes(query)
  );
  const itemsList = document.getElementById('itemsList2');
  itemsList.innerHTML = '';
  filteredInventory.forEach(item => {
    const row = document.createElement('tr');
    row.innerHTML = `
      <td>${item.code}</td>
      <td>${item.name}</td>
      <td>${item.description}</td>
      <td>₹${item.price.toFixed(2)}</td>
    `;
    row.addEventListener('click', () => {
      const newRow = document.createElement('tr');
      newRow.className = 'item-row';
      newRow.innerHTML = `
        <td><input type="text" class="item-code code-input" value="${item.code}" placeholder="Enter HSN/SAC code..."><div class="dropdown item-dropdown"></div></td>
        <td><input type="text" class="item-desc desc-input" value="${item.description}" placeholder="Service or product description"></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="${item.price.toFixed(2)}" step="0.01" min="0"></td>
        <td><input type="number" class="item-disc disc-input" value="0" step="0.01" min="0" max="100"></td>
        <td><input type="text" class="item-total total-input" value="${item.price.toFixed(2)}" readonly></td>
        <td><button class="remove-btn" onclick="removeItem(this)">Remove</button></td>
      `;
      document.getElementById('itemsList').querySelector('tbody').appendChild(newRow);
      attachInputListeners(newRow);
      setupItemAutocomplete(newRow);
      updateItemTotals();
      closeDialog(null, 'dialogOverlay');
    });
    itemsList.appendChild(row);
  });
}

function closeDialog(event, dialogId) {
  if (event && event.target.id !== dialogId) return;
  document.getElementById(dialogId).style.display = 'none';
  activeDialog = null;
}

function applyCustomSize(dialogId, widthInputId, heightInputId) {
  const dialog = document.getElementById(dialogId);
  const width = parseInt(document.getElementById(widthInputId).value) || 600;
  const height = parseInt(document.getElementById(heightInputId).value) || 450;
  dialog.style.width = `${Math.max(300, Math.min(1200, width))}px`;
  dialog.style.height = `${Math.max(200, Math.min(800, height))}px`;
}

function quickResize(width, height, dialogId, widthInputId, heightInputId) {
  document.getElementById(widthInputId).value = width;
  document.getElementById(heightInputId).value = height;
  applyCustomSize(dialogId, widthInputId, heightInputId);
}

function addStockItem() {
  const code = sanitizeInput(document.getElementById('stockCode').value);
  const hsn = sanitizeInput(document.getElementById('stockHSN').value);
  const description = sanitizeInput(document.getElementById('stockDescription').value);
  const price = parseFloat(document.getElementById('stockPrice').value) || 0;
  const unit = document.getElementById('stockUnit').value;
  const quantity = parseInt(document.getElementById('stockQuantity').value) || 0;

  if (!code || !hsn || !description || price <= 0 || quantity < 0) {
    showStatus('Please fill in all stock fields correctly.', 'error');
    return;
  }

  const existingItem = inventory.find(item => item.code === code);
  if (existingItem) {
    existingItem.hsn = hsn;
    existingItem.description = description;
    existingItem.price = price;
    existingItem.unit = unit;
    existingItem.quantity = quantity;
    showStatus('Item updated successfully!', 'success');
  } else {
    inventory.push({ code, hsn, name: description.split(' ')[0], description, price, unit, quantity });
    showStatus('Item added to inventory!', 'success');
  }

  document.getElementById('stockCode').value = '';
  document.getElementById('stockHSN').value = '';
  document.getElementById('stockDescription').value = '';
  document.getElementById('stockPrice').value = '';
  document.getElementById('stockQuantity').value = '';
  loadStockTable();
}

function loadStockTable() {
  const stockTableBody = document.getElementById('stockTableBody');
  stockTableBody.innerHTML = '';
  inventory.forEach((item, index) => {
    const row = document.createElement('tr');
    row.innerHTML = `
      <td>${item.code}</td>
      <td>${item.hsn}</td>
      <td>${item.description}</td>
      <td>₹${item.price.toFixed(2)}</td>
      <td>${item.unit}</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(${index})">Delete</button>
      </td>
    `;
    stockTableBody.appendChild(row);
  });
}

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;
  inventory.splice(index, 1);
  loadStockTable();
}

function deleteStockItem(index) {
  if (confirm('Are you sure you want to delete this item?')) {
    inventory.splice(index, 1);
    loadStockTable();
    showStatus('Item deleted successfully!', 'success');
  }
}

function addCustomer() {
  const contact = sanitizeInput(document.getElementById('newCustomerContact').value);
  const name = sanitizeInput(document.getElementById('newCustomerName').value);
  const email = sanitizeInput(document.getElementById('newCustomerEmail').value);
  const address = sanitizeInput(document.getElementById('newCustomerAddress').value);

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

  const existingCustomer = customerDatabase.find(c => c.contact === contact);
  if (existingCustomer) {
    existingCustomer.name = name;
    existingCustomer.email = email;
    existingCustomer.address = address;
    showStatus('Customer updated successfully!', 'success');
  } else {
    customerDatabase.push({ contact, name, email, address });
    showStatus('Customer added successfully!', 'success');
  }

  document.getElementById('newCustomerContact').value = '';
  document.getElementById('newCustomerName').value = '';
  document.getElementById('newCustomerEmail').value = '';
  document.getElementById('newCustomerAddress').value = '';
  loadCustomerTable();
}

function loadCustomerTable() {
  const customerTableBody = document.getElementById('customerTableBody');
  customerTableBody.innerHTML = '';
  customerDatabase.forEach((customer, index) => {
    const row = document.createElement('tr');
    row.innerHTML = `
      <td>${customer.contact}</td>
      <td>${customer.name}</td>
      <td>${customer.email || 'N/A'}</td>
      <td>${customer.address || 'N/A'}</td>
      <td>
        <button class="edit-btn" onclick="editCustomer(${index})">Edit</button>
        <button class="delete-btn" onclick="deleteCustomer(${index})">Delete</button>
      </td>
    `;
    customerTableBody.appendChild(row);
  });
}

function editCustomer(index) {
  const customer = customerDatabase[index];
  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';
  activeDialog = document.getElementById('editCustomerDialogOverlay');
  editingCustomerIndex = index;
}

function saveEditedCustomer() {
  const contact = sanitizeInput(document.getElementById('editCustomerContact').value);
  const name = sanitizeInput(document.getElementById('editCustomerName').value);
  const email = sanitizeInput(document.getElementById('editCustomerEmail').value);
  const address = sanitizeInput(document.getElementById('editCustomerAddress').value);

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

  customerDatabase[editingCustomerIndex] = { contact, name, email, address };
  loadCustomerTable();
  closeDialog(null, 'editCustomerDialogOverlay');
  showStatus('Customer updated successfully!', 'success');
}

function deleteCustomer(index) {
  if (confirm('Are you sure you want to delete this customer?')) {
    customerDatabase.splice(index, 1);
    loadCustomerTable();
    showStatus('Customer deleted successfully!', 'success');
  }
}

function setupClientAutocomplete() {
  const clientContact = document.getElementById('clientContact');
  const contactDropdown = document.getElementById('contactDropdown');
  clientContact.addEventListener('input', debounce(() => {
    const query = clientContact.value.toLowerCase();
    contactDropdown.innerHTML = '';
    if (query) {
      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', () => {
          clientContact.value = customer.contact;
          document.getElementById('clientName').value = customer.name;
          document.getElementById('clientEmail').value = customer.email || '';
          document.getElementById('clientAddress').value = customer.address || '';
          contactDropdown.innerHTML = '';
          contactDropdown.style.display = 'none';
          ['clientName', 'clientEmail', 'clientAddress'].forEach(id => {
            const input = document.getElementById(id);
            input.classList.add('auto-populated');
            setTimeout(() => input.classList.remove('auto-populated'), 1000);
          });
        });
        contactDropdown.appendChild(div);
      });
      contactDropdown.style.display = filtered.length ? 'block' : 'none';
    } else {
      contactDropdown.style.display = 'none';
    }
  }, 300));
}

function backupData() {
  const data = {
    inventory,
    customerDatabase,
    invoices
  };
  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');
}

function restoreData() {
  const fileInput = document.getElementById('restoreFileInput');
  const file = fileInput.files[0];
  if (!file) {
    showStatus('Please select a backup file.', 'error');
    return;
  }
  const reader = new FileReader();
  reader.onload = function(e) {
    try {
      const data = JSON.parse(e.target.result);
      if (data.inventory) inventory.length = 0;
      inventory.push(...data.inventory);
      if (data.customerDatabase) customerDatabase = data.customerDatabase;
      if (data.invoices) {
        invoices = data.invoices;
        localStorage.setItem('invoices', JSON.stringify(invoices));
      }
      loadStockTable();
      loadCustomerTable();
      updateDashboard();
      showStatus('Data restored successfully!', 'success');
    } catch (error) {
      showStatus('Error restoring data: Invalid file format.', 'error');
    }
  };
  reader.readAsText(file);
}

function updateDashboard() {
  const dateRange = document.getElementById('dateRangeFilter').value;
  let startDate, endDate = new Date();
  if (dateRange === 'custom') {
    startDate = new Date(document.getElementById('fromDate').value);
    endDate = new Date(document.getElementById('toDate').value);
  } else {
    startDate = new Date();
    startDate.setDate(endDate.getDate() - parseInt(dateRange));
  }

  const filteredInvoices = invoices.filter(invoice => {
    const invoiceDate = new Date(invoice.timestamp);
    return invoiceDate >= startDate && invoiceDate <= endDate;
  });

  const totalRevenue = filteredInvoices.reduce((sum, inv) => sum + inv.grandTotal, 0);
  const totalOrders = filteredInvoices.length;
  const totalCustomers = new Set(filteredInvoices.map(inv => inv.clientContact)).size;
  const itemCounts = {};
  filteredInvoices.forEach(inv => {
    inv.items.forEach(item => {
      itemCounts[item.code] = (itemCounts[item.code] || 0) + item.quantity;
    });
  });

  document.getElementById('totalRevenue').textContent = `₹${totalRevenue.toFixed(2)}`;
  document.getElementById('totalOrders').textContent = totalOrders;
  document.getElementById('totalCustomers').textContent = totalCustomers;
  document.getElementById('totalProducts').textContent = Object.values(itemCounts).reduce((sum, qty) => sum + qty, 0);

  const topProductsList = document.getElementById('topProductsList');
  topProductsList.innerHTML = '';
  const sortedItems = Object.entries(itemCounts)
    .map(([code, quantity]) => {
      const item = inventory.find(i => i.code === code);
      return { code, quantity, description: item ? item.description : 'Unknown Item' };
    })
    .sort((a, b) => b.quantity - a.quantity)
    .slice(0, 5);
  sortedItems.forEach(item => {
    const div = document.createElement('div');
    div.innerHTML = `<span>${item.description}</span><span>${item.quantity} units</span>`;
    topProductsList.appendChild(div);
  });

  const recentOrdersList = document.getElementById('recentOrdersList');
  recentOrdersList.innerHTML = '';
  filteredInvoices
    .sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
    .slice(0, 5)
    .forEach(invoice => {
      const div = document.createElement('div');
      div.innerHTML = `<span>Invoice #${invoice.invoiceNumber}</span><span>₹${invoice.grandTotal.toFixed(2)}</span>`;
      recentOrdersList.appendChild(div);
    });
}

function toggleCustomDateRange() {
  const dateRange = document.getElementById('dateRangeFilter').value;
  const customDateRange = document.getElementById('customDateRange');
  customDateRange.classList.toggle('hidden', dateRange !== 'custom');
  if (dateRange === 'custom') {
    document.getElementById('fromDate').value = '';
    document.getElementById('toDate').value = '';
  }
}

function clearInvoices() {
  if (confirm('Are you sure you want to clear all invoices? This action cannot be undone.')) {
    invoices = [];
    localStorage.setItem('invoices', JSON.stringify(invoices));
    updateDashboard();
    showStatus('All invoices cleared!', 'success');
  }
}

// Initialize
document.addEventListener('DOMContentLoaded', () => {
  // Set default dates
  const today = new Date();
  document.getElementById('invoiceDate').value = today.toISOString().split('T')[0];
  const dueDate = new Date();
  dueDate.setDate(today.getDate() + 30);
  document.getElementById('dueDate').value = dueDate.toISOString().split('T')[0];
  document.getElementById('invoiceNumber').value = generateInvoiceNumber();

  // Setup navigation
  document.querySelectorAll('.nav-btn').forEach(button => {
    button.addEventListener('click', () => {
      document.querySelectorAll('.nav-btn').forEach(btn => btn.classList.remove('active'));
      button.classList.add('active');
      document.querySelectorAll('.section').forEach(section => section.classList.remove('active'));
      document.getElementById(button.dataset.section).classList.add('active');
    });
  });

  // Initialize tables and listeners
  document.querySelectorAll('.item-row').forEach(row => {
    attachInputListeners(row);
    setupItemAutocomplete(row);
  });
  setupClientAutocomplete();
  loadStockTable();
  loadCustomerTable();
  updateDashboard();
  setupLogoUpload();

  // Setup logo size input listeners
  const logoWidthInput = document.getElementById('logoWidth');
  const logoHeightInput = document.getElementById('logoHeight');
  logoWidthInput.addEventListener('input', applyLogoSize);
  logoHeightInput.addEventListener('input', applyLogoSize);
});

// Prevent dropdown from closing when clicking inside
document.querySelectorAll('.dropdown').forEach(dropdown => {
  dropdown.addEventListener('click', e => e.stopPropagation());
});
document.addEventListener('click', () => {
  document.querySelectorAll('.dropdown').forEach(dropdown => {
    dropdown.style.display = 'none';
  });
});
</script>
</body>
</html>

No comments:

Post a Comment