/ easyshell-web / src / components / StatusTag.tsx
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;