Файловый менеджер - Редактировать - /home/gqdcvggs/imators.systems/waterloo/shop.php
Назад
<?php include 'header.php'; include 'db.php'; function parseShopHours($hours, $days) { list($openHour, $closeHour) = explode(' à ', $hours); $daysArray = explode(',', $days); $daysArray = array_map('trim', $daysArray); $isMorningOpen = strtotime($openHour) <= strtotime('10:00'); $isLateOpen = strtotime($closeHour) >= strtotime('20:00'); $isWeekendOpen = in_array('Saturday', $daysArray) || in_array('Sunday', $daysArray); $schedule = []; $allDays = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']; $dayTranslation = [ 'Monday' => 'Lundi', 'Tuesday' => 'Mardi', 'Wednesday' => 'Mercredi', 'Thursday' => 'Jeudi', 'Friday' => 'Vendredi', 'Saturday' => 'Samedi', 'Sunday' => 'Dimanche' ]; foreach ($allDays as $day) { if (in_array($day, $daysArray)) { $schedule[$dayTranslation[$day]] = [$openHour . ' - ' . $closeHour]; } else { $schedule[$dayTranslation[$day]] = ['Fermé']; } } return [ 'open_hour' => $openHour, 'close_hour' => $closeHour, 'open_days' => $daysArray, 'morning_open' => $isMorningOpen, 'late_open' => $isLateOpen, 'weekend_open' => $isWeekendOpen, 'formatted_schedule' => $schedule ]; } $shops = mysqli_query($conn, "SELECT * FROM shop ORDER BY price_smilemore DESC, title ASC"); ?> <!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Commerces - Vert Chasseur</title> <link rel="icon" type="image/png" href="logo_new.png"> <meta name="description" content="Découvrez tous les commerces et restaurants partenaires dans le quartier de Vert Chasseur à Uccle, Bruxelles."> <script src="https://cdn.tailwindcss.com"></script> <script> tailwind.config = { darkMode: 'class', theme: { extend: {} } } </script> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Princess+Sofia&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> <style> body { font-family: 'Poppins', sans-serif; letter-spacing: -0.01em; } .card { animation: fadeIn 0.5s ease-out forwards; opacity: 0; transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1); } .card:hover { transform: translateY(-8px); } @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .status-dot { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .txt-chasseur { font-family: "Princess Sofia", serif; font-weight: 400; font-style: normal; } .shop-image { transition: transform 0.7s ease; } .card:hover .shop-image { transform: scale(1.05); } </style> </head> <body class="bg-white dark:bg-black text-black dark:text-white transition-colors duration-300"> <script> if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { document.documentElement.classList.add('dark'); } window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { if (e.matches) { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } }); document.addEventListener('DOMContentLoaded', function() { let searchInput = document.getElementById('shop-search'); let filterMorning = document.getElementById('filter-morning'); let filterLate = document.getElementById('filter-late'); let filterWeekend = document.getElementById('filter-weekend'); let shopCards = document.querySelectorAll('[data-shop]'); let currentDay = ''; let currentTime = ''; let shopStatus = {}; let nextOpenings = {}; let showScheduleDetails = null; function updateCurrentTime() { const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; const now = new Date(); currentDay = days[now.getDay()]; let hours = now.getHours(); let minutes = now.getMinutes(); hours = hours < 10 ? '0' + hours : hours; minutes = minutes < 10 ? '0' + minutes : minutes; currentTime = `${hours}:${minutes}`; checkShopOpenStatus(); } function timeToMinutes(timeString) { const [hours, minutes] = timeString.split(':').map(Number); return hours * 60 + minutes; } function isShopOpen(openDays, openHour, closeHour) { if (!openDays.includes(currentDay)) { return false; } const currentTimeMinutes = timeToMinutes(currentTime); const openTimeMinutes = timeToMinutes(openHour); const closeTimeMinutes = timeToMinutes(closeHour); return currentTimeMinutes >= openTimeMinutes && currentTimeMinutes <= closeTimeMinutes; } function calculateNextOpening(openDays, openHour) { if (openDays.length === 0) { return null; } const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; const currentDayIndex = days.indexOf(currentDay); const currentTimeMinutes = timeToMinutes(currentTime); const openTimeMinutes = timeToMinutes(openHour); if (openDays.includes(currentDay) && currentTimeMinutes < openTimeMinutes) { return { day: currentDay, time: openHour }; } for (let i = 1; i <= 7; i++) { const nextDayIndex = (currentDayIndex + i) % 7; const nextDay = days[nextDayIndex]; if (openDays.includes(nextDay)) { return { day: nextDay, time: openHour }; } } return null; } function formatNextOpeningDay(day) { const dayTranslations = { 'Monday': 'Lundi', 'Tuesday': 'Mardi', 'Wednesday': 'Mercredi', 'Thursday': 'Jeudi', 'Friday': 'Vendredi', 'Saturday': 'Samedi', 'Sunday': 'Dimanche' }; if (day === currentDay) { return "Aujourd'hui"; } return dayTranslations[day]; } function checkShopOpenStatus() { shopCards.forEach(shop => { const shopId = shop.getAttribute('data-shop-id'); const openHour = shop.getAttribute('data-open-hour'); const closeHour = shop.getAttribute('data-close-hour'); const openDays = JSON.parse(shop.getAttribute('data-open-days')); const isOpen = isShopOpen(openDays, openHour, closeHour); shopStatus[shopId] = isOpen; const statusBadge = shop.querySelector('.status-badge'); const statusText = shop.querySelector('.status-text'); if (statusBadge && statusText) { if (isOpen) { statusBadge.classList.remove('bg-red-500'); statusBadge.classList.add('bg-green-500'); statusText.textContent = 'Ouvert'; } else { statusBadge.classList.remove('bg-green-500'); statusBadge.classList.add('bg-red-500'); statusText.textContent = 'Fermé'; const nextOpen = calculateNextOpening(openDays, openHour); if (nextOpen) { nextOpenings[shopId] = nextOpen; const nextOpeningElement = shop.querySelector('.next-opening'); if (nextOpeningElement) { const nextOpeningText = nextOpeningElement.querySelector('.next-opening-text'); if (nextOpeningText) { nextOpeningText.textContent = formatNextOpeningDay(nextOpen.day) + ' à ' + nextOpen.time; nextOpeningElement.style.display = 'block'; } } } } } }); } function filterShops() { const searchTerm = searchInput.value.toLowerCase(); const filterMorningActive = filterMorning.classList.contains('filter-active'); const filterLateActive = filterLate.classList.contains('filter-active'); const filterWeekendActive = filterWeekend.classList.contains('filter-active'); shopCards.forEach(shop => { const title = shop.getAttribute('data-title').toLowerCase(); const description = shop.getAttribute('data-description').toLowerCase(); const morning = shop.getAttribute('data-morning') === 'true'; const late = shop.getAttribute('data-late') === 'true'; const weekend = shop.getAttribute('data-weekend') === 'true'; const matchesSearch = !searchTerm || title.includes(searchTerm) || description.includes(searchTerm); const matchesFilters = (!filterMorningActive || morning) && (!filterLateActive || late) && (!filterWeekendActive || weekend); shop.style.display = matchesSearch && matchesFilters ? 'block' : 'none'; }); } searchInput.addEventListener('input', filterShops); filterMorning.addEventListener('click', function() { this.classList.toggle('filter-active'); if (this.classList.contains('filter-active')) { this.classList.remove('bg-white', 'text-black', 'dark:bg-black', 'dark:text-white', 'border', 'border-gray-200', 'dark:border-gray-800'); this.classList.add('bg-black', 'text-white', 'dark:bg-white', 'dark:text-black'); } else { this.classList.add('bg-white', 'text-black', 'dark:bg-black', 'dark:text-white', 'border', 'border-gray-200', 'dark:border-gray-800'); this.classList.remove('bg-black', 'text-white', 'dark:bg-white', 'dark:text-black'); } filterShops(); }); filterLate.addEventListener('click', function() { this.classList.toggle('filter-active'); if (this.classList.contains('filter-active')) { this.classList.remove('bg-white', 'text-black', 'dark:bg-black', 'dark:text-white', 'border', 'border-gray-200', 'dark:border-gray-800'); this.classList.add('bg-black', 'text-white', 'dark:bg-white', 'dark:text-black'); } else { this.classList.add('bg-white', 'text-black', 'dark:bg-black', 'dark:text-white', 'border', 'border-gray-200', 'dark:border-gray-800'); this.classList.remove('bg-black', 'text-white', 'dark:bg-white', 'dark:text-black'); } filterShops(); }); filterWeekend.addEventListener('click', function() { this.classList.toggle('filter-active'); if (this.classList.contains('filter-active')) { this.classList.remove('bg-white', 'text-black', 'dark:bg-black', 'dark:text-white', 'border', 'border-gray-200', 'dark:border-gray-800'); this.classList.add('bg-black', 'text-white', 'dark:bg-white', 'dark:text-black'); } else { this.classList.add('bg-white', 'text-black', 'dark:bg-black', 'dark:text-white', 'border', 'border-gray-200', 'dark:border-gray-800'); this.classList.remove('bg-black', 'text-white', 'dark:bg-white', 'dark:text-black'); } filterShops(); }); document.querySelectorAll('.schedule-button').forEach(button => { button.addEventListener('click', function() { const shopId = this.getAttribute('data-shop-id'); const scheduleDetails = document.getElementById('schedule-' + shopId); if (scheduleDetails.style.display === 'none' || scheduleDetails.style.display === '') { scheduleDetails.style.display = 'block'; } else { scheduleDetails.style.display = 'none'; } }); }); updateCurrentTime(); setInterval(updateCurrentTime, 60000); }); </script> <main class="container mx-auto px-4 py-16 max-w-6xl"> <header class="text-center mb-16 mt-20"> <p class="text-gray-500 dark:text-gray-400 text-sm tracking-wider uppercase mb-3">Uccle · Bruxelles</p> <h1 class="text-4xl md:text-6xl font-light mb-5 text-black dark:text-white"> <span class="txt-chasseur">Commerces</span> à Vert Chasseur </h1> <p class="text-lg text-gray-600 dark:text-gray-300 leading-relaxed max-w-2xl mx-auto"> Découvrez les enseignes qui font la richesse du quartier </p> </header> <div class="space-y-8 mb-16"> <div class="relative max-w-xl mx-auto"> <input type="text" id="shop-search" placeholder="Rechercher un commerce..." class="w-full px-6 py-4 rounded-2xl bg-white dark:bg-black shadow-sm dark:shadow-none border border-gray-200 dark:border-gray-800 focus:border-gray-400 dark:focus:border-gray-600 focus:outline-none text-black dark:text-white text-lg"> <i class="fas fa-search absolute right-6 top-1/2 transform -translate-y-1/2 text-gray-400 dark:text-gray-500"></i> </div> <div class="flex flex-wrap justify-center gap-4 mt-8"> <button id="filter-morning" class="px-5 py-3 rounded-xl transition-all duration-300 hover:shadow-lg text-sm font-medium bg-white text-black dark:bg-black dark:text-white border border-gray-200 dark:border-gray-800"> <i class="fas fa-sun mr-2"></i>Ouvert le matin </button> <button id="filter-late" class="px-5 py-3 rounded-xl transition-all duration-300 hover:shadow-lg text-sm font-medium bg-white text-black dark:bg-black dark:text-white border border-gray-200 dark:border-gray-800"> <i class="fas fa-moon mr-2"></i>Ouvert après 20h </button> <button id="filter-weekend" class="px-5 py-3 rounded-xl transition-all duration-300 hover:shadow-lg text-sm font-medium bg-white text-black dark:bg-black dark:text-white border border-gray-200 dark:border-gray-800"> <i class="fas fa-calendar mr-2"></i>Ouvert le week-end </button> </div> </div> <div class="grid gap-8 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3"> <?php $delay = 0; $shopCount = 0; while($shop = mysqli_fetch_assoc($shops)): $shopCount++; $openingInfo = parseShopHours($shop['hour_open'], $shop['day_open']); $mainImage = trim(explode(',', trim($shop['url_image'], '()'))[0]); ?> <article class="card bg-white dark:bg-black rounded-3xl overflow-hidden border border-gray-100 dark:border-gray-800 shadow-lg dark:shadow-gray-900/30" data-shop data-shop-id="<?= $shopCount ?>" data-open-hour="<?= htmlspecialchars($openingInfo['open_hour']) ?>" data-close-hour="<?= htmlspecialchars($openingInfo['close_hour']) ?>" data-open-days='<?= json_encode($openingInfo['open_days']) ?>' data-title="<?= htmlspecialchars($shop['title']) ?>" data-description="<?= htmlspecialchars($shop['description']) ?>" data-morning="<?= $openingInfo['morning_open'] ? 'true' : 'false' ?>" data-late="<?= $openingInfo['late_open'] ? 'true' : 'false' ?>" data-weekend="<?= $openingInfo['weekend_open'] ? 'true' : 'false' ?>" style="animation-delay: <?= $delay ?>s"> <div class="aspect-[4/3] relative overflow-hidden"> <img src="<?= htmlspecialchars($mainImage) ?>" alt="<?= htmlspecialchars($shop['title']) ?>" class="w-full h-full object-cover shop-image"> <div class="absolute inset-0 bg-gradient-to-t from-black/60 via-black/20 to-transparent"></div> <?php if($shop['price_smilemore'] == 1): ?> <div class="absolute top-4 right-4 bg-white/10 backdrop-blur-md px-3 py-1.5 rounded-full text-sm font-medium text-white border border-white/20"> <i class="fas fa-award mr-1.5"></i>Le plus fréquenté </div> <?php endif; ?> <div class="absolute top-4 left-4"> <span class="status-badge inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-red-500 text-white"> <span class="status-dot w-1.5 h-1.5 rounded-full bg-white mr-1.5"></span> <span class="status-text">Fermé</span> </span> </div> <div class="absolute bottom-4 left-4 flex gap-2"> <?php if($openingInfo['morning_open']): ?> <span class="px-2 py-1 bg-blue-500/70 text-white backdrop-blur-md rounded-full text-xs border border-blue-400/20"> <i class="fas fa-sun"></i> </span> <?php endif; ?> <?php if($openingInfo['late_open']): ?> <span class="px-2 py-1 bg-indigo-500/70 text-white backdrop-blur-md rounded-full text-xs border border-indigo-400/20"> <i class="fas fa-moon"></i> </span> <?php endif; ?> <?php if($openingInfo['weekend_open']): ?> <span class="px-2 py-1 bg-purple-500/70 text-white backdrop-blur-md rounded-full text-xs border border-purple-400/20"> <i class="fas fa-calendar"></i> </span> <?php endif; ?> </div> </div> <div class="p-6"> <h3 class="text-xl font-medium text-black dark:text-white mb-3"><?= htmlspecialchars($shop['title']) ?></h3> <p class="text-gray-600 dark:text-gray-300 text-sm line-clamp-3 mb-4"><?= htmlspecialchars($shop['description']) ?></p> <div class="text-sm text-gray-600 dark:text-gray-300 space-y-1 mb-5"> <div class="flex items-center gap-2"> <i class="fas fa-clock w-5 text-gray-400 dark:text-gray-500"></i> <button class="schedule-button flex-1 text-left hover:underline" data-shop-id="<?= $shopCount ?>"> Voir les horaires </button> </div> <div id="schedule-<?= $shopCount ?>" class="mt-3 p-3 bg-gray-50 dark:bg-gray-900 rounded-lg text-xs space-y-1" style="display: none;"> <?php foreach($openingInfo['formatted_schedule'] as $day => $hours): ?> <div class="flex justify-between"> <span class="font-medium"><?= $day ?>:</span> <span> <?php if (count($hours) === 1 && $hours[0] === 'Fermé'): ?> <span class="text-red-500">Fermé</span> <?php else: ?> <?= implode(' & ', $hours) ?> <?php endif; ?> </span> </div> <?php endforeach; ?> </div> <div class="next-opening text-xs bg-gray-50 dark:bg-gray-900 p-2 rounded-lg mt-2" style="display: none;"> <span class="font-medium">Prochaine ouverture: </span> <span class="next-opening-text"></span> </div> </div> <a href="shop-details.php?id=<?= $shop['id'] ?>" class="group block w-full text-center py-3 rounded-xl transition-all duration-300 text-sm font-medium relative overflow-hidden bg-black dark:bg-white text-white dark:text-black hover:shadow-lg"> <span class="flex items-center justify-center"> Plus d'informations <i class="fas fa-arrow-right ml-2 transform group-hover:translate-x-1 transition-transform"></i> </span> </a> </div> </article> <?php $delay += 0.1; endwhile; ?> </div> </main> <footer class="w-full py-8 mt-16 border-t border-gray-100 dark:border-gray-900"> <p class="text-xs text-gray-500 dark:text-gray-400 text-center max-w-3xl mx-auto px-4">© 2025 Vert Chasseur · A <a href="https://aktascorp.com" class="underline hover:text-gray-600 dark:hover:text-gray-300">aktascorp</a> member · <a href="https://aktascorp.com/privacy" class="hover:text-gray-600 dark:hover:text-gray-300">Confidentialité</a></p> </footer> </body> </html>
| ver. 1.6 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0.01 |
proxy
|
phpinfo
|
Настройка