ai insight rework #3, add root cause to daily ai insight

This commit is contained in:
Alberto-Audrix committed 2026-10-06 14:14:11 +07:00
1 parent c963bb778c
commit d5b0c12c40
8 files changed
+385 -47

No files matched your search

+61 -7
View File
@@ -1,5 +1,5 @@
/**
* Dashboard AI Insight card (page / daily / weekly / end_cycle report modes).
* Dashboard AI Insight card (daily / end_cycle report modes).
*
* Parallel client to `PageAiInsight` (topic pages) — same API, different UX.
* Architecture: docs/ai-insight/README.md
@@ -23,6 +23,7 @@ import {
scopeDashboardInsightMetrics,
} from '../utils/insightContextBuilders.ts';
import { getCobbStandardForDay } from '../utils/insightHelpers.ts';
import { parseAiResult, type AiResult } from '../utils/insightParse.ts';
import { formatRatio } from '../utils/format.ts';
import {
HeroFigure,
@@ -253,6 +254,7 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
const { selectedCycle, selectedKandang, selectedSite, selectedKandangId } = useFarm();
const [insightText, setInsightText] = useState('');
const [dailyInsight, setDailyInsight] = useState<AiResult | null>(null);
const [structuredInsight, setStructuredInsight] = useState<InsightStructuredReport | null>(null);
const [endCycleInsight, setEndCycleInsight] = useState<EndCycleStructuredInsight | null>(null);
const [citations, setCitations] = useState<InsightCitation[]>([]);
@@ -275,9 +277,7 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
reportType === 'daily'
? (dayPeriod ??
(typeof currentDayVal === 'number' && currentDayVal >= 0 ? `Hari ${currentDayVal}` : null))
: reportType === 'weekly'
? dayPeriod
: null;
: null;
const scopedMetrics = useMemo(() => {
if (!dashboardMetrics) return null;
@@ -293,7 +293,9 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
text: string,
nextCitations?: InsightCitation[] | 'cache' | 'local_fallback',
structuredEndCycle?: EndCycleStructuredInsight | null,
summary?: string | null
summary?: string | null,
akarMasalah?: string | null,
insightBody?: string | null
) => {
const citationsArg = Array.isArray(nextCitations) ? nextCitations : [];
setInsightText(text);
@@ -305,6 +307,22 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
// Prefer end-cycle structured UI over legacy multi-topic structured dump.
setStructuredInsight(endCycle ? null : normalizeStructuredInsight(text));
setCitations(citationsArg);
if (!endCycle) {
if (summary || akarMasalah || insightBody) {
setDailyInsight({
summary: summary || '',
akar_masalah: akarMasalah || undefined,
insight: insightBody || text || '',
});
} else if (text) {
setDailyInsight(parseAiResult(text));
} else {
setDailyInsight(null);
}
} else {
setDailyInsight(null);
}
},
[]
);
@@ -451,7 +469,9 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
apiResult.insight_text,
apiResult.citations,
apiResult.structured_end_cycle ?? null,
apiResult.summary
apiResult.summary,
apiResult.akar_masalah,
apiResult.insight
);
setLastUpdated(new Date());
setDetailsOpen(false);
@@ -1013,11 +1033,45 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
</>
)}
</div>
) : dailyInsight ? (
<div className="space-y-4">
<div className="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<h4 className="text-sm font-bold text-gray-800 mb-2 flex items-center gap-2">
<i className="fa-solid fa-circle-check text-green-600" /> Kesimpulan
</h4>
<p className="text-sm text-gray-700 bg-gray-50 p-3 rounded-lg border border-gray-100">
{dailyInsight.summary}
</p>
</div>
{dailyInsight.akar_masalah && (
<div className="rounded-xl border border-amber-100/80 bg-amber-50/40 p-5 shadow-sm">
<h4 className="text-sm font-bold text-gray-800 mb-2 flex items-center gap-2">
<i className="fa-solid fa-magnifying-glass-chart text-amber-600" /> Akar Masalah
</h4>
<p className="text-sm text-gray-700 bg-white/80 p-3 rounded-lg border border-amber-100/80">
{dailyInsight.akar_masalah}
</p>
</div>
)}
<div className="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<h4 className="text-sm font-bold text-gray-800 mb-2 flex items-center gap-2">
<i className="fa-solid fa-brain text-red-600" /> AI Insight & Rekomendasi
</h4>
<p className="text-sm text-gray-700 bg-gray-50 p-3 rounded-lg border border-gray-100 whitespace-pre-wrap">
{dailyInsight.insight}
</p>
<CitationsBlock citations={citations} />
</div>
</div>
) : insightText ? (
<div className="text-sm text-gray-800 leading-relaxed whitespace-pre-wrap">
{insightText.includes(END_CYCLE_JSON_MARKER)
? insightText.split(END_CYCLE_JSON_MARKER)[0]?.trim()
: insightText}
: insightText.includes('<!--daily_json-->')
? insightText.split('<!--daily_json-->')[0]?.trim()
: insightText}
<CitationsBlock citations={citations} />
</div>
) : (
+16 -3
View File
@@ -603,10 +603,11 @@ export const PageAiInsight: React.FC<PageAiInsightProps> = ({
}
const text = apiResult.insight_text ?? '';
let parsed: { summary: string; insight: string } | null = null;
if (apiResult.summary || apiResult.insight) {
let parsed: AiResult | null = null;
if (apiResult.summary || apiResult.insight || apiResult.akar_masalah) {
parsed = {
summary: apiResult.summary || '',
akar_masalah: apiResult.akar_masalah || undefined,
insight: apiResult.insight || apiResult.insight_text || '',
};
} else {
@@ -619,6 +620,7 @@ export const PageAiInsight: React.FC<PageAiInsightProps> = ({
const wrapped: PageInsightResult = {
summary: parsed.summary,
akar_masalah: parsed.akar_masalah,
insight: parsed.insight,
citations: apiResult.citations,
};
@@ -1041,9 +1043,20 @@ export const PageAiInsight: React.FC<PageAiInsightProps> = ({
</p>
</div>
{result.akar_masalah && (
<div className="mt-4">
<h4 className="text-sm font-bold text-gray-800 mb-2 flex items-center gap-2">
<i className="fa-solid fa-magnifying-glass-chart text-amber-600" /> Akar Masalah
</h4>
<p className="text-sm text-gray-700 bg-amber-50/50 p-3 rounded-lg border border-amber-100/80">
{result.akar_masalah}
</p>
</div>
)}
<div className="mt-4">
<h4 className="text-sm font-bold text-gray-800 mb-2 flex items-center gap-2">
<i className="fa-solid fa-brain text-red-600" /> AI Insight
<i className="fa-solid fa-brain text-red-600" /> AI Insight & Rekomendasi
</h4>
<p className="text-sm text-gray-700 bg-gray-50 p-3 rounded-lg border border-gray-100 whitespace-pre-wrap">
{result.insight}