Edit file File name : script.js Content : <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Omni Rewards</title> <meta name="description" content="Loyalty Reward System"> <link rel="manifest" href="manifest.php"> <link id="favicon-link" rel="icon" href=""> <script src="https://cdn.tailwindcss.com"></script> <script src="https://unpkg.com/html5-qrcode"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&family=Lexend:wght@700&display=swap" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.3/dist/confetti.browser.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.23/jspdf.plugin.autotable.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/color-thief/2.3.0/color-thief.umd.js"></script> <style> body { font-family: 'Inter', sans-serif; } .font-headline { font-family: 'Lexend', sans-serif; } :root { --primary-hsl: 262 83% 57%; --background-hsl: 240 60% 99%; --accent-hsl: 220 14% 96%; } .bg-primary-gradient { background: linear-gradient(to bottom right, hsl(var(--primary-hsl)), hsl(var(--primary-hsl) / 0.8)); } .bg-primary { background-color: hsl(var(--primary-hsl)); } .text-primary { color: hsl(var(--primary-hsl)); } .border-primary { border-color: hsl(var(--primary-hsl)); } .ring-primary:focus-visible { --tw-ring-color: hsl(var(--primary-hsl)); } .bg-app-background { background-color: hsl(var(--background-hsl)); } .bg-app-accent { background-color: hsl(var(--accent-hsl)); } .modal-container { transition: opacity 0.3s ease; } .notification-container { position: fixed; bottom: 1rem; left: 50%; transform: translateX(-50%); z-index: 1000; } .dropdown-menu { z-index: 50; } </style> </head> <body class="bg-app-background text-slate-800 flex flex-col min-h-screen"> <!-- Login Page --> <div id="login-page" class="hidden flex-grow flex flex-col items-center justify-center p-4" style="background-image: radial-gradient(circle at top, hsl(var(--primary-hsl) / 0.05), transparent 40%)"> <div class="text-center mb-8 flex flex-col items-center gap-2"> <div class="logo-placeholder w-20 h-20 bg-primary/10 rounded-full flex items-center justify-center"> <i class="fas fa-star text-3xl text-primary"></i> </div> <div class="flex flex-col"> <h1 id="login-business-name" class="text-5xl font-headline font-bold text-slate-800">Omni Rewards</h1> <p class="text-slate-500">Loyalty Reward System</p> </div> </div> <div id="login-tabs" class="w-full max-w-md mb-8"> <div class="shadow-2xl rounded-2xl bg-white"> <div class="text-center p-6"> <h2 class="text-3xl font-bold text-primary font-headline">Welcome Back</h2> <p class="text-sm text-slate-500">Sign in to your account</p> </div> <div class="px-6 pb-6"> <div class="grid w-full grid-cols-2 bg-slate-100 p-1 rounded-full"> <button id="customer-tab" class="tab-trigger inline-flex items-center justify-center whitespace-nowrap rounded-full px-3 py-1.5 text-sm font-medium"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mr-2"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> Customer </button> <button id="admin-tab" class="tab-trigger inline-flex items-center justify-center whitespace-nowrap rounded-full px-3 py-1.5 text-sm font-medium"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mr-2"><rect width="18" height="18" x="3" y="4" rx="2" ry="2"/><line x1="16" x2="16" y1="2" y2="4"/><line x1="8" x2="8" y1="2" y2="4"/><line x1="3" x2="21" y1="10" y2="10"/></svg> Business </button> </div> <div id="customer-form" class="tab-content mt-6"> <form id="customer-login-form"> <input type="hidden" name="action" value="login"> <input type="hidden" name="type" value="customer"> <div id="customer-login-error" class="hidden mb-4 p-3 bg-red-50 text-red-600 rounded-md text-sm"></div> <div class="space-y-6"> <div class="space-y-2 text-left"> <label for="customer-phone" class="text-sm font-medium">Phone Number</label> <input id="customer-phone" name="customer_phone" type="tel" placeholder="+501-xxx-xxxx" required class="flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-base ring-offset-white focus-visible:outline-none focus-visible:ring-2 ring-primary"> </div> <div class="space-y-2 text-left"> <label for="customer-password" class="text-sm font-medium">Password</label> <input id="customer-password" name="customer_password" type="password" placeholder="Enter password" required class="flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-base ring-offset-white focus-visible:outline-none focus-visible:ring-2 ring-primary"> </div> </div> <button type="submit" class="w-full mt-8 text-base bg-primary text-white h-10 px-4 py-2 inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium hover:bg-opacity-90"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mr-2"><line x1="5" x2="19" y1="12" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> Sign In as Customer </button> </form> <div class="text-center mt-4 text-sm"> <span class="text-slate-600">Not a member?</span> <button id="signup-now-btn" class="font-medium text-primary hover:opacity-80">Signup now</button> </div> </div> <div id="admin-form" class="tab-content mt-6 hidden"> <form id="admin-login-form"> <input type="hidden" name="action" value="login"> <input type="hidden" name="type" value="admin"> <div id="admin-login-error" class="hidden mb-4 p-3 bg-red-50 text-red-600 rounded-md text-sm"></div> <div class="space-y-6"> <div class="space-y-2 text-left"> <label for="admin-username" class="text-sm font-medium">Username</label> <input id="admin-username" name="admin_username" type="text" placeholder="Enter username" required class="flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-base ring-offset-white focus-visible:outline-none focus-visible:ring-2 ring-primary"> </div> <div class="space-y-2 text-left"> <label for="admin-password" class="text-sm font-medium">Password</label> <input id="admin-password" name="admin_password" type="password" placeholder="Enter password" required class="flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-base ring-offset-white focus-visible:outline-none focus-visible:ring-2 ring-primary"> </div> </div> <button type="submit" class="w-full mt-8 text-base bg-primary text-white h-10 px-4 py-2 inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium hover:bg-opacity-90"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mr-2"><line x1="5" x2="19" y1="12" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> Sign In as Business </button> </form> </div> </div> </div> </div> </div> <div id="admin-dashboard" class="hidden flex-grow flex flex-col"> <main class="container mx-auto p-4 md:p-8"> <header class="flex flex-col items-center gap-8 mb-8"> <div class="flex items-center gap-4"> <div id="admin-logo-container" class="logo-placeholder w-20 h-20 bg-primary/10 rounded-full flex items-center justify-center"> <i class="fas fa-star text-3xl text-primary"></i> </div> <div class="text-left"> <h1 id="admin-business-name" class="text-4xl font-bold font-headline text-slate-800">Omni Rewards</h1> <p class="text-slate-500 mt-1">Manage your loyalty program</p> </div> </div> <div class="hidden md:flex flex-wrap justify-center items-center gap-2"> <button id="qr-scanner-btn" class="bg-green-500 hover:bg-green-600 text-white font-medium py-2 px-4 rounded-md inline-flex items-center gap-2 border border-green-600"> <i class="fas fa-plus-circle"></i> Add Point </button> <button id="settings-btn" class="bg-white hover:bg-slate-100 text-slate-700 font-medium py-2 px-4 rounded-md inline-flex items-center gap-2 border border-slate-200"> <i class="fas fa-cog"></i> Settings </button> <button id="logout-btn" class="bg-white hover:bg-slate-100 text-slate-700 font-medium py-2 px-4 rounded-md inline-flex items-center gap-2 border border-slate-200"> <i class="fas fa-sign-out-alt"></i> Logout </button> </div> </header> <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> <div class="p-6 rounded-2xl text-white shadow-lg bg-gradient-to-br from-blue-500 to-blue-600"> <div class="flex justify-between items-start mb-4"><h3 class="font-semibold text-lg">Total Customers</h3><i class="fas fa-users text-2xl opacity-80"></i></div> <p id="total-customers" class="text-5xl font-bold font-headline">0</p> <p class="text-sm opacity-90 mt-1">Registered users</p> </div> <div class="p-6 rounded-2xl text-white shadow-lg bg-primary-gradient"> <div class="flex justify-between items-start mb-4"><h3 class="font-semibold text-lg">Points This Month</h3><i class="fas fa-chart-line text-2xl opacity-80"></i></div> <p id="points-this-month" class="text-5xl font-bold font-headline">0</p> <p class="text-sm opacity-90 mt-1">Earned this month</p> </div> <div class="p-6 rounded-2xl text-white shadow-lg bg-gradient-to-br from-amber-500 to-orange-600"> <div class="flex justify-between items-start mb-4"><h3 class="font-semibold text-lg">Total Points Distributed</h3><i class="fas fa-star text-2xl opacity-80"></i></div> <p id="total-points" class="text-5xl font-bold font-headline">0</p> <p class="text-sm opacity-90 mt-1">Since program start</p> </div> <div class="p-6 rounded-2xl text-white shadow-lg bg-gradient-to-br from-emerald-500 to-green-600"> <div class="flex justify-between items-start mb-4"><h3 class="font-semibold text-lg">Rewards Claimed</h3><i class="fas fa-gift text-2xl opacity-80"></i></div> <p id="rewards-claimed" class="text-5xl font-bold font-headline">0</p> <p class="text-sm opacity-90 mt-1">Happy customers</p> </div> </div> <div id="admin-tabs-container" class="mt-8"> <div class="border-b border-gray-200"> <nav class="-mb-px flex space-x-6" aria-label="Tabs"> <button class="admin-tab-btn whitespace-nowrap py-3 px-1 border-b-2 font-medium text-sm border-primary text-primary" data-tab="all-customers"> All Customers </button> <button class="admin-tab-btn whitespace-nowrap py-3 px-1 border-b-2 font-medium text-sm border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" data-tab="activity"> Monthly Activity </button> <button class="admin-tab-btn whitespace-nowrap py-3 px-1 border-b-2 font-medium text-sm border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" data-tab="reports"> Reports </button> </nav> </div> <div id="all-customers-tab-content" class="admin-tab-content py-4"> <div class="flex flex-col sm:flex-row items-center justify-between gap-4 my-6"> <div class="relative w-full sm:max-w-xs"> <i class="fas fa-search absolute left-3 top-1/2 -translate-y-1/2 h-5 w-5 text-slate-400"></i> <input type="text" id="customer-search" class="w-full pl-10 h-10 px-3 py-2 border border-slate-200 rounded-md focus:outline-none focus-visible:ring-2 ring-primary" placeholder="Search customers..."> </div> <button id="add-customer-btn" class="w-full sm:w-auto px-4 py-2 bg-primary text-white rounded-md text-sm hover:bg-opacity-90 transition duration-200 flex items-center justify-center gap-2"> <i class="fas fa-user-plus"></i> Add Customer </button> </div> <div id="customer-display-area" class="space-y-12"> <!-- Customer cards and table will be rendered here by JavaScript --> </div> </div> <div id="activity-tab-content" class="admin-tab-content hidden py-4"> <div class="bg-white rounded-lg shadow p-4 md:p-6"> <h3 class="text-xl font-bold mb-1">Monthly Points Activity</h3> <p class="text-sm text-gray-500 mb-4">(Double-click to zoom)</p> <div class="min-h-[350px] w-full"> <canvas id="activity-chart"></canvas> </div> </div> </div> <div id="reports-tab-content" class="admin-tab-content hidden py-4"> <div class="bg-white rounded-lg shadow p-4 md:p-6"> <h3 class="text-xl font-bold mb-4">Generate Reports</h3> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 items-end"> <div> <label for="report-type" class="block text-sm font-medium text-gray-700 mb-1">Report Type</label> <select id="report-type" class="w-full p-2 border border-gray-300 rounded-md"> <option value="monthly_points">Total Points for the Month</option> <option value="yearly_points">All Points for the Year</option> <option value="points_by_customer">Points by Single Customer</option> </select> </div> <div id="customer-selector-container" class="hidden relative"> <label for="report-customer-search" class="block text-sm font-medium text-gray-700 mb-1">Select Customer</label> <input type="text" id="report-customer-search" class="w-full p-2 border border-gray-300 rounded-md" placeholder="Search for customer..."> <input type="hidden" id="report-customer-id"> <div id="report-search-results" class="absolute z-10 w-full bg-white border border-gray-300 rounded-md mt-1 max-h-48 overflow-y-auto hidden"></div> </div> <div id="date-range-selector" class="grid grid-cols-1 sm:grid-cols-2 gap-4 col-span-1 lg:col-span-1"> <div> <label for="start-date" class="block text-sm font-medium text-gray-700 mb-1">Start Date</label> <input type="date" id="start-date" class="w-full p-2 border border-gray-300 rounded-md"> </div> <div> <label for="end-date" class="block text-sm font-medium text-gray-700 mb-1">End Date</label> <input type="date" id="end-date" class="w-full p-2 border border-gray-300 rounded-md"> </div> </div> </div> <div class="mt-6"> <button id="generate-pdf-btn" class="bg-primary text-white font-medium py-2 px-5 rounded-md inline-flex items-center gap-2 hover:bg-opacity-90"> <i class="fas fa-file-pdf"></i> Generate PDF </button> </div> </div> </div> </div> </main> <!-- Mobile Footer Nav for Admin --> <div id="admin-mobile-footer" class="md:hidden sticky bottom-0 left-0 right-0 bg-white border-t border-gray-200 p-2 flex justify-around items-center h-16"> <button id="mobile-settings-btn" class="flex flex-col items-center text-gray-600 hover:text-primary text-sm w-1/3"> <i class="fas fa-cog text-xl"></i> <span class="mt-1">Settings</span> </button> <button id="mobile-add-point-btn" class="flex flex-col items-center text-green-600 text-sm font-medium w-1/3"> <div class="w-16 h-16 flex items-center justify-center bg-green-500 text-white rounded-full shadow-lg -mt-8 border-4 border-white"> <i class="fas fa-plus text-2xl"></i> </div> <span class="mt-1">Add Point</span> </button> <button id="mobile-logout-btn" class="flex flex-col items-center text-gray-600 hover:text-primary text-sm w-1/3"> <i class="fas fa-sign-out-alt text-xl"></i> <span class="mt-1">Logout</span> </button> </div> </div> <div id="customer-dashboard" class="hidden flex-grow flex flex-col"> <div class="container mx-auto p-4 md:p-8 flex-grow"> <!-- This container will be filled by renderCustomerDashboard() --> </div> </div> <!-- MODALS CONTAINER --> <div id="modals-container"></div> <!-- NOTIFICATION CONTAINER --> <div class="notification-container"> <div id="success-notification" class="hidden mb-2"><div class="bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg flex items-center"><i class="fas fa-check-circle mr-3"></i><span id="success-message"></span></div></div> <div id="error-notification" class="hidden"><div class="bg-red-500 text-white px-6 py-3 rounded-lg shadow-lg flex items-center"><i class="fas fa-exclamation-circle mr-3"></i><span id="error-message"></span></div></div> </div> <!-- FOOTER --> <footer id="app-footer" class="py-4 px-2 text-center text-gray-600 text-sm border-t border-gray-100 mt-auto"> <div class="flex flex-col sm:flex-row sm:gap-2 justify-center items-center"> <span>Copyright © <span id="current-year"></span> <span id="business-name-footer"></span>. All Rights Reserved</span> <span class="hidden sm:inline">|</span> <span>Developed by Omni Studio</span> </div> </footer> <script src="app.js"></script> </body> </html> Save