import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { fetchAgentJourneys } from '../../service/agent-analytics/agent-analytics.service'; import type { IAgentDateRange, IJourneyListItem, } from '../../service/agent-analytics/agent-analytics.interface'; import ThumbsDownIcon from '../svg/ThumbsDownIcon'; import ThumbsUpIcon from '../svg/ThumbsUpIcon'; import EmptyState from './EmptyState'; import ErrorBanner from './ErrorBanner'; import JourneyDetailModal from './JourneyDetailModal'; import { formatNumber, formatDateTime, formatIntentScore } from './helpers'; import { getOutcomeBadgeTone } from './conversationsTab.utils'; const OUTCOME_OPTIONS = [ { label: 'All outcomes', value: '' }, { label: 'Purchase intent', value: 'purchase_intent' }, { label: 'Abandoned', value: 'abandoned' }, { label: 'Information only', value: 'information_only' }, { label: 'Comparison', value: 'comparison' }, { label: 'Support resolved', value: 'support_resolved' }, { label: 'Complaint', value: 'complaint' }, ]; const SENTIMENT_OPTIONS = [ { label: 'All sentiments', value: '' }, { label: 'Positive', value: 'positive' }, { label: 'Neutral', value: 'neutral' }, { label: 'Negative', value: 'negative' }, ]; interface ConversationsTabProps { dateRange: IAgentDateRange; initialOutcomeFilter?: string; initialSentimentFilter?: string; } const BADGE_TONE_CLASSES: Record = { success: 'bg-green-100 text-green-800', critical: 'bg-red-100 text-red-800', warning: 'bg-yellow-100 text-yellow-800', info: 'bg-blue-100 text-blue-800', }; const ConversationsTab = ({ dateRange, initialOutcomeFilter = '', initialSentimentFilter = '', }: ConversationsTabProps): JSX.Element => { const [journeys, setJourneys] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selectedFp, setSelectedFp] = useState(null); const [outcomeFilter, setOutcomeFilter] = useState(initialOutcomeFilter); const [sentimentFilter, setSentimentFilter] = useState( initialSentimentFilter ); const fetchJourneys = useCallback(() => { setLoading(true); setError(null); fetchAgentJourneys(dateRange.start, dateRange.end) .then(d => { setJourneys(d.journeys || []); setLoading(false); }) .catch(e => { setError(e.message); setLoading(false); }); }, [dateRange.start, dateRange.end]); useEffect(() => { fetchJourneys(); }, [fetchJourneys]); const filteredJourneys = useMemo(() => { let result = journeys; if (outcomeFilter) { result = result.filter(j => j.outcome === outcomeFilter); } if (sentimentFilter) { result = result.filter(j => j.sentiment === sentimentFilter); } return result; }, [journeys, outcomeFilter, sentimentFilter]); if (loading) { return (
{Array.from({ length: 8 }).map((_, i) => (
))}
); } if (error) return ; if (journeys.length === 0) return ; return (

{filteredJourneys.length} Conversations {(outcomeFilter || sentimentFilter) && ( {` (filtered from ${journeys.length})`} )}

{filteredJourneys.length > 0 ? ( <>
{filteredJourneys.map((j, idx) => ( setSelectedFp(j.fingerprint)} > ))}
Date Duration Messages Outcome Intent Clicks Carts Feedback Stage
{formatDateTime(j.first_message_at)} {j.duration_minutes != null ? formatNumber(j.duration_minutes, 1) + 'm' : '-'} {j.message_count || 0} {j.outcome || '-'} {formatIntentScore(j.purchase_intent_score)} {(j.clicked_products || []).length > 0 ? (
{j.clicked_products.map((product, index) => ( {product.name || product.sku} ))}
) : ( j.product_clicks || 0 )}
{(j.carted_products || []).length > 0 ? (
{j.carted_products.map((product, index) => ( {product.name || product.sku} ))}
) : ( j.add_to_cart_count || 0 )}
{j.liked_messages_count || j.disliked_messages_count ? (
{j.liked_messages_count > 0 && ( {j.liked_messages_count} )} {j.disliked_messages_count > 0 && ( {j.disliked_messages_count} )}
) : ( - )}
{j.last_stage ? ( {j.last_stage} ) : ( '-' )}

Click a row to view conversation details

) : ( )}
{selectedFp && ( setSelectedFp(null)} /> )}
); }; export default ConversationsTab;