update ai insight card to include status

This commit is contained in:
Alberto-Audrix committed 2026-10-09 16:24:54 +07:00
1 parent 3e3eb88751
commit a9a2acb705
3 files changed
+416 -240

No files matched your search

+80 -6
View File
@@ -7,11 +7,85 @@ import React from 'react';
export type InsightStatus = 'ok' | 'warning' | 'critical' | 'unknown';
const STATUS_CHIP: Record<InsightStatus, { cls: string; glyph: string }> = {
ok: { cls: 'bg-green-50 text-green-800 border-green-200', glyph: '✓' },
warning: { cls: 'bg-amber-50 text-amber-800 border-amber-200', glyph: '!' },
critical: { cls: 'bg-red-50 text-red-800 border-red-200', glyph: '⚠' },
unknown: { cls: 'bg-gray-50 text-gray-500 border-gray-200', glyph: '–' },
export const INSIGHT_STATUS_META: Record<
InsightStatus,
{ cls: string; glyph: string; label: string; bg: string; text: string; containerCls: string }
> = {
ok: {
cls: 'bg-green-50 text-green-800 border-green-200',
glyph: '✓',
label: 'Normal',
bg: 'bg-green-50',
text: 'text-green-800',
containerCls: 'bg-green-50/40 border-green-200',
},
warning: {
cls: 'bg-amber-50 text-amber-800 border-amber-200',
glyph: '!',
label: 'Perhatian',
bg: 'bg-amber-50',
text: 'text-amber-800',
containerCls: 'bg-amber-50/40 border-amber-200',
},
critical: {
cls: 'bg-red-50 text-red-800 border-red-200',
glyph: '⚠',
label: 'Kritis',
bg: 'bg-red-50',
text: 'text-red-800',
containerCls: 'bg-red-50/40 border-red-200',
},
unknown: {
cls: 'bg-gray-50 text-gray-600 border-gray-200',
glyph: '–',
label: 'Belum Dinilai',
bg: 'bg-gray-50',
text: 'text-gray-600',
containerCls: 'bg-gray-50/60 border-gray-200',
},
};
export const normalizeInsightStatus = (status: unknown): InsightStatus => {
if (!status || typeof status !== 'string') return 'unknown';
const lower = status.toLowerCase();
if (lower === 'ok' || lower === 'healthy' || lower === 'normal' || lower === 'aman') return 'ok';
if (lower === 'warning' || lower === 'perhatian' || lower === 'waspada') return 'warning';
if (lower === 'critical' || lower === 'kritis' || lower === 'bahaya') return 'critical';
return 'unknown';
};
export interface InsightStatusBadgeProps {
status: InsightStatus | string;
customLabel?: string;
className?: string;
size?: 'xs' | 'sm' | 'md';
}
export const InsightStatusBadge: React.FC<InsightStatusBadgeProps> = ({
status,
customLabel,
className = '',
size = 'sm',
}) => {
const norm = normalizeInsightStatus(status);
const meta = INSIGHT_STATUS_META[norm];
const sizeClasses =
size === 'xs'
? 'px-2 py-0.5 text-[10px]'
: size === 'md'
? 'px-3 py-1 text-xs'
: 'px-2.5 py-0.5 text-[11px]';
return (
<span
className={`inline-flex items-center gap-1.5 rounded-full border font-semibold tracking-wide ${meta.cls} ${sizeClasses} ${className}`}
>
<span aria-hidden="true" className="font-bold">
{meta.glyph}
</span>
<span>{customLabel || meta.label}</span>
</span>
);
};
interface DeltaChipProps {
@@ -20,7 +94,7 @@ interface DeltaChipProps {
}
export const DeltaChip: React.FC<DeltaChipProps> = ({ status, label }) => {
const chip = STATUS_CHIP[status];
const chip = INSIGHT_STATUS_META[status] ?? INSIGHT_STATUS_META.unknown;
return (
<span
className={`inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[11px] font-semibold ${chip.cls}`}