'use client' import React, { useState, useEffect } from 'react' import Image from 'next/image' import type { Media, Page } from '@/payload-types' type LinkGroup = { type?: 'reference' | 'custom' | null reference?: Page | string | number | null url?: string | null newTab?: boolean | null } // specificPages is now a relationship array — each item is a populated Page or just an id type SpecificPage = Page | string | number interface PopupAnnouncementProps { enabled?: boolean heading?: string subheading?: string body?: string ctaText?: string ctaLink?: LinkGroup | null image?: Media | string | null badgeText?: string theme?: 'light' | 'dark' showOnPages?: 'all' | 'home' | 'specific' specificPages?: SpecificPage[] | null dismissDays?: number } function resolveUrl(link?: LinkGroup | null): string | null { if (!link) return null if (link.type === 'reference' && link.reference) { if (typeof link.reference === 'object' && 'slug' in link.reference) { return link.reference.slug ? `/${link.reference.slug}` : null } return null } return link.url ?? null } function resolveSpecificPageSlugs(pages?: SpecificPage[] | null): string[] { if (!pages) return [] return pages.flatMap((p) => { if (typeof p === 'object' && p !== null && 'slug' in p && typeof p.slug === 'string') { return [`/${p.slug}`] } return [] }) } export const PopupAnnouncementComponent: React.FC = ({ enabled, heading, subheading, body, ctaText = 'Läs mer', ctaLink, image, badgeText, theme = 'light', showOnPages = 'all', specificPages, dismissDays = 7, }) => { const [isVisible, setIsVisible] = useState(false) const [isClosing, setIsClosing] = useState(false) useEffect(() => { if (!enabled) return // Check if dismissed const dismissedAt = localStorage.getItem('fd-popup-dismissed') if (dismissedAt) { const dismissDate = new Date(dismissedAt) const now = new Date() const daysDiff = (now.getTime() - dismissDate.getTime()) / (1000 * 60 * 60 * 24) if (daysDiff < dismissDays) return } // Check page targeting const path = window.location.pathname if (showOnPages === 'home' && path !== '/') return if (showOnPages === 'specific') { const slugs = resolveSpecificPageSlugs(specificPages) if (!slugs.includes(path)) return } // Show after short delay const timer = setTimeout(() => setIsVisible(true), 1500) return () => clearTimeout(timer) }, [enabled, showOnPages, specificPages, dismissDays]) const handleClose = () => { setIsClosing(true) localStorage.setItem('fd-popup-dismissed', new Date().toISOString()) setTimeout(() => setIsVisible(false), 300) } if (!isVisible || !enabled) return null const media = typeof image === 'object' && image !== null ? (image as Media) : null const isDark = theme === 'dark' const href = resolveUrl(ctaLink) const newTab = ctaLink?.newTab ?? false // ── FIX: Resolve optimized image URL via Payload size or fall back to original ── const imageSrc = media?.sizes?.medium?.url || media?.sizes?.large?.url || media?.url || '' const imageWidth = media?.sizes?.medium?.width || media?.sizes?.large?.width || media?.width || 560 const imageHeight = media?.sizes?.medium?.height || media?.sizes?.large?.height || media?.height || 720 const isSvg = media?.mimeType === 'image/svg+xml' return ( <> {/* Backdrop */}
{/* Popup */}
e.stopPropagation()} > {/* Close button */} {/* Content */}
{badgeText && ( {badgeText} )} {heading && (

{heading}

)} {subheading && (

{subheading}

)} {body && (

{body}

)} {ctaText && href && ( {ctaText} )}
{/* Optional image — FIX: use next/image instead of raw */} {media?.url && imageSrc && (
{isSvg ? ( // SVGs skip optimization (same as FDImage convention) // eslint-disable-next-line @next/next/no-img-element {media.alt ) : ( {media.alt )}
)}
) }