Files
TriggerFrontend/src/components/WeatherModal/CurrentWeather.tsx
Sean Edmunds 3d5a2dd88a
All checks were successful
Deploy to production / build (push) Successful in 11s
New Weather API
2026-07-13 14:30:56 -05:00

322 lines
8.2 KiB
TypeScript

import { Box, Card, Group, Stack, Text } from '@mantine/core';
import { useCommonHooks } from 'hooks';
import { FaLongArrowAltDown, FaLongArrowAltUp, FaWind } from 'react-icons/fa';
import { WiBarometer, WiHumidity, WiSunrise, WiSunset } from 'react-icons/wi';
import { textClasses } from 'styles';
import type { MeteoWeather } from 'types';
import WeatherFeaturePill from './WeatherFeaturePill';
import WeatherIcon from './WeatherIcon';
const WeatherCodes: { [key: number]: string } = {
0: 'Clear sky',
1: 'Mainly clear',
2: 'Partly cloudy',
3: 'Overcast',
45: 'Fog',
48: 'Depositing rime fog',
51: 'Drizzle: Light',
53: 'Drizzle: Moderate',
55: 'Drizzle: Dense',
56: 'Freezing Drizzle: Light',
57: 'Freezing Drizzle: Dense',
61: 'Rain: Slight',
63: 'Rain: Moderate',
65: 'Rain: Heavy',
66: 'Freezing Rain: Light',
67: 'Freezing Rain: Heavy',
71: 'Snowfall: Slight',
73: 'Snowfall: Moderate',
75: 'Snowfall: Heavy',
77: 'Snow grains',
80: 'Rain showers: Slight',
81: 'Rain showers: Moderate',
82: 'Rain showers: Violent',
85: 'Snow showers: Slight',
86: 'Snow showers: Heavy',
95: 'Thunderstorm: Slight or moderate',
96: 'Thunderstorm with slight hail',
99: 'Thunderstorm with heavy hail',
} as const;
export default function CurrentWeather({
current,
}: {
current: MeteoWeather | undefined;
}) {
const { isMobile, theme, textShadowStyle } = useCommonHooks();
const sunrise = new Date(current?.daily.sunrise[0] || 0).toLocaleTimeString();
const sunset = new Date(current?.daily.sunset[0] || 0).toLocaleTimeString();
return (
<>
{current && (
<Card
style={{
color: 'var(--mantine-color-primary-0)',
backgroundColor: 'var(--mantine-color-search-0)',
padding: '1rem',
borderRadius: '8px',
paddingBottom: '.5rem',
marginTop: '1rem',
overflow: 'visible',
}}
>
<Text
className={textClasses.weatherTitle}
classNames={textClasses}
style={{
textShadow: theme.textShadowsEnabled
? '2px 2px var(--mantine-color-border-0)'
: undefined,
}}
>
Current Weather
</Text>
<Group gap={32} w={'100%'} align='center' justify='center' pt={'.5rem'}>
<Stack gap={4} align='center'>
<Stack
gap={0}
style={{
overflow: 'hidden',
backgroundColor: 'var(--mantine-color-background-0)',
border: 'thin solid var(--mantine-color-primary-0)',
zIndex: 1,
padding: '1rem',
borderRadius: '8px',
}}
>
<Group pos={'relative'}>
<Box
style={{
position: 'absolute',
right: '-1.25rem',
bottom: '-1.25rem',
zIndex: -1,
opacity: 0.5,
}}
>
<WeatherIcon size={'lg'} code={current.current.weather_code} />
</Box>
<Text fz={isMobile ? '5rem' : '7rem'} fw={400}>
{current.current.temperature_2m?.toFixed(0)}°
<sup style={{ fontSize: '3rem' }}>F</sup>
</Text>
<Box
style={{
position: 'absolute',
backgroundColor:
'color-mix(in srgb, var(--mantine-color-accent-0), transparent 80%)',
height: '200%',
width: '100%',
bottom: -40,
right: -72,
transform: 'skewX(-25deg)',
zIndex: -1,
borderRadius: '2px',
backdropFilter: 'brightness(0.5)',
}}
/>
</Group>
<Group
justify={
WeatherCodes[Number(current.current.weather_code)].length > 25
? 'flex-start'
: 'center'
}
style={{
width: '100%',
maxWidth: '180px',
whiteSpace: 'nowrap',
overflow: 'hidden',
boxSizing: 'border-box',
position: 'relative',
}}
>
<Text
className={
WeatherCodes[Number(current.current.weather_code)].length > 25
? textClasses.autoScrollText
: undefined
}
classNames={textClasses}
>
{current.current.temperature_2m?.toFixed(0) === '69'
? 'Nice'
: WeatherCodes[Number(current.current.weather_code)]}
</Text>
</Group>
</Stack>
<WeatherFeaturePill
leftSide={<Text>Feels like </Text>}
rightSide={
<Text>
{current.current.apparent_temperature?.toFixed(0) ??
current.current.temperature_2m?.toFixed(0)}
°<sup>F</sup>
</Text>
}
highlight='right'
/>
</Stack>
<Stack gap={10}>
<Stack gap={0} align='center'>
<Text
className={textClasses.sectionTitle}
classNames={textClasses}
style={{
textAlign: 'center',
textShadow: theme.textShadowsEnabled ? textShadowStyle : undefined,
}}
w={'100%'}
>
Temperatures
</Text>
<Group justify='center'>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<FaLongArrowAltUp size={16} />
High
</Group>
}
rightSide={
<Text>
{current.daily.temperature_2m_max?.[0].toFixed(0)}°<sup>F</sup>
</Text>
}
highlight='right'
/>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<FaLongArrowAltDown size={16} />
Low
</Group>
}
rightSide={
<Text>
{current.daily.temperature_2m_min?.[0].toFixed(0)}°<sup>F</sup>
</Text>
}
highlight='right'
/>
</Group>
</Stack>
<Stack gap={0} align='center'>
<Text
className={textClasses.sectionTitle}
classNames={textClasses}
style={{
textAlign: 'center',
textShadow: theme.textShadowsEnabled ? textShadowStyle : undefined,
}}
w={'100%'}
>
Conditions
</Text>
<Group justify='center'>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<WiHumidity size={16} />
Humidity
</Group>
}
rightSide={<Text>{current.current.relative_humidity_2m}%</Text>}
highlight='right'
/>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<FaWind size={16} />
Wind
</Group>
}
rightSide={
<Text>{current.current.wind_speed_10m?.toFixed(0)}mph</Text>
}
highlight='right'
/>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<WiBarometer size={16} />
Pressure
</Group>
}
rightSide={
<Text>{current.current.surface_pressure?.toFixed(0)} mbar</Text>
}
highlight='right'
/>
</Group>
</Stack>
<Stack gap={0} align='center'>
<Text
className={textClasses.sectionTitle}
classNames={textClasses}
style={{
textAlign: 'center',
textShadow: theme.textShadowsEnabled ? textShadowStyle : undefined,
}}
w={'100%'}
>
Sun Cycle
</Text>
<Group justify='center'>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<WiSunrise
size={18}
style={{
marginTop: '2px',
marginBottom: '2px',
marginLeft: -6,
marginRight: -6,
}}
/>
</Group>
}
rightSide={<Text>{sunrise}</Text>}
highlight='left'
/>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<WiSunset
size={18}
style={{
marginTop: '2px',
marginBottom: '2px',
marginLeft: -6,
marginRight: -6,
}}
/>
</Group>
}
rightSide={<Text>{sunset}</Text>}
highlight='left'
/>
</Group>
</Stack>
</Stack>
</Group>
</Card>
)}
</>
);
}