update ai insight card to include status
This commit is contained in:
1 parent
3e3eb88751
commit
a9a2acb705
3 files changed
+416
-240
No files matched your search
@@ -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}`}
|
||||
|
||||
Reference in new issue
Block a user