Файловый менеджер - Редактировать - /home/gqdcvggs/imators.systems/quarter-app/resident-dashboard.php
Назад
<?php session_start(); include 'db.php'; include 'header-mobile.php'; $is_guest = false; $resident = null; if (!isset($_SESSION['resident_id']) && !isset($_SESSION['guest_mode'])) { header('Location: login.php'); exit; } if (isset($_SESSION['guest_mode'])) { $is_guest = true; } else { $resident_id = $_SESSION['resident_id']; $stmt = $conn->prepare("SELECT * FROM residents WHERE id = ?"); $stmt->bind_param("i", $resident_id); $stmt->execute(); $resident = $stmt->get_result()->fetch_assoc(); } $offers_query = "SELECT * FROM resident_offers WHERE is_active = 1 AND valid_until >= NOW() ORDER BY created_at DESC"; $offers = mysqli_query($conn, $offers_query); $success_message = ''; $error_message = ''; if (!$is_guest && isset($_POST['action'])) { if ($_POST['action'] == 'update_profile') { $first_name = trim($_POST['first_name']); $last_name = trim($_POST['last_name']); $email = trim($_POST['email']); $address = trim($_POST['address']); if (empty($first_name) || empty($last_name) || empty($email)) { $error_message = 'Tous les champs obligatoires doivent être remplis.'; } else { $update_stmt = $conn->prepare("UPDATE residents SET first_name = ?, last_name = ?, email = ?, address = ? WHERE id = ?"); $update_stmt->bind_param("ssssi", $first_name, $last_name, $email, $address, $resident_id); if ($update_stmt->execute()) { $success_message = 'Profil mis à jour avec succès !'; $stmt = $conn->prepare("SELECT * FROM residents WHERE id = ?"); $stmt->bind_param("i", $resident_id); $stmt->execute(); $resident = $stmt->get_result()->fetch_assoc(); } else { $error_message = 'Erreur lors de la mise à jour du profil.'; } } } if ($_POST['action'] == 'change_password') { $current_password = $_POST['current_password']; $new_password = $_POST['new_password']; $confirm_password = $_POST['confirm_password']; if (password_verify($current_password, $resident['password'])) { if ($new_password === $confirm_password && strlen($new_password) >= 6) { $hashed_password = password_hash($new_password, PASSWORD_DEFAULT); $pwd_stmt = $conn->prepare("UPDATE residents SET password = ? WHERE id = ?"); $pwd_stmt->bind_param("si", $hashed_password, $resident_id); if ($pwd_stmt->execute()) { $success_message = 'Mot de passe modifié avec succès !'; } else { $error_message = 'Erreur lors de la modification du mot de passe.'; } } else { $error_message = 'Le nouveau mot de passe doit contenir au moins 6 caractères et les mots de passe doivent correspondre.'; } } else { $error_message = 'Mot de passe actuel incorrect.'; } } } if (isset($_GET['action']) && $_GET['action'] == 'logout') { header('Location: logout.php'); exit; } ?> <!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?= $is_guest ? 'Vert Chasseur' : 'Mon Compte - Vert Chasseur' ?></title> <link rel="icon" type="image/png" href="logo_new.png"> <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=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Princess+Sofia&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> <style> @media (min-width: 768px) { body { background-image: url('font-homepage.png'); background-size: cover; background-position: center; background-attachment: fixed; background-repeat: no-repeat; } } @media (max-width: 767px) { body { background-color: #ffffff !important; background-image: none !important; } .dark body { background-color: #000000 !important; background-image: none !important; } } body { font-family: 'Inter', sans-serif; } .txt-chasseur { font-family: "Princess Sofia", serif; font-weight: 400; } .weather-card { background-image: linear-gradient( 10deg, hsl(240deg 70% 73%) 0%, hsl(296deg 45% 68%) 4%, hsl(335deg 73% 76%) 8%, hsl(359deg 84% 82%) 14%, hsl(18deg 77% 82%) 22%, hsl(33deg 56% 84%) 33%, hsl(56deg 29% 90%) 49%, hsl(72deg 32% 90%) 66%, hsl(88deg 36% 91%) 79%, hsl(108deg 40% 92%) 87%, hsl(130deg 49% 92%) 92%, hsl(146deg 61% 92%) 97%, hsl(158deg 73% 91%) 100% ); } .weather-icon { filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1)); } .weather-card { cursor: pointer; transition: transform 0.2s ease; } .weather-card:hover { transform: scale(1.02); } .weather-detailed { display: none; margin-top: 20px; padding: 20px; background: rgba(255, 255, 255, 0.2); border-radius: 15px; backdrop-filter: blur(10px); } .weather-detailed.show { display: block; } .forecast-item { display: flex; align-items: center; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.2); } .forecast-item:last-child { border-bottom: none; } .settings-modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); z-index: 9999; display: flex; align-items: center; justify-content: center; opacity: 0; visibility: hidden; transition: all 0.3s ease; } .settings-modal.show { opacity: 1; visibility: visible; } .settings-content { background: white; border-radius: 1rem; max-width: 90vw; max-height: 90vh; overflow-y: auto; transform: scale(0.9); transition: transform 0.3s ease; } .dark .settings-content { background: #1c1917; } .settings-modal.show .settings-content { transform: scale(1); } .tab-button { padding: 0.75rem 1rem; border-radius: 0.5rem; transition: all 0.2s ease; cursor: pointer; } .tab-button.active { background: #16a34a; color: white; } .tab-button:not(.active) { color: #6b7280; } .tab-button:not(.active):hover { background: #f3f4f6; color: #374151; } .dark .tab-button:not(.active):hover { background: #374151; color: #e5e7eb; } .tab-content { display: none; } .tab-content.active { display: block; } </style> </head> <body class="bg-white dark:bg-black transition-colors duration-300"> <script> if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } </script> <main class="min-h-screen px-4 py-8 md:py-16"> <div class="max-w-7xl mx-auto"> <div class="flex flex-col items-center justify-center mb-8 md:mb-12 text-center relative"> <?php if (!$is_guest): ?> <button onclick="openSettings()" class="absolute top-0 right-0 p-2 text-stone-600 dark:text-stone-400 hover:text-stone-800 dark:hover:text-stone-200 transition-colors"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/> </svg> </button> <?php else: ?> <a href="?action=logout" class="absolute top-0 right-0 p-2 text-stone-600 dark:text-stone-400 hover:text-stone-800 dark:hover:text-stone-200 transition-colors" title="Retour"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/> </svg> </a> <?php endif; ?> <h1 class="mt-4 md:mt-12 text-3xl md:text-5xl lg:text-6xl font-light text-stone-800 dark:text-white mb-2 md:mb-3 tracking-tight"> <?php if ($is_guest): ?> Bienvenue à <span class="txt-chasseur text-green-600">Vert Chasseur</span> <?php else: ?> Salutations <span><?= htmlspecialchars($resident['first_name']) ?></span> <?php endif; ?> </h1> <p class="text-lg md:text-xl text-stone-600 dark:text-stone-400 font-light"> <?= $is_guest ? 'Découvre ton quartier.' : 'Ravis de te voir.' ?> </p> </div> <div class="grid grid-cols-1 lg:grid-cols-4 gap-6 md:gap-8 mb-8 md:mb-16"> <div class="lg:col-span-3 space-y-6 md:space-y-8"> <div id="weather-card" class="weather-card rounded-2xl md:rounded-3xl p-6 md:p-8 text-black shadow-lg" onclick="toggleWeatherDetails()"> <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center space-y-4 sm:space-y-0"> <div> <h3 class="text-xl md:text-2xl font-medium mb-2">La météo d'aujourd'hui à Vert Chasseur</h3> <div id="weather-content" class="flex items-center space-x-4"> <div class="animate-pulse flex space-x-4"> <div class="w-16 h-16 bg-white/20 rounded-lg"></div> <div class="space-y-2"> <div class="h-4 bg-white/20 rounded w-24"></div> <div class="h-3 bg-white/20 rounded w-32"></div> </div> </div> </div> </div> <div id="weather-details" class="text-right opacity-90"> <div class="animate-pulse space-y-2"> <div class="h-3 bg-white/20 rounded w-20 ml-auto"></div> <div class="h-3 bg-white/20 rounded w-16 ml-auto"></div> </div> </div> </div> <div id="weather-detailed" class="weather-detailed"> <h4 class="text-lg font-medium mb-4">Prévisions sur 7 jours</h4> <div id="forecast-container"> <div class="animate-pulse space-y-3"> <div class="h-10 bg-white/20 rounded"></div> <div class="h-10 bg-white/20 rounded"></div> <div class="h-10 bg-white/20 rounded"></div> <div class="h-10 bg-white/20 rounded"></div> <div class="h-10 bg-white/20 rounded"></div> <div class="h-10 bg-white/20 rounded"></div> <div class="h-10 bg-white/20 rounded"></div> </div> </div> </div> </div> <div class="bg-white dark:bg-stone-900 rounded-2xl md:rounded-3xl p-6 md:p-8 border border-stone-200 dark:border-stone-800 shadow-lg dark:shadow-stone-900/30"> <h2 class="text-2xl md:text-3xl font-light text-stone-800 dark:text-white mb-6 md:mb-8 tracking-tight">Offres du moment</h2> <?php if (mysqli_num_rows($offers) > 0): ?> <div class="grid gap-4 md:gap-6"> <?php while($offer = mysqli_fetch_assoc($offers)): ?> <div class="bg-gradient-to-r from-green-50 to-emerald-50 dark:from-green-900/20 dark:to-emerald-900/20 p-4 md:p-6 rounded-xl md:rounded-2xl border border-green-100 dark:border-green-800"> <div class="flex flex-col sm:flex-row sm:items-start justify-between space-y-3 sm:space-y-0"> <div class="flex-1"> <h3 class="text-base md:text-lg font-medium text-stone-900 dark:text-white mb-1"><?= htmlspecialchars($offer['shop_name']) ?></h3> <p class="text-green-700 dark:text-green-400 font-medium mb-2 text-sm md:text-base"><?= htmlspecialchars($offer['offer_title']) ?></p> <?php if ($offer['time_restriction']): ?> <p class="text-stone-600 dark:text-stone-300 text-xs md:text-sm">Valable <?= htmlspecialchars($offer['time_restriction']) ?></p> <?php endif; ?> <?php if ($offer['conditions']): ?> <p class="text-stone-500 dark:text-stone-400 text-xs mt-1"><?= htmlspecialchars($offer['conditions']) ?></p> <?php endif; ?> </div> <div class="flex-shrink-0"> <span class="bg-green-100 dark:bg-green-800 text-green-800 dark:text-green-200 px-3 py-1 rounded-full text-xs font-medium"> Jusqu'au <?= date('d/m', strtotime($offer['valid_until'])) ?> </span> </div> </div> </div> <?php endwhile; ?> </div> <?php else: ?> <div class="text-center py-8 md:py-12"> <svg class="w-12 h-12 md:w-16 md:h-16 text-stone-300 dark:text-stone-600 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v13m0-13V6a2 2 0 112 2h-2zm0 0V5.5A2.5 2.5 0 109.5 8H12zm-7 4h14M5 12a2 2 0 110-4h14a2 2 0 110 4M5 12v7a2 2 0 002 2h10a2 2 0 002-2v-7"/> </svg> <p class="text-stone-500 dark:text-stone-400">Aucune offre disponible pour le moment</p> <p class="text-stone-400 dark:text-stone-500 text-sm mt-1">Reviens bientôt pour découvrir de nouvelles promotions !</p> </div> <?php endif; ?> </div> </div> <div class="space-y-6 md:space-y-8"> <?php if ($is_guest): ?> <div class="bg-gradient-to-br from-amber-50 to-orange-50 dark:from-amber-900/20 dark:to-orange-900/20 rounded-2xl md:rounded-3xl p-6 md:p-8 border border-amber-200 dark:border-amber-800 shadow-lg"> <div class="flex items-center mb-4"> <svg class="w-6 h-6 text-amber-600 dark:text-amber-400 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/> </svg> <h3 class="text-xl md:text-2xl font-light text-amber-800 dark:text-amber-200 tracking-tight">Mode Invité</h3> </div> <p class="text-amber-700 dark:text-amber-300 text-sm md:text-base mb-6">Tu navigues en mode invité. Crée un compte pour accéder à toutes les fonctionnalités !</p> <div class="space-y-3 text-xs md:text-sm text-amber-600 dark:text-amber-400 mb-6"> <div class="flex items-center space-x-2"> <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/> </svg> <span>Voir les offres du quartier</span> </div> <div class="flex items-center space-x-2"> <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/> </svg> <span>Consulter la météo locale</span> </div> <div class="flex items-center space-x-2 opacity-60"> <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/> </svg> <span>Carte de résident exclusive</span> </div> <div class="flex items-center space-x-2 opacity-60"> <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/> </svg> <span>Profil personnalisé</span> </div> </div> <a href="login.php" class="block w-full bg-amber-600 hover:bg-amber-700 text-white font-medium py-3 px-4 rounded-lg transition-colors text-center"> Créer mon compte </a> </div> <?php else: ?> <div class="bg-white dark:bg-stone-900 rounded-2xl md:rounded-3xl p-6 md:p-8 border border-stone-200 dark:border-stone-800 shadow-lg dark:shadow-stone-900/30"> <h3 class="text-xl md:text-2xl font-light text-stone-800 dark:text-white mb-4 md:mb-6 tracking-tight">Mes informations</h3> <div class="space-y-4 md:space-y-6"> <div> <label class="text-xs md:text-sm font-medium text-stone-700 dark:text-stone-300 block mb-1">Nom complet</label> <p class="text-sm md:text-base text-stone-900 dark:text-white"><?= htmlspecialchars($resident['first_name'] . ' ' . $resident['last_name']) ?></p> </div> <div> <label class="text-xs md:text-sm font-medium text-stone-700 dark:text-stone-300 block mb-1">Email</label> <p class="text-sm md:text-base text-stone-900 dark:text-white break-all"><?= htmlspecialchars($resident['email']) ?></p> </div> <div> <label class="text-xs md:text-sm font-medium text-stone-700 dark:text-stone-300 block mb-1">Adresse</label> <p class="text-sm md:text-base text-stone-900 dark:text-white"><?= htmlspecialchars($resident['address']) ?></p> </div> <div> <label class="text-xs md:text-sm font-medium text-stone-700 dark:text-stone-300 block mb-1">Membre depuis</label> <p class="text-sm md:text-base text-stone-900 dark:text-white"><?= date('F Y', strtotime($resident['created_at'])) ?></p> </div> </div> </div> <?php endif; ?> </div> </div> </div> <?php if (!$is_guest): ?> <div id="settingsModal" class="settings-modal"> <div class="settings-content w-full md:w-2xl p-6"> <div class="flex items-center justify-between mb-6"> <h2 class="text-2xl font-light text-stone-800 dark:text-white">Paramètres</h2> <button onclick="closeSettings()" class="text-stone-500 hover:text-stone-700 dark:text-stone-400 dark:hover:text-stone-200"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/> </svg> </button> </div> <div class="flex space-x-1 mb-6 bg-stone-100 dark:bg-stone-800 p-1 rounded-lg"> <button class="tab-button active" onclick="switchTab(event, 'profile')">Profil</button> <button class="tab-button" onclick="switchTab(event, 'security')">Sécurité</button> <button class="tab-button" onclick="switchTab(event, 'account')">Compte</button> </div> <?php if ($success_message): ?> <div class="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 text-green-800 dark:text-green-200 px-4 py-3 rounded-lg mb-4"> <?= htmlspecialchars($success_message) ?> </div> <?php endif; ?> <?php if ($error_message): ?> <div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 text-red-800 dark:text-red-200 px-4 py-3 rounded-lg mb-4"> <?= htmlspecialchars($error_message) ?> </div> <?php endif; ?> <div id="profile" class="tab-content active"> <form method="POST" class="space-y-4"> <input type="hidden" name="action" value="update_profile"> <div> <label class="text-sm font-medium text-stone-700 dark:text-stone-300 block mb-2">Prénom *</label> <input type="text" name="first_name" value="<?= htmlspecialchars($resident['first_name']) ?>" required class="w-full px-3 py-2 border border-stone-300 dark:border-stone-600 rounded-lg bg-white dark:bg-stone-800 text-stone-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-green-500"> </div> <div> <label class="text-sm font-medium text-stone-700 dark:text-stone-300 block mb-2">Nom *</label> <input type="text" name="last_name" value="<?= htmlspecialchars($resident['last_name']) ?>" required class="w-full px-3 py-2 border border-stone-300 dark:border-stone-600 rounded-lg bg-white dark:bg-stone-800 text-stone-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-green-500"> </div> <div> <label class="text-sm font-medium text-stone-700 dark:text-stone-300 block mb-2">Email *</label> <input type="email" name="email" value="<?= htmlspecialchars($resident['email']) ?>" required class="w-full px-3 py-2 border border-stone-300 dark:border-stone-600 rounded-lg bg-white dark:bg-stone-800 text-stone-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-green-500"> </div> <div> <label class="text-sm font-medium text-stone-700 dark:text-stone-300 block mb-2">Adresse</label> <textarea name="address" rows="3" class="w-full px-3 py-2 border border-stone-300 dark:border-stone-600 rounded-lg bg-white dark:bg-stone-800 text-stone-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-green-500"><?= htmlspecialchars($resident['address']) ?></textarea> </div> <button type="submit" class="w-full bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-lg transition-colors"> Mettre à jour le profil </button> </form> </div> <div id="security" class="tab-content"> <form method="POST" class="space-y-4"> <input type="hidden" name="action" value="change_password"> <div> <label class="text-sm font-medium text-stone-700 dark:text-stone-300 block mb-2">Mot de passe actuel *</label> <input type="password" name="current_password" required class="w-full px-3 py-2 border border-stone-300 dark:border-stone-600 rounded-lg bg-white dark:bg-stone-800 text-stone-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-green-500"> </div> <div> <label class="text-sm font-medium text-stone-700 dark:text-stone-300 block mb-2">Nouveau mot de passe *</label> <input type="password" name="new_password" required minlength="6" class="w-full px-3 py-2 border border-stone-300 dark:border-stone-600 rounded-lg bg-white dark:bg-stone-800 text-stone-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-green-500"> </div> <div> <label class="text-sm font-medium text-stone-700 dark:text-stone-300 block mb-2">Confirmer le nouveau mot de passe *</label> <input type="password" name="confirm_password" required minlength="6" class="w-full px-3 py-2 border border-stone-300 dark:border-stone-600 rounded-lg bg-white dark:bg-stone-800 text-stone-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-green-500"> </div> <button type="submit" class="w-full bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-lg transition-colors"> Changer le mot de passe </button> </form> </div> <div id="account" class="tab-content"> <div class="space-y-4"> <div class="bg-stone-50 dark:bg-stone-800 p-4 rounded-lg"> <h3 class="text-lg font-medium text-stone-900 dark:text-white mb-2">Informations du compte</h3> <div class="space-y-2 text-sm text-stone-600 dark:text-stone-400"> <p><strong>ID :</strong> <?= $resident['id'] ?></p> <p><strong>Membre depuis :</strong> <?= date('d/m/Y à H:i', strtotime($resident['created_at'])) ?></p> <p><strong>Dernière connexion :</strong> <?= isset($resident['last_login']) ? date('d/m/Y à H:i', strtotime($resident['last_login'])) : 'Jamais' ?></p> </div> </div> <div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 p-4 rounded-lg"> <h3 class="text-lg font-medium text-red-800 dark:text-red-200 mb-2">Zone de danger</h3> <p class="text-sm text-red-600 dark:text-red-300 mb-4">Actions irréversibles concernant ton compte.</p> <div class="space-y-2"> <a href="?action=logout" onclick="return confirm('Es-tu sûr de vouloir te déconnecter ?')" class="inline-flex items-center px-4 py-2 bg-red-600 hover:bg-red-700 text-white text-sm font-medium rounded-lg transition-colors mr-2"> <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/> </svg> Se déconnecter </a> <a href="delete-account.php" class="inline-flex items-center px-4 py-2 bg-red-600 hover:bg-red-700 text-white text-sm font-medium rounded-lg transition-colors"> <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/> </svg> Supprimer mon compte </a> </div> </div> </div> </div> </div> </div> <?php endif; ?> </main> <footer class="w-full py-4 md:py-6 border-t border-stone-200 dark:border-stone-800"> <p class="text-xs text-stone-500 dark:text-stone-400 text-center px-4"> © 2025 Vert Chasseur · <a href="https://aktascorp.com" class="underline hover:text-stone-700 dark:hover:text-stone-300">aktascorp</a> member </p> </footer> <script> let weatherDetailsVisible = false; async function loadWeather() { try { const response = await fetch('https://api.weatherapi.com/v1/current.json?key=fa1a36a37c3f4e7ab7e233043252305&q=Uccle,Belgium&lang=fr'); if (!response.ok) { throw new Error('API non disponible'); } const data = await response.json(); const weatherContent = document.getElementById('weather-content'); const weatherDetails = document.getElementById('weather-details'); const iconUrl = `https:${data.current.condition.icon}`; weatherContent.innerHTML = ` <div class="flex items-center space-x-4"> <img src="${iconUrl}" alt="${data.current.condition.text}" class="w-12 h-12 md:w-16 md:h-16 weather-icon"> <div> <div class="text-2xl md:text-3xl font-bold">${Math.round(data.current.temp_c)}°C</div> <div class="text-sm md:text-base opacity-90">${data.current.condition.text}</div> </div> </div> `; weatherDetails.innerHTML = ` <div class="text-xs md:text-sm space-y-1"> <div>Ressenti: ${Math.round(data.current.feelslike_c)}°C</div> <div>Humidité: ${data.current.humidity}%</div> <div>Vent: ${Math.round(data.current.wind_kph)} km/h</div> <div>UV: ${data.current.uv}</div> </div> `; } catch (error) { const weatherContent = document.getElementById('weather-content'); const weatherDetails = document.getElementById('weather-details'); weatherContent.innerHTML = ` <div class="flex items-center space-x-4"> <div class="w-12 h-12 md:w-16 md:h-16 bg-white/20 rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 md:w-8 md:h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z"/> </svg> </div> <div> <div class="text-2xl md:text-3xl font-bold">--°C</div> <div class="text-sm md:text-base opacity-90">Météo indisponible</div> </div> </div> `; weatherDetails.innerHTML = ` <div class="text-xs md:text-sm opacity-75"> Service temporairement indisponible </div> `; } } async function loadForecast() { try { const response = await fetch('https://api.weatherapi.com/v1/forecast.json?key=fa1a36a37c3f4e7ab7e233043252305&q=Uccle,Belgium&days=7&lang=fr'); if (!response.ok) { throw new Error('API non disponible'); } const data = await response.json(); const forecastContainer = document.getElementById('forecast-container'); let forecastHtml = ''; data.forecast.forecastday.forEach((day, index) => { const date = new Date(day.date); const dayName = index === 0 ? 'Aujourd\'hui' : index === 1 ? 'Demain' : date.toLocaleDateString('fr-FR', { weekday: 'long' }); forecastHtml += ` <div class="forecast-item"> <div class="flex items-center space-x-3"> <img src="https:${day.day.condition.icon}" alt="${day.day.condition.text}" class="w-8 h-8"> <div> <div class="font-medium">${dayName}</div> <div class="text-sm opacity-75">${day.day.condition.text}</div> </div> </div> <div class="text-right"> <div class="font-bold">${Math.round(day.day.maxtemp_c)}° / ${Math.round(day.day.mintemp_c)}°</div> <div class="text-xs opacity-75">${Math.round(day.day.avghumidity)}% • ${Math.round(day.day.maxwind_kph)} km/h</div> </div> </div> `; }); forecastContainer.innerHTML = forecastHtml; } catch (error) { const forecastContainer = document.getElementById('forecast-container'); forecastContainer.innerHTML = ` <div class="text-center py-4 opacity-75"> <p>Prévisions indisponibles</p> </div> `; } } function toggleWeatherDetails() { const weatherDetailed = document.getElementById('weather-detailed'); if (!weatherDetailsVisible) { loadForecast(); weatherDetailed.classList.add('show'); weatherDetailsVisible = true; } else { weatherDetailed.classList.remove('show'); weatherDetailsVisible = false; } } <?php if (!$is_guest): ?> function openSettings() { document.getElementById('settingsModal').classList.add('show'); document.body.style.overflow = 'hidden'; } function closeSettings() { document.getElementById('settingsModal').classList.remove('show'); document.body.style.overflow = 'auto'; } function switchTab(event, tabName) { const tabButtons = document.querySelectorAll('.tab-button'); const tabContents = document.querySelectorAll('.tab-content'); tabButtons.forEach(btn => btn.classList.remove('active')); tabContents.forEach(content => content.classList.remove('active')); event.target.classList.add('active'); document.getElementById(tabName).classList.add('active'); } <?php endif; ?> document.addEventListener('DOMContentLoaded', function() { loadWeather(); <?php if (!$is_guest): ?> document.getElementById('settingsModal').addEventListener('click', function(e) { if (e.target === this) { closeSettings(); } }); <?php endif; ?> }); </script> </body> </html>
| ver. 1.6 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0.01 |
proxy
|
phpinfo
|
Настройка