/* global React, Icon, Avatar, fmtAED */ const { useState, useEffect, useMemo } = React; const TEMP_COLOR = { cold: '#6b7280', warm: '#3b82f6', hot: '#f97316', engaged: '#22c55e' }; function _initialsP(name) { if (!name) return '?'; const parts = String(name).replace(/[._@-]/g, ' ').split(/\s+/).filter(Boolean); if (!parts.length) return name.slice(0, 2).toUpperCase(); if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase(); return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase(); } function _colorP(s) { const palette = ['#22c55e', '#3b82f6', '#a855f7', '#f97316', '#eab308', '#ec4899', '#06b6d4', '#84cc16']; let h = 0; for (let i = 0; i < (s || '').length; i++) h = ((h << 5) - h) + s.charCodeAt(i); return palette[Math.abs(h) % palette.length]; } function Pipeline({ goto }) { const [tab, setTab] = useState('outbound'); const [data, setData] = useState({ outbound: null, inbound: null }); const [draggedId, setDraggedId] = useState(null); const [dropStage, setDropStage] = useState(null); const [moving, setMoving] = useState(false); const load = (which) => { fetch(`/api/pipeline?pipeline=${which}`, { credentials: 'include' }) .then((r) => r.ok ? r.json() : Promise.reject(r.statusText)) .then((d) => setData((prev) => ({ ...prev, [which]: d }))) .catch(() => setData((prev) => ({ ...prev, [which]: { columns: [] } }))); }; useEffect(() => { load('outbound'); load('inbound'); }, []); const active = tab === 'combined' ? mergeCombined(data.outbound, data.inbound) : data[tab]; const onDrop = async (stageName) => { if (!draggedId || moving) return; const allItems = (active?.columns || []).flatMap((c) => c.items.map((i) => ({ ...i, stage: c.stage }))); const card = allItems.find((c) => c.contact_id === draggedId); setDraggedId(null); setDropStage(null); if (!card || card.stage === stageName) return; setMoving(true); try { await fetch(`/api/pipeline/contacts/${draggedId}/stage`, { method: 'POST', credentials: 'include', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ stage: stageName }), }); load('outbound'); load('inbound'); } finally { setMoving(false); } }; const totalCount = active?.columns?.reduce((a, c) => a + c.count, 0) || 0; const totalValue = active?.columns?.reduce((a, c) => a + (c.value_aed || 0), 0) || 0; return (