Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>RetailPro POS - Modern Retail Management System</title> | |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/animejs/lib/anime.iife.min.js"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap'); | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| } | |
| .glass-effect { | |
| backdrop-filter: blur(10px); | |
| background: rgba(255, 255, 255, 0.1); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .dark .glass-effect { | |
| background: rgba(0, 0, 0, 0.3); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| } | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| } | |
| .dark .gradient-bg { | |
| background: linear-gradient(135deg, #4c51bf 0%, #553c9a 100%); | |
| } | |
| .hover-scale { | |
| transition: transform 0.2s ease-in-out; | |
| } | |
| .hover-scale:hover { | |
| transform: scale(1.02); | |
| } | |
| .animate-float { | |
| animation: float 3s ease-in-out infinite; | |
| } | |
| @keyframes float { | |
| 0%, 100% { transform: translateY(0px); } | |
| 50% { transform: translateY(-10px); } | |
| } | |
| .custom-scrollbar::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| .custom-scrollbar::-webkit-scrollbar-track { | |
| background: rgba(0, 0, 0, 0.1); | |
| border-radius: 3px; | |
| } | |
| .custom-scrollbar::-webkit-scrollbar-thumb { | |
| background: rgba(0, 0, 0, 0.3); | |
| border-radius: 3px; | |
| } | |
| .dark .custom-scrollbar::-webkit-scrollbar-track { | |
| background: rgba(255, 255, 255, 0.1); | |
| } | |
| .dark .custom-scrollbar::-webkit-scrollbar-thumb { | |
| background: rgba(255, 255, 255, 0.3); | |
| } | |
| .pulse-animation { | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { opacity: 1; } | |
| 50% { opacity: 0.7; } | |
| 100% { opacity: 1; } | |
| } | |
| .slide-in { | |
| animation: slideIn 0.3s ease-out; | |
| } | |
| @keyframes slideIn { | |
| from { transform: translateY(-20px); opacity: 0; } | |
| to { transform: translateY(0); opacity: 1; } | |
| } | |
| .fade-in { | |
| animation: fadeIn 0.5s ease-out; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; } | |
| to { opacity: 1; } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 dark:bg-gray-900 transition-colors duration-300"> | |
| <div id="app"> | |
| <!-- Loading Screen --> | |
| <div class="fixed inset-0 bg-gradient-to-br from-blue-600 to-purple-700 flex items-center justify-center z-50" id="loading-screen"> | |
| <div class="text-center text-white"> | |
| <div class="animate-float mb-4"> | |
| <i data-feather="shopping-cart" class="w-16 h-16 mx-auto"></i> | |
| </div> | |
| <h1 class="text-3xl font-bold mb-2">RetailPro POS</h1> | |
| <p class="text-blue-100">Loading your retail management system...</p> | |
| <div class="mt-4 flex justify-center"> | |
| <div class="w-2 h-2 bg-white rounded-full mx-1 pulse-animation"></div> | |
| <div class="w-2 h-2 bg-white rounded-full mx-1 pulse-animation" style="animation-delay: 0.2s;"></div> | |
| <div class="w-2 h-2 bg-white rounded-full mx-1 pulse-animation" style="animation-delay: 0.4s;"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Main App Container --> | |
| <div class="min-h-screen transition-colors duration-300" id="main-app" style="display: none;"> | |
| <!-- Header --> | |
| <header class="bg-white/80 dark:bg-gray-800/80 backdrop-blur-md shadow-lg border-b border-white/20 dark:border-gray-700/20 sticky top-0 z-40"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="flex justify-between items-center py-4"> | |
| <div class="flex items-center space-x-4"> | |
| <div class="w-10 h-10 bg-gradient-to-br from-blue-500 to-purple-600 rounded-xl flex items-center justify-center shadow-lg hover-scale"> | |
| <i data-feather="shopping-bag" class="w-6 h-6 text-white"></i> | |
| </div> | |
| <div> | |
| <h1 class="text-2xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">RetailPro POS</h1> | |
| <p class="text-sm text-gray-500 dark:text-gray-400">Modern Retail Management</p> | |
| </div> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <div class="hidden sm:flex items-center text-sm text-gray-600 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 px-3 py-1 rounded-full"> | |
| <i data-feather="user" class="w-4 h-4 mr-2"></i> | |
| <span id="owner-name">Rajesh Kumar</span> | |
| </div> | |
| <button id="theme-toggle" class="p-2 rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"> | |
| <i data-feather="sun" class="w-5 h-5 text-yellow-500 dark:hidden"></i> | |
| <i data-feather="moon" class="w-5 h-5 text-blue-400 hidden dark:block"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Navigation --> | |
| <nav class="bg-white/70 dark:bg-gray-800/70 backdrop-blur-md shadow-sm border-b border-white/30 dark:border-gray-700/30 sticky top-16 z-30"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="flex space-x-1 sm:space-x-4 overflow-x-auto py-2" id="nav-tabs"> | |
| <!-- Navigation tabs will be generated by JavaScript --> | |
| </div> | |
| </div> | |
| </nav> | |
| <!-- Main Content --> | |
| <main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> | |
| <div id="content-area"> | |
| <!-- Content will be dynamically loaded here --> | |
| </div> | |
| </main> | |
| <!-- Modals --> | |
| <div id="modal-container"></div> | |
| </div> | |
| </div> | |
| <script> | |
| // Global state management | |
| class AppState { | |
| constructor() { | |
| this.state = { | |
| activeTab: 'billing', | |
| theme: 'light', | |
| products: [ | |
| { id: 1, name: 'Parle-G Biscuits', barcode: '8901234567890', price: 10, gst: 18, stock: 100, category: 'Snacks' }, | |
| { id: 2, name: 'Dairy Milk Chocolate', barcode: '8901234567891', price: 20, gst: 12, stock: 50, category: 'Chocolates' }, | |
| { id: 3, name: 'Nescafe Coffee', barcode: '8901234567892', price: 180, gst: 18, stock: 30, category: 'Beverages' }, | |
| { id: 4, name: 'Amul Butter', barcode: '8901234567893', price: 45, gst: 5, stock: 40, category: 'Dairy' }, | |
| { id: 5, name: 'Colgate Toothpaste', barcode: '8901234567894', price: 85, gst: 18, stock: 60, category: 'Personal Care' } | |
| ], | |
| suppliers: [ | |
| { id: 1, name: 'ABC Distributors', address: '123 Main Street, Mumbai', gstNo: '27AABCCDDEEFFG', openingBalance: 5000, balanceType: 'Credit' }, | |
| { id: 2, name: 'XYZ Wholesalers', address: '456 Market Road, Delhi', gstNo: '07XYZPQRST1234Z', openingBalance: 2500, balanceType: 'Credit' } | |
| ], | |
| categories: [ | |
| { id: 1, name: 'Snacks' }, | |
| { id: 2, name: 'Chocolates' }, | |
| { id: 3, name: 'Beverages' }, | |
| { id: 4, name: 'Dairy' }, | |
| { id: 5, name: 'Personal Care' } | |
| ], | |
| gstRates: [ | |
| { id: 1, rate: 5, description: 'Dairy Products' }, | |
| { id: 2, rate: 12, description: 'Chocolates & Confectionery' }, | |
| { id: 3, rate: 18, description: 'General Goods' }, | |
| { id: 4, rate: 28, description: 'Luxury Items' } | |
| ], | |
| cart: [], | |
| purchaseCart: [], | |
| searchTerm: '', | |
| purchaseSearchTerm: '', | |
| invoiceNumber: 1001, | |
| purchaseInvoiceNumber: 2001, | |
| customerName: '', | |
| supplierName: '', | |
| customerPhone: '', | |
| supplierPhone: '', | |
| paymentMethod: 'cash', | |
| purchasePaymentMethod: 'cash', | |
| salesReport: [], | |
| purchaseReport: [], | |
| dayBook: [], | |
| selectedDate: new Date().toISOString().split('T')[0], | |
| shopProfile: { | |
| shopName: 'SHREE GANESH TRADERS', | |
| ownerName: 'Rajesh Kumar', | |
| address: '123 Main Street, Mumbai, Maharashtra', | |
| phone: '9876543210', | |
| email: 'info@shreeganeshtraders.com', | |
| gstin: '27AABCCDDEEFFG' | |
| } | |
| }; | |
| this.listeners = []; | |
| } | |
| getState() { | |
| return this.state; | |
| } | |
| setState(newState) { | |
| this.state = { ...this.state, ...newState }; | |
| this.notifyListeners(); | |
| } | |
| subscribe(listener) { | |
| this.listeners.push(listener); | |
| } | |
| notifyListeners() { | |
| this.listeners.forEach(listener => listener(this.state)); | |
| } | |
| } | |
| // Initialize app state | |
| const appState = new AppState(); | |
| // UI Components | |
| class UIComponents { | |
| static createProductCard(product, onAddToCart) { | |
| return ` | |
| <div class="border border-gray-200 dark:border-gray-700 rounded-xl p-4 hover:shadow-lg transition-all duration-300 cursor-pointer bg-white dark:bg-gray-800 hover:bg-blue-50 dark:hover:bg-blue-900/20 hover-scale" onclick="${onAddToCart}"> | |
| <div class="flex justify-between items-start mb-2"> | |
| <h3 class="font-semibold text-gray-800 dark:text-white text-sm">${product.name}</h3> | |
| <span class="text-xs bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-400 px-2 py-1 rounded-full">${product.category}</span> | |
| </div> | |
| <p class="text-xs text-gray-500 dark:text-gray-400 mb-2">Barcode: ${product.barcode}</p> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-lg font-bold text-blue-600 dark:text-blue-400">₹${product.price}</span> | |
| <span class="text-xs text-green-600 dark:text-green-400 bg-green-100 dark:bg-green-900 px-2 py-1 rounded-full">${product.gst}% GST</span> | |
| </div> | |
| <p class="text-xs text-gray-500 dark:text-gray-400 mt-2">Stock: ${product.stock}</p> | |
| </div> | |
| `; | |
| } | |
| static createCartItem(item, isPurchase = false) { | |
| const updateFunction = isPurchase ? `updatePurchaseQuantity(${item.id}, ${item.quantity - 1})` : `updateQuantity(${item.id}, ${item.quantity - 1})`; | |
| const removeFunction = isPurchase ? `removeFromPurchaseCart(${item.id})` : `removeFromCart(${item.id})`; | |
| const price = isPurchase ? (item.purchasePrice || item.price) : item.price; | |
| return ` | |
| <div class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700 rounded-lg slide-in"> | |
| <div class="flex-1"> | |
| <h4 class="font-medium text-sm text-gray-800 dark:text-white">${item.name}</h4> | |
| <p class="text-xs text-gray-600 dark:text-gray-300">₹${price} × ${item.quantity}</p> | |
| ${isPurchase ? `<p class="text-xs text-blue-600 dark:text-blue-400">Purchase: ₹${(item.purchasePrice || item.price).toFixed(2)}</p>` : ''} | |
| </div> | |
| <div class="flex items-center space | |
| </body> | |
| </html> |