| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Advanced Cash Register System</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <style> |
| .sidebar { |
| transition: all 0.3s ease; |
| } |
| .product-card:hover { |
| transform: translateY(-5px); |
| box-shadow: 0 10px 20px rgba(0,0,0,0.1); |
| } |
| .receipt-item:hover { |
| background-color: #f3f4f6; |
| } |
| .modal { |
| transition: opacity 0.3s ease; |
| } |
| .tabs-container { |
| scrollbar-width: none; |
| } |
| .tabs-container::-webkit-scrollbar { |
| display: none; |
| } |
| @keyframes pulse { |
| 0%, 100% { |
| opacity: 1; |
| } |
| 50% { |
| opacity: 0.5; |
| } |
| } |
| .animate-pulse { |
| animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; |
| } |
| </style> |
| </head> |
| <body class="bg-gray-100 font-sans"> |
| <div class="flex h-screen overflow-hidden"> |
| |
| <div class="sidebar bg-indigo-800 text-white w-64 flex-shrink-0 flex flex-col"> |
| <div class="p-4 flex items-center justify-between border-b border-indigo-700"> |
| <h1 class="text-2xl font-bold">Cash Register</h1> |
| <button id="sidebarToggle" class="md:hidden text-white"> |
| <i class="fas fa-bars"></i> |
| </button> |
| </div> |
| <nav class="flex-1 overflow-y-auto"> |
| <div class="p-4"> |
| <button id="posTab" class="w-full flex items-center space-x-3 p-3 rounded-lg bg-indigo-900 text-white mb-2"> |
| <i class="fas fa-cash-register"></i> |
| <span>Point of Sale</span> |
| </button> |
| <button id="productsTab" class="w-full flex items-center space-x-3 p-3 rounded-lg hover:bg-indigo-700 text-white mb-2"> |
| <i class="fas fa-boxes"></i> |
| <span>Products</span> |
| </button> |
| <button id="inventoryTab" class="w-full flex items-center space-x-3 p-3 rounded-lg hover:bg-indigo-700 text-white mb-2"> |
| <i class="fas fa-warehouse"></i> |
| <span>Inventory</span> |
| </button> |
| <button id="salesTab" class="w-full flex items-center space-x-3 p-3 rounded-lg hover:bg-indigo-700 text-white mb-2"> |
| <i class="fas fa-chart-line"></i> |
| <span>Sales Reports</span> |
| </button> |
| <button id="settingsTab" class="w-full flex items-center space-x-3 p-3 rounded-lg hover:bg-indigo-700 text-white"> |
| <i class="fas fa-cog"></i> |
| <span>Settings</span> |
| </button> |
| </div> |
| </nav> |
| <div class="p-4 border-t border-indigo-700"> |
| <div class="flex items-center space-x-3"> |
| <div class="w-10 h-10 rounded-full bg-indigo-600 flex items-center justify-center"> |
| <i class="fas fa-user"></i> |
| </div> |
| <div> |
| <div class="font-medium" id="usernameDisplay">Admin</div> |
| <div class="text-xs text-indigo-300">Logged In</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="flex-1 flex flex-col overflow-hidden"> |
| |
| <header class="bg-white shadow-sm p-4 flex items-center justify-between"> |
| <h2 class="text-xl font-semibold text-gray-800" id="currentTabTitle">Point of Sale</h2> |
| <div class="flex items-center space-x-4"> |
| <div class="relative"> |
| <button id="notificationsBtn" class="text-gray-600 hover:text-indigo-600"> |
| <i class="fas fa-bell"></i> |
| <span class="absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center">3</span> |
| </button> |
| </div> |
| <div class="relative"> |
| <button id="syncBtn" class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 flex items-center space-x-2"> |
| <i class="fas fa-sync-alt"></i> |
| <span>Sync with Google</span> |
| </button> |
| <div id="syncStatus" class="hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1 z-10"> |
| <div class="px-4 py-2 text-sm text-gray-700">Last sync: <span id="lastSyncTime">Never</span></div> |
| </div> |
| </div> |
| </div> |
| </header> |
|
|
| |
| <main class="flex-1 overflow-y-auto p-6 bg-gray-50"> |
| |
| <div id="posContent" class="tab-content"> |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-6"> |
| |
| <div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-6"> |
| <div class="flex justify-between items-center mb-6"> |
| <h3 class="text-lg font-semibold text-gray-800">Products</h3> |
| <div class="relative w-64"> |
| <input type="text" id="productSearch" placeholder="Search products..." class="w-full pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| <i class="fas fa-search absolute left-3 top-3 text-gray-400"></i> |
| </div> |
| </div> |
| |
| |
| <div class="mb-6 overflow-x-auto tabs-container"> |
| <div class="flex space-x-2 pb-2"> |
| <button class="category-btn px-4 py-2 bg-indigo-600 text-white rounded-lg whitespace-nowrap">All</button> |
| <button class="category-btn px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 whitespace-nowrap">Electronics</button> |
| <button class="category-btn px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 whitespace-nowrap">Groceries</button> |
| <button class="category-btn px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 whitespace-nowrap">Clothing</button> |
| <button class="category-btn px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 whitespace-nowrap">Home Goods</button> |
| </div> |
| </div> |
| |
| |
| <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4" id="productGrid"> |
| |
| <div class="product-card bg-white border border-gray-200 rounded-lg overflow-hidden shadow-sm cursor-pointer transition-all duration-300"> |
| <div class="h-32 bg-gray-100 flex items-center justify-center"> |
| <i class="fas fa-box-open text-4xl text-gray-400"></i> |
| </div> |
| <div class="p-3"> |
| <h4 class="font-medium text-gray-800 truncate">Sample Product</h4> |
| <div class="flex justify-between items-center mt-2"> |
| <span class="text-indigo-600 font-semibold">$19.99</span> |
| <button class="bg-indigo-600 text-white p-1 rounded-full hover:bg-indigo-700"> |
| <i class="fas fa-plus"></i> |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <div class="flex justify-between items-center mb-6"> |
| <h3 class="text-lg font-semibold text-gray-800">Current Sale</h3> |
| <button id="clearCartBtn" class="text-red-500 hover:text-red-700 text-sm flex items-center"> |
| <i class="fas fa-trash-alt mr-1"></i> Clear |
| </button> |
| </div> |
| |
| |
| <div class="mb-4 max-h-96 overflow-y-auto" id="receiptItems"> |
| |
| <div class="receipt-item flex justify-between items-center py-3 px-2 border-b border-gray-100 transition-colors duration-200"> |
| <div> |
| <div class="font-medium">Sample Product</div> |
| <div class="text-sm text-gray-500">1 x $19.99</div> |
| </div> |
| <div class="flex items-center"> |
| <span class="font-semibold mr-4">$19.99</span> |
| <button class="text-red-500 hover:text-red-700"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="border-t border-gray-200 pt-4 mb-4"> |
| <div class="flex justify-between mb-2"> |
| <span class="text-gray-600">Subtotal:</span> |
| <span class="font-semibold" id="subtotal">$0.00</span> |
| </div> |
| <div class="flex justify-between mb-2"> |
| <span class="text-gray-600">Tax (10%):</span> |
| <span class="font-semibold" id="tax">$0.00</span> |
| </div> |
| <div class="flex justify-between text-lg font-bold"> |
| <span>Total:</span> |
| <span id="total">$0.00</span> |
| </div> |
| </div> |
| |
| |
| <div class="mb-6"> |
| <h4 class="text-sm font-semibold text-gray-600 mb-2">PAYMENT METHOD</h4> |
| <div class="grid grid-cols-3 gap-2"> |
| <button class="payment-method-btn bg-indigo-100 text-indigo-800 py-2 rounded-lg hover:bg-indigo-200">Cash</button> |
| <button class="payment-method-btn bg-gray-100 text-gray-800 py-2 rounded-lg hover:bg-gray-200">Card</button> |
| <button class="payment-method-btn bg-gray-100 text-gray-800 py-2 rounded-lg hover:bg-gray-200">Mobile</button> |
| </div> |
| </div> |
| |
| |
| <button id="completeSaleBtn" class="w-full bg-green-600 text-white py-3 rounded-lg hover:bg-green-700 font-semibold flex items-center justify-center space-x-2"> |
| <i class="fas fa-check-circle"></i> |
| <span>Complete Sale ($0.00)</span> |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="productsContent" class="tab-content hidden"> |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <div class="flex justify-between items-center mb-6"> |
| <h3 class="text-lg font-semibold text-gray-800">Product Management</h3> |
| <button id="addProductBtn" class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 flex items-center space-x-2"> |
| <i class="fas fa-plus"></i> |
| <span>Add Product</span> |
| </button> |
| </div> |
| |
| |
| <div class="overflow-x-auto"> |
| <table class="min-w-full divide-y divide-gray-200"> |
| <thead class="bg-gray-50"> |
| <tr> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Image</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">SKU</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Price</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Stock</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Category</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th> |
| </tr> |
| </thead> |
| <tbody class="bg-white divide-y divide-gray-200" id="productTableBody"> |
| |
| <tr> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="w-10 h-10 bg-gray-200 rounded flex items-center justify-center"> |
| <i class="fas fa-box text-gray-500"></i> |
| </div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm font-medium text-gray-900">Sample Product</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm text-gray-500">SKU123</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm text-gray-900">$19.99</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm text-gray-900">25</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <span class="px-2 py-1 text-xs rounded-full bg-blue-100 text-blue-800">Electronics</span> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> |
| <button class="text-indigo-600 hover:text-indigo-900 mr-3"> |
| <i class="fas fa-edit"></i> |
| </button> |
| <button class="text-red-600 hover:text-red-900"> |
| <i class="fas fa-trash-alt"></i> |
| </button> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="inventoryContent" class="tab-content hidden"> |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <div class="flex justify-between items-center mb-6"> |
| <h3 class="text-lg font-semibold text-gray-800">Inventory Management</h3> |
| <div class="flex space-x-3"> |
| <button id="exportInventoryBtn" class="bg-gray-200 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-300 flex items-center space-x-2"> |
| <i class="fas fa-file-export"></i> |
| <span>Export</span> |
| </button> |
| <button id="importInventoryBtn" class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 flex items-center space-x-2"> |
| <i class="fas fa-file-import"></i> |
| <span>Import</span> |
| </button> |
| </div> |
| </div> |
| |
| |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6"> |
| <div class="bg-blue-50 p-4 rounded-lg border border-blue-100"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-sm text-blue-600">Total Products</p> |
| <h3 class="text-2xl font-bold text-blue-900">125</h3> |
| </div> |
| <div class="bg-blue-100 p-2 rounded-lg"> |
| <i class="fas fa-boxes text-blue-600"></i> |
| </div> |
| </div> |
| </div> |
| <div class="bg-green-50 p-4 rounded-lg border border-green-100"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-sm text-green-600">In Stock Items</p> |
| <h3 class="text-2xl font-bold text-green-900">98</h3> |
| </div> |
| <div class="bg-green-100 p-2 rounded-lg"> |
| <i class="fas fa-check-circle text-green-600"></i> |
| </div> |
| </div> |
| </div> |
| <div class="bg-red-50 p-4 rounded-lg border border-red-100"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-sm text-red-600">Out of Stock</p> |
| <h3 class="text-2xl font-bold text-red-900">27</h3> |
| </div> |
| <div class="bg-red-100 p-2 rounded-lg"> |
| <i class="fas fa-exclamation-circle text-red-600"></i> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="overflow-x-auto"> |
| <table class="min-w-full divide-y divide-gray-200"> |
| <thead class="bg-gray-50"> |
| <tr> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Product</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">SKU</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Current Stock</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Low Stock Alert</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Last Updated</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th> |
| </tr> |
| </thead> |
| <tbody class="bg-white divide-y divide-gray-200" id="inventoryTableBody"> |
| |
| <tr> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="flex items-center"> |
| <div class="flex-shrink-0 h-10 w-10 bg-gray-200 rounded flex items-center justify-center"> |
| <i class="fas fa-box text-gray-500"></i> |
| </div> |
| <div class="ml-4"> |
| <div class="text-sm font-medium text-gray-900">Sample Product</div> |
| <div class="text-sm text-gray-500">Electronics</div> |
| </div> |
| </div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm text-gray-900">SKU123</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm text-gray-900">25</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <span class="px-2 py-1 text-xs rounded-full bg-green-100 text-green-800">In Stock</span> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm text-gray-500">2023-06-15</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> |
| <button class="text-indigo-600 hover:text-indigo-900 mr-3"> |
| <i class="fas fa-edit"></i> |
| </button> |
| <button class="text-red-600 hover:text-red-900"> |
| <i class="fas fa-trash-alt"></i> |
| </button> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="salesContent" class="tab-content hidden"> |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <div class="flex justify-between items-center mb-6"> |
| <h3 class="text-lg font-semibold text-gray-800">Sales Reports</h3> |
| <div class="flex space-x-3"> |
| <div class="relative"> |
| <select id="reportPeriod" class="appearance-none bg-gray-100 border border-gray-300 text-gray-700 py-2 px-4 pr-8 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| <option>Today</option> |
| <option>This Week</option> |
| <option>This Month</option> |
| <option>This Year</option> |
| <option>Custom Range</option> |
| </select> |
| <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"> |
| <i class="fas fa-chevron-down"></i> |
| </div> |
| </div> |
| <button id="exportReportBtn" class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 flex items-center space-x-2"> |
| <i class="fas fa-file-export"></i> |
| <span>Export</span> |
| </button> |
| </div> |
| </div> |
| |
| |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6"> |
| <div class="bg-purple-50 p-4 rounded-lg border border-purple-100"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-sm text-purple-600">Total Sales</p> |
| <h3 class="text-2xl font-bold text-purple-900">$12,345.67</h3> |
| </div> |
| <div class="bg-purple-100 p-2 rounded-lg"> |
| <i class="fas fa-dollar-sign text-purple-600"></i> |
| </div> |
| </div> |
| </div> |
| <div class="bg-blue-50 p-4 rounded-lg border border-blue-100"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-sm text-blue-600">Transactions</p> |
| <h3 class="text-2xl font-bold text-blue-900">87</h3> |
| </div> |
| <div class="bg-blue-100 p-2 rounded-lg"> |
| <i class="fas fa-receipt text-blue-600"></i> |
| </div> |
| </div> |
| </div> |
| <div class="bg-green-50 p-4 rounded-lg border border-green-100"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-sm text-green-600">Avg. Sale</p> |
| <h3 class="text-2xl font-bold text-green-900">$141.90</h3> |
| </div> |
| <div class="bg-green-100 p-2 rounded-lg"> |
| <i class="fas fa-chart-bar text-green-600"></i> |
| </div> |
| </div> |
| </div> |
| <div class="bg-orange-50 p-4 rounded-lg border border-orange-100"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-sm text-orange-600">Items Sold</p> |
| <h3 class="text-2xl font-bold text-orange-900">256</h3> |
| </div> |
| <div class="bg-orange-100 p-2 rounded-lg"> |
| <i class="fas fa-shopping-cart text-orange-600"></i> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6"> |
| <div class="bg-white p-4 rounded-lg border border-gray-200"> |
| <h4 class="text-md font-semibold text-gray-800 mb-4">Sales Over Time</h4> |
| <canvas id="salesChart" height="250"></canvas> |
| </div> |
| <div class="bg-white p-4 rounded-lg border border-gray-200"> |
| <h4 class="text-md font-semibold text-gray-800 mb-4">Top Selling Products</h4> |
| <canvas id="productsChart" height="250"></canvas> |
| </div> |
| </div> |
| |
| |
| <div class="overflow-x-auto"> |
| <table class="min-w-full divide-y divide-gray-200"> |
| <thead class="bg-gray-50"> |
| <tr> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Transaction ID</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Items</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Payment Method</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Total</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th> |
| </tr> |
| </thead> |
| <tbody class="bg-white divide-y divide-gray-200" id="salesTableBody"> |
| |
| <tr> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm text-gray-900">2023-06-15</div> |
| <div class="text-sm text-gray-500">10:45 AM</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm font-medium text-indigo-600">TXN-20230615-001</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm text-gray-900">3 items</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <span class="px-2 py-1 text-xs rounded-full bg-blue-100 text-blue-800">Card</span> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap"> |
| <div class="text-sm font-semibold text-gray-900">$87.50</div> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> |
| <button class="text-indigo-600 hover:text-indigo-900 mr-3"> |
| <i class="fas fa-receipt"></i> |
| </button> |
| <button class="text-red-600 hover:text-red-900"> |
| <i class="fas fa-trash-alt"></i> |
| </button> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="settingsContent" class="tab-content hidden"> |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <h3 class="text-lg font-semibold text-gray-800 mb-6">System Settings</h3> |
| |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-6"> |
| |
| <div class="lg:col-span-2"> |
| <div class="bg-gray-50 p-6 rounded-lg border border-gray-200 mb-6"> |
| <h4 class="text-md font-semibold text-gray-800 mb-4">General Settings</h4> |
| |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Business Name</label> |
| <input type="text" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" value="My Retail Store"> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Currency</label> |
| <select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| <option>USD ($)</option> |
| <option>EUR (€)</option> |
| <option>GBP (£)</option> |
| <option>JPY (¥)</option> |
| </select> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Tax Rate (%)</label> |
| <input type="number" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" value="10"> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Receipt Footer</label> |
| <textarea class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" rows="3">Thank you for shopping with us!</textarea> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-gray-50 p-6 rounded-lg border border-gray-200"> |
| <h4 class="text-md font-semibold text-gray-800 mb-4">Google Sheets Integration</h4> |
| |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Google Sheet ID</label> |
| <input type="text" id="sheetId" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder="Enter your Google Sheet ID"> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Sync Frequency</label> |
| <select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| <option>Manual</option> |
| <option>Every 15 minutes</option> |
| <option>Every hour</option> |
| <option>Every day</option> |
| </select> |
| </div> |
| |
| <div class="pt-2"> |
| <button id="testConnectionBtn" class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 flex items-center space-x-2"> |
| <i class="fas fa-plug"></i> |
| <span>Test Connection</span> |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div> |
| <div class="bg-gray-50 p-6 rounded-lg border border-gray-200"> |
| <h4 class="text-md font-semibold text-gray-800 mb-4">User Management</h4> |
| |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Current User</label> |
| <div class="flex items-center space-x-3 p-3 bg-white border border-gray-200 rounded-lg"> |
| <div class="w-10 h-10 rounded-full bg-indigo-100 flex items-center justify-center"> |
| <i class="fas fa-user text-indigo-600"></i> |
| </div> |
| <div> |
| <div class="font-medium">Admin User</div> |
| <div class="text-xs text-gray-500">Administrator</div> |
| </div> |
| </div> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Change Password</label> |
| <input type="password" placeholder="Current password" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 mb-2"> |
| <input type="password" placeholder="New password" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 mb-2"> |
| <input type="password" placeholder="Confirm new password" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| </div> |
| |
| <div class="pt-2"> |
| <button class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 w-full"> |
| Update Password |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-gray-50 p-6 rounded-lg border border-gray-200 mt-6"> |
| <h4 class="text-md font-semibold text-gray-800 mb-4">Backup & Restore</h4> |
| |
| <div class="space-y-4"> |
| <button class="w-full bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 flex items-center justify-center space-x-2"> |
| <i class="fas fa-download"></i> |
| <span>Create Backup</span> |
| </button> |
| |
| <button class="w-full bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 flex items-center justify-center space-x-2"> |
| <i class="fas fa-upload"></i> |
| <span>Restore Backup</span> |
| </button> |
| |
| <button class="w-full bg-red-600 text-white px-4 py-2 rounded-lg hover:bg-red-700 flex items-center justify-center space-x-2"> |
| <i class="fas fa-trash-alt"></i> |
| <span>Reset System</span> |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </main> |
| </div> |
| </div> |
|
|
| |
| <div id="addProductModal" class="modal fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center hidden z-50"> |
| <div class="bg-white rounded-lg shadow-xl w-full max-w-2xl"> |
| <div class="p-6"> |
| <div class="flex justify-between items-center mb-4"> |
| <h3 class="text-xl font-semibold text-gray-800">Add New Product</h3> |
| <button id="closeAddProductModal" class="text-gray-500 hover:text-gray-700"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| |
| <div class="space-y-4"> |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Product Name</label> |
| <input type="text" id="productName" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">SKU</label> |
| <input type="text" id="productSKU" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| </div> |
| </div> |
| |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4"> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Price</label> |
| <input type="number" id="productPrice" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Cost</label> |
| <input type="number" id="productCost" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Initial Stock</label> |
| <input type="number" id="productStock" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| </div> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Category</label> |
| <select id="productCategory" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> |
| <option value="">Select a category</option> |
| <option>Electronics</option> |
| <option>Groceries</option> |
| <option>Clothing</option> |
| <option>Home Goods</option> |
| <option>Other</option> |
| </select> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Description</label> |
| <textarea id="productDescription" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" rows="3"></textarea> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Product Image</label> |
| <div class="mt-1 flex items-center"> |
| <span class="inline-block h-24 w-24 rounded-full overflow-hidden bg-gray-100"> |
| <svg class="h-full w-full text-gray-300" fill="currentColor" viewBox="0 0 24 24"> |
| <path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" /> |
| </svg> |
| </span> |
| <button type="button" class="ml-5 bg-white py-2 px-3 border border-gray-300 rounded-lg shadow-sm text-sm leading-4 font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> |
| Upload Image |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| <div class="mt-6 flex justify-end space-x-3"> |
| <button id="cancelAddProduct" class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50"> |
| Cancel |
| </button> |
| <button id="saveProduct" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700"> |
| Save Product |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="receiptModal" class="modal fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center hidden z-50"> |
| <div class="bg-white rounded-lg shadow-xl w-full max-w-md"> |
| <div class="p-6"> |
| <div class="flex justify-between items-center mb-4"> |
| <h3 class="text-xl font-semibold text-gray-800">Sale Receipt</h3> |
| <button id="closeReceiptModal" class="text-gray-500 hover:text-gray-700"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| |
| <div class="text-center mb-6"> |
| <div class="text-lg font-bold">MY RETAIL STORE</div> |
| <div class="text-sm text-gray-600">123 Main Street, City</div> |
| <div class="text-sm text-gray-600">Tel: (123) 456-7890</div> |
| </div> |
| |
| <div class="border-t border-b border-gray-200 py-3 mb-4"> |
| <div class="flex justify-between text-sm mb-1"> |
| <span class="text-gray-600">Date:</span> |
| <span id="receiptDate" class="font-medium">2023-06-15 10:45 AM</span> |
| </div> |
| <div class="flex justify-between text-sm"> |
| <span class="text-gray-600">Transaction #:</span> |
| <span id="receiptTransactionId" class="font-medium">TXN-20230615-001</span> |
| </div> |
| </div> |
| |
| <div class="mb-4" id="receiptItemsList"> |
| |
| <div class="flex justify-between py-1"> |
| <div> |
| <div>Sample Product</div> |
| <div class="text-sm text-gray-600">1 x $19.99</div> |
| </div> |
| <div class="font-medium">$19.99</div> |
| </div> |
| </div> |
| |
| <div class="border-t border-gray-200 pt-3 mb-4"> |
| <div class="flex justify-between mb-1"> |
| <span class="text-gray-600">Subtotal:</span> |
| <span id="receiptSubtotal" class="font-medium">$19.99</span> |
| </div> |
| <div class="flex justify-between mb-1"> |
| <span class="text-gray-600">Tax (10%):</span> |
| <span id="receiptTax" class="font-medium">$2.00</span> |
| </div> |
| <div class="flex justify-between text-lg font-bold"> |
| <span>Total:</span> |
| <span id="receiptTotal" class="text-indigo-600">$21.99</span> |
| </div> |
| </div> |
| |
| <div class="text-center text-sm text-gray-600 mb-4"> |
| Thank you for shopping with us! |
| </div> |
| |
| <div class="flex justify-center space-x-4"> |
| <button id="printReceipt" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 flex items-center space-x-2"> |
| <i class="fas fa-print"></i> |
| <span>Print Receipt</span> |
| </button> |
| <button id="emailReceipt" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 flex items-center space-x-2"> |
| <i class="fas fa-envelope"></i> |
| <span>Email Receipt</span> |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="syncToast" class="fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded-lg shadow-lg hidden flex items-center space-x-2"> |
| <i class="fas fa-check-circle"></i> |
| <span>Data synchronized successfully!</span> |
| </div> |
|
|
| <script> |
| |
| const sidebarToggle = document.getElementById('sidebarToggle'); |
| const sidebar = document.querySelector('.sidebar'); |
| const tabButtons = { |
| pos: document.getElementById('posTab'), |
| products: document.getElementById('productsTab'), |
| inventory: document.getElementById('inventoryTab'), |
| sales: document.getElementById('salesTab'), |
| settings: document.getElementById('settingsTab') |
| }; |
| const tabContents = { |
| pos: document.getElementById('posContent'), |
| products: document.getElementById('productsContent'), |
| inventory: document.getElementById('inventoryContent'), |
| sales: document.getElementById('salesContent'), |
| settings: document.getElementById('settingsContent') |
| }; |
| const currentTabTitle = document.getElementById('currentTabTitle'); |
| const addProductBtn = document.getElementById('addProductBtn'); |
| const addProductModal = document.getElementById('addProductModal'); |
| const closeAddProductModal = document.getElementById('closeAddProductModal'); |
| const cancelAddProduct = document.getElementById('cancelAddProduct'); |
| const saveProduct = document.getElementById('saveProduct'); |
| const receiptModal = document.getElementById('receiptModal'); |
| const closeReceiptModal = document.getElementById('closeReceiptModal'); |
| const printReceipt = document.getElementById('printReceipt'); |
| const emailReceipt = document.getElementById('emailReceipt'); |
| const syncBtn = document.getElementById('syncBtn'); |
| const syncStatus = document.getElementById('syncStatus'); |
| const syncToast = document.getElementById('syncToast'); |
| const completeSaleBtn = document.getElementById('completeSaleBtn'); |
| const clearCartBtn = document.getElementById('clearCartBtn'); |
| const productSearch = document.getElementById('productSearch'); |
| const categoryBtns = document.querySelectorAll('.category-btn'); |
| const productGrid = document.getElementById('productGrid'); |
| const receiptItems = document.getElementById('receiptItems'); |
| const subtotalEl = document.getElementById('subtotal'); |
| const taxEl = document.getElementById('tax'); |
| const totalEl = document.getElementById('total'); |
| const testConnectionBtn = document.getElementById('testConnectionBtn'); |
| const sheetId = document.getElementById('sheetId'); |
| |
| |
| let products = [ |
| { id: 1, name: "Wireless Headphones", sku: "SKU001", price: 99.99, cost: 60.00, stock: 25, category: "Electronics", image: null }, |
| { id: 2, name: "Organic Apples", sku: "SKU002", price: 3.99, cost: 2.00, stock: 50, category: "Groceries", image: null }, |
| { id: 3, name: "Cotton T-Shirt", sku: "SKU003", price: 19.99, cost: 10.00, stock: 30, category: "Clothing", image: null }, |
| { id: 4, name: "Smartphone", sku: "SKU004", price: 799.99, cost: 500.00, stock: 15, category: "Electronics", image: null }, |
| { id: 5, name: "Coffee Mug", sku: "SKU005", price: 12.99, cost: 5.00, stock: 40, category: "Home Goods", image: null }, |
| { id: 6, name: "Bluetooth Speaker", sku: "SKU006", price: 59.99, cost: 35.00, stock: 20, category: "Electronics", image: null }, |
| { id: 7, name: "Jeans", sku: "SKU007", price: 49.99, cost: 25.00, stock: 25, category: "Clothing", image: null }, |
| { id: 8, name: "Desk Lamp", sku: "SKU008", price: 29.99, cost: 15.00, stock: 18, category: "Home Goods", image: null } |
| ]; |
| |
| let cart = []; |
| let sales = []; |
| let currentCategory = 'All'; |
| |
| |
| function init() { |
| |
| const now = new Date(); |
| document.getElementById('receiptDate').textContent = now.toLocaleString(); |
| |
| |
| document.getElementById('receiptTransactionId').textContent = `TXN-${now.getFullYear()}${(now.getMonth()+1).toString().padStart(2, '0')}${now.getDate().toString().padStart(2, '0')}-${Math.floor(Math.random() * 1000).toString().padStart(3, '0')}`; |
| |
| |
| renderProducts(); |
| |
| |
| setupEventListeners(); |
| |
| |
| initCharts(); |
| } |
| |
| |
| function setupEventListeners() { |
| |
| sidebarToggle.addEventListener('click', () => { |
| sidebar.classList.toggle('-translate-x-full'); |
| }); |
| |
| |
| Object.keys(tabButtons).forEach(tab => { |
| tabButtons[tab].addEventListener('click', () => { |
| |
| Object.keys(tabContents).forEach(content => { |
| tabContents[content].classList.add('hidden'); |
| }); |
| |
| |
| tabContents[tab].classList.remove('hidden'); |
| |
| |
| currentTabTitle.textContent = tabButtons[tab].querySelector('span').textContent; |
| |
| |
| Object.keys(tabButtons).forEach(btn => { |
| tabButtons[btn].classList.remove('bg-indigo-900'); |
| tabButtons[btn].classList.add('hover:bg-indigo-700'); |
| }); |
| tabButtons[tab].classList.add('bg-indigo-900'); |
| tabButtons[tab].classList.remove('hover:bg-indigo-700'); |
| }); |
| }); |
| |
| |
| addProductBtn.addEventListener('click', () => { |
| addProductModal.classList.remove('hidden'); |
| }); |
| |
| closeAddProductModal.addEventListener('click', () => { |
| addProductModal.classList.add('hidden'); |
| }); |
| |
| cancelAddProduct.addEventListener('click', () => { |
| addProductModal.classList.add('hidden'); |
| }); |
| |
| saveProduct.addEventListener('click', () => { |
| |
| const newProduct = { |
| id: products.length + 1, |
| name: document.getElementById('productName').value, |
| sku: document.getElementById('productSKU').value, |
| price: parseFloat(document.getElementById('productPrice').value), |
| cost: parseFloat(document.getElementById('productCost').value), |
| stock: parseInt(document.getElementById('productStock').value), |
| category: document.getElementById('productCategory').value, |
| description: document.getElementById('productDescription').value, |
| image: null |
| }; |
| |
| products.push(newProduct); |
| renderProducts(); |
| addProductModal.classList.add('hidden'); |
| |
| |
| document.getElementById('productName').value = ''; |
| document.getElementById('productSKU').value = ''; |
| document.getElementById('productPrice').value = ''; |
| document.getElementById('productCost').value = ''; |
| document.getElementById('productStock').value = ''; |
| document.getElementById('productCategory').value = ''; |
| document.getElementById('productDescription').value = ''; |
| }); |
| |
| |
| categoryBtns.forEach(btn => { |
| btn.addEventListener('click', () => { |
| currentCategory = btn.textContent; |
| renderProducts(); |
| |
| |
| categoryBtns.forEach(b => { |
| b.classList.remove('bg-indigo-600', 'text-white'); |
| b.classList.add('bg-gray-200', 'text-gray-700', 'hover:bg-gray-300'); |
| }); |
| |
| btn.classList.add('bg-indigo-600', 'text-white'); |
| btn.classList.remove('bg-gray-200', 'text-gray-700', 'hover:bg-gray-300'); |
| }); |
| }); |
| |
| productSearch.addEventListener('input', () => { |
| renderProducts(); |
| }); |
| |
| completeSaleBtn.addEventListener('click', () => { |
| if (cart.length === 0) return; |
| |
| |
| const sale = { |
| id: sales.length + 1, |
| date: new Date(), |
| items: [...cart], |
| subtotal: calculateSubtotal(), |
| tax: calculateTax(), |
| total: calculateTotal(), |
| paymentMethod: 'Cash' |
| }; |
| |
| sales.push(sale); |
| |
| |
| cart.forEach(item => { |
| const product = products.find(p => p.id === item.id); |
| if (product) { |
| product.stock -= item.quantity; |
| } |
| }); |
| |
| |
| showReceipt(sale); |
| |
| |
| cart = []; |
| renderCart(); |
| |
| |
| renderProducts(); |
| }); |
| |
| clearCartBtn.addEventListener('click', () => { |
| cart = []; |
| renderCart(); |
| }); |
| |
| |
| syncBtn.addEventListener('click', () => { |
| |
| syncBtn.innerHTML = '<i class="fas fa-sync-alt animate-spin"></i><span>Syncing...</span>'; |
| |
| setTimeout(() => { |
| syncBtn.innerHTML = '<i class="fas fa-sync-alt"></i><span>Sync with Google</span>'; |
| showSyncToast('Data synchronized successfully!'); |
| |
| |
| const now = new Date(); |
| document.getElementById('lastSyncTime').textContent = now.toLocaleString(); |
| }, 1500); |
| }); |
| |
| syncBtn.addEventListener('mouseenter', () => { |
| syncStatus.classList.remove('hidden'); |
| }); |
| |
| syncBtn.addEventListener('mouseleave', () => { |
| syncStatus.classList.add('hidden'); |
| }); |
| |
| |
| testConnectionBtn.addEventListener('click', () => { |
| const id = sheetId.value; |
| if (!id) { |
| alert('Please enter a Google Sheet ID'); |
| return; |
| } |
| |
| testConnectionBtn.innerHTML = '<i class="fas fa-plug animate-pulse"></i><span>Testing Connection...</span>'; |
| |
| |
| setTimeout(() => { |
| testConnectionBtn.innerHTML = '<i class="fas fa-plug"></i><span>Test Connection</span>'; |
| showSyncToast('Connection to Google Sheets successful!'); |
| }, 1500); |
| }); |
| |
| |
| closeReceiptModal.addEventListener('click', () => { |
| receiptModal.classList.add('hidden'); |
| }); |
| |
| printReceipt.addEventListener('click', () => { |
| |
| alert('Receipt printed!'); |
| }); |
| |
| emailReceipt.addEventListener('click', () => { |
| |
| alert('Receipt emailed!'); |
| }); |
| } |
| |
| |
| function renderProducts() { |
| productGrid.innerHTML = ''; |
| |
| const searchTerm = productSearch.value.toLowerCase(); |
| |
| products |
| .filter(product => { |
| const matchesCategory = currentCategory === 'All' || product.category === currentCategory; |
| const matchesSearch = product.name.toLowerCase().includes(searchTerm) || |
| product.sku.toLowerCase().includes(searchTerm); |
| return matchesCategory && matchesSearch; |
| }) |
| .forEach(product => { |
| const productCard = document.createElement('div'); |
| productCard.className = 'product-card bg-white border border-gray-200 rounded-lg overflow-hidden shadow-sm cursor-pointer transition-all duration-300'; |
| productCard.innerHTML = ` |
| <div class="h-32 bg-gray-100 flex items-center justify-center"> |
| ${product.image ? |
| `<img src="${product.image}" alt="${product.name}" class="h-full w-full object-cover">` : |
| `<i class="fas fa-box-open text-4xl text-gray-400"></i>`} |
| </div> |
| <div class="p-3"> |
| <h4 class="font-medium text-gray-800 truncate">${product.name}</h4> |
| <div class="flex justify-between items-center mt-2"> |
| <span class="text-indigo-600 font-semibold">$${product.price.toFixed(2)}</span> |
| <button class="add-to-cart-btn bg-indigo-600 text-white p-1 rounded-full hover:bg-indigo-700" data-id="${product.id}"> |
| <i class="fas fa-plus"></i> |
| </button> |
| </div> |
| ${product.stock <= 0 ? |
| `<div class="text-xs text-red-500 mt-1">Out of Stock</div>` : |
| `<div class="text-xs text-gray-500 mt-1">Stock: ${product.stock}</div>`} |
| </div> |
| `; |
| |
| productGrid.appendChild(productCard); |
| }); |
| |
| |
| document.querySelectorAll('.add-to-cart-btn').forEach(btn => { |
| btn.addEventListener('click', (e) => { |
| const productId = parseInt(e.currentTarget.getAttribute('data-id')); |
| addToCart(productId); |
| }); |
| }); |
| } |
| |
| |
| function addToCart(productId) { |
| const product = products.find(p => p.id === productId); |
| if (!product || product.stock <= 0) return; |
| |
| const existingItem = cart.find(item => item.id === productId); |
| if (existingItem) { |
| existingItem.quantity += 1; |
| } else { |
| cart.push({ |
| id: productId, |
| name: product.name, |
| price: product.price, |
| quantity: 1 |
| }); |
| } |
| |
| renderCart(); |
| } |
| |
| |
| function renderCart() { |
| receiptItems.innerHTML = ''; |
| |
| if (cart.length === 0) { |
| receiptItems.innerHTML = '<div class="text-center py-8 text-gray-500">Your cart is empty</div>'; |
| subtotalEl.textContent = '$0.00'; |
| taxEl.textContent = '$0.00'; |
| totalEl.textContent = '$0.00'; |
| completeSaleBtn.innerHTML = '<i class="fas fa-check-circle"></i><span>Complete Sale ($0.00)</span>'; |
| return; |
| } |
| |
| cart.forEach(item => { |
| const product = products.find(p => p.id === item.id); |
| if (!product) return; |
| |
| const receiptItem = document.createElement('div'); |
| receiptItem.className = 'receipt-item flex justify-between items-center py-3 px-2 border-b border-gray-100 transition-colors duration-200'; |
| receiptItem.innerHTML = ` |
| <div> |
| <div class="font-medium">${item.name}</div> |
| <div class="text-sm text-gray-500">${item.quantity} x $${item.price.toFixed(2)}</div> |
| </div> |
| <div class="flex items-center"> |
| <span class="font-semibold mr-4">$${(item.price * item.quantity).toFixed(2)}</span> |
| <button class="remove-item-btn text-red-500 hover:text-red-700" data-id="${item.id}"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| `; |
| |
| receiptItems.appendChild(receiptItem); |
| }); |
| |
| |
| document.querySelectorAll('.remove-item-btn').forEach(btn => { |
| btn.addEventListener('click', (e) => { |
| const productId = parseInt(e.currentTarget.getAttribute('data-id')); |
| removeFromCart(productId); |
| }); |
| }); |
| |
| |
| const subtotal = calculateSubtotal(); |
| const tax = calculateTax(); |
| const total = calculateTotal(); |
| |
| subtotalEl.textContent = `$${subtotal.toFixed(2)}`; |
| taxEl.textContent = `$${tax.toFixed(2)}`; |
| totalEl.textContent = `$${total.toFixed(2)}`; |
| completeSaleBtn.innerHTML = `<i class="fas fa-check-circle"></i><span>Complete Sale ($${total.toFixed(2)})</span>`; |
| } |
| |
| |
| function removeFromCart(productId) { |
| const itemIndex = cart.findIndex(item => item.id === productId); |
| if (itemIndex !== -1) { |
| if (cart[itemIndex].quantity > 1) { |
| cart[itemIndex].quantity -= 1; |
| } else { |
| cart.splice(itemIndex, 1); |
| } |
| } |
| |
| renderCart(); |
| } |
| |
| |
| function calculateSubtotal() { |
| return cart.reduce((sum, item) => sum + (item.price * item.quantity), 0); |
| } |
| |
| |
| function calculateTax() { |
| return calculateSubtotal() * 0.1; |
| } |
| |
| |
| function calculateTotal() { |
| return calculateSubtotal() + calculateTax(); |
| } |
| |
| |
| function showReceipt(sale) { |
| const receiptItemsList = document.getElementById('receiptItemsList'); |
| receiptItemsList.innerHTML = ''; |
| |
| sale.items.forEach(item => { |
| const receiptItem = document.createElement('div'); |
| receiptItem.className = 'flex justify-between py-1'; |
| receiptItem.innerHTML = ` |
| <div> |
| <div>${item.name}</div> |
| <div class="text-sm text-gray-600">${item.quantity} x $${item.price.toFixed(2)}</div> |
| </div> |
| <div class="font-medium">$${(item.price * item.quantity).toFixed(2)}</div> |
| `; |
| |
| receiptItemsList.appendChild(receiptItem); |
| }); |
| |
| document.getElementById('receiptSubtotal').textContent = `$${sale.subtotal.toFixed(2)}`; |
| document.getElementById('receiptTax').textContent = `$${sale.tax.toFixed(2)}`; |
| document.getElementById('receiptTotal').textContent = `$${sale.total.toFixed(2)}`; |
| |
| receiptModal.classList.remove('hidden'); |
| } |
| |
| |
| function showSyncToast(message) { |
| syncToast.querySelector('span').textContent = message; |
| syncToast.classList.remove('hidden'); |
| |
| setTimeout(() => { |
| syncToast.classList.add('hidden'); |
| }, 3000); |
| } |
| |
| |
| function initCharts() { |
| |
| const salesCtx = document.getElementById('salesChart').getContext('2d'); |
| const salesChart = new Chart(salesCtx, { |
| type: 'line', |
| data: { |
| labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], |
| datasets: [{ |
| label: 'Sales', |
| data: [1200, 1900, 1500, 2000, 1800, 2200], |
| backgroundColor: 'rgba(79, 70, 229, 0.1)', |
| borderColor: 'rgba(79, 70, 229, 1)', |
| borderWidth: 2, |
| tension: 0.3, |
| fill: true |
| }] |
| }, |
| options: { |
| responsive: true, |
| plugins: { |
| legend: { |
| display: false |
| } |
| }, |
| scales: { |
| y: { |
| beginAtZero: true |
| } |
| } |
| } |
| }); |
| |
| |
| const productsCtx = document.getElementById('productsChart').getContext('2d'); |
| const productsChart = new Chart(productsCtx, { |
| type: 'bar', |
| data: { |
| labels: ['Headphones', 'Apples', 'T-Shirt', 'Smartphone', 'Mug'], |
| datasets: [{ |
| label: 'Units Sold', |
| data: [45, 38, 29, 22, 18], |
| backgroundColor: [ |
| 'rgba(79, 70, 229, 0.7)', |
| 'rgba(99, 102, 241, 0.7)', |
| 'rgba(129, 140, 248, 0.7)', |
| 'rgba(165, 180, 252, 0.7)', |
| 'rgba(199, 210, 254, 0.7)' |
| ], |
| borderColor: [ |
| 'rgba(79, 70, 229, 1)', |
| 'rgba(99, 102, 241, 1)', |
| 'rgba(129, 140, 248, 1)', |
| 'rgba(165, 180, 252, 1)', |
| 'rgba(199, 210, 254, 1)' |
| ], |
| borderWidth: 1 |
| }] |
| }, |
| options: { |
| responsive: true, |
| plugins: { |
| legend: { |
| display: false |
| } |
| }, |
| scales: { |
| y: { |
| beginAtZero: true |
| } |
| } |
| } |
| }); |
| } |
| |
| |
| document.addEventListener('DOMContentLoaded', init); |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=gtkh/test" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |