Spaces:
Running
Running
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Gestion RDV - Centre Médico-Radiologique Avicenne</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://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| colors: { | |
| medical: { | |
| blue: '#0077B6', | |
| lightblue: '#90E0EF', | |
| darkblue: '#03045E', | |
| teal: '#00B4D8', | |
| white: '#CAF0F8' | |
| } | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| .sidebar { | |
| transition: all 0.3s ease; | |
| } | |
| .sidebar-collapsed { | |
| width: 70px; | |
| } | |
| .sidebar-expanded { | |
| width: 250px; | |
| } | |
| .main-content { | |
| transition: margin-left 0.3s ease; | |
| } | |
| .fade-in { | |
| animation: fadeIn 0.5s; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; } | |
| to { opacity: 1; } | |
| } | |
| .card-hover:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-100 font-sans"> | |
| <div class="flex h-screen overflow-hidden"> | |
| <!-- Sidebar --> | |
| <div id="sidebar" class="sidebar sidebar-expanded bg-medical-blue text-white flex flex-col"> | |
| <div class="p-4 flex items-center justify-between border-b border-medical-lightblue"> | |
| <div class="flex items-center space-x-2"> | |
| <div class="flex items-center justify-center w-10 h-10 rounded-full bg-white text-medical-blue"> | |
| <i class="fas fa-heartbeat text-2xl"></i> | |
| </div> | |
| <span id="logo-text" class="text-xl font-bold text-white">Avicenne</span> | |
| </div> | |
| <button id="toggle-sidebar" class="text-white hover:text-medical-lightblue"> | |
| <i class="fas fa-bars"></i> | |
| </button> | |
| </div> | |
| <div class="p-4 flex items-center space-x-3 border-b border-medical-lightblue"> | |
| <div class="w-10 h-10 rounded-full bg-white text-medical-blue flex items-center justify-center"> | |
| <i class="fas fa-user-md"></i> | |
| </div> | |
| <div id="user-info"> | |
| <p class="font-semibold">Dr. Yassine</p> | |
| <p class="text-xs text-medical-white">Radiologue</p> | |
| </div> | |
| </div> | |
| <nav class="flex-1 overflow-y-auto py-4"> | |
| <ul> | |
| <li> | |
| <a href="#" id="dashboard-link" class="flex items-center space-x-3 p-3 hover:bg-medical-darkblue rounded-lg mx-2"> | |
| <i class="fas fa-tachometer-alt w-6 text-center"></i> | |
| <span id="dashboard-text">Tableau de bord</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" id="appointments-link" class="flex items-center space-x-3 p-3 bg-medical-darkblue rounded-lg mx-2"> | |
| <i class="fas fa-calendar-check w-6 text-center"></i> | |
| <span id="appointments-text">Rendez-vous</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" id="patients-link" class="flex items-center space-x-3 p-3 hover:bg-medical-darkblue rounded-lg mx-2"> | |
| <i class="fas fa-procedures w-6 text-center"></i> | |
| <span id="patients-text">Patients</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" id="reports-link" class="flex items-center space-x-3 p-3 hover:bg-medical-darkblue rounded-lg mx-2"> | |
| <i class="fas fa-file-medical w-6 text-center"></i> | |
| <span id="reports-text">Rapports</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" id="logs-link" class="flex items-center space-x-3 p-3 hover:bg-medical-darkblue rounded-lg mx-2"> | |
| <i class="fas fa-clipboard-list w-6 text-center"></i> | |
| <span id="logs-text">Journal d'activité</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" id="settings-link" class="flex items-center space-x-3 p-3 hover:bg-medical-darkblue rounded-lg mx-2"> | |
| <i class="fas fa-cog w-6 text-center"></i> | |
| <span id="settings-text">Paramètres</span> | |
| </a> | |
| </li> | |
| </ul> | |
| </nav> | |
| <div class="p-4 border-t border-medical-lightblue"> | |
| <button id="logout-btn" class="flex items-center space-x-3 w-full p-2 hover:bg-medical-darkblue rounded-lg"> | |
| <i class="fas fa-sign-out-alt w-6 text-center"></i> | |
| <span id="logout-text">Déconnexion</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Main Content --> | |
| <div id="main-content" class="main-content flex-1 overflow-y-auto"> | |
| <!-- Header --> | |
| <header class="bg-white shadow-sm p-4 flex justify-between items-center"> | |
| <h1 class="text-2xl font-bold text-medical-blue">Gestion des Rendez-vous</h1> | |
| <div class="flex items-center space-x-4"> | |
| <div class="relative"> | |
| <input type="text" placeholder="Rechercher..." class="pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| <i class="fas fa-search absolute left-3 top-3 text-gray-400"></i> | |
| </div> | |
| <div class="relative"> | |
| <button id="notifications-btn" class="text-gray-600 hover:text-medical-blue relative"> | |
| <i class="fas fa-bell text-xl"></i> | |
| <span class="absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center">3</span> | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Content --> | |
| <main class="p-6"> | |
| <!-- Stats Cards --> | |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-6"> | |
| <div class="bg-white rounded-lg shadow-md p-6 card-hover transition-all duration-300 border-l-4 border-medical-blue"> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500">RDV aujourd'hui</p> | |
| <h3 class="text-2xl font-bold text-medical-blue">12</h3> | |
| </div> | |
| <div class="bg-medical-lightblue text-medical-blue p-3 rounded-full"> | |
| <i class="fas fa-calendar-day text-xl"></i> | |
| </div> | |
| </div> | |
| <p class="text-sm text-green-500 mt-2"><i class="fas fa-arrow-up"></i> 2 de plus qu'hier</p> | |
| </div> | |
| <div class="bg-white rounded-lg shadow-md p-6 card-hover transition-all duration-300 border-l-4 border-medical-teal"> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500">RDV cette semaine</p> | |
| <h3 class="text-2xl font-bold text-medical-blue">42</h3> | |
| </div> | |
| <div class="bg-blue-100 text-medical-teal p-3 rounded-full"> | |
| <i class="fas fa-calendar-week text-xl"></i> | |
| </div> | |
| </div> | |
| <p class="text-sm text-green-500 mt-2"><i class="fas fa-arrow-up"></i> 5% vs semaine dernière</p> | |
| </div> | |
| <div class="bg-white rounded-lg shadow-md p-6 card-hover transition-all duration-300 border-l-4 border-green-500"> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500">Patients confirmés</p> | |
| <h3 class="text-2xl font-bold text-medical-blue">38</h3> | |
| </div> | |
| <div class="bg-green-100 text-green-500 p-3 rounded-full"> | |
| <i class="fas fa-check-circle text-xl"></i> | |
| </div> | |
| </div> | |
| <p class="text-sm text-gray-500 mt-2">4 en attente de confirmation</p> | |
| </div> | |
| <div class="bg-white rounded-lg shadow-md p-6 card-hover transition-all duration-300 border-l-4 border-red-500"> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500">Annulations</p> | |
| <h3 class="text-2xl font-bold text-medical-blue">2</h3> | |
| </div> | |
| <div class="bg-red-100 text-red-500 p-3 rounded-full"> | |
| <i class="fas fa-times-circle text-xl"></i> | |
| </div> | |
| </div> | |
| <p class="text-sm text-gray-500 mt-2">1% du total des RDV</p> | |
| </div> | |
| </div> | |
| <!-- Appointments Table --> | |
| <div class="bg-white rounded-lg shadow-md overflow-hidden mb-6"> | |
| <div class="p-4 border-b flex justify-between items-center"> | |
| <h2 class="text-xl font-semibold text-medical-blue">Liste des Rendez-vous</h2> | |
| <div class="flex space-x-2"> | |
| <button id="export-pdf" class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg flex items-center space-x-2"> | |
| <i class="fas fa-file-pdf"></i> | |
| <span>PDF</span> | |
| </button> | |
| <button id="export-excel" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg flex items-center space-x-2"> | |
| <i class="fas fa-file-excel"></i> | |
| <span>Excel</span> | |
| </button> | |
| <button id="add-appointment" class="bg-medical-blue hover:bg-medical-darkblue text-white px-4 py-2 rounded-lg flex items-center space-x-2"> | |
| <i class="fas fa-plus"></i> | |
| <span>Nouveau RDV</span> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <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">Patient</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date/Heure</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type d'examen</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Statut</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="appointments-table-body"> | |
| <!-- Rows will be added dynamically --> | |
| </tbody> | |
| </table> | |
| </div> | |
| <div class="p-4 border-t flex justify-between items-center"> | |
| <div class="text-sm text-gray-500"> | |
| Affichage de <span id="start-item">1</span> à <span id="end-item">10</span> sur <span id="total-items">24</span> rendez-vous | |
| </div> | |
| <div class="flex space-x-2"> | |
| <button class="px-3 py-1 border rounded-md text-gray-700 disabled:opacity-50" id="prev-page" disabled> | |
| <i class="fas fa-chevron-left"></i> | |
| </button> | |
| <button class="px-3 py-1 border rounded-md bg-medical-blue text-white">1</button> | |
| <button class="px-3 py-1 border rounded-md text-gray-700 hover:bg-gray-100">2</button> | |
| <button class="px-3 py-1 border rounded-md text-gray-700 hover:bg-gray-100">3</button> | |
| <button class="px-3 py-1 border rounded-md text-gray-700" id="next-page"> | |
| <i class="fas fa-chevron-right"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Calendar View --> | |
| <div class="bg-white rounded-lg shadow-md overflow-hidden mb-6"> | |
| <div class="p-4 border-b flex justify-between items-center"> | |
| <h2 class="text-xl font-semibold text-medical-blue">Vue Calendrier</h2> | |
| <div class="flex items-center space-x-4"> | |
| <div class="flex items-center space-x-2"> | |
| <button class="px-3 py-1 border rounded-md text-gray-700"> | |
| <i class="fas fa-chevron-left"></i> | |
| </button> | |
| <span class="font-medium">Mai 2023</span> | |
| <button class="px-3 py-1 border rounded-md text-gray-700"> | |
| <i class="fas fa-chevron-right"></i> | |
| </button> | |
| </div> | |
| <div class="relative"> | |
| <select class="appearance-none bg-white border rounded-md pl-3 pr-8 py-1 focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| <option>Vue semaine</option> | |
| <option selected>Vue mois</option> | |
| <option>Vue jour</option> | |
| </select> | |
| <i class="fas fa-chevron-down absolute right-3 top-2 text-gray-400 pointer-events-none"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-4"> | |
| <div class="grid grid-cols-7 gap-1 mb-2"> | |
| <div class="text-center font-medium text-gray-500 py-2">Lun</div> | |
| <div class="text-center font-medium text-gray-500 py-2">Mar</div> | |
| <div class="text-center font-medium text-gray-500 py-2">Mer</div> | |
| <div class="text-center font-medium text-gray-500 py-2">Jeu</div> | |
| <div class="text-center font-medium text-gray-500 py-2">Ven</div> | |
| <div class="text-center font-medium text-gray-500 py-2">Sam</div> | |
| <div class="text-center font-medium text-gray-500 py-2">Dim</div> | |
| </div> | |
| <div class="grid grid-cols-7 gap-1" id="calendar-grid"> | |
| <!-- Calendar cells will be added dynamically --> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| </div> | |
| <!-- Add Appointment Modal --> | |
| <div id="add-appointment-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden"> | |
| <div class="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-screen overflow-y-auto"> | |
| <div class="p-4 border-b flex justify-between items-center"> | |
| <h3 class="text-xl font-semibold text-medical-blue">Nouveau Rendez-vous</h3> | |
| <button id="close-add-modal" class="text-gray-500 hover:text-gray-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="p-6"> | |
| <form id="appointment-form"> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6"> | |
| <div> | |
| <label class="block text-gray-700 mb-2" for="patient">Patient</label> | |
| <select id="patient" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| <option value="">Sélectionner un patient</option> | |
| <option value="1">Jean Martin</option> | |
| <option value="2">Marie Dubois</option> | |
| <option value="3">Pierre Lambert</option> | |
| <option value="4">Sophie Moreau</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-gray-700 mb-2" for="examen-type">Type d'examen</label> | |
| <select id="examen-type" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| <option value="">Sélectionner un type</option> | |
| <option value="radiographie">Radiographie</option> | |
| <option value="irm">IRM</option> | |
| <option value="scanner">Scanner</option> | |
| <option value="echographie">Échographie</option> | |
| <option value="mammographie">Mammographie</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-gray-700 mb-2" for="appointment-date">Date</label> | |
| <input type="date" id="appointment-date" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| </div> | |
| <div> | |
| <label class="block text-gray-700 mb-2" for="appointment-time">Heure</label> | |
| <input type="time" id="appointment-time" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| </div> | |
| <div class="md:col-span-2"> | |
| <label class="block text-gray-700 mb-2" for="notes">Notes</label> | |
| <textarea id="notes" rows="3" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"></textarea> | |
| </div> | |
| </div> | |
| <div class="flex justify-end space-x-3"> | |
| <button type="button" id="cancel-add-appointment" class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-100"> | |
| Annuler | |
| </button> | |
| <button type="submit" class="px-4 py-2 bg-medical-blue text-white rounded-lg hover:bg-medical-darkblue"> | |
| Enregistrer | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Edit Appointment Modal --> | |
| <div id="edit-appointment-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden"> | |
| <div class="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-screen overflow-y-auto"> | |
| <div class="p-4 border-b flex justify-between items-center"> | |
| <h3 class="text-xl font-semibold text-medical-blue">Modifier Rendez-vous</h3> | |
| <button id="close-edit-modal" class="text-gray-500 hover:text-gray-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="p-6"> | |
| <form id="edit-appointment-form"> | |
| <input type="hidden" id="edit-appointment-id"> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6"> | |
| <div> | |
| <label class="block text-gray-700 mb-2" for="edit-patient">Patient</label> | |
| <select id="edit-patient" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| <option value="">Sélectionner un patient</option> | |
| <option value="1">Jean Martin</option> | |
| <option value="2">Marie Dubois</option> | |
| <option value="3">Pierre Lambert</option> | |
| <option value="4">Sophie Moreau</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-gray-700 mb-2" for="edit-examen-type">Type d'examen</label> | |
| <select id="edit-examen-type" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| <option value="">Sélectionner un type</option> | |
| <option value="radiographie">Radiographie</option> | |
| <option value="irm">IRM</option> | |
| <option value="scanner">Scanner</option> | |
| <option value="echographie">Échographie</option> | |
| <option value="mammographie">Mammographie</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-gray-700 mb-2" for="edit-appointment-date">Date</label> | |
| <input type="date" id="edit-appointment-date" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| </div> | |
| <div> | |
| <label class="block text-gray-700 mb-2" for="edit-appointment-time">Heure</label> | |
| <input type="time" id="edit-appointment-time" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| </div> | |
| <div class="md:col-span-2"> | |
| <label class="block text-gray-700 mb-2" for="edit-status">Statut</label> | |
| <select id="edit-status" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"> | |
| <option value="confirmed">Confirmé</option> | |
| <option value="pending">En attente</option> | |
| <option value="cancelled">Annulé</option> | |
| <option value="completed">Terminé</option> | |
| </select> | |
| </div> | |
| <div class="md:col-span-2"> | |
| <label class="block text-gray-700 mb-2" for="edit-notes">Notes</label> | |
| <textarea id="edit-notes" rows="3" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-medical-blue"></textarea> | |
| </div> | |
| </div> | |
| <div class="flex justify-end space-x-3"> | |
| <button type="button" id="cancel-edit-appointment" class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-100"> | |
| Annuler | |
| </button> | |
| <button type="submit" class="px-4 py-2 bg-medical-blue text-white rounded-lg hover:bg-medical-darkblue"> | |
| Enregistrer | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- View Appointment Modal --> | |
| <div id="view-appointment-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden"> | |
| <div class="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-screen overflow-y-auto"> | |
| <div class="p-4 border-b flex justify-between items-center"> | |
| <h3 class="text-xl font-semibold text-medical-blue">Détails du Rendez-vous</h3> | |
| <button id="close-view-modal" class="text-gray-500 hover:text-gray-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="p-6"> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6"> | |
| <div> | |
| <h4 class="text-lg font-semibold text-medical-blue mb-4">Informations patient</h4> | |
| <div class="space-y-4"> | |
| <div> | |
| <p class="text-gray-500">Nom complet</p> | |
| <p id="view-patient-name" class="font-medium">Jean Martin</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-500">Date de naissance</p> | |
| <p id="view-patient-dob" class="font-medium">15/03/1975</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-500">Numéro de sécurité sociale</p> | |
| <p id="view-patient-ssn" class="font-medium">1 85 03 75 123 456 78</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-500">Téléphone</p> | |
| <p id="view-patient-phone" class="font-medium">06 12 34 56 78</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div> | |
| <h4 class="text-lg font-semibold text-medical-blue mb-4">Détails du rendez-vous</h4> | |
| <div class="space-y-4"> | |
| <div> | |
| <p class="text-gray-500">Date et heure</p> | |
| <p id="view-appointment-datetime" class="font-medium">15 mai 2023 à 14:30</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-500">Type d'examen</p> | |
| <p id="view-examen-type" class="font-medium">IRM cérébrale</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-500">Statut</p> | |
| <p id="view-status" class="font-medium"> | |
| <span class="px-2 py-1 rounded-full bg-green-100 text-green-800">Confirmé</span> | |
| </p> | |
| </div> | |
| <div> | |
| <p class="text-gray-500">Médecin assigné</p> | |
| <p id="view-doctor" class="font-medium">Dr. Dupont</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="md:col-span-2"> | |
| <h4 class="text-lg font-semibold text-medical-blue mb-4">Notes</h4> | |
| <div class="bg-gray-50 p-4 rounded-lg"> | |
| <p id="view-notes">Le patient présente des maux de tête persistants. Une IRM cérébrale a été prescrite pour évaluer d'éventuelles anomalies.</p> | |
| </div> | |
| </div> | |
| <div class="md:col-span-2"> | |
| <h4 class="text-lg font-semibold text-medical-blue mb-4">Historique des modifications</h4> | |
| <div class="space-y-3"> | |
| <div class="flex items-start space-x-3"> | |
| <div class="mt-1"> | |
| <div class="w-2 h-2 rounded-full bg-medical-blue"></div> | |
| </div> | |
| <div> | |
| <p class="text-sm font-medium">Modifié par Dr. Dupont</p> | |
| <p class="text-sm text-gray-500">15/05/2023 à 09:15 - Changement d'horaire</p> | |
| </div> | |
| </div> | |
| <div class="flex items-start space-x-3"> | |
| <div class="mt-1"> | |
| <div class="w-2 h-2 rounded-full bg-medical-blue"></div> | |
| </div> | |
| <div> | |
| <p class="text-sm font-medium">Créé par Sec. Martin</p> | |
| <p class="text-sm text-gray-500">10/05/2023 à 14:30 - Rendez-vous créé</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex justify-end space-x-3"> | |
| <button id="print-appointment" class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-100 flex items-center space-x-2"> | |
| <i class="fas fa-print"></i> | |
| <span>Imprimer</span> | |
| </button> | |
| <button id="edit-from-view" class="px-4 py-2 bg-medical-blue text-white rounded-lg hover:bg-medical-darkblue flex items-center space-x-2"> | |
| <i class="fas fa-edit"></i> | |
| <span>Modifier</span> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Notification Panel --> | |
| <div id="notification-panel" class="fixed right-0 top-0 h-full w-80 bg-white shadow-lg transform translate-x-full transition-transform duration-300 z-50"> | |
| <div class="p-4 border-b flex justify-between items-center"> | |
| <h3 class="text-lg font-semibold">Notifications</h3> | |
| <button id="close-notifications" class="text-gray-500 hover:text-gray-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="overflow-y-auto h-full"> | |
| <div class="p-4 border-b hover:bg-gray-50 cursor-pointer"> | |
| <div class="flex items-start space-x-3"> | |
| <div class="mt-1"> | |
| <div class="w-2 h-2 rounded-full bg-red-500"></div> | |
| </div> | |
| <div> | |
| <p class="font-medium">Nouveau rendez-vous</p> | |
| <p class="text-sm text-gray-500">Sophie Moreau a pris rendez-vous pour une échographie</p> | |
| <p class="text-xs text-gray-400">Il y a 10 minutes</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-4 border-b hover:bg-gray-50 cursor-pointer"> | |
| <div class="flex items-start space-x-3"> | |
| <div class="mt-1"> | |
| <div class="w-2 h-2 rounded-full bg-blue-500"></div> | |
| </div> | |
| <div> | |
| <p class="font-medium">Rappel de rendez-vous</p> | |
| <p class="text-sm text-gray-500">Jean Martin a un rendez-vous demain à 14h30</p> | |
| <p class="text-xs text-gray-400">Il y a 1 heure</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-4 border-b hover:bg-gray-50 cursor-pointer"> | |
| <div class="flex items-start space-x-3"> | |
| <div class="mt-1"> | |
| <div class="w-2 h-2 rounded-full bg-yellow-500"></div> | |
| </div> | |
| <div> | |
| <p class="font-medium">Rendez-vous annulé</p> | |
| <p class="text-sm text-gray-500">Pierre Lambert a annulé son scanner</p> | |
| <p class="text-xs text-gray-400">Il y a 3 heures</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-4 hover:bg-gray-50 cursor-pointer"> | |
| <div class="flex items-start space-x-3"> | |
| <div class="mt-1"> | |
| <div class="w-2 h-2 rounded-full bg-green-500"></div> | |
| </div> | |
| <div> | |
| <p class="font-medium">Nouveau message</p> | |
| <p class="text-sm text-gray-500">Vous avez reçu un message du Dr. Lefèvre</p> | |
| <p class="text-xs text-gray-400">Hier à 16:45</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Sample data for appointments | |
| const appointments = [ | |
| { | |
| id: 1, | |
| patient: "Jean Martin", | |
| date: "2023-05-15", | |
| time: "14:30", | |
| type: "IRM cérébrale", | |
| status: "confirmed", | |
| doctor: "Dr. Yassine", | |
| notes: "Le patient présente des maux de tête persistants." | |
| }, | |
| { | |
| id: 2, | |
| patient: "Marie Dubois", | |
| date: "2023-05-16", | |
| time: "09:15", | |
| type: "Mammographie", | |
| status: "pending", | |
| doctor: "Dr. Lefèvre", | |
| notes: "Contrôle annuel." | |
| }, | |
| { | |
| id: 3, | |
| patient: "Pierre Lambert", | |
| date: "2023-05-16", | |
| time: "11:00", | |
| type: "Radiographie thoracique", | |
| status: "confirmed", | |
| doctor: "Dr. Yassine", | |
| notes: "Douleurs thoraciques persistantes." | |
| }, | |
| { | |
| id: 4, | |
| patient: "Sophie Moreau", | |
| date: "2023-05-17", | |
| time: "15:45", | |
| type: "Échographie abdominale", | |
| status: "confirmed", | |
| doctor: "Dr. Lefèvre", | |
| notes: "Douleurs abdominales inexpliquées." | |
| }, | |
| { | |
| id: 5, | |
| patient: "Lucie Bernard", | |
| date: "2023-05-17", | |
| time: "16:30", | |
| type: "Scanner", | |
| status: "cancelled", | |
| doctor: "Dr. Yassine", | |
| notes: "Annulé par le patient." | |
| }, | |
| { | |
| id: 6, | |
| patient: "Thomas Petit", | |
| date: "2023-05-18", | |
| time: "10:00", | |
| type: "IRM lombaire", | |
| status: "in-progress", | |
| doctor: "Dr. Yassine", | |
| notes: "Lombalgie chronique." | |
| }, | |
| { | |
| id: 7, | |
| patient: "Emma Laurent", | |
| date: "2023-05-18", | |
| time: "13:15", | |
| type: "Échographie thyroïdienne", | |
| status: "pending", | |
| doctor: "Dr. Lefèvre", | |
| notes: "Nodule détecté lors de la consultation." | |
| }, | |
| { | |
| id: 8, | |
| patient: "Nicolas Roux", | |
| date: "2023-05-19", | |
| time: "08:30", | |
| type: "Radiographie du genou", | |
| status: "confirmed", | |
| doctor: "Dr. Yassine", | |
| notes: "Douleur au genou suite à une chute." | |
| }, | |
| { | |
| id: 9, | |
| patient: "Camille Leroy", | |
| date: "2023-05-19", | |
| time: "14:00", | |
| type: "Mammographie", | |
| status: "confirmed", | |
| doctor: "Dr. Lefèvre", | |
| notes: "Dépistage annuel." | |
| }, | |
| { | |
| id: 10, | |
| patient: "Antoine Michel", | |
| date: "2023-05-20", | |
| time: "11:45", | |
| type: "Scanner abdominal", | |
| status: "confirmed", | |
| doctor: "Dr. Dupont", | |
| notes: "Suspicion d'appendicite." | |
| } | |
| ]; | |
| // DOM Elements | |
| const sidebar = document.getElementById('sidebar'); | |
| const toggleSidebarBtn = document.getElementById('toggle-sidebar'); | |
| const mainContent = document.getElementById('main-content'); | |
| const appointmentsTableBody = document.getElementById('appointments-table-body'); | |
| const addAppointmentBtn = document.getElementById('add-appointment'); | |
| const addAppointmentModal = document.getElementById('add-appointment-modal'); | |
| const closeAddModalBtn = document.getElementById('close-add-modal'); | |
| const cancelAddAppointmentBtn = document.getElementById('cancel-add-appointment'); | |
| const appointmentForm = document.getElementById('appointment-form'); | |
| const editAppointmentModal = document.getElementById('edit-appointment-modal'); | |
| const closeEditModalBtn = document.getElementById('close-edit-modal'); | |
| const cancelEditAppointmentBtn = document.getElementById('cancel-edit-appointment'); | |
| const editAppointmentForm = document.getElementById('edit-appointment-form'); | |
| const viewAppointmentModal = document.getElementById('view-appointment-modal'); | |
| const closeViewModalBtn = document.getElementById('close-view-modal'); | |
| const editFromViewBtn = document.getElementById('edit-from-view'); | |
| const printAppointmentBtn = document.getElementById('print-appointment'); | |
| const exportPdfBtn = document.getElementById('export-pdf'); | |
| const exportExcelBtn = document.getElementById('export-excel'); | |
| const notificationsBtn = document.getElementById('notifications-btn'); | |
| const notificationPanel = document.getElementById('notification-panel'); | |
| const closeNotificationsBtn = document.getElementById('close-notifications'); | |
| // Initialize the app | |
| document.addEventListener('DOMContentLoaded', function() { | |
| renderAppointments(); | |
| renderCalendar(); | |
| // Set today's date as default in the add appointment form | |
| const today = new Date().toISOString().split('T')[0]; | |
| document.getElementById('appointment-date').value = today; | |
| document.getElementById('appointment-date').min = today; | |
| }); | |
| // Toggle sidebar | |
| toggleSidebarBtn.addEventListener('click', function() { | |
| sidebar.classList.toggle('sidebar-collapsed'); | |
| sidebar.classList.toggle('sidebar-expanded'); | |
| // Toggle text elements in sidebar | |
| const textElements = ['logo-text', 'user-info', 'dashboard-text', 'appointments-text', | |
| 'patients-text', 'reports-text', 'logs-text', 'settings-text', 'logout-text']; | |
| textElements.forEach(id => { | |
| const element = document.getElementById(id); | |
| if (element) { | |
| element.classList.toggle('hidden'); | |
| } | |
| }); | |
| // Adjust main content margin | |
| if (sidebar.classList.contains('sidebar-collapsed')) { | |
| mainContent.classList.add('ml-16'); | |
| } else { | |
| mainContent.classList.remove('ml-16'); | |
| } | |
| }); | |
| // Render appointments table | |
| function renderAppointments() { | |
| appointmentsTableBody.innerHTML = ''; | |
| appointments.forEach(appointment => { | |
| const row = document.createElement('tr'); | |
| row.className = 'hover:bg-gray-50'; | |
| row.innerHTML = ` | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="flex items-center"> | |
| <div class="flex-shrink-0 h-10 w-10 bg-medical-lightblue rounded-full flex items-center justify-center"> | |
| <i class="fas fa-user text-medical-blue"></i> | |
| </div> | |
| <div class="ml-4"> | |
| <div class="text-sm font-medium text-gray-900">${appointment.patient}</div> | |
| <div class="text-sm text-gray-500">${appointment.doctor}</div> | |
| </div> | |
| </div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900">${formatDate(appointment.date)}</div> | |
| <div class="text-sm text-gray-500">${appointment.time}</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900">${appointment.type}</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${getStatusClass(appointment.status)}"> | |
| ${getStatusText(appointment.status)} | |
| </span> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"> | |
| <button class="text-medical-blue hover:text-medical-darkblue mr-3 view-btn" data-id="${appointment.id}"> | |
| <i class="fas fa-eye"></i> | |
| </button> | |
| <button class="text-yellow-600 hover:text-yellow-900 mr-3 edit-btn" data-id="${appointment.id}"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| <button class="text-red-600 hover:text-red-900 delete-btn" data-id="${appointment.id}"> | |
| <i class="fas fa-trash"></i> | |
| </button> | |
| </td> | |
| `; | |
| appointmentsTableBody.appendChild(row); | |
| }); | |
| // Add event listeners to buttons | |
| document.querySelectorAll('.view-btn').forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const appointmentId = parseInt(this.getAttribute('data-id')); | |
| viewAppointment(appointmentId); | |
| }); | |
| }); | |
| document.querySelectorAll('.edit-btn').forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const appointmentId = parseInt(this.getAttribute('data-id')); | |
| editAppointment(appointmentId); | |
| }); | |
| }); | |
| document.querySelectorAll('.delete-btn').forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const appointmentId = parseInt(this.getAttribute('data-id')); | |
| deleteAppointment(appointmentId); | |
| }); | |
| }); | |
| } | |
| // Format date | |
| function formatDate(dateString) { | |
| const options = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric' }; | |
| return new Date(dateString).toLocaleDateString('fr-FR', options); | |
| } | |
| // Get status class | |
| function getStatusClass(status) { | |
| switch(status) { | |
| case 'confirmed': | |
| return 'bg-green-100 text-green-800'; | |
| case 'pending': | |
| return 'bg-yellow-100 text-yellow-800'; | |
| case 'cancelled': | |
| return 'bg-red-100 text-red-800'; | |
| case 'completed': | |
| return 'bg-blue-100 text-blue-800'; | |
| case 'in-progress': | |
| return 'bg-purple-100 text-purple-800'; | |
| default: | |
| return 'bg-gray-100 text-gray-800'; | |
| } | |
| } | |
| // Get status text | |
| function getStatusText(status) { | |
| switch(status) { | |
| case 'confirmed': | |
| return 'Confirmé'; | |
| case 'pending': | |
| return 'En attente'; | |
| case 'cancelled': | |
| return 'Annulé'; | |
| case 'completed': | |
| return 'Terminé'; | |
| case 'in-progress': | |
| return 'En cours'; | |
| default: | |
| return 'Inconnu'; | |
| } | |
| } | |
| // Render calendar | |
| function renderCalendar() { | |
| const calendarGrid = document.getElementById('calendar-grid'); | |
| calendarGrid.innerHTML = ''; | |
| // Get current date | |
| const currentDate = new Date(); | |
| const currentMonth = currentDate.getMonth(); | |
| const currentYear = currentDate.getFullYear(); | |
| // Get first day of month | |
| const firstDay = new Date(currentYear, currentMonth, 1).getDay(); | |
| // Adjust for Monday as first day (French calendar) | |
| const firstDayAdjusted = firstDay === 0 ? 6 : firstDay - 1; | |
| // Get days in month | |
| const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate(); | |
| // Get days from previous month to show | |
| const prevMonthDays = new Date(currentYear, currentMonth, 0).getDate(); | |
| // Create calendar cells | |
| let dayCount = 0; | |
| let nextMonthDay = 1; | |
| // 6 rows x 7 columns = 42 cells | |
| for (let i = 0; i < 42; i++) { | |
| const cell = document.createElement('div'); | |
| cell.className = 'min-h-24 p-1 border border-gray-100'; | |
| // Days from previous month | |
| if (i < firstDayAdjusted) { | |
| const prevDay = prevMonthDays - (firstDayAdjusted - i - 1); | |
| cell.innerHTML = `<div class="text-right text-gray-400">${prevDay}</div>`; | |
| cell.classList.add('bg-gray-50'); | |
| } | |
| // Days in current month | |
| else if (dayCount < daysInMonth) { | |
| dayCount++; | |
| const dateStr = `${currentYear}-${String(currentMonth + 1).padStart(2, '0')}-${String(dayCount).padStart(2, '0')}`; | |
| cell.innerHTML = ` | |
| <div class="text-right font-medium">${dayCount}</div> | |
| <div class="mt-1 space-y-1" id="events-${dateStr}"></div> | |
| `; | |
| // Highlight today | |
| if (dayCount === currentDate.getDate() && currentMonth === new Date().getMonth() && currentYear === new Date().getFullYear()) { | |
| cell.querySelector('div:first-child').classList.add('bg-medical-blue', 'text-white', 'rounded-full', 'w-6', 'h-6', 'flex', 'items-center', 'justify-center', 'mx-auto'); | |
| } | |
| // Add appointments to the cell | |
| const eventsContainer = cell.querySelector(`#events-${dateStr}`); | |
| const dayAppointments = appointments.filter(apt => apt.date === dateStr); | |
| dayAppointments.forEach(apt => { | |
| const event = document.createElement('div'); | |
| event.className = `text-xs p-1 rounded truncate ${getStatusClass(apt.status)}`; | |
| event.textContent = `${apt.time} - ${apt.patient.split(' ')[0]}`; | |
| eventsContainer.appendChild(event); | |
| }); | |
| } | |
| // Days from next month | |
| else { | |
| cell.innerHTML = `<div class="text-right text-gray-400">${nextMonthDay}</div>`; | |
| cell.classList.add('bg-gray-50'); | |
| nextMonthDay++; | |
| } | |
| calendarGrid.appendChild(cell); | |
| } | |
| } | |
| // Add new appointment | |
| addAppointmentBtn.addEventListener('click', function() { | |
| addAppointmentModal.classList.remove('hidden'); | |
| }); | |
| closeAddModalBtn.addEventListener('click', function() { | |
| addAppointmentModal.classList.add('hidden'); | |
| }); | |
| cancelAddAppointmentBtn.addEventListener('click', function() { | |
| addAppointmentModal.classList.add('hidden'); | |
| }); | |
| appointmentForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| // Get form values | |
| const patientSelect = document.getElementById('patient'); | |
| const patientText = patientSelect.options[patientSelect.selectedIndex].text; | |
| const examenType = document.getElementById('examen-type').value; | |
| const date = document.getElementById('appointment-date').value; | |
| const time = document.getElementById('appointment-time').value; | |
| const notes = document.getElementById('notes').value; | |
| // Create new appointment | |
| const newAppointment = { | |
| id: appointments.length > 0 ? Math.max(...appointments.map(a => a.id)) + 1 : 1, | |
| patient: patientText, | |
| date: date, | |
| time: time, | |
| type: examenType.charAt(0).toUpperCase() + examenType.slice(1), | |
| status: 'pending', | |
| doctor: 'Dr. Dupont', | |
| notes: notes | |
| }; | |
| // Add to appointments array | |
| appointments.push(newAppointment); | |
| // Show success message | |
| alert('Rendez-vous créé avec succès!'); | |
| // Close modal and reset form | |
| addAppointmentModal.classList.add('hidden'); | |
| appointmentForm.reset(); | |
| // Refresh appointments list and calendar | |
| renderAppointments(); | |
| renderCalendar(); | |
| }); | |
| // View appointment | |
| function viewAppointment(id) { | |
| const appointment = appointments.find(apt => apt.id === id); | |
| if (!appointment) return; | |
| // Populate view modal | |
| document.getElementById('view-patient-name').textContent = appointment.patient; | |
| document.getElementById('view-patient-dob').textContent = '15/03/1975'; // Sample data | |
| document.getElementById('view-patient-ssn').textContent = '1 85 03 75 123 456 78'; // Sample data | |
| document.getElementById('view-patient-phone').textContent = '06 12 34 56 78'; // Sample data | |
| const formattedDate = new Date(appointment.date).toLocaleDateString('fr-FR', { | |
| weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' | |
| }); | |
| document.getElementById('view-appointment-datetime').textContent = | |
| `${formattedDate} à ${appointment.time}`; | |
| document.getElementById('view-examen-type').textContent = appointment.type; | |
| document.getElementById('view-status').innerHTML = | |
| `<span class="px-2 py-1 rounded-full ${getStatusClass(appointment.status)}">${getStatusText(appointment.status)}</span>`; | |
| document.getElementById('view-doctor').textContent = appointment.doctor; | |
| document.getElementById('view-notes').textContent = appointment.notes; | |
| // Store appointment ID in edit button | |
| editFromViewBtn.setAttribute('data-id', appointment.id); | |
| // Show modal | |
| viewAppointmentModal.classList.remove('hidden'); | |
| } | |
| closeViewModalBtn.addEventListener('click', function() { | |
| viewAppointmentModal.classList.add('hidden'); | |
| }); | |
| // Edit from view | |
| editFromViewBtn.addEventListener('click', function() { | |
| const appointmentId = parseInt(this.getAttribute('data-id')); | |
| viewAppointmentModal.classList.add('hidden'); | |
| editAppointment(appointmentId); | |
| }); | |
| // Print appointment | |
| printAppointmentBtn.addEventListener('click', function() { | |
| window.print(); | |
| }); | |
| // Edit appointment | |
| function editAppointment(id) { | |
| const appointment = appointments.find(apt => apt.id === id); | |
| if (!appointment) return; | |
| // Populate edit form | |
| document.getElementById('edit-appointment-id').value = appointment.id; | |
| document.getElementById('edit-patient').value = '1'; // Sample data - would be appointment.patientId in real app | |
| document.getElementById('edit-examen-type').value = appointment.type.toLowerCase().split(' ')[0]; // Simplified for demo | |
| document.getElementById('edit-appointment-date').value = appointment.date; | |
| document.getElementById('edit-appointment-time').value = appointment.time; | |
| document.getElementById('edit-status').value = appointment.status; | |
| document.getElementById('edit-notes').value = appointment.notes; | |
| // Show modal | |
| editAppointmentModal.classList.remove('hidden'); | |
| } | |
| closeEditModalBtn.addEventListener('click', function() { | |
| editAppointmentModal.classList.add('hidden'); | |
| }); | |
| cancelEditAppointmentBtn.addEventListener('click', function() { | |
| editAppointmentModal.classList.add('hidden'); | |
| }); | |
| editAppointmentForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| // Get form values | |
| const id = parseInt(document.getElementById('edit-appointment-id').value); | |
| const patientSelect = document.getElementById('edit-patient'); | |
| const patientText = patientSelect.options[patientSelect.selectedIndex].text; | |
| const examenType = document.getElementById('edit-examen-type').value; | |
| const date = document.getElementById('edit-appointment-date').value; | |
| const time = document.getElementById('edit-appointment-time').value; | |
| const status = document.getElementById('edit-status').value; | |
| const notes = document.getElementById('edit-notes').value; | |
| // Find and update appointment | |
| const appointmentIndex = appointments.findIndex(apt => apt.id === id); | |
| if (appointmentIndex !== -1) { | |
| appointments[appointmentIndex] = { | |
| ...appointments[appointmentIndex], | |
| patient: patientText, | |
| date: date, | |
| time: time, | |
| type: examenType.charAt(0).toUpperCase() + examenType.slice(1), | |
| status: status, | |
| notes: notes | |
| }; | |
| } | |
| // Show success message | |
| alert('Rendez-vous modifié avec succès!'); | |
| // Close modal and reset form | |
| editAppointmentModal.classList.add('hidden'); | |
| editAppointmentForm.reset(); | |
| // Refresh appointments list and calendar | |
| renderAppointments(); | |
| renderCalendar(); | |
| }); | |
| // Delete appointment | |
| function deleteAppointment(id) { | |
| if (confirm('Êtes-vous sûr de vouloir supprimer ce rendez-vous?')) { | |
| // Find and remove appointment | |
| const appointmentIndex = appointments.findIndex(apt => apt.id === id); | |
| if (appointmentIndex !== -1) { | |
| appointments.splice(appointmentIndex, 1); | |
| } | |
| // Show success message | |
| alert('Rendez-vous supprimé avec succès!'); | |
| // Refresh appointments list and calendar | |
| renderAppointments(); | |
| renderCalendar(); | |
| } | |
| } | |
| // Export to PDF | |
| exportPdfBtn.addEventListener('click', function() { | |
| // In a real app, you would use jsPDF to generate a PDF | |
| alert('Export PDF en cours de développement'); | |
| }); | |
| // Export to Excel | |
| exportExcelBtn.addEventListener('click', function() { | |
| // Create a worksheet | |
| const ws = XLSX.utils.json_to_sheet(appointments.map(apt => ({ | |
| 'Patient': apt.patient, | |
| 'Date': apt.date, | |
| 'Heure': apt.time, | |
| 'Type d\'examen': apt.type, | |
| 'Statut': getStatusText(apt.status), | |
| 'Médecin': apt.doctor | |
| }))); | |
| // Create a workbook | |
| const wb = XLSX.utils.book_new(); | |
| XLSX.utils.book_append_sheet(wb, ws, "Rendez-vous"); | |
| // Export the workbook | |
| XLSX.writeFile(wb, "rendez-vous_avicenne.xlsx"); | |
| }); | |
| // Notifications panel | |
| notificationsBtn.addEventListener('click', function() { | |
| notificationPanel.classList.remove('translate-x-full'); | |
| }); | |
| closeNotificationsBtn.addEventListener('click', function() { | |
| notificationPanel.classList.add('translate-x-full'); | |
| }); | |
| </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=Dannylova31/nnnn" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |