Download index.html from JOHNFAYEZ/https-huggingface-co-spaces-enzostvs-deepsite: direct link, hf CLI and curl.
- Browser
- Download file 65.5 kB
-
https://huggingface.co/spaces/JOHNFAYEZ/https-huggingface-co-spaces-enzostvs-deepsite/resolve/main/index.html
- Command line
-
hf download hf://spaces/JOHNFAYEZ/https-huggingface-co-spaces-enzostvs-deepsite/index.html
-
curl -L -o index.html https://huggingface.co/spaces/JOHNFAYEZ/https-huggingface-co-spaces-enzostvs-deepsite/resolve/main/index.html
65.5 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Voice-Powered Smart Personal Assistant</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #6e8efb, #a777e3); | |
| } | |
| .voice-pulse { | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { box-shadow: 0 0 0 0 rgba(110, 142, 251, 0.7); } | |
| 70% { box-shadow: 0 0 0 15px rgba(110, 142, 251, 0); } | |
| 100% { box-shadow: 0 0 0 0 rgba(110, 142, 251, 0); } | |
| } | |
| .feature-card:hover { | |
| transform: translateY(-5px); | |
| transition: all 0.3s ease; | |
| } | |
| .language-flag { | |
| width: 30px; | |
| height: 20px; | |
| object-fit: cover; | |
| border-radius: 3px; | |
| margin-right: 8px; | |
| } | |
| .manual-controls-form { | |
| display: none; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background-color: rgba(0,0,0,0.5); | |
| z-index: 1000; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| .manual-controls-form.active { | |
| display: flex; | |
| } | |
| </style> | |
| </head> | |
| <body class="font-sans bg-gray-50"> | |
| <!-- Header --> | |
| <header class="gradient-bg text-white py-12 px-4 md:px-8 relative"> | |
| <!-- New Ringtone Notification --> | |
| <div id="ringtoneNotification" class="fixed bottom-6 left-6 bg-green-600 text-white px-6 py-3 rounded-full shadow-lg flex items-center space-x-2 z-50 animate-pulse cursor-pointer" onclick="startVoiceAssistant()"> | |
| <i class="fas fa-bell text-xl"></i> | |
| <span>Tap to activate voice assistant</span> | |
| </div> | |
| <!-- User Status --> | |
| <div class="absolute top-4 right-4 flex items-center space-x-2"> | |
| <div class="bg-white bg-opacity-20 px-4 py-1 rounded-full flex items-center" id="userStatus"> | |
| <i class="fas fa-user-circle mr-2"></i> | |
| <span>Guest</span> | |
| </div> | |
| <div class="relative group"> | |
| <button class="bg-white bg-opacity-20 p-2 rounded-full hover:bg-opacity-30"> | |
| <i class="fas fa-cog"></i> | |
| </button> | |
| <div class="absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1 z-10 hidden group-hover:block"> | |
| <a href="#" class="block px-4 py-2 text-gray-800 hover:bg-purple-100" id="adminPanelLink">Admin Panel</a> | |
| <a href="#" class="block px-4 py-2 text-gray-800 hover:bg-purple-100" id="resetData">Reset All Data</a> | |
| <a href="#" class="block px-4 py-2 text-gray-800 hover:bg-purple-100" id="logoutBtn">Logout</a> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="container mx-auto max-w-6xl"> | |
| <div class="flex flex-col md:flex-row items-center justify-between"> | |
| <div class="md:w-1/2 mb-8 md:mb-0"> | |
| <h1 class="text-4xl md:text-5xl font-bold mb-4">Voice-Powered Smart Personal Assistant</h1> | |
| <p class="text-xl mb-6">Manage finances, appointments, and reminders through natural voice commands in multiple languages.</p> | |
| <div class="flex flex-wrap gap-3 mb-6"> | |
| <span class="bg-white bg-opacity-20 px-4 py-2 rounded-full flex items-center"> | |
| <img src="https://flagcdn.com/w20/us.png" class="language-flag"> English | |
| </span> | |
| <span class="bg-white bg-opacity-20 px-4 py-2 rounded-full flex items-center"> | |
| <img src="https://flagcdn.com/w20/eg.png" class="language-flag"> Arabic | |
| </span> | |
| <span class="bg-white bg-opacity-20 px-4 py-2 rounded-full flex items-center"> | |
| <img src="https://flagcdn.com/w20/es.png" class="language-flag"> Spanish | |
| </span> | |
| </div> | |
| <button class="bg-white text-purple-700 font-bold px-6 py-3 rounded-lg hover:bg-gray-100 transition"> | |
| <i class="fas fa-microphone mr-2"></i> Try Voice Demo | |
| </button> | |
| </div> | |
| <div class="md:w-1/2 flex justify-center"> | |
| <div class="relative"> | |
| <div class="bg-white bg-opacity-20 rounded-3xl p-2 inline-block"> | |
| <img src="https://i.imgur.com/JYw0lY7.png" alt="App Mockup" class="h-80 md:h-96 rounded-2xl"> | |
| </div> | |
| <div class="absolute -bottom-6 -right-6 bg-white p-4 rounded-full shadow-xl voice-pulse"> | |
| <i class="fas fa-microphone text-purple-600 text-2xl"></i> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Login Form --> | |
| <div class="mt-8 bg-white bg-opacity-20 rounded-xl p-6 max-w-md mx-auto"> | |
| <h3 class="text-xl font-bold mb-4 text-center">Login to Your Account</h3> | |
| <form class="space-y-4" id="loginForm"> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Username</label> | |
| <input type="text" name="username" class="w-full px-4 py-2 bg-white bg-opacity-20 border border-white border-opacity-30 rounded-lg focus:outline-none focus:ring-2 focus:ring-white" placeholder="Enter username"> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Password</label> | |
| <input type="password" name="password" class="w-full px-4 py-2 bg-white bg-opacity-20 border border-white border-opacity-30 rounded-lg focus:outline-none focus:ring-2 focus:ring-white" placeholder="Enter password"> | |
| </div> | |
| <div class="flex items-center"> | |
| <input type="checkbox" id="adminLogin" name="admin" class="mr-2"> | |
| <label for="adminLogin" class="text-sm">Login as Admin</label> | |
| </div> | |
| <button type="submit" class="w-full bg-white text-purple-700 font-bold px-6 py-2 rounded-lg hover:bg-gray-100 transition"> | |
| Login | |
| </button> | |
| <p class="text-sm text-center"> | |
| Don't have an account? | |
| <a href="#" class="font-medium hover:underline">Sign up</a> | |
| </p> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Dashboard Section (Visible After Login) --> | |
| <section id="dashboard" class="py-16 px-4 md:px-8 hidden"> | |
| <div class="container mx-auto max-w-6xl"> | |
| <h2 class="text-3xl font-bold mb-8">Dashboard Overview</h2> | |
| <!-- Summary Cards --> | |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12"> | |
| <!-- Balance Summary --> | |
| <div class="bg-white rounded-xl shadow-lg p-6"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-gray-500">Current Balance</p> | |
| <h3 class="text-2xl font-bold" id="currentBalance">€0.00</h3> | |
| </div> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-wallet text-white text-xl"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Upcoming Appointments --> | |
| <div class="bg-white rounded-xl shadow-lg p-6"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-gray-500">Upcoming</p> | |
| <h3 class="text-2xl font-bold" id="upcomingCount">0</h3> | |
| <p class="text-sm text-gray-500">Appointments</p> | |
| </div> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-calendar-alt text-white text-xl"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Debts Owed --> | |
| <div class="bg-white rounded-xl shadow-lg p-6"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-gray-500">You Owe</p> | |
| <h3 class="text-2xl font-bold text-red-600" id="youOwe">€0.00</h3> | |
| </div> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-hand-holding-usd text-white text-xl"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Debts Owed to You --> | |
| <div class="bg-white rounded-xl shadow-lg p-6"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-gray-500">Owed to You</p> | |
| <h3 class="text-2xl font-bold text-green-600" id="owedToYou">€0.00</h3> | |
| </div> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-money-bill-wave text-white text-xl"></i> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Financial Charts --> | |
| <div class="bg-white rounded-xl shadow-lg p-6 mb-8"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h3 class="text-xl font-bold">Financial Overview</h3> | |
| <div class="flex space-x-2"> | |
| <button class="px-3 py-1 bg-purple-100 text-purple-700 rounded-lg text-sm">Monthly</button> | |
| <button class="px-3 py-1 bg-gray-100 text-gray-700 rounded-lg text-sm">Yearly</button> | |
| </div> | |
| </div> | |
| <div class="h-64 bg-gray-50 rounded-lg flex items-center justify-center"> | |
| <p class="text-gray-400">Charts will appear here</p> | |
| </div> | |
| </div> | |
| <!-- Upcoming Appointments Table --> | |
| <div class="bg-white rounded-xl shadow-lg p-6"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h3 class="text-xl font-bold">Upcoming Appointments</h3> | |
| <button class="px-3 py-1 bg-purple-600 text-white rounded-lg text-sm flex items-center"> | |
| <i class="fas fa-plus mr-1"></i> Add | |
| </button> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <table class="min-w-full"> | |
| <thead> | |
| <tr class="text-left border-b"> | |
| <th class="pb-3">Date</th> | |
| <th class="pb-3">Contact</th> | |
| <th class="pb-3">Location</th> | |
| <th class="pb-3">Notes</th> | |
| </tr> | |
| </thead> | |
| <tbody id="appointmentsTable"> | |
| <tr class="border-b"> | |
| <td class="py-3">No upcoming appointments</td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Features Section --> | |
| <section class="py-16 px-4 md:px-8"> | |
| <div class="container mx-auto max-w-6xl"> | |
| <h2 class="text-3xl font-bold text-center mb-12">Core Features</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> | |
| <!-- Feature 1 --> | |
| <div class="feature-card bg-white rounded-xl shadow-lg p-6 hover:shadow-xl"> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center mb-4"> | |
| <i class="fas fa-microphone text-white text-xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold mb-3">Voice Commands</h3> | |
| <p class="text-gray-600 mb-4">Control everything with natural voice in multiple languages. Example: "Add 100 euros to Sarah for the wedding, due next Friday."</p> | |
| <div class="bg-gray-100 rounded-lg p-3 text-sm"> | |
| <p class="font-mono text-purple-700">"Set meeting with Alex tomorrow at 3pm at coffee shop"</p> | |
| </div> | |
| </div> | |
| <!-- Feature 2 --> | |
| <div class="feature-card bg-white rounded-xl shadow-lg p-6 hover:shadow-xl"> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center mb-4"> | |
| <i class="fas fa-user-friends text-white text-xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold mb-3">Personal Profiles</h3> | |
| <p class="text-gray-600 mb-4">Each contact has a dedicated profile with full financial history, appointments, and balance tracking.</p> | |
| <div class="flex items-center mt-4"> | |
| <div class="w-8 h-8 rounded-full bg-purple-100 flex items-center justify-center mr-2"> | |
| <i class="fas fa-user text-purple-600 text-sm"></i> | |
| </div> | |
| <div> | |
| <p class="font-medium">New User</p> | |
| <p class="text-xs text-gray-500">Balance: <span class="text-gray-500">€0</span></p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Feature 3 --> | |
| <div class="feature-card bg-white rounded-xl shadow-lg p-6 hover:shadow-xl"> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center mb-4"> | |
| <i class="fas fa-hand-holding-usd text-white text-xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold mb-3">Dual-Sided Debt Tracking</h3> | |
| <p class="text-gray-600 mb-4">Track both what others owe you and what you owe others with timestamps and categorization.</p> | |
| <div class="flex justify-between text-sm mt-4"> | |
| <div class="text-center"> | |
| <div class="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-1"> | |
| <i class="fas fa-arrow-down text-green-600"></i> | |
| </div> | |
| <p>You Owe</p> | |
| <p class="font-bold text-green-600">€0</p> | |
| </div> | |
| <div class="text-center"> | |
| <div class="w-10 h-10 bg-red-100 rounded-full flex items-center justify-center mx-auto mb-1"> | |
| <i class="fas fa-arrow-up text-red-600"></i> | |
| </div> | |
| <p>Owed to You</p> | |
| <p class="font-bold text-red-600">€0</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Feature 4 --> | |
| <div class="feature-card bg-white rounded-xl shadow-lg p-6 hover:shadow-xl"> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center mb-4"> | |
| <i class="fas fa-calendar-alt text-white text-xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold mb-3">Appointment Scheduler</h3> | |
| <p class="text-gray-600 mb-4">Schedule meetings with date, time, location and reason - all by voice command.</p> | |
| <div class="bg-blue-50 rounded-lg p-3 text-sm mt-4"> | |
| <div class="flex items-center mb-1"> | |
| <i class="fas fa-clock text-blue-500 mr-2"></i> | |
| <p>No upcoming</p> | |
| </div> | |
| <div class="flex items-center"> | |
| <i class="fas fa-map-marker-alt text-blue-500 mr-2"></i> | |
| <p>No location</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Feature 5 --> | |
| <div class="feature-card bg-white rounded-xl shadow-lg p-6 hover:shadow-xl"> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center mb-4"> | |
| <i class="fas fa-bell text-white text-xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold mb-3">Smart Reminders</h3> | |
| <p class="text-gray-600 mb-4">Get automatic reminders for due payments and upcoming appointments.</p> | |
| <div class="bg-yellow-50 rounded-lg p-3 text-sm mt-4"> | |
| <div class="flex items-start"> | |
| <i class="fas fa-exclamation-circle text-yellow-500 mt-1 mr-2"></i> | |
| <div> | |
| <p class="font-medium">No reminders</p> | |
| <p class="text-xs">No pending payments</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Feature 6 - Manual Controls --> | |
| <div class="feature-card bg-white rounded-xl shadow-lg p-6 hover:shadow-xl"> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center mb-4"> | |
| <i class="fas fa-edit text-white text-xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold mb-3">Manual Controls</h3> | |
| <p class="text-gray-600 mb-4">Add, edit, or delete transactions, debts, or appointments manually through an intuitive interface.</p> | |
| <div class="flex flex-col space-y-2 mt-4"> | |
| <button onclick="showManualForm('transaction')" class="bg-purple-100 text-purple-700 px-3 py-2 rounded-lg text-sm flex items-center"> | |
| <i class="fas fa-exchange-alt mr-2"></i> Add Transaction | |
| </button> | |
| <button onclick="showManualForm('debt')" class="bg-blue-100 text-blue-700 px-3 py-2 rounded-lg text-sm flex items-center"> | |
| <i class="fas fa-hand-holding-usd mr-2"></i> Add Debt | |
| </button> | |
| <button onclick="showManualForm('appointment')" class="bg-green-100 text-green-700 px-3 py-2 rounded-lg text-sm flex items-center"> | |
| <i class="fas fa-calendar-plus mr-2"></i> Add Appointment | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Admin Panel --> | |
| <div id="adminPanel" class="manual-controls-form"> | |
| <div class="bg-white rounded-xl shadow-2xl p-6 w-full max-w-2xl"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-bold">Admin Panel - All Users</h3> | |
| <button onclick="hideAdminPanel()" class="text-gray-500 hover:text-gray-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="overflow-y-auto max-h-96"> | |
| <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">Username</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Balance</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Last Login</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="usersTableBody"> | |
| <!-- Users will be populated here --> | |
| </tbody> | |
| </table> | |
| </div> | |
| <div class="mt-4 flex justify-end"> | |
| <button onclick="hideAdminPanel()" class="px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50"> | |
| Close | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Add Contact Form --> | |
| <div id="addContactForm" class="manual-controls-form"> | |
| <div class="bg-white rounded-xl shadow-2xl p-6 w-full max-w-md"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-bold">Add New Contact</h3> | |
| <button onclick="hideAddContactForm()" class="text-gray-500 hover:text-gray-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <form id="contactForm" class="space-y-4"> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Name</label> | |
| <input type="text" id="contactName" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Enter contact name"> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Phone (Optional)</label> | |
| <input type="text" id="contactPhone" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Enter phone number"> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Email (Optional)</label> | |
| <input type="email" id="contactEmail" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Enter email address"> | |
| </div> | |
| <div class="flex justify-end space-x-3 pt-4"> | |
| <button type="button" onclick="hideAddContactForm()" class="px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50"> | |
| Cancel | |
| </button> | |
| <button type="submit" class="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700"> | |
| Save Contact | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <!-- Manual Controls Form --> | |
| <div id="manualControlsForm" class="manual-controls-form"> | |
| <div class="bg-white rounded-xl shadow-2xl p-6 w-full max-w-md"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-bold" id="formTitle">Add Transaction</h3> | |
| <button onclick="hideManualForm()" class="text-gray-500 hover:text-gray-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <form id="manualForm" class="space-y-4"> | |
| <div id="contactField"> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Contact</label> | |
| <select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> | |
| <option>Select contact</option> | |
| <option>New Contact 1</option> | |
| <option>New Contact 2</option> | |
| <option>New Contact 3</option> | |
| </select> | |
| </div> | |
| <div id="amountField"> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Amount</label> | |
| <div class="flex"> | |
| <select class="w-20 px-3 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> | |
| <option>€</option> | |
| <option>$</option> | |
| <option>£</option> | |
| </select> | |
| <input type="number" class="flex-1 px-3 py-2 border-t border-b border-r border-gray-300 rounded-r-lg focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="0.00"> | |
| </div> | |
| </div> | |
| <div id="typeField"> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Type</label> | |
| <div class="grid grid-cols-2 gap-2"> | |
| <button type="button" class="bg-green-100 text-green-700 px-3 py-2 rounded-lg text-sm flex items-center justify-center"> | |
| <i class="fas fa-arrow-up mr-2"></i> You Owe | |
| </button> | |
| <button type="button" class="bg-red-100 text-red-700 px-3 py-2 rounded-lg text-sm flex items-center justify-center"> | |
| <i class="fas fa-arrow-down mr-2"></i> They Owe | |
| </button> | |
| </div> | |
| </div> | |
| <div id="dateField"> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Date</label> | |
| <input type="date" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> | |
| </div> | |
| <div id="descriptionField"> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Description</label> | |
| <textarea class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500" rows="2" placeholder="Enter description..."></textarea> | |
| </div> | |
| <div id="locationField" class="hidden"> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Location</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-purple-500" placeholder="Enter location..."> | |
| </div> | |
| <div class="flex justify-end space-x-3 pt-4"> | |
| <button type="button" onclick="hideManualForm()" class="px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50"> | |
| Cancel | |
| </button> | |
| <button type="submit" class="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700"> | |
| Save | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <!-- Advanced Features --> | |
| <section class="py-16 px-4 md:px-8 bg-gray-100"> | |
| <div class="container mx-auto max-w-6xl"> | |
| <h2 class="text-3xl font-bold text-center mb-12">Advanced Features</h2> | |
| <div class="overflow-x-auto"> | |
| <table class="min-w-full bg-white rounded-xl overflow-hidden"> | |
| <thead class="gradient-bg text-white"> | |
| <tr> | |
| <th class="py-3 px-4 text-left">Feature</th> | |
| <th class="py-3 px-4 text-left">Description</th> | |
| </tr> | |
| </thead> | |
| <tbody class="divide-y divide-gray-200"> | |
| <tr class="hover:bg-gray-50"> | |
| <td class="py-4 px-4 font-medium">📈 Smart Analytics</td> | |
| <td class="py-4 px-4">Financial trends, summaries, and spending patterns</td> | |
| </tr> | |
| <tr class="hover:bg-gray-50"> | |
| <td class="py-4 px-4 font-medium">🔁 Recurring Transactions</td> | |
| <td class="py-4 px-4">Automate regular payments like rent or subscriptions</td> | |
| </tr> | |
| <tr class="hover:bg-gray-50"> | |
| <td class="py-4 px-4 font-medium">🗂️ Tagging & Filtering</td> | |
| <td class="py-4 px-4">Organize with custom tags and advanced search</td> | |
| </tr> | |
| <tr class="hover:bg-gray-50"> | |
| <td class="py-4 px-4 font-medium">🌍 Multi-Currency</td> | |
| <td class="py-4 px-4">Support for USD, EUR, EGP with live conversion</td> | |
| </tr> | |
| <tr class="hover:bg-gray-50"> | |
| <td class="py-4 px-4 font-medium">📤 Export Options</td> | |
| <td class="py-4 px-4">PDF/Excel export for accounting or backup</td> | |
| </tr> | |
| <tr class="hover:bg-gray-50"> | |
| <td class="py-4 px-4 font-medium">🧠 AI Suggestions</td> | |
| <td class="py-4 px-4">Proactive reminders and financial insights</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Calendar Integration --> | |
| <section class="py-16 px-4 md:px-8 bg-gray-50"> | |
| <div class="container mx-auto max-w-6xl"> | |
| <h2 class="text-3xl font-bold text-center mb-12">Calendar Integration</h2> | |
| <div class="bg-white rounded-xl shadow-lg p-8 max-w-3xl mx-auto"> | |
| <div class="flex flex-col md:flex-row gap-8"> | |
| <div class="md:w-1/2"> | |
| <h3 class="text-xl font-bold mb-4">Google Calendar</h3> | |
| <p class="text-gray-600 mb-4">Sync your appointments and reminders with Google Calendar</p> | |
| <button id="googleAuthBtn" class="bg-blue-500 text-white px-4 py-2 rounded-lg flex items-center"> | |
| <i class="fab fa-google mr-2"></i> Connect Google | |
| </button> | |
| </div> | |
| <div class="md:w-1/2"> | |
| <h3 class="text-xl font-bold mb-4">Apple Calendar</h3> | |
| <p class="text-gray-600 mb-4">Sync with your iOS/Mac Calendar app</p> | |
| <button id="appleAuthBtn" class="bg-black text-white px-4 py-2 rounded-lg flex items-center"> | |
| <i class="fab fa-apple mr-2"></i> Connect Apple | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Tech Stack --> | |
| <section class="py-16 px-4 md:px-8"> | |
| <div class="container mx-auto max-w-6xl"> | |
| <h2 class="text-3xl font-bold text-center mb-12">Technology Stack</h2> | |
| <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-6"> | |
| <div class="flex flex-col items-center p-4 bg-white rounded-lg shadow"> | |
| <img src="https://i.imgur.com/5H5uK5x.png" alt="Flutter" class="h-12 mb-2"> | |
| <span class="text-sm font-medium">Flutter</span> | |
| </div> | |
| <div class="flex flex-col items-center p-4 bg-white rounded-lg shadow"> | |
| <img src="https://i.imgur.com/3QZxJ7d.png" alt="Firebase" class="h-12 mb-2"> | |
| <span class="text-sm font-medium">Firebase</span> | |
| </div> | |
| <div class="flex flex-col items-center p-4 bg-white rounded-lg shadow"> | |
| <img src="https://i.imgur.com/7Z5vXZa.png" alt="OpenAI" class="h-12 mb-2"> | |
| <span class="text-sm font-medium">OpenAI</span> | |
| </div> | |
| <div class="flex flex-col items-center p-4 bg-white rounded-lg shadow"> | |
| <img src="https://i.imgur.com/9m7bwXk.png" alt="Hugging Face" class="h-12 mb-2"> | |
| <span class="text-sm font-medium">Hugging Face</span> | |
| </div> | |
| <div class="flex flex-col items-center p-4 bg-white rounded-lg shadow"> | |
| <img src="https://i.imgur.com/1YhZp9L.png" alt="Google Cloud" class="h-12 mb-2"> | |
| <span class="text-sm font-medium">Google Cloud</span> | |
| </div> | |
| <div class="flex flex-col items-center p-4 bg-white rounded-lg shadow"> | |
| <img src="https://i.imgur.com/vTnQ2Uw.png" alt="Dialogflow" class="h-12 mb-2"> | |
| <span class="text-sm font-medium">Dialogflow</span> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- CTA Section --> | |
| <section class="gradient-bg text-white py-16 px-4 md:px-8"> | |
| <div class="container mx-auto max-w-4xl text-center"> | |
| <h2 class="text-3xl font-bold mb-6">Ready to Transform Your Personal Management?</h2> | |
| <p class="text-xl mb-8">Integrate with Hugging Face to enhance multilingual voice understanding and smart suggestions.</p> | |
| <div class="flex flex-col sm:flex-row justify-center gap-4"> | |
| <button class="bg-white text-purple-700 font-bold px-6 py-3 rounded-lg hover:bg-gray-100 transition"> | |
| <i class="fas fa-code mr-2"></i> View API Documentation | |
| </button> | |
| <button class="bg-transparent border-2 border-white font-bold px-6 py-3 rounded-lg hover:bg-white hover:bg-opacity-10 transition"> | |
| <i class="fas fa-comment mr-2"></i> Contact Support | |
| </button> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Footer --> | |
| <footer class="bg-gray-900 text-white py-8 px-4 md:px-8"> | |
| <div class="container mx-auto max-w-6xl"> | |
| <div class="flex flex-col md:flex-row justify-between items-center"> | |
| <div class="mb-6 md:mb-0"> | |
| <h3 class="text-xl font-bold mb-2">Voice Personal Assistant</h3> | |
| <p class="text-gray-400">Smart financial and appointment management through voice</p> | |
| </div> | |
| <div class="flex space-x-6"> | |
| <a href="https://github.com" target="_blank" class="text-gray-400 hover:text-white"> | |
| <i class="fab fa-github text-xl"></i> | |
| </a> | |
| <a href="#" class="text-gray-400 hover:text-white"> | |
| <i class="fab fa-twitter text-xl"></i> | |
| </a> | |
| <a href="#" class="text-gray-400 hover:text-white"> | |
| <i class="fab fa-linkedin text-xl"></i> | |
| </a> | |
| <a href="github-setup.html" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-code text-xl"></i> | |
| </a> | |
| </div> | |
| </div> | |
| <div class="border-t border-gray-800 mt-8 pt-8 text-center text-gray-400 text-sm"> | |
| <p>© 2023 Voice Personal Assistant. All rights reserved.</p> | |
| <p class="mt-1">Designed by John Fayez</p> | |
| </div> | |
| </div> | |
| </footer> | |
| <script> | |
| // Initialize with sample data | |
| let assistantActive = true; | |
| let listening = false; | |
| // Pre-populate with sample data | |
| let users = [{ | |
| username: 'user1', | |
| password: 'pass123', | |
| isAdmin: false, | |
| balance: 1500.50, | |
| transactions: [ | |
| {type: 'payment', amount: 200, date: '2023-06-15', reason: 'Dinner with friends'}, | |
| {type: 'debt', amount: 100, date: '2023-06-10', reason: 'Loan to Ahmed', direction: 'them'}, | |
| {type: 'debt', amount: 50, date: '2023-06-05', reason: 'Taxi fare', direction: 'you'} | |
| ], | |
| appointments: [ | |
| {date: '2023-06-20T15:00:00', contact: 'Dr. Smith', location: 'Medical Center', notes: 'Annual checkup'}, | |
| {date: '2023-06-22T10:30:00', contact: 'Team Meeting', location: 'Office', notes: 'Project review'} | |
| ], | |
| contacts: [ | |
| {name: 'Ahmed', phone: '0123456789', email: 'ahmed@example.com'}, | |
| {name: 'Dr. Smith', phone: '0111222333', email: 'dr.smith@clinic.com'} | |
| ] | |
| }]; | |
| currentUser = users[0]; | |
| isAdmin = false; | |
| // Skip ringtone and auto-activate | |
| function playRingtone() { | |
| // Skip the ringtone | |
| startVoiceAssistant(); | |
| } | |
| function stopRingtone() { | |
| document.getElementById('ringtoneNotification').style.display = 'none'; | |
| } | |
| // Start voice assistant | |
| function startVoiceAssistant() { | |
| stopRingtone(); | |
| assistantActive = true; | |
| document.getElementById('assistantStatus').innerText = "Assistant Active - Ready for your command"; | |
| document.getElementById('assistantStatus').classList.remove('bg-red-100', 'text-red-700'); | |
| document.getElementById('assistantStatus').classList.add('bg-green-100', 'text-green-700'); | |
| document.getElementById('floatingMic').classList.add('bg-green-500'); | |
| } | |
| // Show welcome message | |
| function showWelcomeMessage() { | |
| // Auto-activate assistant immediately | |
| startVoiceAssistant(); | |
| updateDashboard(); | |
| // Show dashboard and hide login form | |
| document.getElementById('dashboard').classList.remove('hidden'); | |
| document.querySelector('header .container > div:last-child').classList.add('hidden'); | |
| // Update user status | |
| document.getElementById('userStatus').querySelector('span').textContent = currentUser.username; | |
| } | |
| // Voice Authentication | |
| function registerVoicePrint() { | |
| if (!('webkitSpeechRecognition' in window)) { | |
| alert('Voice authentication not supported in your browser'); | |
| return; | |
| } | |
| const recognition = new webkitSpeechRecognition(); | |
| recognition.lang = 'en-US'; | |
| recognition.interimResults = false; | |
| alert('Please say your passphrase 3 times for voice authentication'); | |
| let samples = []; | |
| recognition.onresult = function(event) { | |
| const transcript = event.results[0][0].transcript; | |
| samples.push(transcript); | |
| if (samples.length < 3) { | |
| alert(`Sample ${samples.length} recorded. Please say it again.`); | |
| recognition.start(); | |
| } else { | |
| localStorage.setItem('voicePrint', JSON.stringify(samples)); | |
| alert('Voice print registered successfully!'); | |
| } | |
| }; | |
| recognition.start(); | |
| } | |
| function authenticateWithVoice() { | |
| return new Promise((resolve) => { | |
| if (!localStorage.getItem('voicePrint')) { | |
| resolve(true); // Skip if no voice print | |
| return; | |
| } | |
| const recognition = new webkitSpeechRecognition(); | |
| recognition.lang = 'en-US'; | |
| recognition.interimResults = false; | |
| alert('Please say your passphrase to authenticate'); | |
| recognition.onresult = function(event) { | |
| const transcript = event.results[0][0].transcript; | |
| const savedSamples = JSON.parse(localStorage.getItem('voicePrint')); | |
| // Simple comparison (in real app, use proper voice recognition API) | |
| const isMatch = savedSamples.some(sample => | |
| sample.toLowerCase() === transcript.toLowerCase() | |
| ); | |
| resolve(isMatch); | |
| }; | |
| recognition.start(); | |
| }); | |
| } | |
| // Contact management | |
| let contacts = JSON.parse(localStorage.getItem('contacts')) || []; | |
| function loadContacts() { | |
| const select = document.getElementById('contactSelect'); | |
| select.innerHTML = '<option>Select contact</option>'; | |
| contacts.forEach(contact => { | |
| const option = document.createElement('option'); | |
| option.value = contact.name; | |
| option.textContent = contact.name; | |
| select.appendChild(option); | |
| }); | |
| } | |
| function showAddContactForm() { | |
| document.getElementById('addContactForm').classList.add('active'); | |
| } | |
| function hideAddContactForm() { | |
| document.getElementById('addContactForm').classList.remove('active'); | |
| document.getElementById('contactForm').reset(); | |
| } | |
| document.getElementById('contactForm').addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const name = document.getElementById('contactName').value.trim(); | |
| const phone = document.getElementById('contactPhone').value.trim(); | |
| const email = document.getElementById('contactEmail').value.trim(); | |
| if (!name) { | |
| alert('Please enter a contact name'); | |
| return; | |
| } | |
| const newContact = { | |
| name, | |
| phone, | |
| email, | |
| createdAt: new Date().toISOString() | |
| }; | |
| contacts.push(newContact); | |
| localStorage.setItem('contacts', JSON.stringify(contacts)); | |
| loadContacts(); | |
| hideAddContactForm(); | |
| alert('Contact added successfully!'); | |
| }); | |
| // Initialize contacts on page load | |
| document.addEventListener('DOMContentLoaded', loadContacts); | |
| // Manual controls form functions | |
| function showManualForm(type) { | |
| const form = document.getElementById('manualControlsForm'); | |
| const formTitle = document.getElementById('formTitle'); | |
| const locationField = document.getElementById('locationField'); | |
| const typeField = document.getElementById('typeField'); | |
| // Set form title based on type | |
| if (type === 'transaction') { | |
| formTitle.textContent = 'Add Transaction'; | |
| typeField.classList.remove('hidden'); | |
| locationField.classList.add('hidden'); | |
| } else if (type === 'debt') { | |
| formTitle.textContent = 'Add Debt'; | |
| typeField.classList.remove('hidden'); | |
| locationField.classList.add('hidden'); | |
| } else if (type === 'appointment') { | |
| formTitle.textContent = 'Add Appointment'; | |
| typeField.classList.add('hidden'); | |
| locationField.classList.remove('hidden'); | |
| } | |
| form.classList.add('active'); | |
| } | |
| function hideManualForm() { | |
| document.getElementById('manualControlsForm').classList.remove('active'); | |
| } | |
| // Close form when clicking outside | |
| document.getElementById('manualControlsForm').addEventListener('click', function(e) { | |
| if (e.target === this) { | |
| hideManualForm(); | |
| } | |
| }); | |
| // Security improvements | |
| function encryptData(data, key) { | |
| // In a real app, use proper encryption like Web Crypto API | |
| return btoa(JSON.stringify(data)); | |
| } | |
| function decryptData(encrypted, key) { | |
| try { | |
| return JSON.parse(atob(encrypted)); | |
| } catch { | |
| return null; | |
| } | |
| } | |
| // Secure user data storage | |
| const SECURE_KEY = 'voice-assistant-secure-key'; | |
| let users = []; | |
| const encryptedUsers = localStorage.getItem('users'); | |
| if (encryptedUsers) { | |
| users = decryptData(encryptedUsers, SECURE_KEY) || []; | |
| } | |
| let currentUser = null; | |
| let isAdmin = false; | |
| // Cloud Backup and Offline Mode | |
| const enableCloudBackup = true; // Toggle for cloud backup | |
| let isOnline = navigator.onLine; | |
| // Firebase configuration (replace with your actual config) | |
| const firebaseConfig = { | |
| apiKey: "YOUR_API_KEY", | |
| authDomain: "YOUR_AUTH_DOMAIN", | |
| projectId: "YOUR_PROJECT_ID", | |
| storageBucket: "YOUR_STORAGE_BUCKET", | |
| messagingSenderId: "YOUR_SENDER_ID", | |
| appId: "YOUR_APP_ID" | |
| }; | |
| // Initialize Firebase if enabled | |
| if (enableCloudBackup && isOnline) { | |
| firebase.initializeApp(firebaseConfig); | |
| const db = firebase.firestore(); | |
| // Sync local data with cloud | |
| function syncWithCloud() { | |
| if (!currentUser) return; | |
| const userRef = db.collection('users').doc(currentUser.username); | |
| userRef.set({ | |
| contacts: currentUser.contacts || [], | |
| transactions: currentUser.transactions || [], | |
| reminders: currentUser.reminders || [], | |
| lastSync: new Date().toISOString() | |
| }, { merge: true }); | |
| } | |
| // Load from cloud if available | |
| function loadFromCloud() { | |
| if (!currentUser) return; | |
| const userRef = db.collection('users').doc(currentUser.username); | |
| userRef.get().then(doc => { | |
| if (doc.exists) { | |
| const data = doc.data(); | |
| currentUser.contacts = data.contacts || []; | |
| currentUser.transactions = data.transactions || []; | |
| currentUser.reminders = data.reminders || []; | |
| localStorage.setItem('users', JSON.stringify(users)); | |
| } | |
| }); | |
| } | |
| } | |
| // Offline mode handling | |
| window.addEventListener('online', () => { | |
| isOnline = true; | |
| if (enableCloudBackup) syncWithCloud(); | |
| }); | |
| window.addEventListener('offline', () => { | |
| isOnline = false; | |
| alert('Offline mode activated. Some features may be limited.'); | |
| }); | |
| // Skip voice authentication | |
| function authenticateWithVoice() { | |
| return Promise.resolve(true); | |
| } | |
| // Auto-login with sample user | |
| document.addEventListener('DOMContentLoaded', function() { | |
| showWelcomeMessage(); | |
| // Initialize assistant status | |
| document.getElementById('assistantStatus').classList.add('transition-colors', 'duration-300'); | |
| document.getElementById('assistantStatus').innerText = "Assistant Active - Ready for your command"; | |
| document.getElementById('assistantStatus').classList.remove('bg-red-100', 'text-red-700'); | |
| document.getElementById('assistantStatus').classList.add('bg-green-100', 'text-green-700'); | |
| document.getElementById('floatingMic').classList.add('bg-green-500'); | |
| // Hide login form and show dashboard | |
| document.getElementById('dashboard').classList.remove('hidden'); | |
| document.querySelector('header .container > div:last-child').classList.add('hidden'); | |
| }); | |
| } | |
| // Bill Management | |
| function showBillManagement() { | |
| const bills = currentUser?.bills || []; | |
| const billForm = ` | |
| <div class="bg-white rounded-xl shadow-lg p-6 w-full max-w-3xl"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h3 class="text-xl font-bold">Bill Management</h3> | |
| <button onclick="hideModal()" class="text-gray-500 hover:text-gray-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6"> | |
| <button class="bg-purple-600 text-white px-4 py-2 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-plus mr-2"></i> Create Bill | |
| </button> | |
| <button class="bg-blue-600 text-white px-4 py-2 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-paper-plane mr-2"></i> Send Bill | |
| </button> | |
| <button class="bg-green-600 text-white px-4 py-2 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-file-export mr-2"></i> Export Bills | |
| </button> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <table class="min-w-full"> | |
| <thead> | |
| <tr class="text-left border-b"> | |
| <th class="pb-3">Bill #</th> | |
| <th class="pb-3">Amount</th> | |
| <th class="pb-3">Due Date</th> | |
| <th class="pb-3">Status</th> | |
| <th class="pb-3">Actions</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| ${bills.length > 0 ? | |
| bills.map(bill => ` | |
| <tr class="border-b"> | |
| <td class="py-3">${bill.id}</td> | |
| <td>${bill.amount} ${bill.currency}</td> | |
| <td>${new Date(bill.dueDate).toLocaleDateString()}</td> | |
| <td> | |
| <span class="px-2 py-1 rounded-full text-xs ${bill.paid ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'}"> | |
| ${bill.paid ? 'Paid' : 'Pending'} | |
| </span> | |
| </td> | |
| <td> | |
| <button class="text-blue-600 hover:text-blue-800 mr-2"> | |
| <i class="fas fa-eye"></i> | |
| </button> | |
| <button class="text-purple-600 hover:text-purple-800"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| </td> | |
| </tr> | |
| `).join('') : | |
| `<tr><td colspan="5" class="py-4 text-center text-gray-500">No bills found</td></tr>` | |
| } | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| `; | |
| showModal(billForm); | |
| } | |
| // Admin panel functionality | |
| function showAdminPanel() { | |
| if (!isAdmin) return; | |
| const panel = document.getElementById('adminPanel'); | |
| const tbody = document.getElementById('usersTableBody'); | |
| // Populate users table | |
| tbody.innerHTML = users.map(user => ` | |
| <tr> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="flex items-center"> | |
| <div class="text-sm font-medium text-gray-900">${user.username}</div> | |
| ${user.isAdmin ? '<span class="ml-2 px-2 py-1 text-xs bg-purple-100 text-purple-800 rounded">Admin</span>' : ''} | |
| </div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> | |
| ${user.balance} € | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> | |
| ${user.lastLogin ? new Date(user.lastLogin).toLocaleString() : 'Never'} | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm font-medium"> | |
| <button onclick="viewUserTransactions('${user.username}')" class="text-purple-600 hover:text-purple-900 mr-3">View</button> | |
| <button onclick="editUserBalance('${user.username}')" class="text-green-600 hover:text-green-900">Edit</button> | |
| </td> | |
| </tr> | |
| `).join(''); | |
| panel.classList.add('active'); | |
| } | |
| function hideAdminPanel() { | |
| document.getElementById('adminPanel').classList.remove('active'); | |
| } | |
| function viewUserTransactions(username) { | |
| const user = users.find(u => u.username === username); | |
| if (!user) return; | |
| alert(`Transactions for ${username}:\n\n${ | |
| user.transactions.map(t => | |
| `${t.amount}€ - ${t.type} - ${new Date(t.date).toLocaleDateString()}\nReason: ${t.reason}` | |
| ).join('\n\n') || 'No transactions yet' | |
| }`); | |
| } | |
| function editUserBalance(username) { | |
| const user = users.find(u => u.username === username); | |
| if (!user) return; | |
| const amount = prompt(`Enter new balance for ${username}:`, user.balance); | |
| if (amount !== null && !isNaN(amount)) { | |
| user.balance = parseFloat(amount); | |
| localStorage.setItem('users', JSON.stringify(users)); | |
| showAdminPanel(); // Refresh the view | |
| } | |
| } | |
| // Reset all data | |
| resetDataBtn.addEventListener('click', function() { | |
| if (confirm('Are you sure you want to reset ALL data? This cannot be undone!')) { | |
| users = [{ | |
| username: 'admin', | |
| password: 'admin123', | |
| isAdmin: true, | |
| balance: 0, | |
| transactions: [] | |
| }]; | |
| localStorage.setItem('users', JSON.stringify(users)); | |
| alert('All data has been reset. Only admin account remains.'); | |
| if (currentUser) logout(); | |
| } | |
| }); | |
| // Logout functionality | |
| logoutBtn.addEventListener('click', logout); | |
| function updateDashboard() { | |
| if (!currentUser) return; | |
| // Update balance summary | |
| document.getElementById('currentBalance').textContent = `€${currentUser.balance.toFixed(2)}`; | |
| // Calculate debts | |
| const debts = currentUser.transactions?.filter(t => t.type === 'debt') || []; | |
| const youOwe = debts.filter(d => d.direction === 'you').reduce((sum, d) => sum + d.amount, 0); | |
| const owedToYou = debts.filter(d => d.direction === 'them').reduce((sum, d) => sum + d.amount, 0); | |
| document.getElementById('youOwe').textContent = `€${youOwe.toFixed(2)}`; | |
| document.getElementById('owedToYou').textContent = `€${owedToYou.toFixed(2)}`; | |
| // Update appointments | |
| const appointments = currentUser.appointments?.filter(a => | |
| new Date(a.date) > new Date() | |
| ) || []; | |
| document.getElementById('upcomingCount').textContent = appointments.length; | |
| const appointmentsTable = document.getElementById('appointmentsTable'); | |
| appointmentsTable.innerHTML = appointments.length > 0 ? | |
| appointments.map(a => ` | |
| <tr class="border-b"> | |
| <td class="py-3">${new Date(a.date).toLocaleDateString()}</td> | |
| <td>${a.contact || 'N/A'}</td> | |
| <td>${a.location || 'N/A'}</td> | |
| <td>${a.notes || ''}</td> | |
| </tr> | |
| `).join('') : | |
| `<tr class="border-b"><td class="py-3" colspan="4">No upcoming appointments</td></tr>`; | |
| } | |
| // Update floating mic status | |
| function setMicListening(listeningState) { | |
| listening = listeningState; | |
| const mic = document.getElementById('floatingMic'); | |
| if (listeningState) { | |
| mic.classList.remove('bg-purple-600'); | |
| mic.classList.add('bg-red-500', 'voice-pulse', 'animate-pulse'); | |
| } else { | |
| mic.classList.remove('bg-red-500', 'animate-pulse'); | |
| mic.classList.add('bg-purple-600'); | |
| } | |
| } | |
| // Process voice commands | |
| function processVoiceCommand(command) { | |
| const assistantStatus = document.getElementById('assistantStatus'); | |
| assistantStatus.innerHTML = `<span class="font-semibold">Executing:</span> ${command}`; | |
| // Simple command recognition | |
| if (command.toLowerCase().includes("login")) { | |
| document.getElementById('loginForm').scrollIntoView({behavior: 'smooth'}); | |
| alert("Please use the login form above to access your account"); | |
| } else if (command.toLowerCase().includes("balance")) { | |
| document.getElementById('currentBalance').scrollIntoView({behavior: 'smooth'}); | |
| } else if (command.toLowerCase().includes("appointment")) { | |
| document.querySelector('[onclick*="appointment"]').click(); | |
| } else if (command.toLowerCase().includes("stop") || command.toLowerCase().includes("exit")) { | |
| assistantStatus.innerHTML = "<span class='font-semibold'>Assistant:</span> Goodbye!"; | |
| setTimeout(() => { | |
| assistantStatus.innerText = "Assistant Inactive"; | |
| assistantStatus.classList.remove('bg-green-100', 'text-green-700'); | |
| assistantStatus.classList.add('bg-red-100', 'text-red-700'); | |
| document.getElementById('floatingMic').classList.remove('bg-green-500'); | |
| assistantActive = false; | |
| }, 2000); | |
| } else { | |
| alert(`Command executed: ${command}`); | |
| } | |
| } | |
| // Voice recognition | |
| function startVoiceRecognition() { | |
| if (!assistantActive) { | |
| alert("Please activate the assistant first by clicking the bell notification"); | |
| return; | |
| } | |
| if (!('webkitSpeechRecognition' in window)) { | |
| alert('Voice recognition not supported in your browser'); | |
| return; | |
| } | |
| const recognition = new webkitSpeechRecognition(); | |
| recognition.lang = 'en-US'; | |
| recognition.continuous = true; | |
| recognition.interimResults = true; | |
| setMicListening(true); | |
| recognition.start(); | |
| recognition.onresult = function(event) { | |
| for (let i = event.resultIndex; i < event.results.length; i++) { | |
| const transcript = event.results[i][0].transcript; | |
| document.getElementById('assistantStatus').innerHTML = ` | |
| <span class="font-semibold">Listening:</span> ${transcript} | |
| `; | |
| if (event.results[i].isFinal) { | |
| recognition.stop(); | |
| setMicListening(false); | |
| processVoiceCommand(transcript); | |
| } | |
| } | |
| }; | |
| recognition.onerror = function() { | |
| setMicListening(false); | |
| document.getElementById('assistantStatus').innerText = "Voice recognition error. Try again."; | |
| }; | |
| } | |
| function logout() { | |
| currentUser = null; | |
| isAdmin = false; | |
| userStatus.querySelector('span').textContent = 'Guest'; | |
| adminPanelLink.style.display = 'none'; | |
| // Hide dashboard and show login form | |
| document.getElementById('dashboard').classList.add('hidden'); | |
| document.querySelector('header .container > div:last-child').classList.remove('hidden'); | |
| // Reset assistant | |
| document.getElementById('assistantStatus').innerText = "Assistant Inactive"; | |
| document.getElementById('assistantStatus').classList.remove('bg-green-100', 'text-green-700'); | |
| document.getElementById('assistantStatus').classList.add('bg-red-100', 'text-red-700'); | |
| assistantActive = false; | |
| } | |
| // Google Calendar Integration | |
| document.getElementById('googleAuthBtn').addEventListener('click', () => { | |
| if (!isOnline) { | |
| alert('Internet connection required for calendar integration'); | |
| return; | |
| } | |
| // This would normally use Google OAuth API | |
| alert('Redirecting to Google for authentication...'); | |
| // In a real app, you would: | |
| // 1. Authenticate with Google | |
| // 2. Get calendar API access | |
| // 3. Sync events | |
| }); | |
| // Apple Calendar Integration | |
| document.getElementById('appleAuthBtn').addEventListener('click', () => { | |
| if (!isOnline) { | |
| alert('Internet connection required for calendar integration'); | |
| return; | |
| } | |
| // This would use Apple's Calendar API | |
| alert('Redirecting to Apple for authentication...'); | |
| }); | |
| // Admin panel link | |
| adminPanelLink.addEventListener('click', function(e) { | |
| e.preventDefault(); | |
| showAdminPanel(); | |
| }); | |
| // Close panels when clicking outside | |
| document.getElementById('adminPanel').addEventListener('click', function(e) { | |
| if (e.target === this) { | |
| hideAdminPanel(); | |
| } | |
| }); | |
| </script> | |
| <!-- Floating Mic Button --> | |
| <div id="floatingMic" class="fixed bottom-6 right-6 w-16 h-16 bg-purple-600 rounded-full flex items-center justify-center text-white shadow-lg cursor-pointer z-50 voice-pulse" onclick="startVoiceRecognition()"> | |
| <i class="fas fa-microphone text-2xl"></i> | |
| </div> | |
| <!-- Assistant Status Bar --> | |
| <div id="assistantStatus" class="fixed bottom-24 left-6 right-6 bg-red-100 text-red-700 px-4 py-2 rounded-lg shadow-lg z-50"> | |
| Assistant Inactive - Ring the bell to activate | |
| </div> | |
| </body> | |
| <script> | |
| // Show welcome message when page loads | |
| document.addEventListener('DOMContentLoaded', function() { | |
| showWelcomeMessage(); | |
| // Initialize assistant status | |
| document.getElementById('assistantStatus').classList.add('transition-colors', 'duration-300'); | |
| document.getElementById('ringtoneNotification').style.display = 'none'; | |
| }); | |
| </script> | |
| </html> | |