322 lines
8.2 KiB
TypeScript
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>
|
|
)}
|
|
</>
|
|
);
|
|
}
|