faexpress / index.html
aramka's picture
undefined - Initial Deployment
2092260 verified
<!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 -->
<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 Content -->
<main class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Queue Management Section -->
<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">
<!-- Current Client -->
<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>
<!-- Queue List -->
<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">
<!-- Queue items will be added here dynamically -->
<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>
<!-- Add Client Section -->
<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>
<!-- Estimated Wait Time -->
<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>
<!-- Statistics -->
<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 -->
<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() {
// Initialize queue from localStorage or empty array
let queue = JSON.parse(localStorage.getItem('hairSalonQueue')) || [];
let currentClient = JSON.parse(localStorage.getItem('currentClient')) || null;
let todayCount = parseInt(localStorage.getItem('todayCount')) || 0;
// DOM Elements
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');
// Update UI on load
updateQueueUI();
updateTodayCount();
updateCurrentClientUI();
// Add client to queue
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();
// Reset form
addClientForm.reset();
document.getElementById('client-name').focus();
// Show notification
showNotification(`Client ${name} ajouté à la file d'attente!`);
});
// Next client button
nextClientBtn.addEventListener('click', function() {
if (queue.length > 0) {
// Remove current client (if any) and set new one
currentClient = queue.shift();
saveQueue();
updateQueueUI();
updateCurrentClientUI();
// Show notification
showNotification(`Prise en charge de ${currentClient.name}`);
}
});
// Function to update queue UI
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 to update current client UI
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 to update today's count
function updateTodayCount() {
todayCountElement.textContent = todayCount;
localStorage.setItem('todayCount', todayCount.toString());
}
// Function to save queue to localStorage
function saveQueue() {
localStorage.setItem('hairSalonQueue', JSON.stringify(queue));
if (currentClient) {
localStorage.setItem('currentClient', JSON.stringify(currentClient));
}
}
// Function to show notification
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);
}
// Reset today's count at midnight
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();
}
}
// Check for day change every hour
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>