Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>QR Medical - Health Record Sharing</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"> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/qrcode.min.js"></script> | |
<style> | |
.gradient-bg { | |
background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 50%, #2563eb 100%); | |
} | |
.pulse-animation { | |
animation: pulse 2s infinite; | |
} | |
@keyframes pulse { | |
0% { transform: scale(1); } | |
50% { transform: scale(1.05); } | |
100% { transform: scale(1); } | |
} | |
.qr-container { | |
transition: all 0.3s ease; | |
} | |
.qr-container:hover { | |
transform: translateY(-5px); | |
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); | |
} | |
.recording-wave { | |
height: 40px; | |
background: linear-gradient(90deg, #3b82f6 0%, transparent 100%); | |
animation: wave 1.5s infinite linear; | |
opacity: 0.7; | |
} | |
@keyframes wave { | |
0% { background-position: 0% 50%; } | |
100% { background-position: 100% 50%; } | |
} | |
.permission-modal { | |
display: none; | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(0,0,0,0.7); | |
z-index: 1000; | |
justify-content: center; | |
align-items: center; | |
} | |
.permission-content { | |
background: white; | |
padding: 2rem; | |
border-radius: 0.5rem; | |
max-width: 500px; | |
text-align: center; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-50 min-h-screen"> | |
<!-- Permission Modal --> | |
<div id="permissionModal" class="permission-modal"> | |
<div class="permission-content"> | |
<h3 class="text-xl font-bold mb-4">Microphone Access Required</h3> | |
<p class="mb-6">To record audio, QR Medical needs access to your microphone. Please allow microphone access when prompted by your browser.</p> | |
<div class="flex justify-center space-x-4"> | |
<button id="cancelPermissionBtn" class="bg-gray-500 hover:bg-gray-600 text-white py-2 px-6 rounded-full"> | |
Cancel | |
</button> | |
<button id="retryPermissionBtn" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-6 rounded-full"> | |
Try Again | |
</button> | |
</div> | |
</div> | |
</div> | |
<!-- Header --> | |
<header class="gradient-bg text-white shadow-lg"> | |
<div class="container mx-auto px-4 py-6"> | |
<div class="flex justify-between items-center"> | |
<div class="flex items-center space-x-2"> | |
<i class="fas fa-heartbeat text-3xl"></i> | |
<h1 class="text-2xl font-bold">QR Medical</h1> | |
</div> | |
<nav> | |
<ul class="flex space-x-6"> | |
<li><a href="#" class="hover:underline">Home</a></li> | |
<li><a href="#features" class="hover:underline">Features</a></li> | |
<li><a href="#how-it-works" class="hover:underline">How It Works</a></li> | |
</ul> | |
</nav> | |
</div> | |
</div> | |
</header> | |
<!-- Hero Section --> | |
<section class="gradient-bg text-white py-16"> | |
<div class="container mx-auto px-4 text-center"> | |
<h2 class="text-4xl font-bold mb-6">Secure Medical Record Sharing</h2> | |
<p class="text-xl mb-8 max-w-2xl mx-auto">Record your medical information, generate a secure QR code, and share it with healthcare providers instantly.</p> | |
<button id="getStartedBtn" class="bg-white text-blue-600 font-bold py-3 px-8 rounded-full hover:bg-gray-100 transition duration-300 pulse-animation"> | |
Get Started <i class="fas fa-arrow-right ml-2"></i> | |
</button> | |
</div> | |
</section> | |
<!-- Main Content --> | |
<main class="container mx-auto px-4 py-12"> | |
<!-- Recording Section --> | |
<section id="recordingSection" class="bg-white rounded-xl shadow-md p-8 mb-12"> | |
<h2 class="text-2xl font-bold text-gray-800 mb-6">Record Your Medical Information</h2> | |
<div class="grid md:grid-cols-2 gap-8"> | |
<div> | |
<div class="mb-6"> | |
<label class="block text-gray-700 font-medium mb-2" for="patientName">Patient Name</label> | |
<input type="text" id="patientName" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Enter patient name"> | |
</div> | |
<div class="mb-6"> | |
<label class="block text-gray-700 font-medium mb-2">Medical Information</label> | |
<textarea id="medicalInfo" rows="4" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Enter medical details or record audio below"></textarea> | |
</div> | |
<div class="mb-6"> | |
<label class="block text-gray-700 font-medium mb-2">Record Audio</label> | |
<div class="flex items-center space-x-4"> | |
<button id="recordBtn" class="bg-red-500 hover:bg-red-600 text-white py-2 px-6 rounded-full flex items-center"> | |
<i class="fas fa-microphone mr-2"></i> Record | |
</button> | |
<button id="stopBtn" disabled class="bg-gray-500 text-white py-2 px-6 rounded-full flex items-center opacity-50"> | |
<i class="fas fa-stop mr-2"></i> Stop | |
</button> | |
</div> | |
<div id="recordingIndicator" class="mt-4 hidden"> | |
<div class="recording-wave rounded-full"></div> | |
<p class="text-sm text-gray-500 mt-2">Recording in progress...</p> | |
</div> | |
<p id="permissionHelp" class="text-sm text-gray-500 mt-2 hidden"> | |
<i class="fas fa-info-circle mr-1"></i> If microphone access is blocked, check your browser permissions. | |
</p> | |
</div> | |
<div class="mb-6"> | |
<label class="block text-gray-700 font-medium mb-2">Audio Playback</label> | |
<audio id="audioPlayback" controls class="w-full hidden"></audio> | |
<p id="noAudioMessage" class="text-gray-500">No audio recorded yet.</p> | |
</div> | |
<button id="generateQRBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white py-3 px-6 rounded-lg font-medium transition duration-300"> | |
Generate QR Code <i class="fas fa-qrcode ml-2"></i> | |
</button> | |
</div> | |
<div class="flex flex-col items-center justify-center"> | |
<div id="qrCodeContainer" class="qr-container bg-white p-4 rounded-lg shadow-md mb-4 hidden"> | |
<div id="qrCode" class="mx-auto"></div> | |
</div> | |
<div id="patientInfoDisplay" class="text-center mt-4 hidden"> | |
<h3 class="font-bold text-lg" id="displayName"></h3> | |
<p class="text-gray-600" id="displayInfo"></p> | |
</div> | |
<button id="downloadQRBtn" class="bg-green-600 hover:bg-green-700 text-white py-2 px-6 rounded-full hidden mt-4"> | |
<i class="fas fa-download mr-2"></i> Download QR | |
</button> | |
</div> | |
</div> | |
</section> | |
<!-- Features Section --> | |
<section id="features" class="mb-12"> | |
<h2 class="text-2xl font-bold text-gray-800 mb-8 text-center">Why Use QR Medical?</h2> | |
<div class="grid md:grid-cols-3 gap-8"> | |
<div class="bg-white p-6 rounded-xl shadow-md hover:shadow-lg transition duration-300"> | |
<div class="text-blue-600 text-4xl mb-4"> | |
<i class="fas fa-shield-alt"></i> | |
</div> | |
<h3 class="font-bold text-xl mb-2">Secure Sharing</h3> | |
<p class="text-gray-600">Your medical information is securely encoded in the QR code and can only be accessed by authorized healthcare providers.</p> | |
</div> | |
<div class="bg-white p-6 rounded-xl shadow-md hover:shadow-lg transition duration-300"> | |
<div class="text-blue-600 text-4xl mb-4"> | |
<i class="fas fa-clock"></i> | |
</div> | |
<h3 class="font-bold text-xl mb-2">Quick Access</h3> | |
<p class="text-gray-600">Healthcare providers can instantly access your medical information by scanning the QR code, saving critical time in emergencies.</p> | |
</div> | |
<div class="bg-white p-6 rounded-xl shadow-md hover:shadow-lg transition duration-300"> | |
<div class="text-blue-600 text-4xl mb-4"> | |
<i class="fas fa-notes-medical"></i> | |
</div> | |
<h3 class="font-bold text-xl mb-2">Comprehensive Records</h3> | |
<p class="text-gray-600">Include both text and audio recordings to provide complete medical information to your healthcare team.</p> | |
</div> | |
</div> | |
</section> | |
<!-- How It Works Section --> | |
<section id="how-it-works" class="bg-white rounded-xl shadow-md p-8"> | |
<h2 class="text-2xl font-bold text-gray-800 mb-8 text-center">How It Works</h2> | |
<div class="space-y-8"> | |
<div class="flex flex-col md:flex-row items-center"> | |
<div class="bg-blue-100 text-blue-800 rounded-full w-16 h-16 flex items-center justify-center text-2xl font-bold mb-4 md:mb-0 md:mr-6">1</div> | |
<div class="flex-1"> | |
<h3 class="font-bold text-xl mb-2">Record Your Information</h3> | |
<p class="text-gray-600">Enter your medical details or record an audio message describing your condition, medications, allergies, or other important health information.</p> | |
</div> | |
</div> | |
<div class="flex flex-col md:flex-row items-center"> | |
<div class="bg-blue-100 text-blue-800 rounded-full w-16 h-16 flex items-center justify-center text-2xl font-bold mb-4 md:mb-0 md:mr-6">2</div> | |
<div class="flex-1"> | |
<h3 class="font-bold text-xl mb-2">Generate QR Code</h3> | |
<p class="text-gray-600">Click the "Generate QR Code" button to create a personalized QR code containing your medical information.</p> | |
</div> | |
</div> | |
<div class="flex flex-col md:flex-row items-center"> | |
<div class="bg-blue-100 text-blue-800 rounded-full w-16 h-16 flex items-center justify-center text-2xl font-bold mb-4 md:mb-0 md:mr-6">3</div> | |
<div class="flex-1"> | |
<h3 class="font-bold text-xl mb-2">Share With Providers</h3> | |
<p class="text-gray-600">Download or print the QR code and share it with your healthcare providers. They can scan it to access your medical information instantly.</p> | |
</div> | |
</div> | |
</div> | |
</section> | |
</main> | |
<!-- Footer --> | |
<footer class="bg-gray-800 text-white py-8"> | |
<div class="container mx-auto px-4"> | |
<div class="flex flex-col md:flex-row justify-between items-center"> | |
<div class="mb-4 md:mb-0"> | |
<div class="flex items-center space-x-2"> | |
<i class="fas fa-heartbeat text-2xl"></i> | |
<h2 class="text-xl font-bold">QR Medical</h2> | |
</div> | |
<p class="text-gray-400 mt-2">Secure medical record sharing made simple.</p> | |
</div> | |
<div class="flex space-x-6"> | |
<a href="#" class="hover:text-blue-400"><i class="fab fa-facebook-f"></i></a> | |
<a href="#" class="hover:text-blue-400"><i class="fab fa-twitter"></i></a> | |
<a href="#" class="hover:text-blue-400"><i class="fab fa-linkedin-in"></i></a> | |
</div> | |
</div> | |
<div class="border-t border-gray-700 mt-6 pt-6 text-center text-gray-400"> | |
<p>© 2023 QR Medical. All rights reserved.</p> | |
</div> | |
</div> | |
</footer> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// DOM Elements | |
const recordBtn = document.getElementById('recordBtn'); | |
const stopBtn = document.getElementById('stopBtn'); | |
const recordingIndicator = document.getElementById('recordingIndicator'); | |
const audioPlayback = document.getElementById('audioPlayback'); | |
const noAudioMessage = document.getElementById('noAudioMessage'); | |
const generateQRBtn = document.getElementById('generateQRBtn'); | |
const qrCodeContainer = document.getElementById('qrCodeContainer'); | |
const qrCode = document.getElementById('qrCode'); | |
const downloadQRBtn = document.getElementById('downloadQRBtn'); | |
const patientInfoDisplay = document.getElementById('patientInfoDisplay'); | |
const displayName = document.getElementById('displayName'); | |
const displayInfo = document.getElementById('displayInfo'); | |
const patientName = document.getElementById('patientName'); | |
const medicalInfo = document.getElementById('medicalInfo'); | |
const getStartedBtn = document.getElementById('getStartedBtn'); | |
const permissionModal = document.getElementById('permissionModal'); | |
const cancelPermissionBtn = document.getElementById('cancelPermissionBtn'); | |
const retryPermissionBtn = document.getElementById('retryPermissionBtn'); | |
const permissionHelp = document.getElementById('permissionHelp'); | |
// Variables | |
let mediaRecorder; | |
let audioChunks = []; | |
let audioBlob; | |
let audioUrl; | |
// Event Listeners | |
getStartedBtn.addEventListener('click', function() { | |
document.getElementById('recordingSection').scrollIntoView({ behavior: 'smooth' }); | |
}); | |
recordBtn.addEventListener('click', startRecording); | |
stopBtn.addEventListener('click', stopRecording); | |
generateQRBtn.addEventListener('click', generateQRCode); | |
downloadQRBtn.addEventListener('click', downloadQRCode); | |
cancelPermissionBtn.addEventListener('click', closePermissionModal); | |
retryPermissionBtn.addEventListener('click', retryPermission); | |
// Functions | |
async function startRecording() { | |
try { | |
const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); | |
handleRecordingStart(stream); | |
} catch (err) { | |
if (err.name === 'NotAllowedError') { | |
showPermissionModal(); | |
permissionHelp.classList.remove('hidden'); | |
} else { | |
alert('Error accessing microphone: ' + err.message); | |
} | |
} | |
} | |
function handleRecordingStart(stream) { | |
mediaRecorder = new MediaRecorder(stream); | |
mediaRecorder.ondataavailable = function(e) { | |
if (e.data.size > 0) { | |
audioChunks.push(e.data); | |
} | |
}; | |
mediaRecorder.onstop = function() { | |
audioBlob = new Blob(audioChunks, { type: 'audio/wav' }); | |
audioUrl = URL.createObjectURL(audioBlob); | |
audioPlayback.src = audioUrl; | |
audioPlayback.classList.remove('hidden'); | |
noAudioMessage.classList.add('hidden'); | |
}; | |
mediaRecorder.start(); | |
audioChunks = []; | |
recordBtn.disabled = true; | |
stopBtn.disabled = false; | |
recordingIndicator.classList.remove('hidden'); | |
// Change button styles | |
recordBtn.classList.remove('bg-red-500', 'hover:bg-red-600'); | |
recordBtn.classList.add('bg-gray-500', 'hover:bg-gray-600'); | |
stopBtn.classList.remove('bg-gray-500', 'opacity-50'); | |
stopBtn.classList.add('bg-red-500', 'hover:bg-red-600'); | |
} | |
function stopRecording() { | |
if (mediaRecorder && mediaRecorder.state !== 'inactive') { | |
mediaRecorder.stop(); | |
// Stop all tracks in the stream | |
mediaRecorder.stream.getTracks().forEach(track => track.stop()); | |
recordBtn.disabled = false; | |
stopBtn.disabled = true; | |
recordingIndicator.classList.add('hidden'); | |
// Reset button styles | |
recordBtn.classList.add('bg-red-500', 'hover:bg-red-600'); | |
recordBtn.classList.remove('bg-gray-500', 'hover:bg-gray-600'); | |
stopBtn.classList.add('bg-gray-500', 'opacity-50'); | |
stopBtn.classList.remove('bg-red-500', 'hover:bg-red-600'); | |
} | |
} | |
function showPermissionModal() { | |
permissionModal.style.display = 'flex'; | |
} | |
function closePermissionModal() { | |
permissionModal.style.display = 'none'; | |
} | |
function retryPermission() { | |
closePermissionModal(); | |
startRecording(); | |
} | |
function generateQRCode() { | |
if (!patientName.value.trim() && !medicalInfo.value.trim() && !audioBlob) { | |
alert('Please enter patient information or record audio before generating QR code.'); | |
return; | |
} | |
// Create data object | |
const data = { | |
name: patientName.value.trim(), | |
info: medicalInfo.value.trim(), | |
audio: audioBlob ? 'audio_available' : null | |
}; | |
// Convert to JSON string | |
const jsonData = JSON.stringify(data); | |
// Generate QR code | |
const qr = qrcode(0, 'L'); | |
qr.addData(jsonData); | |
qr.make(); | |
// Clear previous QR code | |
qrCode.innerHTML = ''; | |
// Create QR code image | |
const qrImg = qr.createImgTag(5); | |
qrCode.innerHTML = qrImg; | |
// Show QR code and patient info | |
qrCodeContainer.classList.remove('hidden'); | |
patientInfoDisplay.classList.remove('hidden'); | |
downloadQRBtn.classList.remove('hidden'); | |
// Update displayed info | |
displayName.textContent = data.name || 'Anonymous Patient'; | |
displayInfo.textContent = data.info || 'Medical information available via QR code'; | |
// Scroll to QR code | |
qrCodeContainer.scrollIntoView({ behavior: 'smooth', block: 'center' }); | |
} | |
function downloadQRCode() { | |
if (!qrCodeContainer.classList.contains('hidden')) { | |
const canvas = document.querySelector('#qrCode canvas'); | |
const dataURL = canvas.toDataURL('image/png'); | |
const link = document.createElement('a'); | |
link.download = `QRMedical_${patientName.value || 'patient'}.png`; | |
link.href = dataURL; | |
link.click(); | |
} | |
} | |
}); | |
</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=Mohabedalgani/qrrecord" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |