import type { OnChangeFn, PaginationState } from "@edr/ui-common"; import { Stack, Group, Text, Card, SimpleGrid, Skeleton } from "@mantine/core"; import type { RuleEngineResourceConfig } from "@/pages/ruleEngine/config/resources"; import type { RuleEngineRecord } from "@/types/rule-engine"; import RuleEngineListFooter from "./RuleEngineListFooter"; import RuleEngineRecordActions from "./RuleEngineRecordActions"; import { cardInitials, resolveCardPresentation } from "./ruleEngineCardMeta"; import { formatCell } from "./ruleEngineFormat"; export interface RuleEngineCardGridProps { config: RuleEngineResourceConfig; rows: RuleEngineRecord[]; status: "loading" | "error" | "success"; emptyMessage: string; itemLabel: string; pagination: PaginationState; pageCount: number; totalCount: number; onPaginationChange: OnChangeFn; onEdit?: (record: RuleEngineRecord) => void; onDelete?: (record: RuleEngineRecord) => void; readOnly?: boolean; onViewChain?: () => void; onSubmitRate?: (id: string) => void; onApproveRate?: (record: RuleEngineRecord) => void; } const extractLabel = (value: unknown): string => { if (!value || typeof value !== "object") { return String(value || ""); } const obj = value as Record; return ( (typeof obj.label === "string" ? obj.label : null) || (typeof obj.cargoTypeName === "string" ? obj.cargoTypeName : null) || (typeof obj.serviceName === "string" ? obj.serviceName : null) || (typeof obj.code === "string" ? obj.code : null) || (typeof obj.name === "string" ? obj.name : null) || (typeof obj.actionLabel === "string" ? obj.actionLabel : null) || String(value) ); }; const getSmartValue = (record: RuleEngineRecord, key: string): unknown => { const value = record[key as keyof RuleEngineRecord]; // If the value is already an object, use it directly if (value && typeof value === "object") { return value; } // If the key ends with "Id" and there's a corresponding non-Id key, use that if (typeof key === "string" && key.endsWith("Id")) { const relatedKey = key.slice(0, -2); // Remove "Id" suffix const relatedValue = record[relatedKey as keyof RuleEngineRecord]; if (relatedValue && typeof relatedValue === "object") { return relatedValue; } } return value; }; const RuleEngineCardGrid = ({ config, rows, status, emptyMessage, itemLabel, pagination, pageCount, totalCount, onPaginationChange, onEdit, onDelete, onViewChain, onSubmitRate, onApproveRate, readOnly = false, }: RuleEngineCardGridProps) => { const presentation = resolveCardPresentation(config); if (status === "error") { return ( Failed to load data Please refresh the page or try again later. ); } if (status === "loading") { return ( {Array.from({ length: 6 }).map((_, index) => ( ))} ); } if (status === "success" && rows.length === 0) { return ( {emptyMessage} Try adjusting your search or add a new record. ); } const avatarBg = "var(--mantine-color-gray-1)"; const avatarText = "var(--mantine-color-gray-7)"; return ( {rows.map((record) => { const titleValue = getSmartValue(record, presentation.titleKey); const title = extractLabel(titleValue); const subtitleValue = presentation.subtitleKey ? getSmartValue(record, presentation.subtitleKey) : null; const subtitle = subtitleValue ? extractLabel(subtitleValue) : ""; const codeValue = presentation.codeKey ? getSmartValue(record, presentation.codeKey) : null; const code = codeValue ? extractLabel(codeValue) : ""; const statusValue = presentation.statusKey ? record[presentation.statusKey] : undefined; return (
{cardInitials(title)}
{title} {code && ( {code} )}
{presentation.statusKey && (
{formatCell(statusValue, "activeBadge")}
)}
{(subtitle || presentation.detailColumns.length > 0) && ( {subtitle && ( {presentation.subtitleKey === "stepOrder" ? "Step" : "Type"} : {subtitle} )} {presentation.detailColumns.map((col) => { const displayValue = getSmartValue(record, col.accessorKey); return ( {col.header}:
{formatCell(displayValue, col.format)}
); })}
)} { })} onDelete={onDelete ?? (() => { })} onViewChain={onViewChain} onSubmitRate={onSubmitRate} onApproveRate={onApproveRate} />
); })}
); }; export default RuleEngineCardGrid;