'use client'; import { useState } from 'react'; import { RefreshCw, BarChart3 } from 'lucide-react'; import { ReviewIQFilterProvider, useReviewIQFilters } from '@/contexts/ReviewIQFilterContext'; import { useReviewIQAnalytics } from '@/hooks/useReviewIQAnalytics'; import { FilterBar } from './FilterBar'; import { DashboardSkeleton, DashboardError, DashboardEmpty } from './DashboardSkeleton'; import { SentimentPie } from './charts/SentimentPie'; import { IntensityHeatmap } from './charts/IntensityHeatmap'; import { TimelineChart } from './charts/TimelineChart'; import { IssuesTable } from './tables/IssuesTable'; import { SpansTable } from './tables/SpansTable'; import { ExecutiveSummary } from './insights/ExecutiveSummary'; import { OpportunityMatrix } from './insights/OpportunityMatrix'; import type { URTDomain } from './types'; interface ReviewIQDashboardProps { jobId?: string | null; businessId?: string | null; } /** * Inner dashboard component that uses the filter context. * * Streamlined flow (no redundancy): * 1. Hero: Executive Summary (rating, AI insights, #1 problem/strength, top complaints) * 2. Explore: Sentiment + Category Heatmap (side by side) * 3. Action: Opportunity Matrix (what to fix) * 4. Trends: Timeline * 5. Deep Dive: Issues & Spans tables */ function ReviewIQDashboardInner({ jobId, businessId }: ReviewIQDashboardProps) { const { filters, setURTDomain } = useReviewIQFilters(); const [issuesPage, setIssuesPage] = useState(1); const [spansPage, setSpansPage] = useState(1); const { data, loading, error, refetch } = useReviewIQAnalytics({ jobId, businessId, filters, issuesPage, issuesPageSize: 10, spansPage, spansPageSize: 10, }); const handleIssuesPageChange = (page: number) => setIssuesPage(page); const handleSpansPageChange = (page: number) => setSpansPage(page); // No job selected if (!jobId && !businessId) { return ; } // Loading state if (loading && !data) { return ; } // Error state if (error) { return ; } // No data if (!data) { return ; } // Handle domain click for filtering const handleDomainClick = (domain: URTDomain) => { setURTDomain(filters.urtDomain === domain ? null : domain); }; return (
{/* ═══════════════════════════════════════════════════════════════ HEADER ═══════════════════════════════════════════════════════════════ */}

ReviewIQ Analytics

{data.overview.total_reviews.toLocaleString()} reviews • {data.overview.total_spans.toLocaleString()} insights extracted

{/* Active Filters Bar */} {/* ═══════════════════════════════════════════════════════════════ SECTION 1: EXECUTIVE SUMMARY (Hero) Rating, AI summary, #1 Problem, #1 Strength, Top Complaints ═══════════════════════════════════════════════════════════════ */} {/* ═══════════════════════════════════════════════════════════════ SECTION 2: EXPLORE (Sentiment + Categories) Side-by-side: How customers feel + What they talk about ═══════════════════════════════════════════════════════════════ */}
{/* ═══════════════════════════════════════════════════════════════ SECTION 3: ACTION (Opportunity Matrix) What to fix - prioritized by impact vs effort ═══════════════════════════════════════════════════════════════ */} {/* ═══════════════════════════════════════════════════════════════ SECTION 4: TRENDS (Timeline) How things change over time ═══════════════════════════════════════════════════════════════ */} {/* ═══════════════════════════════════════════════════════════════ SECTION 5: DEEP DIVE (Tables) Detailed issues and individual mentions ═══════════════════════════════════════════════════════════════ */}
{/* Debug Info (dev only) */} {process.env.NODE_ENV === 'development' && (
Debug: Filters Applied
            {JSON.stringify(data.filters_applied, null, 2)}
          
)}
); } /** * Main ReviewIQ Dashboard with filter context provider. */ export function ReviewIQDashboard({ jobId, businessId }: ReviewIQDashboardProps) { return ( ); }