- Create BusinessReport.tsx with 6 sections: 1. Executive Summary (health score, rating, momentum) 2. Risk Scorecard (indicators with colors/trends) 3. Critical Issues (evidence, solutions, timelines) 4. Strengths to Protect (quotes, leverage actions) 5. Action Matrix (effort/impact quadrants) 6. 90-Day Tracking (KPI targets table) - Update types.ts with new interfaces: - SynthesisV2 for new report format - LegacySynthesis for backwards compatibility - Type guard isSynthesisV2() for runtime detection - Update ReportTab to auto-detect synthesis version - Update AnalystReport, ReviewIQDashboard, StoryView for backwards compatibility with union type Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
102 lines
2.9 KiB
TypeScript
102 lines
2.9 KiB
TypeScript
'use client';
|
|
|
|
import { Loader2, FileWarning } from 'lucide-react';
|
|
import { useReviewIQAnalytics } from '@/hooks/useReviewIQAnalytics';
|
|
import { AnalystReport } from './AnalystReport';
|
|
import { BusinessReport } from './BusinessReport';
|
|
import { isSynthesisV2 } from './types';
|
|
import type { ReviewIQFilters, LegacySynthesis, SynthesisV2 } from './types';
|
|
|
|
interface ReportTabProps {
|
|
jobId?: string;
|
|
businessId?: string;
|
|
}
|
|
|
|
// Default filters for Report view - uses 'all' time range for comprehensive analysis
|
|
const defaultFilters: ReviewIQFilters = {
|
|
timeRange: 'all',
|
|
sentiment: [],
|
|
urtDomain: null,
|
|
intensity: [],
|
|
brushRange: null,
|
|
};
|
|
|
|
/**
|
|
* Report Tab - Wraps report components with data fetching.
|
|
* Automatically detects report version and renders appropriate component.
|
|
*/
|
|
export function ReportTab({ jobId, businessId }: ReportTabProps) {
|
|
const { data, loading, error } = useReviewIQAnalytics({
|
|
jobId,
|
|
businessId,
|
|
filters: defaultFilters,
|
|
});
|
|
|
|
// Loading state
|
|
if (loading) {
|
|
return (
|
|
<div className="flex items-center justify-center min-h-[400px]">
|
|
<Loader2 className="w-8 h-8 animate-spin text-indigo-600" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Error state
|
|
if (error) {
|
|
return (
|
|
<div className="bg-red-50 border border-red-200 rounded-lg p-6 text-center">
|
|
<p className="text-red-700">{error}</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// No data state
|
|
if (!data) {
|
|
return (
|
|
<div className="bg-slate-50 border border-slate-200 rounded-lg p-6 text-center">
|
|
<p className="text-slate-600">No data available for this report.</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// No synthesis - AI report not generated yet
|
|
if (!data.synthesis) {
|
|
return (
|
|
<div className="max-w-2xl mx-auto mt-12">
|
|
<div className="bg-amber-50 border border-amber-200 rounded-2xl p-8 text-center">
|
|
<FileWarning className="w-12 h-12 text-amber-500 mx-auto mb-4" />
|
|
<h3 className="text-xl font-semibold text-amber-900 mb-2">
|
|
AI Report Not Generated Yet
|
|
</h3>
|
|
<p className="text-amber-700 mb-4">
|
|
The AI-powered analyst report hasn't been generated for this dataset.
|
|
Run the pipeline with the "synthesize" stage to generate the report.
|
|
</p>
|
|
<div className="text-sm text-amber-600 bg-amber-100 rounded-lg p-3 font-mono">
|
|
Stage 5: Synthesize → Generates narratives, actions & insights
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Render the appropriate report based on synthesis version
|
|
if (isSynthesisV2(data.synthesis)) {
|
|
// New 6-section Business Report (v2.0)
|
|
return <BusinessReport synthesis={data.synthesis} />;
|
|
}
|
|
|
|
// Legacy Analyst Report (v1.x)
|
|
return (
|
|
<AnalystReport
|
|
synthesis={data.synthesis}
|
|
overview={data.overview}
|
|
sentiment={data.sentiment.distribution}
|
|
domains={data.urt.domains}
|
|
timeline={data.timeline}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export default ReportTab;
|