import React, { useState, useEffect, useMemo } from 'react';
|
import { useTranslate } from "react-admin";
|
import {
|
Box,
|
Tabs,
|
Tab,
|
Divider,
|
List,
|
ListItemButton,
|
ListItemText,
|
Typography,
|
Stack,
|
} from '@mui/material';
|
import JsonShow from '../../JsonShow';
|
import { fetchAreaList } from '../../http';
|
|
const AreaInsight = ({ curZone, setTitle }) => {
|
const translate = useTranslate();
|
const [areas, setAreas] = useState([]);
|
const [selectedId, setSelectedId] = useState(null);
|
const [activeTab, setActiveTab] = useState(0);
|
const formatCoord = (value) => {
|
if (value === null || value === undefined) {
|
return '-';
|
}
|
if (typeof value === 'number') {
|
return value.toFixed(2);
|
}
|
const num = Number(value);
|
if (!Number.isNaN(num)) {
|
return num.toFixed(2);
|
}
|
return String(value);
|
};
|
|
useEffect(() => {
|
let mounted = true;
|
if (!curZone) {
|
setAreas([]);
|
setSelectedId(null);
|
return;
|
}
|
fetchAreaList(curZone).then((list) => {
|
if (!mounted) {
|
return;
|
}
|
const nextList = Array.isArray(list) ? list : [];
|
setAreas(nextList);
|
setSelectedId((prev) => {
|
if (prev) {
|
const exists = nextList.some((item) => item?.id === prev);
|
if (exists) {
|
return prev;
|
}
|
}
|
return nextList[0]?.id ?? null;
|
});
|
});
|
return () => {
|
mounted = false;
|
};
|
}, [curZone]);
|
|
const selectedArea = useMemo(
|
() => areas.find((area) => area?.id === selectedId) || null,
|
[areas, selectedId]
|
);
|
|
useEffect(() => {
|
if (setTitle) {
|
const label = selectedArea
|
? `${translate('page.map.devices.area')} - ${selectedArea.name || selectedArea.id}`
|
: translate('page.map.devices.area');
|
setTitle(label);
|
}
|
}, [selectedArea, setTitle, translate]);
|
|
useEffect(() => {
|
return () => {
|
if (setTitle) {
|
setTitle(null);
|
}
|
};
|
}, [setTitle]);
|
|
const handleTabChange = (_event, newValue) => {
|
setActiveTab(newValue);
|
};
|
|
const detailPairs = [
|
{ label: translate('page.map.area.form.name'), value: selectedArea?.name },
|
{ label: translate('page.map.area.form.code'), value: selectedArea?.code },
|
{ label: translate('page.map.area.form.maxQty'), value: selectedArea?.maxCount },
|
{ label: translate('page.map.area.form.speedLimit'), value: selectedArea?.speedLimit },
|
{ label: translate('page.map.area.form.priority'), value: selectedArea?.priority },
|
];
|
|
return (
|
<Box sx={{ height: '100%', display: 'flex', gap: 2 }}>
|
<Box width={220} sx={{ borderRight: 1, borderColor: 'divider', overflowY: 'auto' }}>
|
<List dense disablePadding>
|
{areas.map((area) => (
|
<ListItemButton
|
key={area.id}
|
selected={area.id === selectedId}
|
onClick={() => setSelectedId(area.id)}
|
>
|
<ListItemText
|
primary={area.name || `#${area.id}`}
|
secondary={area.code}
|
/>
|
</ListItemButton>
|
))}
|
{areas.length === 0 && (
|
<Typography variant="body2" color="text.secondary" p={2}>
|
{translate('page.map.area.form.codesEmpty')}
|
</Typography>
|
)}
|
</List>
|
</Box>
|
|
<Box sx={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
|
<Tabs
|
value={activeTab}
|
onChange={handleTabChange}
|
sx={{ mb: 0 }}
|
>
|
<Tab label={translate('page.map.insight.title')} />
|
<Tab label="JSON" />
|
</Tabs>
|
|
<Divider />
|
|
<Box flex={1} pt={2}>
|
{activeTab === 0 && (
|
<Stack spacing={1}>
|
{detailPairs.map(({ label, value }) => (
|
<Stack key={label} direction="row" spacing={1}>
|
<Typography variant="body2" color="text.secondary" minWidth={120}>
|
{label}:
|
</Typography>
|
<Typography variant="body2">
|
{value != null && value !== '' ? value : '-'}
|
</Typography>
|
</Stack>
|
))}
|
{selectedArea?.start && selectedArea?.end && (
|
<>
|
<Typography variant="body2" color="text.secondary">
|
{translate('page.map.area.form.startX')}/{translate('page.map.area.form.startY')}:
|
</Typography>
|
<Typography variant="body2">
|
{`${formatCoord(selectedArea.start.x)} , ${formatCoord(selectedArea.start.y)}`}
|
</Typography>
|
<Typography variant="body2" color="text.secondary">
|
{translate('page.map.area.form.endX')}/{translate('page.map.area.form.endY')}:
|
</Typography>
|
<Typography variant="body2">
|
{`${formatCoord(selectedArea.end.x)} , ${formatCoord(selectedArea.end.y)}`}
|
</Typography>
|
</>
|
)}
|
{(selectedArea?.codeList?.length ?? 0) > 0 && (
|
<Typography variant="body2">
|
{translate('page.map.area.form.codes', { count: selectedArea.codeList.length })}
|
</Typography>
|
)}
|
</Stack>
|
)}
|
{activeTab === 1 && (
|
<JsonShow
|
data={selectedArea || {}}
|
height={550}
|
/>
|
)}
|
</Box>
|
</Box>
|
</Box>
|
);
|
};
|
|
export default AreaInsight;
|