Files
AyposWeb/src/pages/Maintenance.tsx

274 lines
9.2 KiB
TypeScript

import { useState, useEffect } from 'react';
import { Box, Paper, Typography, Fade, useTheme, AppBar, Toolbar, Chip } from '@mui/material';
import { LineChart } from '@mui/x-charts/LineChart';
import { config } from '../config/env';
interface DataItem {
now_timestamp: string;
future_timestamp: string;
power: string;
power_future_min: string;
positive_3p: string;
negative_3p: string;
positive_7p: string;
negative_7p: string;
flag: string;
}
const API_BASE_URL = config.apiUrl;
const Maintenance = () => {
const theme = useTheme();
const [data, setData] = useState<DataItem[]>([]);
const [currentFlag, setCurrentFlag] = useState<string>('');
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(`${API_BASE_URL}/prom/get_chart_data/maintenance/20`);
const result = await response.json();
if (result.data && result.data.length > 0) {
const last20Data = result.data.slice(-20);
setCurrentFlag(last20Data[last20Data.length - 1].flag);
setData(last20Data);
console.log('Fetched data:', last20Data);
}
} catch (error) {
console.error('Error fetching data:', error);
} finally {
setLoading(false);
}
};
fetchData();
const interval = setInterval(fetchData, 5000);
return () => clearInterval(interval);
}, []);
// Process data for charts
const prepareChartData = () => {
if (!data || data.length === 0) {
console.log('No data available, using fallback data');
// Fallback data for testing
const now = new Date();
const fallbackData = Array.from({ length: 10 }, (_, i) => ({
currentTimestamp: new Date(now.getTime() - (9 - i) * 60000), // 1 minute intervals
futureTimestamp: new Date(now.getTime() - (9 - i) * 60000 + 3 * 60000), // 3 minutes in the future
currentPower: 95 + Math.random() * 10,
predictedPower: 115 + Math.random() * 10,
positive3p: 118 + Math.random() * 5,
negative3p: 112 + Math.random() * 5,
positive7p: 123 + Math.random() * 5,
negative7p: 107 + Math.random() * 5,
}));
return fallbackData;
}
const processedData = data.map(item => {
const currentPower = parseFloat(item.power) || 0;
const predictedPower = parseFloat(item.power_future_min) || currentPower * 1.1; // Fallback to 10% higher than current
return {
currentTimestamp: new Date(item.now_timestamp),
futureTimestamp: new Date(item.future_timestamp),
currentPower: currentPower,
predictedPower: predictedPower,
positive3p: parseFloat(item.positive_3p) || predictedPower * 1.03,
negative3p: parseFloat(item.negative_3p) || predictedPower * 0.97,
positive7p: parseFloat(item.positive_7p) || predictedPower * 1.07,
negative7p: parseFloat(item.negative_7p) || predictedPower * 0.93,
};
});
console.log('Processed chart data:', processedData);
console.log('Data validation:', {
hasCurrentPower: processedData.some(d => d.currentPower > 0),
hasPredictedPower: processedData.some(d => d.predictedPower > 0),
currentPowerRange: [Math.min(...processedData.map(d => d.currentPower)), Math.max(...processedData.map(d => d.currentPower))],
predictedPowerRange: [Math.min(...processedData.map(d => d.predictedPower)), Math.max(...processedData.map(d => d.predictedPower))],
rawDataSample: data.slice(0, 2).map(item => ({
power: item.power,
power_future_min: item.power_future_min,
parsedCurrent: parseFloat(item.power),
parsedPredicted: parseFloat(item.power_future_min)
}))
});
return processedData;
};
const chartData = prepareChartData();
// Extract data arrays for charts
const currentTimestamps = chartData.map(item => item.currentTimestamp);
const futureTimestamps = chartData.map(item => item.futureTimestamp);
const currentPowerData = chartData.map(item => item.currentPower);
const predictedPowerData = chartData.map(item => item.predictedPower);
const positive3pData = chartData.map(item => item.positive3p);
const negative3pData = chartData.map(item => item.negative3p);
const positive7pData = chartData.map(item => item.positive7p);
const negative7pData = chartData.map(item => item.negative7p);
// Debug logging
console.log('Chart arrays:', {
currentTimestamps: currentTimestamps.length,
futureTimestamps: futureTimestamps.length,
currentPower: currentPowerData.length,
predictedPower: predictedPowerData.length,
positive3p: positive3pData.length,
negative3p: negative3pData.length,
positive7p: positive7pData.length,
negative7p: negative7pData.length,
});
console.log('Sample timestamps:', {
current: currentTimestamps.slice(0, 3),
future: futureTimestamps.slice(0, 3),
currentPower: currentPowerData.slice(0, 3),
predictedPower: predictedPowerData.slice(0, 3),
});
return (
<Box sx={{ flexGrow: 1, bgcolor: theme.palette.background.default }}>
<AppBar
position="static"
elevation={0}
sx={{
bgcolor: 'background.paper',
borderBottom: `1px solid ${theme.palette.divider}`,
mb: 3
}}
>
<Toolbar sx={{ px: { xs: 2, sm: 4 } }}>
<Typography
variant="h5"
component="h1"
sx={{
color: 'text.primary',
fontWeight: 500,
flex: 1,
textAlign: 'center',
letterSpacing: '-0.5px'
}}
>
Preventive Maintenance
</Typography>
{currentFlag && (
<Chip
label={currentFlag}
color={currentFlag === 'Correct Estimation for PM energy' ? 'success' : 'warning'}
size="medium"
sx={{
height: 32,
'& .MuiChip-label': {
px: 2,
fontSize: '0.875rem',
fontWeight: 600
},
animation: 'pulse 2s infinite',
'@keyframes pulse': {
'0%': {
boxShadow: '0 0 0 0 rgba(0, 0, 0, 0.2)',
},
'70%': {
boxShadow: '0 0 0 6px rgba(0, 0, 0, 0)',
},
'100%': {
boxShadow: '0 0 0 0 rgba(0, 0, 0, 0)',
},
}
}}
/>
)}
</Toolbar>
</AppBar>
<Box sx={{ p: { xs: 2, sm: 4 } }}>
<Fade in timeout={800}>
<Paper
elevation={0}
sx={{
p: { xs: 2, sm: 3 },
bgcolor: 'background.paper',
borderRadius: 2,
border: `1px solid ${theme.palette.divider}`,
}}
>
<Box sx={{ height: 'calc(100vh - 200px)', minHeight: '500px' }}>
<LineChart
height={500}
skipAnimation={false}
series={[
{
data: currentPowerData,
label: 'Current Power',
color: '#028a4a', // B'GREEN brand color
showMark: true,
curve: 'linear'
},
{
data: predictedPowerData,
label: 'Predicted (3min)',
color: '#ff9800',
showMark: true,
curve: 'linear'
},
{
data: positive3pData,
label: '+3% Positive',
color: '#2ca02c',
showMark: false
},
{
data: negative3pData,
label: '-3% Negative',
color: '#d62728',
showMark: false
},
{
data: positive7pData,
label: '+7% Positive',
color: '#9467bd',
showMark: false
},
{
data: negative7pData,
label: '-7% Negative',
color: '#8c564b',
showMark: false
},
]}
xAxis={[
{
scaleType: 'time',
data: [...currentTimestamps, ...futureTimestamps],
valueFormatter: (value: Date) => value.toLocaleTimeString(),
},
]}
yAxis={[
{
width: 50,
valueFormatter: (value: number) => `${value} W`,
}
]}
margin={{ right: 24 }}
slotProps={{
legend: {
direction: 'horizontal',
position: { vertical: 'top', horizontal: 'center' },
},
}}
/>
</Box>
</Paper>
</Fade>
</Box>
</Box>
);
};
export default Maintenance;