| <!DOCTYPE html> |
| <html lang="fr"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Salon de Coiffure - File d'attente</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> |
| .queue-item { |
| transition: all 0.3s ease; |
| } |
| .queue-item:hover { |
| transform: translateY(-3px); |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); |
| } |
| .animate-pulse { |
| animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; |
| } |
| @keyframes pulse { |
| 0%, 100% { opacity: 1; } |
| 50% { opacity: 0.5; } |
| } |
| </style> |
| </head> |
| <body class="bg-gray-50 min-h-screen"> |
| <div class="container mx-auto px-4 py-8"> |
| |
| <header class="flex flex-col md:flex-row justify-between items-center mb-12"> |
| <div class="flex items-center mb-4 md:mb-0"> |
| <i class="fas fa-scissors text-3xl text-indigo-600 mr-3"></i> |
| <h1 class="text-3xl font-bold text-gray-800">Salon Belle Coupe</h1> |
| </div> |
| <div class="flex items-center space-x-4"> |
| <div class="bg-indigo-100 px-4 py-2 rounded-full"> |
| <span class="text-indigo-800 font-medium">Ouvert</span> |
| <span class="ml-2 text-gray-600">9h - 19h</span> |
| </div> |
| <div class="hidden md:block"> |
| <span class="text-gray-600">Tél: </span> |
| <span class="font-medium">01 23 45 67 89</span> |
| </div> |
| </div> |
| </header> |
|
|
| |
| <main class="grid grid-cols-1 lg:grid-cols-3 gap-8"> |
| |
| <div class="lg:col-span-2 bg-white rounded-xl shadow-md overflow-hidden"> |
| <div class="bg-indigo-600 px-6 py-4"> |
| <h2 class="text-xl font-bold text-white">Gestion de la file d'attente</h2> |
| </div> |
| |
| <div class="p-6"> |
| |
| <div class="mb-8"> |
| <h3 class="text-lg font-semibold text-gray-700 mb-4">Client actuel</h3> |
| <div id="current-client" class="bg-indigo-50 border-l-4 border-indigo-600 p-4 rounded-lg flex justify-between items-center"> |
| <div class="flex items-center"> |
| <div class="bg-indigo-100 p-3 rounded-full mr-4"> |
| <i class="fas fa-user text-indigo-600 text-xl"></i> |
| </div> |
| <div> |
| <p class="font-medium text-gray-800">Aucun client en cours</p> |
| <p class="text-sm text-gray-500">En attente du prochain client</p> |
| </div> |
| </div> |
| <button id="next-client-btn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg transition duration-200 hidden"> |
| Client suivant <i class="fas fa-arrow-right ml-2"></i> |
| </button> |
| </div> |
| </div> |
| |
| |
| <div> |
| <div class="flex justify-between items-center mb-4"> |
| <h3 class="text-lg font-semibold text-gray-700">File d'attente</h3> |
| <span id="queue-count" class="bg-gray-200 text-gray-700 px-3 py-1 rounded-full text-sm font-medium">0 clients</span> |
| </div> |
| |
| <div id="queue-list" class="space-y-3"> |
| |
| <div class="text-center py-8 text-gray-500" id="empty-queue-message"> |
| <i class="fas fa-users-slash text-3xl mb-2"></i> |
| <p>Aucun client dans la file d'attente</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white rounded-xl shadow-md overflow-hidden"> |
| <div class="bg-indigo-600 px-6 py-4"> |
| <h2 class="text-xl font-bold text-white">Ajouter un client</h2> |
| </div> |
| |
| <div class="p-6"> |
| <form id="add-client-form" class="space-y-4"> |
| <div> |
| <label for="client-name" class="block text-sm font-medium text-gray-700 mb-1">Nom du client</label> |
| <input type="text" id="client-name" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="Jean Dupont" required> |
| </div> |
| |
| <div> |
| <label for="client-service" class="block text-sm font-medium text-gray-700 mb-1">Service demandé</label> |
| <select id="client-service" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"> |
| <option value="Coupe homme">Coupe homme</option> |
| <option value="Coupe femme">Coupe femme</option> |
| <option value="Coloration">Coloration</option> |
| <option value="Brushing">Brushing</option> |
| <option value="Barbier">Barbier</option> |
| <option value="Autre">Autre</option> |
| </select> |
| </div> |
| |
| <div> |
| <label for="client-phone" class="block text-sm font-medium text-gray-700 mb-1">Téléphone (optionnel)</label> |
| <input type="tel" id="client-phone" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="06 12 34 56 78"> |
| </div> |
| |
| <button type="submit" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white py-2 px-4 rounded-lg transition duration-200 flex items-center justify-center"> |
| <i class="fas fa-plus-circle mr-2"></i> Ajouter à la file |
| </button> |
| </form> |
| |
| |
| <div class="mt-8 bg-gray-50 p-4 rounded-lg"> |
| <h3 class="text-lg font-semibold text-gray-700 mb-2">Temps d'attente estimé</h3> |
| <div class="flex items-center"> |
| <i class="fas fa-clock text-indigo-600 text-xl mr-3"></i> |
| <div> |
| <p class="text-gray-800 font-medium" id="wait-time">~ 0 min</p> |
| <p class="text-sm text-gray-500">(environ 15 min par client)</p> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="mt-6 grid grid-cols-2 gap-4"> |
| <div class="bg-blue-50 p-3 rounded-lg"> |
| <p class="text-sm text-blue-600 font-medium">Clients aujourd'hui</p> |
| <p class="text-2xl font-bold text-blue-800" id="today-count">0</p> |
| </div> |
| <div class="bg-green-50 p-3 rounded-lg"> |
| <p class="text-sm text-green-600 font-medium">En attente</p> |
| <p class="text-2xl font-bold text-green-800" id="waiting-count">0</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </main> |
| |
| |
| <footer class="mt-12 pt-6 border-t border-gray-200"> |
| <div class="flex flex-col md:flex-row justify-between items-center"> |
| <p class="text-gray-600 mb-4 md:mb-0">© 2023 Salon Belle Coupe. Tous droits réservés.</p> |
| <div class="flex space-x-4"> |
| <a href="#" class="text-gray-600 hover:text-indigo-600"><i class="fab fa-facebook-f"></i></a> |
| <a href="#" class="text-gray-600 hover:text-indigo-600"><i class="fab fa-instagram"></i></a> |
| <a href="#" class="text-gray-600 hover:text-indigo-600"><i class="fab fa-twitter"></i></a> |
| </div> |
| </div> |
| </footer> |
| </div> |
|
|
| <script> |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| let queue = JSON.parse(localStorage.getItem('hairSalonQueue')) || []; |
| let currentClient = JSON.parse(localStorage.getItem('currentClient')) || null; |
| let todayCount = parseInt(localStorage.getItem('todayCount')) || 0; |
| |
| |
| const queueList = document.getElementById('queue-list'); |
| const emptyQueueMessage = document.getElementById('empty-queue-message'); |
| const queueCount = document.getElementById('queue-count'); |
| const waitTime = document.getElementById('wait-time'); |
| const todayCountElement = document.getElementById('today-count'); |
| const waitingCountElement = document.getElementById('waiting-count'); |
| const currentClientElement = document.getElementById('current-client'); |
| const nextClientBtn = document.getElementById('next-client-btn'); |
| const addClientForm = document.getElementById('add-client-form'); |
| |
| |
| updateQueueUI(); |
| updateTodayCount(); |
| updateCurrentClientUI(); |
| |
| |
| addClientForm.addEventListener('submit', function(e) { |
| e.preventDefault(); |
| |
| const name = document.getElementById('client-name').value; |
| const service = document.getElementById('client-service').value; |
| const phone = document.getElementById('client-phone').value; |
| |
| const client = { |
| id: Date.now(), |
| name: name, |
| service: service, |
| phone: phone, |
| timestamp: new Date().toISOString() |
| }; |
| |
| queue.push(client); |
| todayCount++; |
| |
| saveQueue(); |
| updateQueueUI(); |
| updateTodayCount(); |
| |
| |
| addClientForm.reset(); |
| document.getElementById('client-name').focus(); |
| |
| |
| showNotification(`Client ${name} ajouté à la file d'attente!`); |
| }); |
| |
| |
| nextClientBtn.addEventListener('click', function() { |
| if (queue.length > 0) { |
| |
| currentClient = queue.shift(); |
| saveQueue(); |
| updateQueueUI(); |
| updateCurrentClientUI(); |
| |
| |
| showNotification(`Prise en charge de ${currentClient.name}`); |
| } |
| }); |
| |
| |
| function updateQueueUI() { |
| queueList.innerHTML = ''; |
| |
| if (queue.length === 0) { |
| emptyQueueMessage.classList.remove('hidden'); |
| queueCount.textContent = '0 clients'; |
| waitTime.textContent = '~ 0 min'; |
| waitingCountElement.textContent = '0'; |
| } else { |
| emptyQueueMessage.classList.add('hidden'); |
| queueCount.textContent = `${queue.length} client${queue.length > 1 ? 's' : ''}`; |
| waitTime.textContent = `~ ${queue.length * 15} min`; |
| waitingCountElement.textContent = queue.length; |
| |
| queue.forEach((client, index) => { |
| const queueItem = document.createElement('div'); |
| queueItem.className = 'queue-item bg-white border border-gray-200 rounded-lg p-4 flex justify-between items-center'; |
| |
| queueItem.innerHTML = ` |
| <div class="flex items-center"> |
| <div class="bg-gray-100 p-2 rounded-full mr-3"> |
| <i class="fas fa-user${index === 0 ? '-check text-green-600' : ' text-gray-600'}"></i> |
| </div> |
| <div> |
| <p class="font-medium text-gray-800">${client.name}</p> |
| <p class="text-sm text-gray-500">${client.service}</p> |
| ${client.phone ? `<p class="text-xs text-gray-400 mt-1"><i class="fas fa-phone mr-1"></i>${client.phone}</p>` : ''} |
| </div> |
| </div> |
| <div class="text-right"> |
| <span class="text-xs text-gray-500">#${index + 1}</span> |
| ${index === 0 ? '<span class="block text-xs text-green-600 font-medium mt-1">Prochain</span>' : ''} |
| </div> |
| `; |
| |
| queueList.appendChild(queueItem); |
| }); |
| } |
| } |
| |
| |
| function updateCurrentClientUI() { |
| if (currentClient) { |
| currentClientElement.innerHTML = ` |
| <div class="flex items-center"> |
| <div class="bg-indigo-100 p-3 rounded-full mr-4"> |
| <i class="fas fa-user text-indigo-600 text-xl"></i> |
| </div> |
| <div> |
| <p class="font-medium text-gray-800">${currentClient.name}</p> |
| <p class="text-sm text-gray-500">${currentClient.service}</p> |
| ${currentClient.phone ? `<p class="text-xs text-indigo-500 mt-1"><i class="fas fa-phone mr-1"></i>${currentClient.phone}</p>` : ''} |
| </div> |
| </div> |
| <button id="complete-service-btn" class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg transition duration-200 flex items-center"> |
| Terminer <i class="fas fa-check ml-2"></i> |
| </button> |
| `; |
| |
| document.getElementById('complete-service-btn').addEventListener('click', function() { |
| currentClient = null; |
| localStorage.removeItem('currentClient'); |
| updateCurrentClientUI(); |
| |
| if (queue.length > 0) { |
| nextClientBtn.classList.remove('hidden'); |
| } |
| |
| showNotification('Service terminé avec succès!'); |
| }); |
| |
| nextClientBtn.classList.add('hidden'); |
| } else { |
| currentClientElement.innerHTML = ` |
| <div class="flex items-center"> |
| <div class="bg-indigo-100 p-3 rounded-full mr-4"> |
| <i class="fas fa-user text-indigo-600 text-xl"></i> |
| </div> |
| <div> |
| <p class="font-medium text-gray-800">Aucun client en cours</p> |
| <p class="text-sm text-gray-500">En attente du prochain client</p> |
| </div> |
| </div> |
| ${queue.length > 0 ? `<button id="next-client-btn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg transition duration-200"> |
| Client suivant <i class="fas fa-arrow-right ml-2"></i> |
| </button>` : ''} |
| `; |
| |
| if (queue.length > 0) { |
| document.getElementById('next-client-btn').addEventListener('click', function() { |
| currentClient = queue.shift(); |
| saveQueue(); |
| updateQueueUI(); |
| updateCurrentClientUI(); |
| |
| showNotification(`Prise en charge de ${currentClient.name}`); |
| }); |
| } |
| } |
| } |
| |
| |
| function updateTodayCount() { |
| todayCountElement.textContent = todayCount; |
| localStorage.setItem('todayCount', todayCount.toString()); |
| } |
| |
| |
| function saveQueue() { |
| localStorage.setItem('hairSalonQueue', JSON.stringify(queue)); |
| if (currentClient) { |
| localStorage.setItem('currentClient', JSON.stringify(currentClient)); |
| } |
| } |
| |
| |
| function showNotification(message) { |
| const notification = document.createElement('div'); |
| notification.className = 'fixed bottom-4 right-4 bg-green-600 text-white px-4 py-2 rounded-lg shadow-lg flex items-center animate-pulse'; |
| notification.innerHTML = ` |
| <i class="fas fa-check-circle mr-2"></i> |
| <span>${message}</span> |
| `; |
| |
| document.body.appendChild(notification); |
| |
| setTimeout(() => { |
| notification.classList.remove('animate-pulse'); |
| notification.classList.add('opacity-0', 'transition-opacity', 'duration-500'); |
| |
| setTimeout(() => { |
| notification.remove(); |
| }, 500); |
| }, 3000); |
| } |
| |
| |
| function checkForDayChange() { |
| const lastUpdated = localStorage.getItem('lastUpdated'); |
| const today = new Date().toDateString(); |
| |
| if (!lastUpdated || lastUpdated !== today) { |
| todayCount = 0; |
| localStorage.setItem('todayCount', '0'); |
| localStorage.setItem('lastUpdated', today); |
| updateTodayCount(); |
| } |
| } |
| |
| |
| setInterval(checkForDayChange, 3600000); |
| checkForDayChange(); |
| }); |
| </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=aramka/faexpress" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |