File manager - Edit - /home/webapp69.cm.in.th/u69319090028/Shop/views/components/navbar.php
Back
<?php $user = Auth::user(); $roles = Auth::roles(); $currentLang = Language::getLocale(); ?> <nav class="navbar navbar-expand-lg cargoo-navbar"> <div class="container py-2"> <!-- Official Brand Logo (Horizontal Blue for Light Background) --> <a class="navbar-brand me-4 py-0" href="<?= url('/') ?>"> <img src="<?= asset('/assets/images/brand/logo2-blue.png') ?>" alt="CARGOO Online Shopping" class="cargoo-brand-img"> </a> <button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#cargooNavbar" aria-controls="cargooNavbar" aria-expanded="false" aria-label="Toggle navigation"> <i class="bi bi-list fs-2 text-dark"></i> </button> <div class="collapse navbar-collapse" id="cargooNavbar"> <!-- Search Bar with Live Suggestion Dropdown --> <div class="position-relative flex-grow-1 mx-lg-4 my-2 my-lg-0" id="navSearchWrapper"> <form class="d-flex w-100" role="search" action="<?= url('/search') ?>" method="GET" id="navSearchForm"> <div class="input-group"> <span class="input-group-text bg-transparent border-end-0 rounded-start-pill ps-3 text-muted"> <i class="bi bi-search"></i> </span> <input class="form-control cargoo-search-bar border-start-0 ps-2" type="search" name="q" id="navSearchInput" value="<?= e($_GET['q'] ?? '') ?>" placeholder="<?= __('search_placeholder') ?>" aria-label="Search" autocomplete="off"> </div> </form> <!-- Suggestion Dropdown Menu --> <div class="position-absolute start-0 end-0 bg-white border rounded-3 shadow-lg p-2 d-none" id="navSearchSuggestions" style="top: 100%; z-index: 1050; margin-top: 4px; max-height: 380px; overflow-y: auto;"></div> </div> <!-- Navigation Actions & Profile Dropdown --> <ul class="navbar-nav ms-auto align-items-center gap-2"> <!-- Cart Icon Button --> <li class="nav-item"> <?php $cartCount = 0; if (Auth::check()) { $cartService = new CartService(); $cartCount = $cartService->getCartCount(Auth::id()); } ?> <a class="nav-link text-dark position-relative px-2 me-1" href="<?= url('/cart') ?>" title="<?= __('cart') ?>"> <i class="bi bi-cart3 fs-5 text-primary"></i> <?php if ($cartCount > 0): ?> <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger" id="navCartBadge" style="font-size: 0.65rem;"> <?= $cartCount ?> </span> <?php endif; ?> </a> </li> <?php if ($user): ?> <!-- Notification Bell Dropdown --> <?php require_once __DIR__ . '/../../app/Models/Notification.php'; $notifModel = new Notification(); $notifUnreadCount = $notifModel->getUnreadCount((int)$user['id']); $latestNotifs = $notifModel->getLatestNotifications((int)$user['id'], 5); ?> <li class="nav-item dropdown" id="navNotifDropdownItem"> <a class="nav-link text-dark position-relative px-2 d-flex align-items-center" href="<?= url('/account/notifications') ?>" role="button" data-bs-toggle="dropdown" aria-expanded="false" title="การแจ้งเตือน" id="navNotifToggle"> <i class="bi bi-bell fs-5 text-primary"></i> <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger <?= $notifUnreadCount > 0 ? '' : 'd-none' ?>" id="navNotifBadge" style="font-size: 0.65rem;"> <?= $notifUnreadCount ?> </span> </a> <ul class="dropdown-menu dropdown-menu-end shadow border-0 rounded-3 p-2" style="width: 340px; max-width: 95vw;"> <li class="d-flex justify-content-between align-items-center px-2 py-1 border-bottom mb-2"> <span class="fw-bold small text-dark"><i class="bi bi-bell-fill text-primary me-1"></i> การแจ้งเตือน</span> <div class="d-flex align-items-center gap-2"> <button type="button" class="btn btn-link text-primary p-0 text-decoration-none small border-0" id="btnNavMarkAllRead" style="font-size: 0.75rem;"> <i class="bi bi-check2-all me-1"></i>อ่านทั้งหมด </button> <span class="text-muted small">•</span> <a href="<?= url('/account/notifications') ?>" class="text-secondary small text-decoration-none" style="font-size: 0.75rem;">ดูทั้งหมด</a> </div> </li> <li id="notifDropdownContent"> <?php if (empty($latestNotifs)): ?> <div class="text-center py-4 text-muted small"> <i class="bi bi-bell-slash text-muted fs-4 d-block mb-1"></i> ไม่มีการแจ้งเตือน </div> <?php else: ?> <div class="d-flex flex-column gap-1 notif-dropdown-list" style="max-height: 320px; overflow-y: auto;"> <?php foreach ($latestNotifs as $ln): ?> <?php $isUnreadLn = empty($ln['is_read']); $targetUrlLn = !empty($ln['action_url']) ? url('/account/notifications/' . (int)$ln['id'] . '/read') : url('/account/notifications'); ?> <a href="<?= $targetUrlLn ?>" class="d-block p-2 rounded-2 text-decoration-none border-bottom border-light notif-dropdown-item <?= $isUnreadLn ? 'bg-primary-subtle bg-opacity-25' : '' ?>" style="transition: background-color 0.15s;"> <div class="d-flex justify-content-between align-items-center mb-1"> <span class="fw-bold small text-truncate <?= $isUnreadLn ? 'text-primary' : 'text-dark' ?>" style="max-width: 200px;"> <?= e($ln['title']) ?> </span> <span class="text-muted" style="font-size: 0.68rem;"><?= date('d/m H:i', strtotime($ln['created_at'])) ?></span> </div> <p class="text-secondary small mb-0 text-truncate" style="font-size: 0.75rem;"><?= e($ln['message']) ?></p> </a> <?php endforeach; ?> </div> <div class="pt-2 border-top text-center mt-1"> <a href="<?= url('/account/notifications') ?>" class="btn btn-cargoo-outline btn-sm w-100 py-1" style="font-size: 0.75rem;"> เปิดศูนย์การแจ้งเตือนทั้งหมด <i class="bi bi-arrow-right ms-1"></i> </a> </div> <?php endif; ?> </li> </ul> </li> <?php endif; ?> <!-- Language Switcher --> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle text-dark fw-medium px-2 d-flex align-items-center gap-1" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"> <i class="bi bi-globe2 text-primary"></i> <?= strtoupper($currentLang) ?> </a> <ul class="dropdown-menu dropdown-menu-end shadow-sm border-0 rounded-3"> <li> <a class="dropdown-item d-flex align-items-center gap-2 <?= $currentLang === 'th' ? 'active fw-bold' : '' ?>" href="<?= Language::switchUrl('th') ?>"> <span class="badge bg-secondary-subtle text-secondary small border">TH</span> <span>ภาษาไทย</span> </a> </li> <li> <a class="dropdown-item d-flex align-items-center gap-2 <?= $currentLang === 'en' ? 'active fw-bold' : '' ?>" href="<?= Language::switchUrl('en') ?>"> <span class="badge bg-secondary-subtle text-secondary small border">EN</span> <span>English</span> </a> </li> </ul> </li> <?php if ($user): ?> <!-- Logged in State --> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle d-flex align-items-center gap-2 text-dark px-2" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"> <?php if (!empty($user['profile_image'])): ?> <img src="<?= asset('/uploads/profiles/' . e($user['profile_image'])) ?>" alt="Avatar" class="rounded-circle" style="width: 34px; height: 34px; object-fit: cover; border: 2px solid var(--cargoo-border);"> <?php else: ?> <img src="<?= asset('/assets/images/default-avatar.svg') ?>" alt="Default Avatar" class="rounded-circle" style="width: 34px; height: 34px; object-fit: cover;"> <?php endif; ?> <div class="d-none d-md-block text-start lh-1"> <span class="d-block fw-semibold text-dark fs-6"><?= e($user['first_name']) ?></span> <small class="text-muted" style="font-size: 0.75rem;">@<?= e($user['username']) ?></small> </div> </a> <ul class="dropdown-menu dropdown-menu-end shadow-sm border-0 rounded-3 p-2" style="min-width: 240px;"> <li class="px-3 py-2 border-bottom mb-1"> <div class="fw-bold text-dark"><?= e($user['first_name'] . ' ' . $user['last_name']) ?></div> <div class="text-muted small"><?= e($user['email']) ?></div> <div class="mt-2 d-flex flex-wrap gap-1"> <?php foreach ($roles as $r): ?> <span class="badge badge-role <?= $r === 'admin' ? 'badge-role-admin' : ($r === 'seller' ? 'badge-role-seller' : '') ?>"> <?= ucfirst($r) ?> </span> <?php endforeach; ?> </div> </li> <li> <a class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2 text-primary fw-semibold" href="<?= url('/seller') ?>"> <i class="bi bi-shop"></i> ศูนย์ผู้ขาย (Seller Center) </a> </li> <li class="dropdown-divider my-1"></li> <li> <a class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2" href="<?= url('/account/orders') ?>"> <i class="bi bi-bag-check text-primary"></i> <?= __('my_orders') ?> </a> </li> <li> <a class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2" href="<?= url('/account/wishlist') ?>"> <i class="bi bi-heart text-danger"></i> <?= __('my_wishlist') ?> </a> </li> <li> <a class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2" href="<?= url('/account/profile') ?>"> <i class="bi bi-person text-primary"></i> <?= __('profile') ?> </a> </li> <li> <a class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2" href="<?= url('/account/addresses') ?>"> <i class="bi bi-geo-alt text-primary"></i> <?= __('addresses') ?> </a> </li> <li> <a class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2" href="<?= url('/account/security') ?>"> <i class="bi bi-shield-lock text-primary"></i> <?= __('security') ?> </a> </li> <li> <a class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2" href="<?= url('/account/login-history') ?>"> <i class="bi bi-clock-history text-primary"></i> <?= __('login_history') ?> </a> </li> <?php if (Auth::isSeller()): ?> <li><hr class="dropdown-divider my-1"></li> <li> <a class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2 text-primary fw-medium" href="<?= url('/seller') ?>"> <i class="bi bi-shop"></i> <?= __('seller_center') ?> </a> </li> <?php else: ?> <li><hr class="dropdown-divider my-1"></li> <li> <a class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2 text-primary" href="<?= url('/seller/register') ?>"> <i class="bi bi-shop"></i> <?= __('open_store') ?> </a> </li> <?php endif; ?> <?php if (Auth::isAdmin()): ?> <li> <a class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2 text-danger fw-medium" href="<?= url('/admin') ?>"> <i class="bi bi-speedometer2"></i> <?= __('admin_panel') ?> </a> </li> <?php endif; ?> <li><hr class="dropdown-divider my-1"></li> <li> <form action="<?= url('/logout') ?>" method="POST" class="m-0 p-0"> <?= Security::csrfField() ?> <button type="submit" class="dropdown-item rounded-2 d-flex align-items-center gap-2 py-2 text-danger"> <i class="bi bi-box-arrow-right"></i> <?= __('logout') ?> </button> </form> </li> </ul> </li> <?php else: ?> <!-- Guest State --> <li class="nav-item"> <a class="btn btn-cargoo-outline px-3 py-1 me-1 fs-6" href="<?= url('/login') ?>"> <?= __('login') ?> </a> </li> <li class="nav-item"> <a class="btn btn-cargoo-primary px-3 py-1 fs-6" href="<?= url('/register') ?>"> <?= __('register') ?> </a> </li> <?php endif; ?> </ul> </div> </div> </nav> <script> document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('navSearchInput'); const suggestionsBox = document.getElementById('navSearchSuggestions'); let debounceTimer = null; if (searchInput && suggestionsBox) { searchInput.addEventListener('input', function() { const q = this.value.trim(); clearTimeout(debounceTimer); if (q.length < 1) { suggestionsBox.classList.add('d-none'); suggestionsBox.innerHTML = ''; return; } debounceTimer = setTimeout(() => { fetch('<?= url('/api/v1/search/suggest') ?>?q=' + encodeURIComponent(q)) .then(res => res.json()) .then(data => { if (!data.success || ((!data.products || data.products.length === 0) && (!data.categories || data.categories.length === 0))) { suggestionsBox.innerHTML = '<div class="p-3 text-center text-muted small"><i class="bi bi-search me-1"></i> ไม่พบสินค้าที่ตรงกับคำค้นหา</div>'; suggestionsBox.classList.remove('d-none'); return; } let html = ''; // Categories if (data.categories && data.categories.length > 0) { html += '<div class="px-2 py-1 small fw-bold text-muted text-uppercase" style="font-size: 0.7rem;">หมวดหมู่สินค้า</div>'; data.categories.forEach(cat => { html += '<a href="' + cat.url + '" class="d-flex align-items-center gap-2 px-3 py-2 text-decoration-none text-dark rounded-2 hover-bg-light small">' + '<i class="bi bi-grid-fill text-primary"></i>' + '<span>' + escapeSearchHtml(cat.name) + '</span>' + '</a>'; }); html += '<hr class="my-1">'; } // Products if (data.products && data.products.length > 0) { html += '<div class="px-2 py-1 small fw-bold text-muted text-uppercase" style="font-size: 0.7rem;">สินค้าแนะนำ</div>'; data.products.forEach(p => { const imgHtml = p.image ? '<img src="' + p.image + '" class="rounded-2 object-fit-cover" style="width: 38px; height: 38px;">' : '<div class="rounded-2 bg-light border d-flex align-items-center justify-content-center text-muted" style="width: 38px; height: 38px;"><i class="bi bi-image"></i></div>'; html += '<a href="' + p.url + '" class="d-flex align-items-center justify-content-between p-2 text-decoration-none text-dark rounded-2 hover-bg-light">' + '<div class="d-flex align-items-center gap-2 text-truncate me-2">' + imgHtml + '<span class="small fw-medium text-truncate">' + escapeSearchHtml(p.name) + '</span>' + '</div>' + '<span class="small fw-bold text-primary text-nowrap">฿' + p.price.toLocaleString('th-TH', {minimumFractionDigits: 2}) + '</span>' + '</a>'; }); } // View all results link html += '<div class="border-top mt-1 pt-1">' + '<a href="<?= url('/search') ?>?q=' + encodeURIComponent(q) + '" class="d-block text-center py-2 small text-primary fw-bold text-decoration-none rounded-2 hover-bg-light">' + 'ดูผลการค้นหาทั้งหมด (' + data.total + ' รายการ) <i class="bi bi-arrow-right"></i>' + '</a>' + '</div>'; suggestionsBox.innerHTML = html; suggestionsBox.classList.remove('d-none'); }) .catch(() => { suggestionsBox.classList.add('d-none'); }); }, 250); }); document.addEventListener('click', function(e) { if (!searchInput.contains(e.target) && !suggestionsBox.contains(e.target)) { suggestionsBox.classList.add('d-none'); } }); searchInput.addEventListener('focus', function() { if (this.value.trim().length >= 1 && suggestionsBox.innerHTML !== '') { suggestionsBox.classList.remove('d-none'); } }); } function escapeSearchHtml(str) { if (!str) return ''; return str.replace(/[&<>"']/g, function(m) { return {'&': '&', '<': '<', '>': '>', '"': '"', "'": '''}[m]; }); } }); </script>
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.26 |
proxy
|
phpinfo
|
Settings