All checks were successful
Deploy to production / build (push) Successful in 19s
203 lines
5.6 KiB
TypeScript
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>
|
|
);
|
|
}
|