File manager - Edit - /home/webapp69.cm.in.th/u69319090036/Shop/db_connect.php
Back
<?php // db_connect.php - Database Connection and Global Shared Helpers if (session_status() === PHP_SESSION_NONE) { session_start(); } // ─── Language / i18n System ─────────────────────────────────────────────────── /** * Set active language from ?lang= GET param, save to session + cookie */ function setLang() { if (isset($_GET['lang']) && in_array($_GET['lang'], ['en', 'th'])) { $_SESSION['lang'] = $_GET['lang']; setcookie('wph_lang', $_GET['lang'], time() + (365 * 86400), '/', '', false, true); } } /** * Get current active language code ('en' or 'th') */ function getLang(): string { if (isset($_SESSION['lang'])) return $_SESSION['lang']; if (isset($_COOKIE['wph_lang']) && in_array($_COOKIE['wph_lang'], ['en', 'th'])) { $_SESSION['lang'] = $_COOKIE['wph_lang']; return $_COOKIE['wph_lang']; } return 'en'; // default } // Load translation strings into global $GLOBALS['_lang_strings'] = []; function _loadLang() { $lang = getLang(); $file = __DIR__ . '/lang/' . $lang . '.php'; if (file_exists($file)) { $GLOBALS['_lang_strings'] = require $file; } } /** * Translate a key. Supports :placeholder replacement. * Usage: __('products_found', ['count' => 5]) */ function __string(string $key, array $replace = []): string { $str = $GLOBALS['_lang_strings'][$key] ?? $key; foreach ($replace as $k => $v) { $str = str_replace(':' . $k, $v, $str); } return $str; } // Alias — call __() for convenience if (!function_exists('__')) { function __(string $key, array $replace = []): string { return __string($key, $replace); } } // Process lang switch first (before any output) setLang(); _loadLang(); // ───────────────────────────────────────────────────────────────────────────── // ─── Database Config ────────────────────────────────────────────────────────── $host = 'localhost'; $db = 'shop69319090036'; $user = 'u69319090036'; $pass = '@6936'; $charset = 'utf8mb4'; $dsn = "mysql:host=$host;dbname=$db;charset=$charset"; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; try { $pdo = new PDO($dsn, $user, $pass, $options); } catch (\PDOException $e) { die("Database Connection failed: " . $e->getMessage()); } // ─── Email / SMTP Config ────────────────────────────────────────────────────── // ⚠️ แก้ค่าด้านล่างให้ตรงกับ email และ password ของคุณ define('SMTP_HOST', 'smtp.gmail.com'); define('SMTP_PORT', 587); define('SMTP_USER', 'koohcoomzx@gmail.com'); define('SMTP_PASS', 'dxrxpsshuditoxlq'); // Gmail App Password define('SMTP_FROM', 'koohcoomzx@gmail.com'); define('SMTP_FROM_NAME','Weeraphat Market'); define('OTP_EXPIRE_MIN', 10); // OTP หมดอายุใน 10 นาที // ───────────────────────────────────────────────────────────────────────────── /** * ส่ง Email OTP ไปยัง address ที่กำหนด * ใช้ PHPMailer + SMTP (Gmail) ที่เชื่อถือได้ * @return bool */ function sendOtpEmail($toEmail, $toName, $otp) { // Load PHPMailer (manual install, no composer required) $base = __DIR__ . '/phpmailer/src/'; require_once $base . 'Exception.php'; require_once $base . 'PHPMailer.php'; require_once $base . 'SMTP.php'; $mail = new PHPMailer\PHPMailer\PHPMailer(true); try { // ─── Server Settings ────────────────────────────── $mail->isSMTP(); $mail->Host = SMTP_HOST; $mail->SMTPAuth = true; $mail->Username = SMTP_USER; $mail->Password = SMTP_PASS; $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS; $mail->Port = SMTP_PORT; $mail->CharSet = 'UTF-8'; // ─── Recipients ─────────────────────────────────── $mail->setFrom(SMTP_FROM, SMTP_FROM_NAME); $mail->addAddress($toEmail, $toName); $mail->addReplyTo(SMTP_FROM, SMTP_FROM_NAME); // ─── Content ────────────────────────────────────── $mail->isHTML(true); $mail->Subject = 'Your Weeraphat Login Code: ' . $otp; $mail->Body = " <div style='font-family:Arial,sans-serif;max-width:480px;margin:0 auto;padding:32px 24px;background:#fff;border-radius:16px;border:1px solid #e5e7eb;'> <h2 style='color:#f97316;margin:0 0 8px;font-size:22px;'>Weeraphat Market</h2> <p style='color:#374151;font-size:14px;margin:0 0 24px;'>Hi <strong>" . htmlspecialchars($toName) . "</strong>, your one-time login code is:</p> <div style='background:#fff7ed;border:2px dashed #fb923c;border-radius:12px;padding:20px;text-align:center;margin-bottom:24px;'> <span style='font-size:40px;font-weight:900;letter-spacing:12px;color:#ea580c;'>" . $otp . "</span> </div> <p style='color:#6b7280;font-size:12px;margin:0;'>This code expires in <strong>" . OTP_EXPIRE_MIN . " minutes</strong>. Do not share it with anyone.</p> <hr style='border:none;border-top:1px solid #f3f4f6;margin:20px 0;'> <p style='color:#9ca3af;font-size:11px;margin:0;'>If you did not request this code, you can safely ignore this email.</p> </div> "; $mail->AltBody = "Your Weeraphat login OTP code is: {$otp}. It expires in " . OTP_EXPIRE_MIN . " minutes."; $mail->send(); return true; } catch (PHPMailer\PHPMailer\Exception $e) { // Log error for debugging (ไม่แสดงให้ user เห็น) error_log('[PHPMailer OTP Error] ' . $mail->ErrorInfo); return false; } } /** * สร้างและบันทึก OTP ลงฐานข้อมูล แล้วส่ง email * คืนค่า true ถ้าส่งสำเร็จ */ function generateAndSendOtp($pdo, $email) { // ตรวจสอบว่า email มีอยู่ในระบบ $stmt = $pdo->prepare("SELECT id, username FROM users WHERE email = ? AND is_banned = 0"); $stmt->execute([$email]); $user = $stmt->fetch(); if (!$user) return false; // สร้าง OTP 6 หลัก $otp = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT); $expires = date('Y-m-d H:i:s', time() + (OTP_EXPIRE_MIN * 60)); $token = bin2hex(random_bytes(24)); // unique token สำหรับ URL // ลบ OTP เก่าของ email นี้ทิ้ง $pdo->prepare("DELETE FROM otp_tokens WHERE email = ?")->execute([$email]); // บันทึก OTP ใหม่ $ins = $pdo->prepare("INSERT INTO otp_tokens (email, otp_code, token, expires_at) VALUES (?, ?, ?, ?)"); $ins->execute([$email, password_hash($otp, PASSWORD_BCRYPT), $token, $expires]); // ส่ง email $sent = sendOtpEmail($email, $user['username'], $otp); if (!$sent) return false; return $token; // คืน token สำหรับ URL } // ─── Remember Me Cookie Handler ─────────────────────────────────────────────── define('REMEMBER_ME_DAYS', 30); define('REMEMBER_ME_COOKIE', 'wph_remember'); /** * ตั้ง Remember Me cookie และบันทึก token ลง DB */ function setRememberMeCookie($pdo, $userId) { $token = bin2hex(random_bytes(32)); $expires = time() + (REMEMBER_ME_DAYS * 86400); // บันทึก hashed token ลง DB $stmt = $pdo->prepare("INSERT INTO remember_tokens (user_id, token_hash, expires_at) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE token_hash = VALUES(token_hash), expires_at = VALUES(expires_at)"); $stmt->execute([$userId, hash('sha256', $token), date('Y-m-d H:i:s', $expires)]); setcookie(REMEMBER_ME_COOKIE, $userId . ':' . $token, [ 'expires' => $expires, 'path' => '/', 'httponly' => true, 'samesite' => 'Lax', ]); } /** * ตรวจสอบ Remember Me cookie และ login อัตโนมัติ */ function checkRememberMeCookie($pdo) { if (isLoggedIn()) return; if (!isset($_COOKIE[REMEMBER_ME_COOKIE])) return; $parts = explode(':', $_COOKIE[REMEMBER_ME_COOKIE], 2); if (count($parts) !== 2) return; list($userId, $token) = $parts; $userId = intval($userId); if ($userId <= 0) return; $stmt = $pdo->prepare("SELECT * FROM remember_tokens WHERE user_id = ? AND expires_at > NOW()"); $stmt->execute([$userId]); $row = $stmt->fetch(); if ($row && hash_equals($row['token_hash'], hash('sha256', $token))) { $userStmt = $pdo->prepare("SELECT * FROM users WHERE id = ? AND is_banned = 0"); $userStmt->execute([$userId]); $user = $userStmt->fetch(); if ($user) { $_SESSION['user_id'] = $user['id']; $_SESSION['username'] = $user['username']; $_SESSION['role'] = $user['role']; } } } /** * ลบ Remember Me cookie และ token ใน DB */ function clearRememberMeCookie($pdo, $userId) { if ($userId) { $pdo->prepare("DELETE FROM remember_tokens WHERE user_id = ?")->execute([$userId]); } setcookie(REMEMBER_ME_COOKIE, '', time() - 3600, '/'); } // ───────────────────────────────────────────────────────────────────────────── // ตรวจ Remember Me cookie ทุกครั้งที่โหลดหน้า checkRememberMeCookie($pdo); // Check if user is logged in function isLoggedIn() { return isset($_SESSION['user_id']); } // Get logged in user details function getLoggedInUser() { global $pdo; if (isLoggedIn()) { $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); $user = $stmt->fetch(); if ($user) { if ($user['is_banned']) { session_unset(); session_destroy(); header("Location: login.php?error=" . urlencode("Your account has been banned by the administrator.")); exit(); } return $user; } } return null; } // ─── Prohibited Product Moderation & Reporting ─────────────────────────── /** * Check title and description against prohibited keyword dictionary. * @param string $title * @param string $description * @return array Array of detected prohibited words, or empty array if clean. */ function checkProhibitedKeywords($title, $description) { $bannedKeywords = [ // อาวุธ / วัตถุระเบิด (Weapons & Explosives) 'ปืน', 'อาวุธ', 'ระเบิด', 'กระสุน', 'มีดพกผิดกฎหมาย', 'สนับมือ', 'gun', 'weapon', 'pistol', 'rifle', 'explosive', 'bomb', 'ammo', 'ammunition', // ยาเสพติด / สารเสพติด (Drugs & Narcotics) 'ยาเสพติด', 'กัญชา', 'ยาเค', 'ยาไอซ์', 'ยาบ้า', 'กระท่อม', 'บุหรี่ไฟฟ้าผิดกฎหมาย', 'drug', 'narcotic', 'cocaine', 'heroin', 'meth', 'cannabis', 'marijuana', // การพนัน / สิ่งลามกอนาจาร (Gambling & Adult Content) 'การพนัน', 'คาสิโน', 'สื่อลามก', 'หนังโป๊', 'gambling', 'casino', 'porn', 'prostitution', // สินค้าละเมิดลิขสิทธิ์ / เอกสารปลอม (Counterfeit & Illegal Docs) 'พาสปอร์ตปลอม', 'บัตรประชาชนปลอม', 'วุฒิการศึกษาปลอม', 'เอกสารปลอม', 'fake id', 'fake passport', 'counterfeit money', 'เงินปลอม' ]; $textToScan = mb_strtolower($title . ' ' . $description, 'UTF-8'); $detected = []; foreach ($bannedKeywords as $keyword) { $pattern = '/' . preg_quote(mb_strtolower($keyword, 'UTF-8'), '/') . '/u'; if (preg_match($pattern, $textToScan)) { $detected[] = $keyword; } } return array_unique($detected); } // Auto-create product_reports table if not exists try { $pdo->exec("CREATE TABLE IF NOT EXISTS product_reports ( id INT AUTO_INCREMENT PRIMARY KEY, product_id INT NOT NULL, user_id INT DEFAULT NULL, reason VARCHAR(255) NOT NULL, details TEXT DEFAULT NULL, status ENUM('pending', 'reviewed', 'dismissed') DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); } catch (\Exception $e) { // Ignore if table setup differs by SQL driver } // Global Product Report Submission Action Handler if (isset($_GET['action']) && $_GET['action'] === 'report_product' && $_SERVER['REQUEST_METHOD'] === 'POST') { $productId = intval($_POST['product_id'] ?? 0); $reason = trim($_POST['reason'] ?? ''); $details = trim($_POST['details'] ?? ''); $userId = $_SESSION['user_id'] ?? null; if ($productId > 0 && !empty($reason)) { $stmt = $pdo->prepare("INSERT INTO product_reports (product_id, user_id, reason, details) VALUES (?, ?, ?, ?)"); $stmt->execute([$productId, $userId, $reason, $details]); $redirect = $_SERVER['HTTP_REFERER'] ?? 'index.php'; $redirectBase = strtok($redirect, '?'); header("Location: " . $redirectBase . "?success=" . urlencode("Product report submitted. Admin will review this listing shortly.")); exit(); } } /** * Switch current user's role to target role ('seller' or 'buyer') */ function switchUserRole($toRole) { global $pdo; if (!isLoggedIn()) return false; if (!in_array($toRole, ['seller', 'buyer'])) return false; $userId = $_SESSION['user_id']; $stmt = $pdo->prepare("UPDATE users SET role = ? WHERE id = ?"); $stmt->execute([$toRole, $userId]); $_SESSION['role'] = $toRole; return true; } // Global Role Switch Action Handler if (isset($_GET['action']) && $_GET['action'] === 'switch_role' && isLoggedIn()) { $to = $_GET['to'] ?? ''; if (in_array($to, ['seller', 'buyer'])) { switchUserRole($to); $roleLabel = ($to === 'seller') ? __('role_seller_label') : __('role_buyer_label'); $msg = __('role_switched_success', ['role' => $roleLabel]); $targetUrl = ($to === 'seller') ? 'sell.php' : 'index.php'; header("Location: " . $targetUrl . "?success=" . urlencode($msg)); exit(); } } /** * Check if the currently logged-in user has a specific role. * @param string|array $roles Single role string or array of roles to check. * @return bool */ function hasRole($roles) { if (!isLoggedIn()) return false; $userRole = $_SESSION['role'] ?? ''; if (is_array($roles)) { return in_array($userRole, $roles); } return $userRole === $roles; } /** * Require the user to have a specific role. * Redirects with an error message if the check fails. * @param string|array $roles Allowed role(s). * @param string $redirectUrl URL to redirect to on failure. */ function requireRole($roles, $redirectUrl = 'index.php') { if (!isLoggedIn()) { header("Location: login.php?error=" . urlencode("Please log in to continue.")); exit(); } if (!hasRole($roles)) { header("Location: {$redirectUrl}?error=" . urlencode("You do not have permission to access this page.")); exit(); } } /** * Check if the current user can sell (is admin or seller). * @return bool */ function canSell() { return hasRole(['admin', 'seller']); } /** * Check if the current user is an admin. * @return bool */ function isAdmin() { return hasRole('admin'); } // ───────────────────────────────────────────────────────────────────────────── // Helper to escape HTML characters function sanitize($str) { return htmlspecialchars($str ?? '', ENT_QUOTES, 'UTF-8'); } // Helper to find or create user via Social OAuth (Google, Facebook, LINE, Apple) function findOrCreateSocialUser($provider, $socialId, $email, $name, $avatar = '') { global $pdo; $columnMap = [ 'google' => 'google_id', 'facebook' => 'facebook_id', 'line' => 'line_id', 'apple' => 'apple_id' ]; if (!isset($columnMap[$provider])) return null; $col = $columnMap[$provider]; // 1. Search by provider social ID $stmt = $pdo->prepare("SELECT * FROM users WHERE {$col} = ?"); $stmt->execute([$socialId]); $user = $stmt->fetch(); if ($user) { return $user; } // 2. Search by email if available if (!empty($email)) { $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?"); $stmt->execute([$email]); $user = $stmt->fetch(); if ($user) { // Bind social ID to existing account $update = $pdo->prepare("UPDATE users SET {$col} = ? WHERE id = ?"); $update->execute([$socialId, $user['id']]); $user[$col] = $socialId; return $user; } } // 3. Create new user account $cleanName = preg_replace('/[^a-zA-Z0-9_]/', '', strtolower(str_replace(' ', '_', $name))); if (empty($cleanName)) $cleanName = $provider . '_user'; $username = $cleanName; while (true) { $chk = $pdo->prepare("SELECT id FROM users WHERE username = ?"); $chk->execute([$username]); if (!$chk->fetch()) break; $username = $cleanName . '_' . rand(100, 999); } $dummyEmail = !empty($email) ? $email : $username . '@' . $provider . '.user'; $insert = $pdo->prepare("INSERT INTO users (username, email, {$col}, role, profile_pic) VALUES (?, ?, ?, 'buyer', ?)"); $insert->execute([$username, $dummyEmail, $socialId, $avatar]); $userId = $pdo->lastInsertId(); $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$userId]); return $stmt->fetch(); } // Helper to find or create user via Phone OTP function findOrCreatePhoneUser($phone) { global $pdo; $cleanPhone = preg_replace('/[^0-9\+]/', '', $phone); if (empty($cleanPhone)) return null; // Search by phone $stmt = $pdo->prepare("SELECT * FROM users WHERE phone = ?"); $stmt->execute([$cleanPhone]); $user = $stmt->fetch(); if ($user) { return $user; } // Create new account for phone user $username = 'phone_' . substr($cleanPhone, -4) . '_' . rand(100, 999); $dummyEmail = $cleanPhone . '@phone.user'; $insert = $pdo->prepare("INSERT INTO users (username, email, phone, role) VALUES (?, ?, ?, 'buyer')"); $insert->execute([$username, $dummyEmail, $cleanPhone]); $userId = $pdo->lastInsertId(); $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$userId]); return $stmt->fetch(); } // Auto fallback Unsplash image paths for mock products across categories function getProductImgUrl($prod_id, $imagesJson) { $imgs = json_decode($imagesJson, true); // If we have a custom uploaded image (not a default mock image), use it first! if (!empty($imgs) && strpos($imgs[0], '/uploads/mock-') === false && strpos($imgs[0], 'placeholder-product.jpg') === false) { $path = $imgs[0]; if (substr($path, 0, 1) === '/') { $path = substr($path, 1); } return $path; } $unsplash = [ 1 => "https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=600", // Headphones 2 => "https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=600", // Smartwatch 3 => "https://images.unsplash.com/photo-1517668808822-9ebe02f2a698?w=600", // Coffee Machine 4 => "https://images.unsplash.com/photo-1587829741301-dc798b83add3?w=600", // Mechanical Keyboard 5 => "https://images.unsplash.com/photo-1553062407-98eeb64c6a62?w=600", // Backpack 6 => "https://images.unsplash.com/photo-1580481072645-022f9a6d8310?w=600", // Chair 7 => "https://images.unsplash.com/photo-1536256263959-770b48d82b0a?w=600", // Matcha Tea 8 => "https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=600" // Running Sneakers ]; if (isset($unsplash[$prod_id])) { return $unsplash[$prod_id]; } if (!empty($imgs)) { $path = $imgs[0]; if (substr($path, 0, 1) === '/') { $path = substr($path, 1); } return $path; } return "https://images.unsplash.com/photo-1526170375885-4d8ecf77b99f?w=600"; } // Shared layout rendering functions function renderHeader($title = "Weeraphat - Multi-Vendor Marketplace") { global $pdo; $user = getLoggedInUser(); // Fetch cart count $cartCount = 0; if ($user) { $stmt = $pdo->prepare("SELECT SUM(quantity) as total FROM cart WHERE user_id = ?"); $stmt->execute([$user['id']]); $res = $stmt->fetch(); $cartCount = $res['total'] ?? 0; } $searchVal = $_GET['search'] ?? ''; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?php echo sanitize($title); ?></title> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet"> <link rel="stylesheet" href="style.css"> </head> <body class="bg-slate-50 min-h-screen flex flex-col text-slate-800"> <!-- Global Header Navbar --> <header class="sticky top-0 z-40 bg-white/95 backdrop-blur-md border-b border-gray-100 shadow-sm"> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div class="flex items-center justify-between h-16 sm:h-18 gap-3"> <!-- Left: Logo --> <a href="index.php" class="flex items-center gap-2 flex-shrink-0"> <span class="text-xl sm:text-2xl font-black bg-gradient-to-r from-orange-500 via-red-500 to-rose-500 bg-clip-text text-transparent tracking-tight"> Weeraphat </span> <span class="px-1.5 py-0.5 text-[10px] font-extrabold uppercase tracking-wider text-white bg-orange-500 rounded hidden sm:inline-block"><?php echo __('site_tagline'); ?></span> </a> <!-- Center: Search Bar --> <form action="index.php" method="GET" class="flex-1 max-w-xs sm:max-w-md hidden md:block"> <div class="relative"> <input type="text" name="search" placeholder="<?php echo __('nav_search_placeholder'); ?>" value="<?php echo sanitize($searchVal); ?>" class="w-full pl-4 pr-10 py-2 bg-gray-50 border border-gray-200 rounded-full text-xs placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-orange-500/20 focus:border-orange-500 focus:bg-white transition-all duration-200" > <button type="submit" class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-orange-500 transition-colors"> <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/></svg> </button> </div> </form> <!-- Right: Navigation Utilities & Profile --> <div class="flex items-center gap-2 sm:gap-3"> <!-- Language Switcher Pill --> <?php $currentLang = getLang(); $currentUrl = strtok($_SERVER['REQUEST_URI'], '?'); $queryParams = $_GET; unset($queryParams['lang']); $baseQuery = http_build_query($queryParams); $enUrl = $currentUrl . '?lang=en' . ($baseQuery ? '&' . $baseQuery : ''); $thUrl = $currentUrl . '?lang=th' . ($baseQuery ? '&' . $baseQuery : ''); ?> <div class="flex items-center gap-0.5 bg-gray-100/80 p-0.5 rounded-lg text-[11px] font-bold border border-gray-200/60"> <a href="<?php echo sanitize($enUrl); ?>" class="px-2 py-0.5 rounded-md transition-all <?php echo $currentLang === 'en' ? 'bg-white shadow-sm text-gray-900' : 'text-gray-500 hover:text-gray-800'; ?>"> EN </a> <a href="<?php echo sanitize($thUrl); ?>" class="px-2 py-0.5 rounded-md transition-all <?php echo $currentLang === 'th' ? 'bg-white shadow-sm text-gray-900' : 'text-gray-500 hover:text-gray-800'; ?>"> TH </a> </div> <!-- User Guide Button --> <a href="guide.php" class="px-2.5 py-1 text-gray-600 hover:text-orange-600 hover:bg-orange-50/60 rounded-lg border border-gray-200/60 text-xs font-bold transition-all flex items-center gap-1.5" title="<?php echo __('nav_guide'); ?>"> <svg class="w-3.5 h-3.5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"/></svg> <span class="hidden lg:inline"><?php echo __('nav_guide'); ?></span> </a> <!-- Cart Indicator Icon --> <a href="cart.php" class="relative p-2 text-gray-600 hover:text-orange-500 hover:bg-gray-50 rounded-full transition-all" title="Shopping Cart"> <svg class="w-4 h-4 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"/></svg> <?php if ($cartCount > 0): ?> <span class="absolute top-0.5 right-0.5 flex h-4 w-4 items-center justify-center rounded-full bg-gradient-to-r from-orange-600 to-rose-600 text-[9px] font-black text-white ring-2 ring-white"> <?php echo $cartCount; ?> </span> <?php endif; ?> </a> <!-- Vertical Divider --> <div class="h-6 w-px bg-gray-200 mx-0.5 hidden sm:block"></div> <!-- User Account Profile Box --> <?php if ($user): ?> <div class="flex items-center gap-2"> <!-- User Info Pill --> <div class="hidden lg:flex items-center gap-1.5 px-2.5 py-1 bg-gray-50 border border-gray-200/60 rounded-lg text-xs"> <span class="font-semibold text-gray-500"><?php echo __('nav_hello'); ?></span> <strong class="text-gray-900 font-bold"><?php echo sanitize($user['username']); ?></strong> <?php if ($user['role'] === 'admin') { $roleBadgeColor = 'bg-red-100 text-red-600'; } elseif ($user['role'] === 'seller') { $roleBadgeColor = 'bg-blue-100 text-blue-600'; } else { $roleBadgeColor = 'bg-emerald-100 text-emerald-700'; } ?> <span class="px-1.5 py-0.2 rounded text-[9px] font-black uppercase tracking-wider <?php echo $roleBadgeColor; ?>"> <?php echo $user['role']; ?> </span> </div> <!-- Seller Panel / Role Switch Buttons --> <?php if ($user['role'] === 'seller'): ?> <a href="sell.php" class="px-3 py-1.5 rounded-lg bg-orange-500 hover:bg-orange-600 text-white font-bold text-xs shadow-sm transition-all flex items-center gap-1.5"> <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/></svg> <span class="hidden sm:inline"><?php echo __('nav_seller_panel'); ?></span> </a> <a href="index.php?action=switch_role&to=buyer" title="<?php echo __('nav_switch_to_buyer'); ?>" class="px-2.5 py-1.5 rounded-lg bg-gray-100 hover:bg-gray-200 text-gray-700 font-bold text-xs transition-all border border-gray-200 flex items-center gap-1.5"> <svg class="w-3.5 h-3.5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"/></svg> <span class="hidden xl:inline"><?php echo __('nav_switch_to_buyer'); ?></span> </a> <?php elseif ($user['role'] === 'buyer'): ?> <a href="index.php?action=switch_role&to=seller" class="px-3 py-1.5 rounded-lg bg-gradient-to-r from-orange-500 to-rose-500 text-white font-bold text-xs shadow-sm hover:shadow transition-all flex items-center gap-1.5"> <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"/></svg> <span><?php echo __('nav_switch_to_seller'); ?></span> </a> <?php endif; ?> <?php if (isAdmin()): ?> <a href="dashboard_admin.php" class="px-3 py-1.5 rounded-lg bg-red-50 hover:bg-red-100 text-red-600 font-bold text-xs transition-all flex items-center gap-1.5"> <svg class="w-3.5 h-3.5" 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"/></svg> <?php echo __('nav_admin_panel'); ?> </a> <?php endif; ?> <!-- Logout Button --> <a href="login.php?action=logout" title="<?php echo __('nav_logout'); ?>" class="px-2 py-1.5 text-gray-400 hover:text-red-500 hover:bg-red-50 rounded-lg text-xs font-semibold transition-colors flex items-center gap-1"> <svg class="w-3.5 h-3.5" 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> <span class="hidden sm:inline"><?php echo __('nav_logout'); ?></span> </a> </div> <?php else: ?> <div class="flex items-center gap-1.5"> <a href="login.php" class="px-3 py-1.5 text-xs font-bold text-gray-700 hover:text-orange-600 transition-colors"><?php echo __('nav_login'); ?></a> <a href="register.php" class="px-3.5 py-1.5 bg-gradient-to-r from-orange-500 to-rose-500 text-white text-xs font-bold rounded-lg shadow hover:shadow-md transition-all"><?php echo __('nav_register'); ?></a> </div> <?php endif; ?> </div> </div> </div> </header> <!-- Message/Toast Banner Helper --> <?php if (isset($_GET['success'])): ?> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mt-4"> <div class="bg-emerald-50 border border-emerald-200 text-emerald-800 px-4 py-3 rounded-xl flex items-center gap-3"> <svg class="w-4 h-4 text-emerald-600 flex-shrink-0" 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 class="text-sm font-semibold"><?php echo sanitize($_GET['success']); ?></span> </div> </div> <?php endif; ?> <?php if (isset($_GET['error'])): ?> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mt-4"> <div class="bg-red-50 border border-red-200 text-red-800 px-4 py-3 rounded-xl flex items-center gap-3"> <svg class="w-4 h-4 text-red-600 flex-shrink-0" 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 class="text-sm font-semibold"><?php echo sanitize($_GET['error']); ?></span> </div> </div> <?php endif; ?> <!-- Main Content Area wrapper --> <main class="flex-grow max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8 py-8"> <?php } function renderFooter() { ?> </main> <footer class="bg-gray-900 border-t border-gray-800 text-gray-400 py-12 mt-20"> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div class="grid grid-cols-1 md:grid-cols-4 gap-8"> <div class="space-y-4"> <span class="text-2xl font-black text-white">Weeraphat</span> <p class="text-sm text-gray-500 leading-relaxed"> <ul class="space-y-2 text-sm"> <li><a href="sell.php" class="hover:text-orange-500 transition-colors"><?php echo __('footer_start_selling'); ?></a></li> <li><a href="cart.php" class="hover:text-orange-500 transition-colors"><?php echo __('footer_cart'); ?></a></li> <li><a href="login.php" class="hover:text-orange-500 transition-colors"><?php echo __('footer_my_account'); ?></a></li> <li><a href="guide.php" class="hover:text-orange-500 transition-colors">📖 <?php echo __('footer_guide'); ?></a></li> </ul> </div> <div> <h4 class="text-white font-semibold mb-4 text-sm uppercase tracking-wider">Customer Support</h4> <p class="text-sm text-gray-500 leading-relaxed"> Need help? Contact support 24/7.<br> 📞 1-800-WEERAPHAT<br> ✉️ support@weeraphat.com </p> </div> </div> <div class="border-t border-gray-800 mt-12 pt-6 flex flex-col sm:flex-row items-center justify-between text-xs text-gray-600 gap-4"> <div>© 2026 Weeraphat Market. All Rights Reserved.</div> <div class="flex gap-4"> <a href="#" class="hover:text-gray-400">Privacy Policy</a> <a href="#" class="hover:text-gray-400">Terms of Service</a> </div> </div> </div> </footer> </body> </html> <?php } ?>
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.26 |
proxy
|
phpinfo
|
Settings