ai insight rework #2

This commit is contained in:
Alberto-Audrix committed 2026-10-01 13:23:45 +07:00
1 parent 9d76f54d33
commit e1987d6999
39 files changed
+2311 -830

No files matched your search

+26 -19
View File
@@ -24,7 +24,12 @@ import {
} from '../utils/insightContextBuilders.ts';
import { getCobbStandardForDay } from '../utils/insightHelpers.ts';
import { formatRatio } from '../utils/format.ts';
import { HeroFigure, MutedStatRow, StatTile, type InsightStatus } from './shared/InsightStatTiles.tsx';
import {
HeroFigure,
MutedStatRow,
StatTile,
type InsightStatus,
} from './shared/InsightStatTiles.tsx';
import InsightTrendChart from './shared/InsightTrendChart.tsx';
const CLIENT_TIMEOUT_MS = 1_200_000; // 20 minutes
@@ -265,8 +270,7 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
? contextProp.hari_ke
: null;
// Prefer context/data day over cycle calendar day (can be ahead of KPI/weight data).
const currentDayVal =
contextDay ?? dashboardMetrics?.hari_ke ?? selectedCycle?.current_day ?? 0;
const currentDayVal = contextDay ?? dashboardMetrics?.hari_ke ?? selectedCycle?.current_day ?? 0;
const reportPeriod =
reportType === 'daily'
? (dayPeriod ?? (currentDayVal > 0 ? `Hari ${currentDayVal}` : null))
@@ -354,6 +358,13 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
contextPayload.tonase_panen_kg = scopedMetrics.tonase_panen_kg;
contextPayload.uniformity_persen = scopedMetrics.uniformity_persen;
contextPayload.pakan_kumulatif_karung = scopedMetrics.pakan_kumulatif_karung;
// EEF series for trend computation (eef, dashboard, end_cycle topics)
if (topic === 'eef' || topic === 'dashboard' || reportType === 'end_cycle') {
contextPayload.eef_seri = scopedMetrics.kpiSeries
.filter((row) => row.eef != null && row.hari > 0)
.map((row) => ({ hari: row.hari, eef: row.eef }));
}
}
if (reportType === 'end_cycle' && scopedMetrics) {
@@ -529,7 +540,7 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
const detailed = structuredInsight?.detailed;
const gradeDay = scopedMetrics?.hari_ke ?? (currentDayVal > 0 ? currentDayVal : null);
const fcrStandard = gradeDay ? getCobbStandardForDay(gradeDay)?.fcr ?? null : null;
const fcrStandard = gradeDay ? (getCobbStandardForDay(gradeDay)?.fcr ?? null) : null;
const fcrStatus = ((): InsightStatus => {
const actual = scopedMetrics?.fcr ?? null;
@@ -558,8 +569,7 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
const weightTarget =
scopedMetrics?.weightSeries.find((row) => row.hari === gradeDay)?.target ??
[...(scopedMetrics?.weightSeries ?? [])].reverse().find((row) => row.target != null)
?.target ??
[...(scopedMetrics?.weightSeries ?? [])].reverse().find((row) => row.target != null)?.target ??
null;
const weightStatus = ((): InsightStatus => {
@@ -658,9 +668,7 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
value={bobotVal == null ? 'N/A' : Math.round(bobotVal).toLocaleString('id-ID')}
unit={bobotVal == null ? undefined : 'g'}
status={weightStatus}
deltaLabel={
weightGapPct == null ? null : `${weightGapPct.toFixed(0)}% vs target`
}
deltaLabel={weightGapPct == null ? null : `${weightGapPct.toFixed(0)}% vs target`}
/>
</div>
@@ -834,7 +842,10 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
<h4 className="text-sm font-bold text-gray-800 mb-3 flex items-center gap-2">
<i className="fa-solid fa-triangle-exclamation text-amber-600" /> Masalah
</h4>
{renderBulletList(endCycleInsight.masalah, 'Tidak ada masalah kritis dari graded facts')}
{renderBulletList(
endCycleInsight.masalah,
'Tidak ada masalah kritis dari graded facts'
)}
</div>
<div className="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
@@ -842,7 +853,9 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
<i className="fa-solid fa-magnifying-glass-chart text-red-600" /> Akar penyebab
</h4>
{endCycleInsight.akar_penyebab.length === 0 ? (
<p className="text-sm text-gray-500">Belum ada kandidat akar penyebab berbukti.</p>
<p className="text-sm text-gray-500">
Belum ada kandidat akar penyebab berbukti.
</p>
) : (
<ul className="space-y-3">
{endCycleInsight.akar_penyebab.map((item, index) => (
@@ -901,9 +914,7 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
</p>
<p className="mt-1 text-sm text-gray-800">{item.aksi}</p>
{item.metrik_pantau ? (
<p className="mt-1 text-xs text-gray-500">
Pantau: {item.metrik_pantau}
</p>
<p className="mt-1 text-xs text-gray-500">Pantau: {item.metrik_pantau}</p>
) : null}
</li>
))}
@@ -929,11 +940,7 @@ export const AiInsightCard: React.FC<AiInsightCardProps> = ({
<i className="fa-solid fa-brain text-red-600" /> AI Insight
</h4>
<div className="text-sm text-gray-700 space-y-2 leading-relaxed">
{renderBulletList([
...summary.bullets,
...summary.risks,
...summary.actions,
])}
{renderBulletList([...summary.bullets, ...summary.risks, ...summary.actions])}
</div>
</div>
<CitationsBlock citations={citations} />