// ================================================================ // frontend/src/components/dashboard/OrchestrationSummaryCard.tsx // ================================================================ /** * Orchestration Summary Card - What the system did for you * * Builds trust by showing transparency into automation decisions. * Narrative format makes it feel like a helpful assistant. */ import React, { useState } from 'react'; import { Bot, TrendingUp, Package, Clock, CheckCircle, FileText, Users, Brain, ChevronDown, ChevronUp, Loader2, } from 'lucide-react'; import { OrchestrationSummary } from '../../api/hooks/newDashboard'; import { runDailyWorkflow } from '../../api/services/orchestrator'; import { formatDistanceToNow } from 'date-fns'; import { useTranslation } from 'react-i18next'; import { useTenant } from '../../stores/tenant.store'; import toast from 'react-hot-toast'; interface OrchestrationSummaryCardProps { summary: OrchestrationSummary; loading?: boolean; onWorkflowComplete?: () => void; } export function OrchestrationSummaryCard({ summary, loading, onWorkflowComplete }: OrchestrationSummaryCardProps) { const [expanded, setExpanded] = useState(false); const [isRunning, setIsRunning] = useState(false); const { t } = useTranslation('reasoning'); const { currentTenant } = useTenant(); const handleRunPlanning = async () => { if (!currentTenant?.id) { toast.error(t('jtbd.orchestration_summary.no_tenant_error') || 'No tenant ID found'); return; } setIsRunning(true); try { const result = await runDailyWorkflow(currentTenant.id); if (result.success) { toast.success(t('jtbd.orchestration_summary.planning_started') || 'Planning started successfully'); // Call callback to refresh the orchestration summary if (onWorkflowComplete) { onWorkflowComplete(); } } else { toast.error(result.message || t('jtbd.orchestration_summary.planning_failed') || 'Failed to start planning'); } } catch (error) { console.error('Error running daily workflow:', error); toast.error(t('jtbd.orchestration_summary.planning_error') || 'An error occurred while starting planning'); } finally { setIsRunning(false); } }; if (loading || !summary) { return (
); } // Handle case where no orchestration has run yet if (summary.status === 'no_runs') { return (

{t('jtbd.orchestration_summary.ready_to_plan')}

{summary.message || ''}

); } const runTime = summary.runTimestamp ? formatDistanceToNow(new Date(summary.runTimestamp), { addSuffix: true }) : 'recently'; return (
{/* Header */}

{t('jtbd.orchestration_summary.title')}

{t('jtbd.orchestration_summary.run_info', { runNumber: summary.runNumber || 0 })} • {runTime} {summary.durationSeconds && ( • {t('jtbd.orchestration_summary.took', { seconds: summary.durationSeconds })} )}
{/* Purchase Orders Created */} {summary.purchaseOrdersCreated > 0 && (

{t('jtbd.orchestration_summary.created_pos', { count: summary.purchaseOrdersCreated })}

{summary.purchaseOrdersSummary && summary.purchaseOrdersSummary.length > 0 && ( )}
)} {/* Production Batches Created */} {summary.productionBatchesCreated > 0 && (

{t('jtbd.orchestration_summary.scheduled_batches', { count: summary.productionBatchesCreated, })}

{summary.productionBatchesSummary && summary.productionBatchesSummary.length > 0 && ( )} {summary.productionBatchesSummary && summary.productionBatchesSummary.length > 3 && ( )}
)} {/* No actions created */} {summary.purchaseOrdersCreated === 0 && summary.productionBatchesCreated === 0 && (

{t('jtbd.orchestration_summary.no_actions')}

)} {/* Reasoning Inputs (How decisions were made) */}

{t('jtbd.orchestration_summary.based_on')}

{summary.reasoningInputs.customerOrders > 0 && (
{t('jtbd.orchestration_summary.customer_orders', { count: summary.reasoningInputs.customerOrders, })}
)} {summary.reasoningInputs.historicalDemand && (
{t('jtbd.orchestration_summary.historical_demand')}
)} {summary.reasoningInputs.inventoryLevels && (
{t('jtbd.orchestration_summary.inventory_levels')}
)} {summary.reasoningInputs.aiInsights && (
{t('jtbd.orchestration_summary.ai_optimization')}
)}
{/* Actions Required Footer */} {summary.userActionsRequired > 0 && (

{t('jtbd.orchestration_summary.actions_required', { count: summary.userActionsRequired, })}

)}
); }