167 lines
4.6 KiB
TypeScript
167 lines
4.6 KiB
TypeScript
import IconFont from '@/components/IconFont';
|
|
import { StatisticCard } from '@ant-design/pro-components';
|
|
import {
|
|
Divider,
|
|
Flex,
|
|
GlobalToken,
|
|
Grid,
|
|
theme,
|
|
Tooltip,
|
|
Typography,
|
|
} from 'antd';
|
|
const { Text } = Typography;
|
|
type BinarySensorsProps = {
|
|
nodeConfigs: MasterModel.NodeConfig[];
|
|
};
|
|
|
|
export const getBinaryEntities = (
|
|
nodeConfigs: MasterModel.NodeConfig[] = [],
|
|
): MasterModel.Entity[] =>
|
|
nodeConfigs.flatMap((nodeConfig) =>
|
|
nodeConfig.type === 'din'
|
|
? nodeConfig.entities.filter(
|
|
(entity) => entity.type === 'bin' && entity.active === 1,
|
|
)
|
|
: [],
|
|
);
|
|
interface IconTypeResult {
|
|
iconType: string;
|
|
color: string;
|
|
name?: string;
|
|
}
|
|
|
|
const getIconTypeByEntity = (
|
|
entity: MasterModel.Entity,
|
|
token: GlobalToken,
|
|
): IconTypeResult => {
|
|
if (!entity.config || entity.config.length === 0) {
|
|
return {
|
|
iconType: 'icon-not-found',
|
|
color: token.colorPrimary,
|
|
};
|
|
}
|
|
switch (entity.config[0].subType) {
|
|
case 'smoke':
|
|
return {
|
|
iconType: 'icon-smoke1',
|
|
color: entity.value === 0 ? token.colorSuccess : token.colorWarning,
|
|
name: entity.value === 0 ? 'Bình thường' : 'Phát hiện',
|
|
};
|
|
case 'heat':
|
|
return {
|
|
iconType: 'icon-fire',
|
|
color: entity.value === 0 ? token.colorSuccess : token.colorWarning,
|
|
name: entity.value === 0 ? 'Bình thường' : 'Phát hiện',
|
|
};
|
|
case 'motion':
|
|
return {
|
|
iconType: 'icon-motion',
|
|
color: entity.value === 0 ? token.colorTextBase : token.colorInfoActive,
|
|
name: entity.value === 0 ? 'Không' : 'Phát hiện',
|
|
};
|
|
case 'flood':
|
|
return {
|
|
iconType: 'icon-water-ingress',
|
|
color: entity.value === 0 ? token.colorSuccess : token.colorWarning,
|
|
name: entity.value === 0 ? 'Không' : 'Phát hiện',
|
|
};
|
|
case 'door':
|
|
return {
|
|
iconType: entity.value === 0 ? 'icon-door' : 'icon-door-open1',
|
|
color: entity.value === 0 ? token.colorText : token.colorWarning,
|
|
name: entity.value === 0 ? 'Đóng' : 'Mở',
|
|
};
|
|
case 'button':
|
|
return {
|
|
iconType: 'icon-alarm-button',
|
|
color: entity.value === 0 ? token.colorText : token.colorSuccess,
|
|
name: entity.value === 0 ? 'Tắt' : 'Bật',
|
|
};
|
|
default:
|
|
return {
|
|
iconType: 'icon-not-found',
|
|
color: token.colorPrimary,
|
|
};
|
|
}
|
|
};
|
|
|
|
const StatisticCardItem = (entity: MasterModel.Entity, token: GlobalToken) => {
|
|
const { iconType, color, name } = getIconTypeByEntity(entity, token);
|
|
return (
|
|
<StatisticCard
|
|
bordered={false}
|
|
key={entity.entityId}
|
|
style={{
|
|
borderRadius: 8,
|
|
background: token.colorBgContainer,
|
|
border: `1px solid ${token.colorBorder}`,
|
|
transition: 'all 0.3s ease',
|
|
}}
|
|
onMouseEnter={(e) => {
|
|
const el = e.currentTarget as HTMLElement;
|
|
el.style.boxShadow = `0 4px 12px ${token.colorPrimary}20`;
|
|
el.style.transform = 'translateY(-2px)';
|
|
}}
|
|
onMouseLeave={(e) => {
|
|
const el = e.currentTarget as HTMLElement;
|
|
el.style.boxShadow = 'none';
|
|
el.style.transform = 'translateY(0)';
|
|
}}
|
|
statistic={{
|
|
icon: (
|
|
<Tooltip title={entity.name}>
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
height: 56,
|
|
marginBottom: 8,
|
|
}}
|
|
>
|
|
<IconFont type={iconType} style={{ color, fontSize: 32 }} />
|
|
</div>
|
|
</Tooltip>
|
|
),
|
|
title: (
|
|
<Text
|
|
ellipsis={{ tooltip: entity.name }}
|
|
style={{ fontSize: 13, fontWeight: 500 }}
|
|
>
|
|
{entity.name}
|
|
</Text>
|
|
),
|
|
value: name,
|
|
valueStyle: { fontSize: 12, color, fontWeight: 600, marginTop: 8 },
|
|
}}
|
|
/>
|
|
);
|
|
};
|
|
|
|
const BinarySensors = ({ nodeConfigs }: BinarySensorsProps) => {
|
|
const binarySensors = getBinaryEntities(nodeConfigs);
|
|
console.log('BinarySensor: ', binarySensors);
|
|
|
|
const { token } = theme.useToken();
|
|
const { useBreakpoint } = Grid;
|
|
const screens = useBreakpoint();
|
|
|
|
return (
|
|
<Flex wrap="wrap" gap="middle">
|
|
<Divider orientation="left">Cảm biến</Divider>
|
|
{binarySensors.map((entity) => (
|
|
<div
|
|
key={entity.entityId}
|
|
style={{
|
|
width: 'fit-content',
|
|
}}
|
|
>
|
|
{StatisticCardItem(entity, token)}
|
|
</div>
|
|
))}
|
|
</Flex>
|
|
);
|
|
};
|
|
|
|
export default BinarySensors;
|