StatusTag.tsx
1 import React from 'react'; 2 import { Tag, Space } from 'antd'; 3 import { useTranslation } from 'react-i18next'; 4 import { 5 taskStatusMap, 6 jobStatusMap, 7 hostStatusMap, 8 riskLevelMap, 9 approvalStatusMap, 10 taskTypeMap, 11 softwareTypeMap, 12 reportStatusMap, 13 provisionStatusMap, 14 type StatusEntry, 15 type StatusEntryWithLabel, 16 } from '../utils/status'; 17 18 type StatusMapType = 19 | 'task' 20 | 'job' 21 | 'host' 22 | 'risk' 23 | 'approval' 24 | 'taskType' 25 | 'software' 26 | 'report' 27 | 'provision'; 28 29 const statusMaps: Record<StatusMapType, Record<string | number, StatusEntry | StatusEntryWithLabel>> = { 30 task: taskStatusMap, 31 job: jobStatusMap, 32 host: hostStatusMap, 33 risk: riskLevelMap, 34 approval: approvalStatusMap, 35 taskType: taskTypeMap, 36 software: softwareTypeMap, 37 report: reportStatusMap, 38 provision: provisionStatusMap, 39 }; 40 41 interface StatusTagProps { 42 type: StatusMapType; 43 value: string | number | undefined | null; 44 fallback?: string; 45 } 46 47 const StatusTag: React.FC<StatusTagProps> = ({ type, value, fallback = 'common.unknown' }) => { 48 const { t } = useTranslation(); 49 50 if (value === undefined || value === null) { 51 return <Tag>{t(fallback)}</Tag>; 52 } 53 54 const map = statusMaps[type]; 55 const entry = map[value]; 56 57 if (!entry) { 58 return <Tag>{String(value)}</Tag>; 59 } 60 61 const text = 'text' in entry ? t(entry.text) : 'label' in entry ? t(entry.label) : String(value); 62 const icon = 'icon' in entry ? (entry as StatusEntry).icon : undefined; 63 64 return ( 65 <Tag color={entry.color}> 66 {icon ? <Space size={4}>{icon}{text}</Space> : text} 67 </Tag> 68 ); 69 }; 70 71 export default StatusTag;