116 lines
3.2 KiB
TypeScript
116 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from 'react';
|
|
import Link from 'next/link';
|
|
import { Package } from 'lucide-react';
|
|
import { parseMetadata } from '@/lib/layoutConfig';
|
|
import { DEFAULT_ANNOUNCEMENT_LINKS } from '@/lib/homepageDefaults';
|
|
import { useAuthStore } from '@/store/authStore';
|
|
|
|
interface AnnouncementLink {
|
|
label: string;
|
|
url: string;
|
|
icon?: string;
|
|
}
|
|
|
|
interface AnnouncementBarProps {
|
|
config?: any;
|
|
isActive?: boolean;
|
|
}
|
|
|
|
function isTrackOrderLink(link: AnnouncementLink): boolean {
|
|
const label = link.label.toLowerCase();
|
|
const path = (link.url || '').split('?')[0];
|
|
return (
|
|
label.includes('track') ||
|
|
/\/track-order\/?$/i.test(path) ||
|
|
/\/services\/tracking/i.test(path)
|
|
);
|
|
}
|
|
|
|
function mapLinks(raw: any[]): AnnouncementLink[] {
|
|
return raw
|
|
.filter((l: any) => l?.label && l?.url)
|
|
.map((l: any) => {
|
|
const link: AnnouncementLink = {
|
|
label: String(l.label),
|
|
url: String(l.url),
|
|
icon: l.icon ? String(l.icon) : undefined,
|
|
};
|
|
if (isTrackOrderLink(link)) {
|
|
return { ...link, url: '/services/tracking' };
|
|
}
|
|
return link;
|
|
});
|
|
}
|
|
|
|
export const AnnouncementBar: React.FC<AnnouncementBarProps> = ({
|
|
config,
|
|
isActive = true,
|
|
}) => {
|
|
const { isAuthenticated, authReady } = useAuthStore();
|
|
const [links, setLinks] = useState<AnnouncementLink[]>(DEFAULT_ANNOUNCEMENT_LINKS);
|
|
const [visible, setVisible] = useState(isActive);
|
|
|
|
useEffect(() => {
|
|
setVisible(isActive);
|
|
if (!isActive) {
|
|
setLinks([]);
|
|
return;
|
|
}
|
|
|
|
if (config) {
|
|
const meta = parseMetadata(config);
|
|
const rawLinks = meta.links;
|
|
if (Array.isArray(rawLinks) && rawLinks.length > 0) {
|
|
setLinks(mapLinks(rawLinks));
|
|
} else {
|
|
setLinks(DEFAULT_ANNOUNCEMENT_LINKS);
|
|
}
|
|
return;
|
|
}
|
|
|
|
fetch('/api/v1/storefront/layout/home?region=announcement_bar', {
|
|
cache: 'no-store',
|
|
})
|
|
.then((r) => (r.ok ? r.json() : null))
|
|
.then((data: any[]) => {
|
|
if (data && data.length > 0) {
|
|
const meta = parseMetadata(data[0]);
|
|
const rawLinks = meta.links;
|
|
if (Array.isArray(rawLinks) && rawLinks.length > 0) {
|
|
setLinks(mapLinks(rawLinks));
|
|
return;
|
|
}
|
|
}
|
|
setLinks(DEFAULT_ANNOUNCEMENT_LINKS);
|
|
})
|
|
.catch(() => setLinks(DEFAULT_ANNOUNCEMENT_LINKS));
|
|
}, [config, isActive]);
|
|
|
|
const visibleLinks = links.filter((link) => {
|
|
if (!isTrackOrderLink(link)) return true;
|
|
return authReady && isAuthenticated;
|
|
});
|
|
|
|
if (!visible || visibleLinks.length === 0) return null;
|
|
|
|
return (
|
|
<div className="bg-white border-b border-gray-200 py-2.5 text-[12px] text-gray-500 font-medium z-50">
|
|
<div className="container mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-start gap-x-5 flex-wrap gap-y-1">
|
|
{visibleLinks.map((link, idx) => (
|
|
<Link
|
|
key={`${link.label}-${idx}`}
|
|
href={link.url}
|
|
className="hover:text-primary transition-colors flex items-center gap-1.5"
|
|
>
|
|
{link.icon === 'package' && (
|
|
<Package size={14} className="text-primary" />
|
|
)}
|
|
{link.label}
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|