Files
TriggerFrontend/src/components/WeatherModal/WeatherGraphs.tsx
Sean Edmunds ffd241dad8
All checks were successful
Deploy to production / build (push) Successful in 19s
Minor updates to styles and package updates
2026-10-15 13:58:35 -05:00

203 lines
5.6 KiB
TypeScript

import { Group, Select, Stack } from '@mantine/core';
import { useState } from 'react';
import {
Area,
AreaChart,
CartesianGrid,
ComposedChart,
Legend,
Line,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis,
} from 'recharts';
import { selectClasses } from 'styles';
import WeatherTooltip from './WeatherTooltip';
export default function WeatherGraphs({
hourly,
formatted,
}: {
hourly: any;
formatted?: boolean;
}) {
const colorPrecipitation = 'colorPrecipitation';
const colorHumidity = 'colorHumidity';
const [timeFrame, setTimeFrame] = useState(24);
const later = new Date();
const now = new Date();
later.setTime(now.getTime() + timeFrame * 60 * 60 * 1000);
const hourlyForecast = formatted
? hourly
: hourly?.time
?.map((_: any, index: number) => {
return {
dewpoint: hourly.dew_point_2m?.[index].toFixed(0),
isDaytime: hourly.is_day?.[index],
name: hourly.time[index].toLocaleString('en-us'),
startTime: hourly.time[index],
endTime: hourly.time[index + 1],
probabilityOfPrecipitation: hourly.precipitation_probability?.[index],
temperature: hourly.temperature_2m?.[index].toFixed(0),
apparentTemperature: hourly.apparent_temperature?.[index].toFixed(0),
relativeHumidity: hourly.relative_humidity_2m?.[index].toFixed(0),
};
})
.filter((hour: any) => hour.startTime > now && hour.startTime < later);
return (
<Stack
w={'100%'}
style={{
background: 'var(--mantine-color-search-0)',
padding: '.5rem',
borderRadius: '8px',
position: 'relative',
marginTop: '.5rem',
}}
>
{!formatted && (
<Group m={0} p={0} mt={'-1.5rem'}>
<Select
classNames={{
input: selectClasses.menuSelectInput,
label: selectClasses.menuSelectLabel,
options: selectClasses.menuSelectOptions,
option: selectClasses.menuSelectOption,
dropdown: selectClasses.dropdown,
}}
className={selectClasses.menuSelect}
defaultValue={24}
value={timeFrame}
data={[
{ value: 12, label: '12 hours' },
{ value: 24, label: '24 hours' },
{ value: 48, label: '2 days' },
{ value: 72, label: '3 days' },
{ value: 168, label: '7 days' },
]}
onChange={(value: any) => setTimeFrame(value)}
/>
</Group>
)}
<ResponsiveContainer width={'100%'} height={150}>
<ComposedChart data={hourlyForecast} responsive>
<XAxis
type='category'
stroke={'var(--mantine-color-primary-0)'}
dataKey={(data) => {
return new Date(data.startTime).toLocaleString('en-US');
}}
/>
<YAxis
stroke={'var(--mantine-color-primary-0)'}
unit={'°F'}
domain={([dataMin, dataMax]) => {
return [dataMin - 5, dataMax + 5];
}}
/>
<CartesianGrid stroke='#f5f5f522' />
<Tooltip wrapperStyle={{ zIndex: 100 }} content={<WeatherTooltip />} />
<Line
unit={'°F'}
type='monotone'
name='Temperature'
dataKey='temperature'
stroke={'var(--mantine-color-primary-0)'}
strokeWidth={2}
dot={{
stroke: 'var(--mantine-color-primary-0)',
strokeWidth: 0,
fill: 'var(--mantine-color-primary-0)',
}}
/>
<Line
unit={'°F'}
type='monotone'
name='Feels Like'
dataKey='apparentTemperature'
stroke={'var(--mantine-color-accent-0)'}
strokeWidth={2}
dot={{
stroke: 'var(--mantine-color-accent-0)',
strokeWidth: 0,
fill: 'var(--mantine-color-accent-0)',
}}
/>
<Legend wrapperStyle={{ zIndex: 0, position: 'absolute' }} />
</ComposedChart>
</ResponsiveContainer>
<ResponsiveContainer width={'100%'} height={150}>
<AreaChart data={hourlyForecast} responsive>
<defs>
<linearGradient id={colorPrecipitation} x1='0' y1='0' x2='0' y2='1'>
<stop
offset='40%'
stopColor='var(--mantine-color-primary-0)'
stopOpacity={1}
/>
<stop
offset='100%'
stopColor='var(--mantine-color-primary-0)'
stopOpacity={0}
/>
</linearGradient>
<linearGradient id={colorHumidity} x1='0' y1='0' x2='0' y2='1'>
<stop
offset='20%'
stopColor='var(--mantine-color-accent-0)'
stopOpacity={1}
/>
<stop
offset='80%'
stopColor='var(--mantine-color-accent-0)'
stopOpacity={0}
/>
</linearGradient>
</defs>
<XAxis
type='category'
stroke={'var(--mantine-color-primary-0)'}
dataKey={(data) => {
return new Date(data.startTime).toLocaleString('en-US');
}}
/>
<YAxis stroke={'var(--mantine-color-primary-0)'} unit={'%'} domain={[0, 100]} />
<CartesianGrid stroke='#f5f5f522' />
<Tooltip wrapperStyle={{ zIndex: 100 }} content={<WeatherTooltip />} />
<Area
unit={'%'}
type='monotone'
name='Humidity'
dataKey={'relativeHumidity'}
stroke={'var(--mantine-color-primary-0)'}
strokeWidth={2}
fill={`url(#${colorPrecipitation})`}
dot={{
stroke: 'var(--mantine-color-primary-0)',
strokeWidth: 0,
fill: 'var(--mantine-color-primary-0)',
}}
/>
<Area
unit={'%'}
type='monotone'
name='Precipitation'
dataKey={'probabilityOfPrecipitation'}
stroke={'var(--mantine-color-accent-0)'}
strokeWidth={2}
fill={`url(#${colorHumidity})`}
dot={{
stroke: 'var(--mantine-color-accent-0)',
strokeWidth: 0,
fill: 'var(--mantine-color-accent-0)',
}}
/>
<Legend wrapperStyle={{ zIndex: 0, position: 'absolute' }} />
</AreaChart>
</ResponsiveContainer>
</Stack>
);
}