Update VAA 7 day updated to change looks

This commit is contained in:
2026-06-30 13:23:05 -07:00
parent 345152b548
commit 95dbd26ca8
2 changed files with 87 additions and 23 deletions
@@ -4,34 +4,109 @@ import Plot from 'react-plotly.js';
import VdapApi from '../../hooks/useVdapApi.js'; // Adjust path as needed import VdapApi from '../../hooks/useVdapApi.js'; // Adjust path as needed
export default function VaaActivity7Day() { export default function VaaActivity7Day() {
// ONE LINE to handle all fetching, loading, and error states! // Clean, single-line data fetching
const { data: apiData, isLoading, error } = VdapApi('/api/v2/comm_coor_vaa'); const { data: apiData, isLoading, error } = VdapApi('/api/v2/comm_coor_vaa');
// 1. Build the Traces (Data parsing)
const plotTraces = useMemo(() => { const plotTraces = useMemo(() => {
if (!apiData || apiData.length === 0) return []; if (!apiData || apiData.length === 0) return [];
const groupedData = apiData.reduce((acc, curr) => { // Array of distinct Plotly shapes
const Symbolway = [
'circle', 'square', 'diamond',
'triangle-up', 'triangle-down',
'star', 'hexagram', 'pentagon',
'hexagon', 'octagon', 'cross', 'x'
];
// Sort data descending by flight level (matching Observable behavior)
const sortedData = [...apiData].sort((a, b) => b.obs_fl - a.obs_fl);
// Efficiently group into Plotly traces by volcano
const groupedData = sortedData.reduce((acc, curr) => {
const name = curr.volc_name || 'Unknown'; const name = curr.volc_name || 'Unknown';
if (!acc[name]) acc[name] = { x: [], y: [], text: [] }; if (!acc[name]) acc[name] = { x: [], y: [] };
acc[name].x.push(new Date(curr.obs_va_epoch)); acc[name].x.push(new Date(curr.obs_va_epoch));
acc[name].y.push(curr.obs_fl); acc[name].y.push(curr.obs_fl);
acc[name].text.push(`Volcano: ${name}<br>Flight Level: ${curr.obs_fl}`);
return acc; return acc;
}, {}); }, {});
return Object.keys(groupedData).map((volcanoName) => ({ return Object.keys(groupedData).map((volcanoName, index) => ({
name: volcanoName, name: volcanoName,
x: groupedData[volcanoName].x, x: groupedData[volcanoName].x,
y: groupedData[volcanoName].y, y: groupedData[volcanoName].y,
text: groupedData[volcanoName].text,
type: 'scatter', type: 'scatter',
mode: 'markers', mode: 'markers',
hoverinfo: 'text', marker: {
marker: { size: 8, line: { width: 1, color: 'white' } } size: 7,
line: { width: .5, color: 'rgba(255, 255, 255, 0.7)' },
symbol: Symbolway[index % Symbolway.length],
},
// Replicating the clean Observable tooltip
hovertemplate:
`<b>${volcanoName}</b><br>` +
'Date: %{x|%b %d %Y %H:%M}<br>' +
'Flight Level: %{y}<extra></extra>'
})); }));
}, [apiData]); }, [apiData]);
// 2. Build the Layout (Styling and Grid)
const layout = useMemo(() => {
return {
autosize: true,
paper_bgcolor: 'transparent', // Let Chakra UI background show through
plot_bgcolor: 'transparent',
font: { color: '#d1d5db' }, // gray.300
// margin: { t: 40, r: 20, l: 30, b: 60 }, // Extra bottom margin for legend
title: {
text: '7 Day Consolidated Flight Levels',
font: { size: 16, color: 'white' },
x: 0.05
},
xaxis: {
title: {
text: 'Date (UTC)',
font: { color: 'white', size: 12 }
},
type: 'date',
tickformat: '%b %d<br>%Y %H:%M', // Multiline ticks from Observable
gridcolor: '#4b5563',
zerolinecolor: '#4b5563',
automargin: true,
},
yaxis: {
title: {
text: 'Flight Level',
font: { color: 'white', size: 12 }
},
gridcolor: '#4b5563',
zerolinecolor: '#ffffff',
automargin: true,
},
// legend: {
// orientation: 'h',
// y: -0.2,
// x: 0.5,
// xanchor: 'center'
// },
hovermode: 'closest',
shapes: [
{
type: 'line',
x0: 0,
x1: 1,
xref: 'paper', // Spans entire chart width
y0: 0,
y1: 0,
yref: 'y',
line: { color: 'white', width: 1 }
}
],
};
}, [apiData]);
if (isLoading) return ( if (isLoading) return (
<Flex w="100%" h="100%" bg="gray.800" borderRadius="md" align="center" justify="center"> <Flex w="100%" h="100%" bg="gray.800" borderRadius="md" align="center" justify="center">
<Spinner size="xl" color="blue.400" thickness="4px" /> <Spinner size="xl" color="blue.400" thickness="4px" />
@@ -51,23 +126,12 @@ export default function VaaActivity7Day() {
); );
return ( return (
<Box height="100%" width="100%" bg="gray.800" borderRadius="md" overflow="hidden"> <Box height="100%" width="100%" bg="gray.800" borderRadius="md" p={2} overflow="hidden">
<Plot <Plot
data={plotTraces} data={plotTraces}
useResizeHandler={true} layout={layout}
useResizeHandler={true} // Essential for dashboard grid resizing!
style={{ width: '100%', height: '100%' }} style={{ width: '100%', height: '100%' }}
layout={{
autosize: true,
paper_bgcolor: 'transparent',
plot_bgcolor: 'transparent',
font: { color: '#d1d5db' },
margin: { t: 40, r: 20, l: 50, b: 40 },
title: { text: '7 Day Consolidated Flight Levels', font: { size: 16, color: 'white' }, x: 0.05 },
xaxis: { title: 'Date (UTC)', type: 'date', gridcolor: '#4b5563', zerolinecolor: '#4b5563' },
yaxis: { title: 'Flight Level', gridcolor: '#4b5563', zerolinecolor: '#ffffff' },
legend: { orientation: 'h', y: -0.2, x: 0.5, xanchor: 'center' },
hovermode: 'closest'
}}
config={{ responsive: true, displayModeBar: true, displaylogo: false }} config={{ responsive: true, displayModeBar: true, displaylogo: false }}
/> />
</Box> </Box>
@@ -9,7 +9,7 @@ export default {
decorators: [ decorators: [
(Story) => ( (Story) => (
<Box <Box
w="100%" maxW="800px" h="400px" w="100%" maxW="1800px" h="400px"
border="2px dashed" borderColor="gray.600" p={2} border="2px dashed" borderColor="gray.600" p={2}
resize="both" overflow="auto" resize="both" overflow="auto"
> >