| | <!DOCTYPE html> |
| | <html lang="en"> |
| | <head> |
| | <meta charset="UTF-8"> |
| | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | <title>COPD Medication Tracker</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> |
| | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); |
| | |
| | body { |
| | font-family: 'Poppins', sans-serif; |
| | background-color: #f0f9ff; |
| | } |
| | |
| | .medication-card { |
| | transition: all 0.3s ease; |
| | } |
| | |
| | .medication-card:hover { |
| | transform: translateY(-3px); |
| | box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); |
| | } |
| | |
| | .progress-bar { |
| | height: 8px; |
| | border-radius: 4px; |
| | background-color: #e0f2fe; |
| | } |
| | |
| | .progress-fill { |
| | height: 100%; |
| | border-radius: 4px; |
| | background-color: #0ea5e9; |
| | transition: width 0.5s ease; |
| | } |
| | |
| | .notification-badge { |
| | position: absolute; |
| | top: -8px; |
| | right: -8px; |
| | width: 20px; |
| | height: 20px; |
| | border-radius: 50%; |
| | background-color: #ef4444; |
| | color: white; |
| | display: flex; |
| | align-items: center; |
| | justify-content: center; |
| | font-size: 12px; |
| | } |
| | |
| | .modal { |
| | transition: opacity 0.3s ease, transform 0.3s ease; |
| | } |
| | |
| | .modal-enter { |
| | opacity: 0; |
| | transform: translateY(-20px); |
| | } |
| | |
| | .modal-enter-active { |
| | opacity: 1; |
| | transform: translateY(0); |
| | } |
| | </style> |
| | </head> |
| | <body class="min-h-screen"> |
| | <div class="container mx-auto px-4 py-8 max-w-6xl"> |
| | |
| | <header class="flex justify-between items-center mb-8"> |
| | <div> |
| | <h1 class="text-3xl font-bold text-sky-900">COPD Care</h1> |
| | <p class="text-sky-700">Medication Tracker</p> |
| | </div> |
| | <div class="relative"> |
| | <button id="notificationBtn" class="p-2 rounded-full bg-sky-100 text-sky-700 hover:bg-sky-200 transition"> |
| | <i class="fas fa-bell"></i> |
| | <div id="notificationCount" class="notification-badge hidden">3</div> |
| | </button> |
| | </div> |
| | </header> |
| | |
| | |
| | <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8"> |
| | <div class="bg-white rounded-xl p-6 shadow-sm"> |
| | <div class="flex items-center"> |
| | <div class="p-3 rounded-full bg-green-100 text-green-600 mr-4"> |
| | <i class="fas fa-check-circle text-xl"></i> |
| | </div> |
| | <div> |
| | <p class="text-gray-500">Today's Taken</p> |
| | <h3 class="text-2xl font-bold" id="takenToday">0</h3> |
| | </div> |
| | </div> |
| | </div> |
| | <div class="bg-white rounded-xl p-6 shadow-sm"> |
| | <div class="flex items-center"> |
| | <div class="p-3 rounded-full bg-yellow-100 text-yellow-600 mr-4"> |
| | <i class="fas fa-clock text-xl"></i> |
| | </div> |
| | <div> |
| | <p class="text-gray-500">Pending</p> |
| | <h3 class="text-2xl font-bold" id="pendingToday">0</h3> |
| | </div> |
| | </div> |
| | </div> |
| | <div class="bg-white rounded-xl p-6 shadow-sm"> |
| | <div class="flex items-center"> |
| | <div class="p-3 rounded-full bg-red-100 text-red-600 mr-4"> |
| | <i class="fas fa-times-circle text-xl"></i> |
| | </div> |
| | <div> |
| | <p class="text-gray-500">Missed</p> |
| | <h3 class="text-2xl font-bold" id="missedToday">0</h3> |
| | </div> |
| | </div> |
| | </div> |
| | </div> |
| | |
| | |
| | <div class="mb-8"> |
| | <div class="flex justify-between items-center mb-4"> |
| | <h2 class="text-xl font-semibold text-sky-900">Today's Medications</h2> |
| | <div class="text-sm text-gray-500" id="currentDate"></div> |
| | </div> |
| | |
| | <div id="todaysMeds" class="space-y-4"> |
| | |
| | </div> |
| | </div> |
| | |
| | |
| | <div class="mb-8"> |
| | <div class="flex justify-between items-center mb-4"> |
| | <h2 class="text-xl font-semibold text-sky-900">Your Medications</h2> |
| | <button id="addMedBtn" class="px-4 py-2 bg-sky-600 text-white rounded-lg hover:bg-sky-700 transition flex items-center"> |
| | <i class="fas fa-plus mr-2"></i> Add Medication |
| | </button> |
| | </div> |
| | |
| | <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" id="allMeds"> |
| | |
| | </div> |
| | </div> |
| | |
| | |
| | <div class="bg-white rounded-xl p-6 shadow-sm mb-8"> |
| | <h2 class="text-xl font-semibold text-sky-900 mb-4">This Week's Progress</h2> |
| | <div class="progress-bar mb-2"> |
| | <div class="progress-fill" style="width: 75%"></div> |
| | </div> |
| | <div class="flex justify-between text-sm text-gray-600"> |
| | <span>75% adherence</span> |
| | <span>7 of 9 doses taken</span> |
| | </div> |
| | </div> |
| | </div> |
| | |
| | |
| | <div id="medModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden modal"> |
| | <div class="bg-white rounded-xl p-6 w-full max-w-md"> |
| | <div class="flex justify-between items-center mb-4"> |
| | <h3 class="text-xl font-semibold text-sky-900">Add New Medication</h3> |
| | <button id="closeModalBtn" class="text-gray-500 hover:text-gray-700"> |
| | <i class="fas fa-times"></i> |
| | </button> |
| | </div> |
| | |
| | <form id="medForm" class="space-y-4"> |
| | <div> |
| | <label for="medName" class="block text-sm font-medium text-gray-700 mb-1">Medication Name</label> |
| | <input type="text" id="medName" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-sky-500 focus:border-sky-500" placeholder="e.g., Spiriva, Advair"> |
| | </div> |
| | |
| | <div> |
| | <label for="medType" class="block text-sm font-medium text-gray-700 mb-1">Type</label> |
| | <select id="medType" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-sky-500 focus:border-sky-500"> |
| | <option value="inhaler">Inhaler</option> |
| | <option value="tablet">Tablet</option> |
| | <option value="capsule">Capsule</option> |
| | <option value="liquid">Liquid</option> |
| | <option value="injection">Injection</option> |
| | </select> |
| | </div> |
| | |
| | <div> |
| | <label for="medDosage" class="block text-sm font-medium text-gray-700 mb-1">Dosage</label> |
| | <input type="text" id="medDosage" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-sky-500 focus:border-sky-500" placeholder="e.g., 250mcg, 10mg"> |
| | </div> |
| | |
| | <div> |
| | <label for="medFrequency" class="block text-sm font-medium text-gray-700 mb-1">Frequency</label> |
| | <select id="medFrequency" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-sky-500 focus:border-sky-500"> |
| | <option value="once">Once daily</option> |
| | <option value="twice">Twice daily</option> |
| | <option value="three">Three times daily</option> |
| | <option value="four">Four times daily</option> |
| | <option value="as_needed">As needed</option> |
| | </select> |
| | </div> |
| | |
| | <div> |
| | <label for="medTimes" class="block text-sm font-medium text-gray-700 mb-1">Times</label> |
| | <div class="space-y-2" id="timeInputs"> |
| | <div class="flex items-center"> |
| | <input type="time" class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-sky-500 focus:border-sky-500" value="08:00"> |
| | <button type="button" class="ml-2 text-red-500 hover:text-red-700"> |
| | <i class="fas fa-times"></i> |
| | </button> |
| | </div> |
| | </div> |
| | <button type="button" id="addTimeBtn" class="mt-2 text-sm text-sky-600 hover:text-sky-800 flex items-center"> |
| | <i class="fas fa-plus mr-1"></i> Add another time |
| | </button> |
| | </div> |
| | |
| | <div> |
| | <label for="medNotes" class="block text-sm font-medium text-gray-700 mb-1">Notes</label> |
| | <textarea id="medNotes" rows="3" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-sky-500 focus:border-sky-500" placeholder="Special instructions..."></textarea> |
| | </div> |
| | |
| | <div class="flex justify-end space-x-3 pt-4"> |
| | <button type="button" id="cancelMedBtn" class="px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-100">Cancel</button> |
| | <button type="submit" class="px-4 py-2 bg-sky-600 text-white rounded-lg hover:bg-sky-700">Save Medication</button> |
| | </div> |
| | </form> |
| | </div> |
| | </div> |
| | |
| | |
| | <div id="notificationModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden"> |
| | <div class="bg-white rounded-xl p-6 w-full max-w-md"> |
| | <div class="flex justify-between items-center mb-4"> |
| | <h3 class="text-xl font-semibold text-sky-900">Notifications</h3> |
| | <button id="closeNotifModalBtn" class="text-gray-500 hover:text-gray-700"> |
| | <i class="fas fa-times"></i> |
| | </button> |
| | </div> |
| | |
| | <div class="space-y-3 max-h-96 overflow-y-auto" id="notificationList"> |
| | <div class="p-3 bg-blue-50 rounded-lg border border-blue-100"> |
| | <div class="flex justify-between"> |
| | <p class="font-medium text-blue-800">Medication Reminder</p> |
| | <span class="text-xs text-blue-600">10 min ago</span> |
| | </div> |
| | <p class="text-sm text-blue-700">Time to take your Spiriva inhaler</p> |
| | </div> |
| | |
| | <div class="p-3 bg-yellow-50 rounded-lg border border-yellow-100"> |
| | <div class="flex justify-between"> |
| | <p class="font-medium text-yellow-800">Refill Reminder</p> |
| | <span class="text-xs text-yellow-600">2 days ago</span> |
| | </div> |
| | <p class="text-sm text-yellow-700">Your Advair inhaler is running low</p> |
| | </div> |
| | |
| | <div class="p-3 bg-red-50 rounded-lg border border-red-100"> |
| | <div class="flex justify-between"> |
| | <p class="font-medium text-red-800">Missed Dose</p> |
| | <span class="text-xs text-red-600">Yesterday</span> |
| | </div> |
| | <p class="text-sm text-red-700">You missed your morning dose of Prednisone</p> |
| | </div> |
| | </div> |
| | |
| | <div class="flex justify-end pt-4"> |
| | <button id="clearNotifBtn" class="px-4 py-2 text-sm text-gray-600 hover:text-gray-800">Clear All</button> |
| | </div> |
| | </div> |
| | </div> |
| | |
| | <script> |
| | |
| | const medications = [ |
| | { |
| | id: 1, |
| | name: "Spiriva", |
| | type: "inhaler", |
| | dosage: "18mcg", |
| | frequency: "once", |
| | times: ["08:00"], |
| | notes: "Take before breakfast", |
| | taken: ["2023-06-15T08:00:00"], |
| | color: "bg-blue-100", |
| | icon: "fa-inhaler", |
| | todayStatus: { taken: true, time: "08:00" } |
| | }, |
| | { |
| | id: 2, |
| | name: "Advair", |
| | type: "inhaler", |
| | dosage: "250/50mcg", |
| | frequency: "twice", |
| | times: ["08:00", "20:00"], |
| | notes: "Rinse mouth after use", |
| | taken: ["2023-06-15T08:05:00"], |
| | color: "bg-green-100", |
| | icon: "fa-inhaler", |
| | todayStatus: { taken: true, time: "08:00" } |
| | }, |
| | { |
| | id: 3, |
| | name: "Prednisone", |
| | type: "tablet", |
| | dosage: "10mg", |
| | frequency: "once", |
| | times: ["07:00"], |
| | notes: "Take with food", |
| | taken: [], |
| | color: "bg-purple-100", |
| | icon: "fa-pills", |
| | todayStatus: { taken: false, time: "07:00" } |
| | }, |
| | { |
| | id: 4, |
| | name: "Albuterol", |
| | type: "inhaler", |
| | dosage: "90mcg", |
| | frequency: "as_needed", |
| | times: [], |
| | notes: "Use for shortness of breath", |
| | taken: [], |
| | color: "bg-red-100", |
| | icon: "fa-inhaler", |
| | todayStatus: null |
| | } |
| | ]; |
| | |
| | |
| | const currentDateEl = document.getElementById('currentDate'); |
| | const todaysMedsEl = document.getElementById('todaysMeds'); |
| | const allMedsEl = document.getElementById('allMeds'); |
| | const takenTodayEl = document.getElementById('takenToday'); |
| | const pendingTodayEl = document.getElementById('pendingToday'); |
| | const missedTodayEl = document.getElementById('missedToday'); |
| | const medModal = document.getElementById('medModal'); |
| | const addMedBtn = document.getElementById('addMedBtn'); |
| | const closeModalBtn = document.getElementById('closeModalBtn'); |
| | const cancelMedBtn = document.getElementById('cancelMedBtn'); |
| | const medForm = document.getElementById('medForm'); |
| | const timeInputs = document.getElementById('timeInputs'); |
| | const addTimeBtn = document.getElementById('addTimeBtn'); |
| | const notificationBtn = document.getElementById('notificationBtn'); |
| | const notificationModal = document.getElementById('notificationModal'); |
| | const closeNotifModalBtn = document.getElementById('closeNotifModalBtn'); |
| | const clearNotifBtn = document.getElementById('clearNotifBtn'); |
| | const notificationCount = document.getElementById('notificationCount'); |
| | |
| | |
| | const today = new Date(); |
| | currentDateEl.textContent = today.toLocaleDateString('en-US', { |
| | weekday: 'long', |
| | month: 'long', |
| | day: 'numeric' |
| | }); |
| | |
| | |
| | function renderTodaysMeds() { |
| | todaysMedsEl.innerHTML = ''; |
| | |
| | const todaysMeds = medications.filter(med => med.todayStatus !== null); |
| | let takenCount = 0; |
| | let pendingCount = 0; |
| | let missedCount = 0; |
| | |
| | if (todaysMeds.length === 0) { |
| | todaysMedsEl.innerHTML = ` |
| | <div class="bg-white rounded-xl p-6 shadow-sm text-center text-gray-500"> |
| | <i class="fas fa-calendar-check text-3xl mb-2 text-sky-300"></i> |
| | <p>No medications scheduled for today</p> |
| | </div> |
| | `; |
| | return; |
| | } |
| | |
| | todaysMeds.forEach(med => { |
| | const isTaken = med.todayStatus.taken; |
| | const time = med.todayStatus.time; |
| | |
| | if (isTaken) takenCount++; |
| | else { |
| | const medTime = new Date(); |
| | const [hours, minutes] = time.split(':'); |
| | medTime.setHours(hours, minutes, 0, 0); |
| | |
| | if (today > medTime) missedCount++; |
| | else pendingCount++; |
| | } |
| | |
| | const card = document.createElement('div'); |
| | card.className = `bg-white rounded-xl p-4 shadow-sm medication-card border-l-4 ${isTaken ? 'border-green-500' : today > new Date(`${today.toDateString()} ${time}`) ? 'border-red-500' : 'border-yellow-500'}`; |
| | |
| | card.innerHTML = ` |
| | <div class="flex justify-between items-start"> |
| | <div class="flex items-center"> |
| | <div class="p-3 rounded-full ${med.color} text-${med.color.replace('bg-', 'text-').replace('-100', '-600')} mr-4"> |
| | <i class="fas ${med.icon} text-xl"></i> |
| | </div> |
| | <div> |
| | <h3 class="font-semibold">${med.name}</h3> |
| | <p class="text-sm text-gray-600">${med.dosage} • ${getFrequencyText(med.frequency)}</p> |
| | </div> |
| | </div> |
| | <div class="text-right"> |
| | <p class="text-sm font-medium ${isTaken ? 'text-green-600' : today > new Date(`${today.toDateString()} ${time}`) ? 'text-red-600' : 'text-yellow-600'}"> |
| | ${isTaken ? 'Taken' : today > new Date(`${today.toDateString()} ${time}`) ? 'Missed' : 'Pending'} at ${time} |
| | </p> |
| | ${!isTaken && today <= new Date(`${today.toDateString()} ${time}`) ? ` |
| | <button class="mt-2 px-3 py-1 bg-sky-600 text-white text-sm rounded-lg hover:bg-sky-700 transition" |
| | onclick="markAsTaken(${med.id})"> |
| | Mark as Taken |
| | </button> |
| | ` : ''} |
| | </div> |
| | </div> |
| | ${med.notes ? `<div class="mt-3 p-3 bg-gray-50 rounded-lg text-sm text-gray-700">${med.notes}</div>` : ''} |
| | `; |
| | |
| | todaysMedsEl.appendChild(card); |
| | }); |
| | |
| | takenTodayEl.textContent = takenCount; |
| | pendingTodayEl.textContent = pendingCount; |
| | missedTodayEl.textContent = missedCount; |
| | |
| | |
| | if (missedCount > 0) { |
| | notificationCount.textContent = missedCount; |
| | notificationCount.classList.remove('hidden'); |
| | } else { |
| | notificationCount.classList.add('hidden'); |
| | } |
| | } |
| | |
| | |
| | function renderAllMeds() { |
| | allMedsEl.innerHTML = ''; |
| | |
| | if (medications.length === 0) { |
| | allMedsEl.innerHTML = ` |
| | <div class="col-span-3 bg-white rounded-xl p-8 shadow-sm text-center"> |
| | <i class="fas fa-prescription-bottle-alt text-4xl mb-4 text-sky-300"></i> |
| | <h3 class="text-lg font-medium text-gray-700 mb-2">No medications added yet</h3> |
| | <p class="text-gray-500 mb-4">Add your first medication to start tracking</p> |
| | <button id="addFirstMedBtn" class="px-4 py-2 bg-sky-600 text-white rounded-lg hover:bg-sky-700 transition"> |
| | <i class="fas fa-plus mr-2"></i> Add Medication |
| | </button> |
| | </div> |
| | `; |
| | |
| | document.getElementById('addFirstMedBtn').addEventListener('click', () => { |
| | medModal.classList.remove('hidden'); |
| | medModal.classList.add('modal-enter-active'); |
| | }); |
| | |
| | return; |
| | } |
| | |
| | medications.forEach(med => { |
| | const card = document.createElement('div'); |
| | card.className = `bg-white rounded-xl p-5 shadow-sm medication-card hover:shadow-md transition`; |
| | |
| | |
| | const adherence = Math.min(100, Math.floor(Math.random() * 30) + 70); |
| | |
| | card.innerHTML = ` |
| | <div class="flex justify-between items-start mb-4"> |
| | <div class="flex items-center"> |
| | <div class="p-3 rounded-full ${med.color} text-${med.color.replace('bg-', 'text-').replace('-100', '-600')} mr-3"> |
| | <i class="fas ${med.icon} text-xl"></i> |
| | </div> |
| | <div> |
| | <h3 class="font-semibold">${med.name}</h3> |
| | <p class="text-sm text-gray-600">${med.dosage}</p> |
| | </div> |
| | </div> |
| | <span class="text-xs px-2 py-1 bg-gray-100 text-gray-700 rounded-full">${med.type}</span> |
| | </div> |
| | |
| | <div class="mb-3"> |
| | <p class="text-sm text-gray-700 mb-1"><i class="fas fa-clock mr-2 text-gray-400"></i> ${getFrequencyText(med.frequency)}</p> |
| | ${med.times.length > 0 ? ` |
| | <p class="text-sm text-gray-700"><i class="fas fa-bell mr-2 text-gray-400"></i> ${med.times.join(', ')}</p> |
| | ` : ''} |
| | </div> |
| | |
| | ${med.notes ? `<div class="mb-4 p-3 bg-gray-50 rounded-lg text-sm text-gray-700">${med.notes}</div>` : ''} |
| | |
| | <div class="flex justify-between items-center"> |
| | <div class="w-full mr-2"> |
| | <div class="text-xs text-gray-500 mb-1">Adherence</div> |
| | <div class="progress-bar"> |
| | <div class="progress-fill" style="width: ${adherence}%"></div> |
| | </div> |
| | </div> |
| | <span class="text-sm font-medium text-gray-700">${adherence}%</span> |
| | </div> |
| | |
| | <div class="flex justify-between mt-4 pt-3 border-t border-gray-100"> |
| | <button class="text-sm text-gray-500 hover:text-gray-700" onclick="editMedication(${med.id})"> |
| | <i class="fas fa-edit mr-1"></i> Edit |
| | </button> |
| | <button class="text-sm text-red-500 hover:text-red-700" onclick="deleteMedication(${med.id})"> |
| | <i class="fas fa-trash-alt mr-1"></i> Delete |
| | </button> |
| | </div> |
| | `; |
| | |
| | allMedsEl.appendChild(card); |
| | }); |
| | } |
| | |
| | |
| | function getFrequencyText(frequency) { |
| | const freqMap = { |
| | once: "Once daily", |
| | twice: "Twice daily", |
| | three: "Three times daily", |
| | four: "Four times daily", |
| | as_needed: "As needed" |
| | }; |
| | return freqMap[frequency] || frequency; |
| | } |
| | |
| | |
| | window.markAsTaken = function(id) { |
| | const medIndex = medications.findIndex(m => m.id === id); |
| | if (medIndex !== -1) { |
| | medications[medIndex].todayStatus.taken = true; |
| | medications[medIndex].taken.push(new Date().toISOString()); |
| | renderTodaysMeds(); |
| | |
| | |
| | const notification = document.createElement('div'); |
| | notification.className = 'fixed top-4 right-4 px-4 py-2 bg-green-500 text-white rounded-lg shadow-lg flex items-center animate-fade-in'; |
| | notification.innerHTML = ` |
| | <i class="fas fa-check-circle mr-2"></i> |
| | <span>${medications[medIndex].name} marked as taken</span> |
| | `; |
| | document.body.appendChild(notification); |
| | |
| | setTimeout(() => { |
| | notification.classList.add('animate-fade-out'); |
| | setTimeout(() => notification.remove(), 300); |
| | }, 3000); |
| | } |
| | } |
| | |
| | |
| | window.editMedication = function(id) { |
| | |
| | alert(`Editing medication with ID ${id}. This would open the edit form in a real application.`); |
| | } |
| | |
| | |
| | window.deleteMedication = function(id) { |
| | if (confirm('Are you sure you want to delete this medication?')) { |
| | const medIndex = medications.findIndex(m => m.id === id); |
| | if (medIndex !== -1) { |
| | medications.splice(medIndex, 1); |
| | renderAllMeds(); |
| | renderTodaysMeds(); |
| | |
| | |
| | const notification = document.createElement('div'); |
| | notification.className = 'fixed top-4 right-4 px-4 py-2 bg-red-500 text-white rounded-lg shadow-lg flex items-center animate-fade-in'; |
| | notification.innerHTML = ` |
| | <i class="fas fa-trash-alt mr-2"></i> |
| | <span>Medication deleted</span> |
| | `; |
| | document.body.appendChild(notification); |
| | |
| | setTimeout(() => { |
| | notification.classList.add('animate-fade-out'); |
| | setTimeout(() => notification.remove(), 300); |
| | }, 3000); |
| | } |
| | } |
| | } |
| | |
| | |
| | addTimeBtn.addEventListener('click', () => { |
| | const timeInput = document.createElement('div'); |
| | timeInput.className = 'flex items-center'; |
| | timeInput.innerHTML = ` |
| | <input type="time" class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-sky-500 focus:border-sky-500" value="12:00"> |
| | <button type="button" class="ml-2 text-red-500 hover:text-red-700 remove-time"> |
| | <i class="fas fa-times"></i> |
| | </button> |
| | `; |
| | timeInputs.appendChild(timeInput); |
| | |
| | |
| | timeInput.querySelector('.remove-time').addEventListener('click', () => { |
| | timeInput.remove(); |
| | }); |
| | }); |
| | |
| | |
| | addMedBtn.addEventListener('click', () => { |
| | medModal.classList.remove('hidden'); |
| | medModal.classList.add('modal-enter-active'); |
| | }); |
| | |
| | closeModalBtn.addEventListener('click', () => { |
| | medModal.classList.add('hidden'); |
| | }); |
| | |
| | cancelMedBtn.addEventListener('click', () => { |
| | medModal.classList.add('hidden'); |
| | }); |
| | |
| | |
| | notificationBtn.addEventListener('click', () => { |
| | notificationModal.classList.remove('hidden'); |
| | }); |
| | |
| | closeNotifModalBtn.addEventListener('click', () => { |
| | notificationModal.classList.add('hidden'); |
| | }); |
| | |
| | clearNotifBtn.addEventListener('click', () => { |
| | document.getElementById('notificationList').innerHTML = ` |
| | <div class="text-center py-8 text-gray-500"> |
| | <i class="fas fa-bell-slash text-3xl mb-2"></i> |
| | <p>No notifications</p> |
| | </div> |
| | `; |
| | notificationCount.classList.add('hidden'); |
| | }); |
| | |
| | |
| | medForm.addEventListener('submit', (e) => { |
| | e.preventDefault(); |
| | |
| | |
| | const name = document.getElementById('medName').value; |
| | const type = document.getElementById('medType').value; |
| | const dosage = document.getElementById('medDosage').value; |
| | const frequency = document.getElementById('medFrequency').value; |
| | const notes = document.getElementById('medNotes').value; |
| | |
| | |
| | const timeElements = timeInputs.querySelectorAll('input[type="time"]'); |
| | const times = Array.from(timeElements).map(el => el.value); |
| | |
| | |
| | const newMed = { |
| | id: medications.length > 0 ? Math.max(...medications.map(m => m.id)) + 1 : 1, |
| | name, |
| | type, |
| | dosage, |
| | frequency, |
| | times, |
| | notes, |
| | taken: [], |
| | color: getRandomColor(), |
| | icon: getIconForType(type), |
| | todayStatus: frequency !== 'as_needed' && times.length > 0 ? |
| | { taken: false, time: times[0] } : null |
| | }; |
| | |
| | medications.push(newMed); |
| | |
| | |
| | medForm.reset(); |
| | timeInputs.innerHTML = ` |
| | <div class="flex items-center"> |
| | <input type="time" class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-sky-500 focus:border-sky-500" value="08:00"> |
| | <button type="button" class="ml-2 text-red-500 hover:text-red-700"> |
| | <i class="fas fa-times"></i> |
| | </button> |
| | </div> |
| | `; |
| | |
| | |
| | medModal.classList.add('hidden'); |
| | |
| | |
| | renderAllMeds(); |
| | renderTodaysMeds(); |
| | |
| | |
| | const notification = document.createElement('div'); |
| | notification.className = 'fixed top-4 right-4 px-4 py-2 bg-green-500 text-white rounded-lg shadow-lg flex items-center animate-fade-in'; |
| | notification.innerHTML = ` |
| | <i class="fas fa-check-circle mr-2"></i> |
| | <span>${name} added successfully</span> |
| | `; |
| | document.body.appendChild(notification); |
| | |
| | setTimeout(() => { |
| | notification.classList.add('animate-fade-out'); |
| | setTimeout(() => notification.remove(), 300); |
| | }, 3000); |
| | }); |
| | |
| | |
| | function getRandomColor() { |
| | const colors = [ |
| | 'bg-blue-100', 'bg-green-100', 'bg-yellow-100', |
| | 'bg-red-100', 'bg-purple-100', 'bg-pink-100', |
| | 'bg-indigo-100', 'bg-teal-100', 'bg-orange-100' |
| | ]; |
| | return colors[Math.floor(Math.random() * colors.length)]; |
| | } |
| | |
| | |
| | function getIconForType(type) { |
| | const icons = { |
| | inhaler: 'fa-inhaler', |
| | tablet: 'fa-pills', |
| | capsule: 'fa-capsules', |
| | liquid: 'fa-flask', |
| | injection: 'fa-syringe' |
| | }; |
| | return icons[type] || 'fa-prescription-bottle-alt'; |
| | } |
| | |
| | |
| | renderTodaysMeds(); |
| | renderAllMeds(); |
| | |
| | |
| | const style = document.createElement('style'); |
| | style.textContent = ` |
| | @keyframes fadeIn { |
| | from { opacity: 0; transform: translateY(10px); } |
| | to { opacity: 1; transform: translateY(0); } |
| | } |
| | |
| | @keyframes fadeOut { |
| | from { opacity: 1; transform: translateY(0); } |
| | to { opacity: 0; transform: translateY(10px); } |
| | } |
| | |
| | .animate-fade-in { |
| | animation: fadeIn 0.3s ease-out forwards; |
| | } |
| | |
| | .animate-fade-out { |
| | animation: fadeOut 0.3s ease-out forwards; |
| | } |
| | `; |
| | document.head.appendChild(style); |
| | </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=mannadamay12/copd-medication-tracker" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| | </html> |