|
<!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> |