172 lines
7.0 KiB
Plaintext
172 lines
7.0 KiB
Plaintext
---
|
|
import { Image } from "astro:assets";
|
|
// Header component
|
|
---
|
|
|
|
<header class="sticky top-0 z-50 bg-transparent">
|
|
<nav class="max-w-5xl mx-auto px-4 py-4">
|
|
<ul class="flex items-center justify-between list-none">
|
|
<li class="flex-shrink-0">
|
|
<a href="/" class="block">
|
|
<!-- Uses Astro's optimized Image component for the site logo -->
|
|
<Image
|
|
src="/enchun-logo.svg"
|
|
alt="Enchun Digital Marketing"
|
|
class="w-32 h-auto"
|
|
width={919}
|
|
height={201}
|
|
loading="eager"
|
|
decoding="async"
|
|
/>
|
|
</a>
|
|
</li>
|
|
<li class="hidden md:flex items-center space-x-6" id="desktop-nav">
|
|
<!-- Navigation items will be populated by JavaScript -->
|
|
</li>
|
|
<!-- Mobile menu button -->
|
|
<li class="md:hidden">
|
|
<button
|
|
class="text-[var(--color-enchunblue)] hover:text-[var(--color-enchunblue)]/80"
|
|
id="mobile-menu-button"
|
|
>
|
|
<svg
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 36 36"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
class="w-6 h-6"
|
|
>
|
|
<path
|
|
d="M6 27H22.5C23.325 27 24 26.325 24 25.5C24 24.675 23.325 24 22.5 24H6C5.175 24 4.5 24.675 4.5 25.5C4.5 26.325 5.175 27 6 27ZM6 19.5H18C18.825 19.5 19.5 18.825 19.5 18C19.5 17.175 18.825 16.5 18 16.5H6C5.175 16.5 4.5 17.175 4.5 18C4.5 18.825 5.175 19.5 6 19.5ZM4.5 10.5C4.5 11.325 5.175 12 6 12H22.5C23.325 12 24 11.325 24 10.5C24 9.675 23.325 9 22.5 9H6C5.175 9 4.5 9.675 4.5 10.5ZM30.45 22.32L26.13 18L30.45 13.68C30.5889 13.5411 30.699 13.3763 30.7742 13.1948C30.8493 13.0134 30.888 12.8189 30.888 12.6225C30.888 12.4261 30.8493 12.2316 30.7742 12.0502C30.699 11.8687 30.5889 11.7039 30.45 11.565C30.3111 11.4261 30.1463 11.316 29.9648 11.2408C29.7834 11.1657 29.5889 11.127 29.3925 11.127C29.1961 11.127 29.0016 11.1657 28.8202 11.2408C28.6387 11.316 28.4739 11.4261 28.335 11.565L22.95 16.95C22.8109 17.0888 22.7006 17.2536 22.6254 17.4351C22.5501 17.6165 22.5113 17.811 22.5113 18.0075C22.5113 18.204 22.5501 18.3985 22.6254 18.5799C22.7006 18.7614 22.8109 18.9262 22.95 19.065L28.335 24.45C28.92 25.035 29.865 25.035 30.45 24.45C31.02 23.865 31.035 22.905 30.45 22.32V22.32Z"
|
|
fill="currentColor"></path>
|
|
</svg>
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
<!-- Mobile menu -->
|
|
<div class="md:hidden hidden" id="mobile-menu">
|
|
<ul class="pt-4 pb-2 space-y-2" id="mobile-nav">
|
|
<!-- Mobile navigation items will be populated by JavaScript -->
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
</header>
|
|
|
|
<script>
|
|
interface NavItem {
|
|
link: {
|
|
type: "reference" | "custom";
|
|
label: string;
|
|
url?: string;
|
|
reference?: {
|
|
slug: string;
|
|
};
|
|
newTab?: boolean;
|
|
};
|
|
}
|
|
|
|
// Fetch navigation data from Payload CMS
|
|
async function fetchNavigation() {
|
|
try {
|
|
// Use local proxy in development to avoid CORS issues
|
|
const apiUrl = `/api/globals/header?depth=2&draft=false&locale=undefined&trash=false`;
|
|
|
|
const response = await fetch(apiUrl);
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
return data.navItems || [];
|
|
} catch (error) {
|
|
console.error("Error fetching navigation:", error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Generate navigation link HTML
|
|
function createNavLink(item: NavItem) {
|
|
const { link } = item;
|
|
let href = "";
|
|
|
|
if (link.type === "custom" && link.url) {
|
|
href = link.url;
|
|
} else if (link.type === "reference" && link.reference?.slug) {
|
|
href = `/${link.reference.slug}`;
|
|
}
|
|
|
|
const target = link.newTab
|
|
? ' target="_blank" rel="noopener noreferrer"'
|
|
: "";
|
|
const label = link.label;
|
|
|
|
// Check if current page matches this link
|
|
const currentPath = window.location.pathname;
|
|
const isActive =
|
|
currentPath === href || (href === "/" && currentPath === "/");
|
|
|
|
// Add badges for specific items (positioned in top right corner)
|
|
let badge = "";
|
|
if (label.includes("行銷方案")) {
|
|
badge =
|
|
'<span class="absolute -top-1 -right-1 bg-red-500 text-white text-[0.5rem] px-1 py-0.5 rounded-full">hot</span>';
|
|
} else if (label.includes("行銷放大鏡")) {
|
|
badge =
|
|
'<span class="absolute -top-1 -right-1 bg-red-500 text-white text-[0.5rem] px-1 py-0.5 rounded-full">new</span>';
|
|
}
|
|
|
|
const containerClass = badge ? "relative inline-block" : "";
|
|
const activeClass = isActive ? " nav-active" : "";
|
|
|
|
return `<a href="${href}" class="${containerClass} text-lg font-normal text-shadow-md hover:text-primary transition-colors px-3 py-2${activeClass}"${target}>${label}${badge}</a>`;
|
|
}
|
|
|
|
// Populate navigation
|
|
async function populateNavigation() {
|
|
const navItems = await fetchNavigation();
|
|
|
|
const desktopNav = document.getElementById("desktop-nav");
|
|
const mobileNav = document.getElementById("mobile-nav");
|
|
|
|
if (desktopNav && mobileNav) {
|
|
// Clear existing content
|
|
desktopNav.innerHTML = "";
|
|
mobileNav.innerHTML = "";
|
|
|
|
// Populate desktop navigation
|
|
navItems.forEach((item) => {
|
|
const linkHtml = createNavLink(item);
|
|
const li = document.createElement("li");
|
|
li.innerHTML = linkHtml;
|
|
desktopNav.appendChild(li);
|
|
});
|
|
|
|
// Populate mobile navigation
|
|
navItems.forEach((item) => {
|
|
const linkHtml = createNavLink(item)
|
|
.replace("px-3 py-2", "block px-3 py-2")
|
|
.replace(
|
|
"relative inline-block",
|
|
"relative inline-block block",
|
|
);
|
|
const li = document.createElement("li");
|
|
li.innerHTML = linkHtml;
|
|
mobileNav.appendChild(li);
|
|
});
|
|
}
|
|
}
|
|
|
|
// Initialize navigation
|
|
populateNavigation();
|
|
|
|
// Simple mobile menu toggle
|
|
const button = document.getElementById("mobile-menu-button");
|
|
const menu = document.getElementById("mobile-menu");
|
|
if (button && menu) {
|
|
button.addEventListener("click", () => {
|
|
menu.classList.toggle("hidden");
|
|
});
|
|
}
|
|
</script>
|