update ai insight root cause

This commit is contained in:
Alberto-Audrix committed 2026-10-06 14:26:26 +07:00
1 parent 7e8c06d36f
commit 15ebdcce78
7 files changed
+297 -48

No files matched your search

+60 -6
View File
@@ -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,
@@ -252,6 +253,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[]>([]);
@@ -274,9 +276,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;
@@ -292,7 +292,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);
@@ -304,6 +306,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);
}
},
[]
);
@@ -426,7 +444,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);
@@ -978,11 +998,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>
) : (