import { useState, useEffect, useCallback, useRef } from 'react'; import { useParams, useSearchParams } from 'react-router-dom'; import apiClient from '../api/client'; import WhitelistModal from '../components/WhitelistModal'; import TestSmsModal from '../components/TestSmsModal'; const STATUS_CONFIG = { generated: { label: 'Generated', bg: 'bg-page-bg', text: 'text-text-muted', border: 'border-border-main' }, pending_whitelisting: { label: 'Pending Whitelisting', bg: 'bg-white', text: 'text-gray-700', border: 'border-gray-200' }, whitelisted: { label: 'Published', bg: 'bg-white', text: 'text-gray-700', border: 'border-gray-200' }, }; export default function Templates() { const { businessId } = useParams(); const [searchParams] = useSearchParams(); const [templates, setTemplates] = useState([]); const [profilesById, setProfilesById] = useState({}); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [whitelistTarget, setWhitelistTarget] = useState(null); const [testTarget, setTestTarget] = useState(null); const [activeTab, setActiveTab] = useState('published'); // 'published' | 'pending' const [highlightedEventSlug, setHighlightedEventSlug] = useState(''); const templateCardRefs = useRef({}); const highlightTimeoutRef = useRef(null); const handledFocusSlugRef = useRef(''); const getTabForStatus = useCallback((status) => { if (status === 'pending_whitelisting') return 'pending'; if (status === 'whitelisted') return 'published'; return null; }, []); const loadTemplates = useCallback(async () => { setLoading(true); setError(''); try { const [templatesRes, profilesRes] = await Promise.all([ apiClient.get(`/api/businesses/${businessId}/templates`), apiClient.get(`/api/businesses/${businessId}/global-sms/profiles`).catch(() => ({ data: { profiles: [] } })), ]); const all = (templatesRes.data.templates || []).filter(t => t.selectedTemplate); const profileMap = Object.fromEntries((profilesRes.data.profiles || []).map(profile => [profile.id, profile])); setTemplates(all); setProfilesById(profileMap); } catch { setError('Failed to load templates'); } finally { setLoading(false); } }, [businessId]); useEffect(() => { loadTemplates(); }, [loadTemplates]); useEffect(() => { return () => { if (highlightTimeoutRef.current) { window.clearTimeout(highlightTimeoutRef.current); } }; }, []); useEffect(() => { const targetEventSlug = searchParams.get('event'); if (!targetEventSlug || templates.length === 0) return; if (handledFocusSlugRef.current === targetEventSlug) return; const targetTemplate = templates.find(tmpl => tmpl.eventSlug === targetEventSlug); if (!targetTemplate) return; const targetTab = getTabForStatus(targetTemplate.status); if (targetTab && activeTab !== targetTab) { setActiveTab(targetTab); return; } const targetCard = templateCardRefs.current[targetEventSlug]; if (!targetCard) return; handledFocusSlugRef.current = targetEventSlug; targetCard.scrollIntoView({ behavior: 'smooth', block: 'center' }); setHighlightedEventSlug(targetEventSlug); if (highlightTimeoutRef.current) { window.clearTimeout(highlightTimeoutRef.current); } highlightTimeoutRef.current = window.setTimeout(() => { setHighlightedEventSlug(currentSlug => (currentSlug === targetEventSlug ? '' : currentSlug)); highlightTimeoutRef.current = null; }, 2200); }, [activeTab, getTabForStatus, searchParams, templates]); async function handleWhitelistSuccess() { setWhitelistTarget(null); await loadTemplates(); } if (loading) { return (
Track whitelisting status and test your SMS templates.
Generate and select templates in the Events section first.
No templates in {activeTab === 'published' ? 'Published' : 'Pending'}.
{tmpl.eventSlug}
{tmpl.templateId}
Submit to the DLT portal, then complete publish from here.
)}