import { useState, useEffect, useCallback } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import apiClient from '../api/client'; import { useBusiness } from '../context/BusinessContext'; export default function GlobalSms() { const { businessId } = useParams(); const navigate = useNavigate(); const { isSetupComplete, setHasGlobalSms, setIsSetupComplete } = useBusiness(); const [loading, setLoading] = useState(true); const [profiles, setProfiles] = useState([]); const [activeProfileId, setActiveProfileId] = useState(null); const [saving, setSaving] = useState(false); const [error, setError] = useState(''); const [success, setSuccess] = useState(''); // Form state for Create / Edit Profile const [editingId, setEditingId] = useState(null); const [formName, setFormName] = useState(''); const [formCurl, setFormCurl] = useState(''); const [formSetActive, setFormSetActive] = useState(true); // Form state for Missing Provider Fields const [providerForm, setProviderForm] = useState({ providerName: '', senderId: '', dltEntityId: '' }); const [savingProvider, setSavingProvider] = useState(false); const eventsPath = `/${businessId}/events`; const loadProfiles = useCallback(async () => { try { setLoading(true); const res = await apiClient.get(`/api/businesses/${businessId}/global-sms/profiles`); const fetchedProfiles = res.data.profiles || []; const fetchActiveId = res.data.activeProfileId; setProfiles(fetchedProfiles); setActiveProfileId(fetchActiveId); const activeProfile = fetchedProfiles.find(p => p.id === fetchActiveId) || null; const hasProfile = !!activeProfile; setHasGlobalSms(hasProfile); const p = activeProfile?.provider || {}; const complete = hasProfile && !!p.providerName && !!p.senderId && !!p.dltEntityId; setIsSetupComplete(complete); setProviderForm({ providerName: p.providerName || '', senderId: p.senderId || '', dltEntityId: p.dltEntityId || '', }); return { activeProfile, hasProfile, complete }; } catch { setError('Failed to load cURL profiles'); setHasGlobalSms(false); setIsSetupComplete(false); return { activeProfile: null, hasProfile: false, complete: false }; } finally { setLoading(false); } }, [businessId, setHasGlobalSms, setIsSetupComplete]); useEffect(() => { loadProfiles(); }, [loadProfiles]); const activeProfile = profiles.find(p => p.id === activeProfileId) || null; const pData = activeProfile?.provider || {}; const missingFields = []; if (activeProfile && !pData.providerName) missingFields.push('providerName'); if (activeProfile && !pData.senderId) missingFields.push('senderId'); if (activeProfile && !pData.dltEntityId) missingFields.push('dltEntityId'); function handleAddClick() { setEditingId(null); setFormName(''); setFormCurl(''); setFormSetActive(profiles.length === 0); setError(''); setSuccess(''); } function handleEditClick(profile) { setEditingId(profile.id); setFormName(profile.name); setFormCurl(profile.rawCurl); setFormSetActive(false); setError(''); setSuccess(''); } async function handleSubmit(e) { e.preventDefault(); if (!formName.trim() || !formCurl.trim()) return; setSaving(true); setError(''); setSuccess(''); const shouldAutoAdvance = !isSetupComplete; try { if (editingId) { await apiClient.patch(`/api/businesses/${businessId}/global-sms/profiles/${editingId}`, { name: formName, rawCurl: formCurl, }); setSuccess('Profile updated successfully.'); } else { await apiClient.post(`/api/businesses/${businessId}/global-sms/profiles`, { name: formName, rawCurl: formCurl, setActive: formSetActive, }); setSuccess('Profile created successfully.'); } const nextState = await loadProfiles(); setFormName(''); setFormCurl(''); setEditingId(null); if (shouldAutoAdvance && nextState.complete) { navigate(eventsPath); } } catch (err) { setError(err.response?.data?.error || 'Failed to save cURL profile'); } finally { setSaving(false); } } async function handleDelete(id) { if (!window.confirm('Delete this cURL profile?')) return; try { await apiClient.delete(`/api/businesses/${businessId}/global-sms/profiles/${id}`); await loadProfiles(); } catch (err) { setError(err.response?.data?.error || 'Failed to delete profile'); } } async function handleActivate(id) { const shouldAutoAdvance = !isSetupComplete; try { await apiClient.post(`/api/businesses/${businessId}/global-sms/profiles/${id}/activate`); const nextState = await loadProfiles(); if (shouldAutoAdvance && nextState.complete) { navigate(eventsPath); } } catch (err) { setError(err.response?.data?.error || 'Failed to activate profile'); } } async function handleProviderSubmit(e) { e.preventDefault(); if (!activeProfileId) return; setSavingProvider(true); setError(''); setSuccess(''); const shouldAutoAdvance = !isSetupComplete; try { await apiClient.patch(`/api/businesses/${businessId}/global-sms/profiles/${activeProfileId}`, { provider: { providerName: providerForm.providerName, senderId: providerForm.senderId.toUpperCase(), dltEntityId: providerForm.dltEntityId, } }); setSuccess('Provider details saved successfully!'); const nextState = await loadProfiles(); if (shouldAutoAdvance && nextState.complete) { navigate(eventsPath); } } catch (err) { setError(err.response?.data?.error || 'Failed to save provider details'); } finally { setSavingProvider(false); } } if (loading) { return (
); } return (

Omni-channel SMS

Complete this flow to configure your cURL profile and brand provider data. You must finish setup before generating templates.

{error && (
{error}
)} {success && (
{success}
)} {/* Active Profile Setup Review Block */} {activeProfile && (

Active Setup: {activeProfile.name}

{isSetupComplete ? ( Setup Complete ) : ( Missing Information )}

Parsed Provider Data:

  • Provider: {pData.providerName || Missing}
  • Sender ID: {pData.senderId || Missing}
  • Entity ID: {pData.dltEntityId || Missing}
  • Auth Key: {pData.authKey ? '••••••••' : 'None setup'}
{!isSetupComplete && (

Please fill in the missing fields:

{missingFields.includes('providerName') && ( setProviderForm({ ...providerForm, providerName: e.target.value })} className="w-full px-3 py-2 border border-border-main rounded text-sm focus:ring-1 focus:ring-primary-blue bg-page-bg" required /> )} {missingFields.includes('senderId') && ( setProviderForm({ ...providerForm, senderId: e.target.value.toUpperCase() })} className="w-full px-3 py-2 border border-border-main rounded text-sm focus:ring-1 focus:ring-primary-blue bg-page-bg uppercase" required /> )} {missingFields.includes('dltEntityId') && ( setProviderForm({ ...providerForm, dltEntityId: e.target.value })} className="w-full px-3 py-2 border border-border-main rounded text-sm focus:ring-1 focus:ring-primary-blue bg-page-bg" required /> )}
)} {isSetupComplete && (

Your active cURL profile is fully configured.

)}
)} {/* Profiles List */}

All Profiles

{profiles.length > 0 ? ( profiles.map(p => { const isActive = p.id === activeProfileId; return (

{p.name}

{isActive && ( Active Profile )} {p.isDefault && !isActive && ( Default )}

Updated: {new Date(p.updatedAt).toLocaleString()}

{p.rawCurl}

{!isActive && ( )} {profiles.length > 1 && ( )}
); }) ) : (

No cURL profiles configured yet.

)}
{/* Inline Form (Create / Edit) */}

{editingId ? 'Edit Profile' : 'Add New Profile'}

{editingId && ( )}
setFormName(e.target.value)} placeholder="e.g. Production SMS, Staging Twilio" className="w-full px-4 py-2 rounded-lg bg-page-bg border border-border-main text-text-primary placeholder-placeholder-bg focus:outline-none focus:ring-2 focus:ring-primary-blue transition text-sm" required />