diff --git a/frontend/src/components/ErrorBoundary.tsx b/frontend/src/components/ErrorBoundary.tsx new file mode 100644 index 00000000..cfd39cb3 --- /dev/null +++ b/frontend/src/components/ErrorBoundary.tsx @@ -0,0 +1,68 @@ +import React, { Component, ErrorInfo, ReactNode } from 'react'; + +interface Props { + children: ReactNode; + componentName?: string; +} + +interface State { + hasError: boolean; + error?: Error; + errorInfo?: ErrorInfo; +} + +/** + * Error Boundary to catch React errors and show debug information + */ +export class ErrorBoundary extends Component { + constructor(props: Props) { + super(props); + this.state = { hasError: false }; + } + + static getDerivedStateFromError(error: Error): State { + return { hasError: true, error }; + } + + componentDidCatch(error: Error, errorInfo: ErrorInfo) { + console.error('🔴 ErrorBoundary caught error:', { + component: this.props.componentName || 'Unknown', + error: error.message, + stack: error.stack, + componentStack: errorInfo.componentStack, + }); + + this.setState({ error, errorInfo }); + } + + render() { + if (this.state.hasError) { + return ( +
+

+ 🔴 Error in {this.props.componentName || 'Component'} +

+
+

+ Error: {this.state.error?.message} +

+ {this.state.error?.stack && ( +
+ Stack Trace +
{this.state.error.stack}
+
+ )} +
+ +
+ ); + } + + return this.props.children; + } +} diff --git a/frontend/src/hooks/useReasoningTranslation.ts b/frontend/src/hooks/useReasoningTranslation.ts index ce4476e6..df9431df 100644 --- a/frontend/src/hooks/useReasoningTranslation.ts +++ b/frontend/src/hooks/useReasoningTranslation.ts @@ -137,40 +137,70 @@ export function useReasoningFormatter() { const translation = useReasoningTranslation(); const formatPOAction = useCallback((reasoningData?: ReasoningData) => { + console.log('🔍 formatPOAction called with:', reasoningData); + if (!reasoningData) { - return { + const fallback = { reasoning: translation.translatePOReasonng({} as ReasoningData) || 'Purchase order required', consequence: '', severity: '' }; + console.log('🔍 formatPOAction: No reasoning data, returning fallback:', fallback); + return fallback; } const reasoning = translation.translatePOReasonng(reasoningData) || 'Purchase order required'; const consequence = translation.translateConsequence(reasoningData.consequence) || ''; const severity = translation.translateSeverity(reasoningData.consequence?.severity) || ''; - return { - reasoning, - consequence, - severity - }; + const result = { reasoning, consequence, severity }; + + // Debug: Check for undefined values + if (reasoning === undefined || consequence === undefined || severity === undefined) { + console.error('🔴 formatPOAction returned undefined value!', { + reasoningData, + result, + reasoning, + consequence, + severity + }); + } else { + console.log('✅ formatPOAction result:', { type: reasoningData.type, result }); + } + + return result; }, [translation]); const formatBatchAction = useCallback((reasoningData?: ReasoningData) => { + console.log('🔍 formatBatchAction called with:', reasoningData); + if (!reasoningData) { - return { + const fallback = { reasoning: translation.translateBatchReasoning({} as ReasoningData) || 'Production batch scheduled', urgency: 'normal' }; + console.log('🔍 formatBatchAction: No reasoning data, returning fallback:', fallback); + return fallback; } const reasoning = translation.translateBatchReasoning(reasoningData) || 'Production batch scheduled'; const urgency = reasoningData.urgency?.level || 'normal'; - return { - reasoning, - urgency - }; + const result = { reasoning, urgency }; + + // Debug: Check for undefined values + if (reasoning === undefined || urgency === undefined) { + console.error('🔴 formatBatchAction returned undefined value!', { + reasoningData, + result, + reasoning, + urgency + }); + } else { + console.log('✅ formatBatchAction result:', { type: reasoningData.type, result }); + } + + return result; }, [translation]); return { diff --git a/frontend/src/pages/app/DashboardPage.tsx b/frontend/src/pages/app/DashboardPage.tsx index 66b99936..575457d3 100644 --- a/frontend/src/pages/app/DashboardPage.tsx +++ b/frontend/src/pages/app/DashboardPage.tsx @@ -15,7 +15,7 @@ * - Trust-building (explain system reasoning) */ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { RefreshCw, ExternalLink } from 'lucide-react'; import { useTenant } from '../../stores/tenant.store'; @@ -34,6 +34,7 @@ import { ActionQueueCard } from '../../components/dashboard/ActionQueueCard'; import { OrchestrationSummaryCard } from '../../components/dashboard/OrchestrationSummaryCard'; import { ProductionTimelineCard } from '../../components/dashboard/ProductionTimelineCard'; import { InsightsGrid } from '../../components/dashboard/InsightsGrid'; +import { ErrorBoundary } from '../../components/ErrorBoundary'; export function NewDashboardPage() { const navigate = useNavigate(); @@ -71,6 +72,25 @@ export function NewDashboardPage() { refetch: refetchInsights, } = useInsights(tenantId); + // Debug logging for data + useEffect(() => { + console.log('🔍 Dashboard Data:', { + healthStatus: healthStatus, + orchestrationSummary: orchestrationSummary, + actionQueue: actionQueue, + productionTimeline: productionTimeline, + insights: insights, + loading: { + health: healthLoading, + orchestration: orchestrationLoading, + actionQueue: actionQueueLoading, + timeline: timelineLoading, + insights: insightsLoading + } + }); + }, [healthStatus, orchestrationSummary, actionQueue, productionTimeline, insights, + healthLoading, orchestrationLoading, actionQueueLoading, timelineLoading, insightsLoading]); + // Mutations const approvePO = useApprovePurchaseOrder(); const startBatch = useStartProductionBatch(); @@ -147,36 +167,46 @@ export function NewDashboardPage() { {/* Main Dashboard Layout */}
{/* SECTION 1: Bakery Health Status */} - + + + {/* SECTION 2: What Needs Your Attention (Action Queue) */} - + + + {/* SECTION 3: What the System Did for You (Orchestration Summary) */} - + + + {/* SECTION 4: Today's Production Timeline */} - + + + {/* SECTION 5: Quick Insights Grid */} -
-

Key Metrics

- -
+ +
+

Key Metrics

+ +
+
{/* SECTION 6: Quick Action Links */}