'use client'; import { useState, useRef, useEffect } from 'react'; import { createPortal } from 'react-dom'; import { useTranslations, useLocale } from 'next-intl'; import { cn } from '@/components/ui/utils'; import { requestBrochureAction } from '@/app/actions/brochure'; import { useAnalytics } from './analytics/useAnalytics'; import { AnalyticsEvents } from './analytics/analytics-events'; interface BrochureModalProps { isOpen: boolean; onClose: () => void; } export default function BrochureModal({ isOpen, onClose }: BrochureModalProps) { const t = useTranslations('Brochure'); const locale = useLocale(); const { trackEvent } = useAnalytics(); const formRef = useRef(null); const modalRef = useRef(null); const [state, setState] = useState<'idle' | 'submitting' | 'success' | 'error'>('idle'); const [errorMsg, setErrorMsg] = useState(''); // Close on escape + lock scroll + focus trap useEffect(() => { if (!isOpen) return; // Auto-focus input when opened const firstInput = document.getElementById('brochure-email'); if (firstInput) { setTimeout(() => firstInput.focus(), 50); } const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); if (e.key === 'Tab' && modalRef.current) { const focusable = modalRef.current.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])', ) as NodeListOf; if (focusable.length > 0) { const first = focusable[0]; const last = focusable[focusable.length - 1]; if (e.shiftKey && document.activeElement === first) { last.focus(); e.preventDefault(); } else if (!e.shiftKey && document.activeElement === last) { first.focus(); e.preventDefault(); } } } }; document.addEventListener('keydown', handleKeyDown); // Strict overflow lock on mobile as well document.body.style.setProperty('overflow', 'hidden', 'important'); return () => { document.removeEventListener('keydown', handleKeyDown); document.body.style.overflow = ''; }; }, [isOpen, onClose]); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!formRef.current) return; setState('submitting'); setErrorMsg(''); try { const formData = new FormData(formRef.current); formData.set('locale', locale); const result = await requestBrochureAction(formData); if (result.success) { setState('success'); trackEvent(AnalyticsEvents.DOWNLOAD, { file_name: `klz-product-catalog-${locale}.pdf`, file_type: 'brochure', location: 'brochure_modal', }); } else { setState('error'); setErrorMsg(result.error || 'Something went wrong'); } } catch { setState('error'); setErrorMsg('Network error'); } }; const handleClose = () => { setState('idle'); setErrorMsg(''); onClose(); }; if (!isOpen) return null; const modal = (
{/* Backdrop */}