320 lines
8.2 KiB
TypeScript
320 lines
8.2 KiB
TypeScript
import { ActionIcon, Box, Card, Group, Stack, Text } from '@mantine/core';
|
|
import { useCommonHooks } from 'hooks';
|
|
import { FaLocationArrow, FaSun, FaWind } from 'react-icons/fa';
|
|
import { FaDroplet, FaX } from 'react-icons/fa6';
|
|
import { WiRain, WiSunrise, WiSunset } from 'react-icons/wi';
|
|
import { textClasses } from 'styles';
|
|
import { WeatherCodes } from 'types';
|
|
import WeatherFeaturePill from './WeatherFeaturePill';
|
|
import WeatherGraphs from './WeatherGraphs';
|
|
import WeatherIcon from './WeatherIcon';
|
|
|
|
export default function ExtendedForecastDetails({
|
|
selectedDay,
|
|
setSelectedDay,
|
|
selectedHourly,
|
|
setSelectedHourly,
|
|
}: {
|
|
selectedDay: any;
|
|
setSelectedDay: (day: any) => void;
|
|
selectedHourly: any;
|
|
setSelectedHourly: (hourly: any) => void;
|
|
}) {
|
|
const { isMobile } = useCommonHooks();
|
|
return (
|
|
<Card
|
|
h={'100%'}
|
|
w={'100%'}
|
|
style={{
|
|
color: 'var(--mantine-color-primary-0)',
|
|
backgroundColor: 'var(--mantine-color-background-0)',
|
|
padding: '1rem',
|
|
borderRadius: '8px',
|
|
overflow: 'visible',
|
|
cursor: 'default',
|
|
boxShadow:
|
|
'15px 15px 2px color-mix(in srgb, var(--mantine-color-border-0), transparent 50%)',
|
|
}}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
}}
|
|
p={0}
|
|
>
|
|
<ActionIcon
|
|
pos={'absolute'}
|
|
top={-12}
|
|
right={-12}
|
|
style={{
|
|
borderRadius: '100%',
|
|
boxShadow: '2px 2px var(--mantine-color-search-0)',
|
|
}}
|
|
onClick={() => {
|
|
setSelectedDay(undefined);
|
|
setSelectedHourly(undefined);
|
|
}}
|
|
>
|
|
<FaX />
|
|
</ActionIcon>
|
|
<Group
|
|
w={'100%'}
|
|
justify='center'
|
|
bg={'var(--mantine-color-search-0)'}
|
|
py={4}
|
|
mt={0}
|
|
style={{
|
|
borderTopLeftRadius: '8px',
|
|
borderTopRightRadius: '8px',
|
|
}}
|
|
>
|
|
<Text fw={600} fz={'1.5rem'}>
|
|
{selectedDay.time.toLocaleDateString('en-US', { weekday: 'long' })}
|
|
</Text>
|
|
<Text fw={600} fz={'1.5rem'}>
|
|
{selectedDay.time.toLocaleDateString()}
|
|
</Text>
|
|
</Group>
|
|
<Stack align='center' p={16}>
|
|
<Group>
|
|
<Stack
|
|
gap={0}
|
|
style={{
|
|
overflow: 'hidden',
|
|
backgroundColor: 'var(--mantine-color-background-0)',
|
|
border: 'thin solid var(--mantine-color-primary-0)',
|
|
zIndex: 1,
|
|
paddingLeft: '2.25rem',
|
|
paddingRight: '2.25rem',
|
|
borderRadius: '100%',
|
|
aspectRatio: 1,
|
|
}}
|
|
align='center'
|
|
justify='center'
|
|
>
|
|
<Box m={0} p={0}>
|
|
<WeatherFeaturePill
|
|
leftSide={<Text>Feels like</Text>}
|
|
rightSide={
|
|
<Text>
|
|
{selectedDay.apparentTemperatureMax?.toFixed(0) ??
|
|
selectedDay.temperatureMax?.toFixed(0)}
|
|
°<sup>F</sup>
|
|
</Text>
|
|
}
|
|
highlight='right'
|
|
/>
|
|
</Box>
|
|
<Group pos={'relative'}>
|
|
<Text fz={isMobile ? '5rem' : '7rem'} fw={400} style={{ lineHeight: 1 }}>
|
|
{selectedDay.temperatureMax?.toFixed(0)}
|
|
<sup style={{ fontSize: '3rem' }}>°F</sup>
|
|
</Text>
|
|
|
|
<Text style={{ lineHeight: 1 }} pos={'absolute'} bottom={20} right={0}>
|
|
/ {selectedDay.temperatureMin?.toFixed(0)}°<sup>F</sup>
|
|
</Text>
|
|
<Box
|
|
style={{
|
|
position: 'absolute',
|
|
backgroundColor:
|
|
'color-mix(in srgb, var(--mantine-color-accent-0), transparent 80%)',
|
|
height: '250%',
|
|
width: '80%',
|
|
bottom: -96,
|
|
right: -60,
|
|
transform: 'skewX(-25deg)',
|
|
zIndex: -1,
|
|
borderRadius: '2px',
|
|
backdropFilter: 'brightness(0.5)',
|
|
lineHeight: 1,
|
|
}}
|
|
/>
|
|
</Group>
|
|
<Group
|
|
justify={
|
|
WeatherCodes[Number(selectedDay.weatherCode)].length > 25
|
|
? 'flex-start'
|
|
: 'center'
|
|
}
|
|
style={{
|
|
width: '100%',
|
|
maxWidth: '180px',
|
|
whiteSpace: 'nowrap',
|
|
overflow: 'hidden',
|
|
boxSizing: 'border-box',
|
|
position: 'relative',
|
|
}}
|
|
>
|
|
<Text
|
|
className={
|
|
WeatherCodes[Number(selectedDay.weatherCode)].length > 25
|
|
? textClasses.autoScrollText
|
|
: undefined
|
|
}
|
|
classNames={textClasses}
|
|
style={{ lineHeight: 1 }}
|
|
>
|
|
{selectedDay.temperature_2m?.toFixed(0) === '69'
|
|
? 'Nice'
|
|
: WeatherCodes[Number(selectedDay.weatherCode)]}
|
|
</Text>
|
|
</Group>
|
|
</Stack>
|
|
<Stack>
|
|
<WeatherIcon size={'xl'} code={selectedDay.weatherCode} />
|
|
</Stack>
|
|
</Group>
|
|
|
|
<Group>
|
|
<Group justify='space-between'>
|
|
<Stack gap={4}>
|
|
<WeatherFeaturePill
|
|
leftSide={
|
|
<Group gap={2}>
|
|
<FaWind size={16} />
|
|
<Text>Wind</Text>
|
|
</Group>
|
|
}
|
|
rightSide={<Text>{selectedDay.windSpeed?.toFixed(0)}mph</Text>}
|
|
highlight='right'
|
|
/>
|
|
<WeatherFeaturePill
|
|
leftSide={
|
|
<Group gap={2}>
|
|
<FaWind size={16} />
|
|
<Text>Gusts</Text>
|
|
</Group>
|
|
}
|
|
rightSide={<Text>{selectedDay.windGusts?.toFixed(0)}mph</Text>}
|
|
highlight='right'
|
|
/>
|
|
</Stack>
|
|
<Stack align='center' gap={0}>
|
|
<Box
|
|
style={{
|
|
border: '2px solid var(--mantine-color-primary-0)',
|
|
borderRadius: '100%',
|
|
aspectRatio: 1,
|
|
width: 'fit-content',
|
|
padding: '.75rem',
|
|
display: 'flex',
|
|
backgroundColor: 'var(--mantine-color-background-0)',
|
|
}}
|
|
>
|
|
<FaLocationArrow
|
|
style={{
|
|
color: 'var(--mantine-color-accent-0)',
|
|
transform: `rotate(${-48 + (selectedDay.windDirection || 0)}deg)`,
|
|
}}
|
|
/>
|
|
</Box>
|
|
<Text fz={12}>{selectedDay.windDirection?.toFixed(0)}°</Text>
|
|
</Stack>
|
|
</Group>
|
|
<Group justify='space-between'>
|
|
<Stack align='center' justify='center' gap={0}>
|
|
<Box
|
|
style={{
|
|
border: '2px solid var(--mantine-color-primary-0)',
|
|
borderRadius: '100%',
|
|
aspectRatio: 1,
|
|
width: 'fit-content',
|
|
padding: '.75rem',
|
|
display: 'flex',
|
|
backgroundColor: 'var(--mantine-color-background-0)',
|
|
}}
|
|
>
|
|
<FaSun
|
|
style={{
|
|
color: 'var(--mantine-color-accent-0)',
|
|
}}
|
|
/>
|
|
</Box>
|
|
<Text fz={12}>UV {selectedDay.uvIndexMax?.toFixed(0)}</Text>
|
|
</Stack>
|
|
<Stack gap={4}>
|
|
<WeatherFeaturePill
|
|
leftSide={
|
|
<Group gap={0}>
|
|
<WiSunrise
|
|
size={18}
|
|
style={{
|
|
marginTop: '2px',
|
|
marginBottom: '2px',
|
|
marginLeft: -6,
|
|
marginRight: -6,
|
|
}}
|
|
/>
|
|
</Group>
|
|
}
|
|
rightSide={<Text>{selectedDay.sunrise}</Text>}
|
|
highlight='left'
|
|
/>
|
|
<WeatherFeaturePill
|
|
leftSide={
|
|
<Group gap={0}>
|
|
<WiSunset
|
|
size={18}
|
|
style={{
|
|
marginTop: '2px',
|
|
marginBottom: '2px',
|
|
marginLeft: -6,
|
|
marginRight: -6,
|
|
}}
|
|
/>
|
|
</Group>
|
|
}
|
|
rightSide={<Text>{selectedDay.sunset}</Text>}
|
|
highlight='left'
|
|
/>
|
|
</Stack>
|
|
</Group>
|
|
</Group>
|
|
<Group justify='space-between'>
|
|
<Stack align='center' justify='center' gap={0}>
|
|
<Box
|
|
style={{
|
|
border: '2px solid var(--mantine-color-primary-0)',
|
|
borderRadius: '100%',
|
|
aspectRatio: 1,
|
|
width: 'fit-content',
|
|
padding: '.75rem',
|
|
display: 'flex',
|
|
backgroundColor: 'var(--mantine-color-background-0)',
|
|
}}
|
|
>
|
|
<FaDroplet
|
|
style={{
|
|
color: 'var(--mantine-color-accent-0)',
|
|
}}
|
|
/>
|
|
</Box>
|
|
</Stack>
|
|
<Stack gap={4}>
|
|
<WeatherFeaturePill
|
|
leftSide={
|
|
<Group gap={2}>
|
|
<WiRain size={16} />
|
|
<Text>Precipitation %</Text>
|
|
</Group>
|
|
}
|
|
rightSide={<Text>{selectedDay.precipitationProbability}%</Text>}
|
|
highlight='right'
|
|
/>
|
|
<WeatherFeaturePill
|
|
leftSide={
|
|
<Group gap={2}>
|
|
<WiRain size={16} />
|
|
<Text>Precipitation In.</Text>
|
|
</Group>
|
|
}
|
|
rightSide={<Text>{selectedDay.precipitationSum.toFixed(2)} in.</Text>}
|
|
highlight='right'
|
|
/>
|
|
</Stack>
|
|
</Group>
|
|
<WeatherGraphs hourly={selectedHourly} formatted />
|
|
</Stack>
|
|
</Card>
|
|
);
|
|
}
|