Fullscreen test

This commit is contained in:
2025-03-12 17:30:41 -05:00
parent bf82a3920d
commit 0ba63f57c4
5 changed files with 369 additions and 204 deletions

View File

@@ -6,7 +6,7 @@ import { FaLongArrowAltDown, FaLongArrowAltUp, FaWind } from 'react-icons/fa';
import { WiBarometer, WiHumidity, WiSunrise, WiSunset } from 'react-icons/wi'; import { WiBarometer, WiHumidity, WiSunrise, WiSunset } from 'react-icons/wi';
import WeatherIcon from './WeatherIcon'; import WeatherIcon from './WeatherIcon';
export default function CurrentWeather({ weather }: any) { export default function CurrentWeather({ current }: any) {
const { currentLocation } = useCommonHooks(); const { currentLocation } = useCommonHooks();
const { data: sunStateData } = useSunStateAPI({ const { data: sunStateData } = useSunStateAPI({
lat: currentLocation.lat, lat: currentLocation.lat,
@@ -28,184 +28,192 @@ export default function CurrentWeather({ weather }: any) {
); );
} }
}, [sunStateData]); }, [sunStateData]);
return ( return (
<Stack <>
gap={0} {current ? (
w={'100%'} <Stack
justify='space-between' gap={0}
style={{ w={'100%'}
backgroundColor: 'var(--color-search-background)', justify='space-between'
padding: '1rem',
borderRadius: '8px',
paddingBottom: '.5rem',
}}
>
<Group gap={0} px={16} w={'100%'} justify='space-between'>
<Text
c={'var(--color-text-pri)'}
style={{ style={{
fontSize: '1.375rem', backgroundColor: 'var(--color-search-background)',
textAlign: 'right', padding: '1rem',
borderRadius: '8px',
paddingBottom: '.5rem',
}} }}
c={'var(--color-text-pri)'}
> >
Current Weather <Group gap={0} px={16} w={'100%'} justify='space-between'>
</Text> <Text
</Group> c={'var(--color-text-pri)'}
<Group gap={8} w={'100%'} justify='space-between'> style={{
<Stack gap={0} w={'45%'}> fontSize: '1.375rem',
<Group gap={0} justify='flex-end'> textAlign: 'right',
<WeatherIcon }}
textDescription={`${ >
weather.textDescription.includes('and') Current Weather
? weather.textDescription.substring(
0,
weather.textDescription.indexOf('and'),
)
: weather.textDescription.includes('then')
? weather.textDescription.substring(
0,
weather.textDescription.indexOf('then'),
)
: weather.textDescription
}`}
/>
<Text fz={'7rem'} fw={200}>
{weather.temperature}°<sup style={{ fontSize: '3rem' }}>F</sup>
</Text> </Text>
</Group> </Group>
<Text <Group gap={8} w={'100%'} justify='space-between'>
c={'var(--color-text-pri)'} <Stack gap={0} w={'45%'}>
style={{ <Group gap={0} justify='flex-end'>
fontSize: '1.375rem', <WeatherIcon
textAlign: 'right', textDescription={`${
marginTop: -32, current.textDescription.includes('and')
marginLeft: 16, ? current.textDescription.substring(
}} 0,
> current.textDescription.indexOf('and'),
{weather.textDescription} )
</Text> : current.textDescription.includes('then')
</Stack> ? current.textDescription.substring(
<Stack gap={4} w={'45%'}> 0,
<Text> current.textDescription.indexOf('then'),
Feels like {weather.heatIndex ?? weather.windChill ?? weather.temperature}° )
<sup>F</sup> : current.textDescription
</Text> }`}
<Grid align='center'> />
<Grid.Col span={1}> <Text fz={'7rem'} fw={200}>
<ThemeIcon {current.temperature}°<sup style={{ fontSize: '3rem' }}>F</sup>
h={'auto'} </Text>
w={'auto'} </Group>
variant='subtle' <Text
c={'var(--color-text-pri)'} c={'var(--color-text-pri)'}
style={{
fontSize: '1.375rem',
textAlign: 'right',
marginTop: -32,
marginLeft: 16,
}}
> >
<FaLongArrowAltUp size={32} /> {current.textDescription}
</ThemeIcon>
</Grid.Col>
<Grid.Col span={3}>
<Text>
{weather.highTemp}°<sup>F</sup>
</Text> </Text>
</Grid.Col> </Stack>
<Grid.Col span={1}> <Stack gap={4} w={'45%'}>
<ThemeIcon
h={'auto'}
w={'auto'}
variant='subtle'
c={'var(--color-text-pri)'}
>
<FaLongArrowAltDown size={32} />
</ThemeIcon>
</Grid.Col>
<Grid.Col span={1}>
<Text> <Text>
{weather.lowTemp}°<sup>F</sup> Feels like {current.heatIndex ?? current.windChill ?? current.temperature}
°<sup>F</sup>
</Text> </Text>
</Grid.Col> <Grid align='center'>
</Grid> <Grid.Col span={1}>
<Grid align='center'> <ThemeIcon
<Grid.Col span={1}> h={'auto'}
<ThemeIcon w={'auto'}
h={'auto'} variant='subtle'
w={'auto'} c={'var(--color-text-pri)'}
variant='subtle' >
c={'var(--color-text-pri)'} <FaLongArrowAltUp size={32} />
> </ThemeIcon>
<WiSunrise size={32} /> </Grid.Col>
</ThemeIcon> <Grid.Col span={3}>
</Grid.Col> <Text>
<Grid.Col span={3}> {current.highTemp}°<sup>F</sup>
<Text>{sunStates[0]?.sunrise}</Text> </Text>
</Grid.Col> </Grid.Col>
<Grid.Col span={1}> <Grid.Col span={1}>
<ThemeIcon <ThemeIcon
h={'auto'} h={'auto'}
w={'auto'} w={'auto'}
variant='subtle' variant='subtle'
c={'var(--color-text-pri)'} c={'var(--color-text-pri)'}
> >
<WiSunset size={32} /> <FaLongArrowAltDown size={32} />
</ThemeIcon> </ThemeIcon>
</Grid.Col> </Grid.Col>
<Grid.Col span={3}> <Grid.Col span={1}>
<Text>{sunStates[0]?.sunset}</Text> <Text>
</Grid.Col> {current.lowTemp}°<sup>F</sup>
</Grid> </Text>
<Grid align='center'> </Grid.Col>
<Grid.Col span={1}> </Grid>
<ThemeIcon <Grid align='center'>
h={'auto'} <Grid.Col span={1}>
w={'auto'} <ThemeIcon
variant='subtle' h={'auto'}
c={'var(--color-text-pri)'} w={'auto'}
> variant='subtle'
<WiHumidity size={32} /> c={'var(--color-text-pri)'}
</ThemeIcon> >
</Grid.Col> <WiSunrise size={32} />
<Grid.Col span={3}> </ThemeIcon>
<Text>Humidity</Text> </Grid.Col>
</Grid.Col> <Grid.Col span={3}>
<Grid.Col span={2}> <Text>{sunStates[0]?.sunrise}</Text>
<Text>{weather.humidity}%</Text> </Grid.Col>
</Grid.Col> <Grid.Col span={1}>
</Grid> <ThemeIcon
<Grid align='center'> h={'auto'}
<Grid.Col span={1}> w={'auto'}
<ThemeIcon variant='subtle'
h={'auto'} c={'var(--color-text-pri)'}
w={'auto'} >
variant='subtle' <WiSunset size={32} />
c={'var(--color-text-pri)'} </ThemeIcon>
> </Grid.Col>
<FaWind size={32} /> <Grid.Col span={3}>
</ThemeIcon> <Text>{sunStates[0]?.sunset}</Text>
</Grid.Col> </Grid.Col>
<Grid.Col span={3}> </Grid>
<Text>Wind</Text> <Grid align='center'>
</Grid.Col> <Grid.Col span={1}>
<Grid.Col span={2}> <ThemeIcon
<Text>{weather.windSpeed}mph</Text> h={'auto'}
</Grid.Col> w={'auto'}
</Grid> variant='subtle'
<Grid align='center'> c={'var(--color-text-pri)'}
<Grid.Col span={1}> >
<ThemeIcon <WiHumidity size={32} />
h={'auto'} </ThemeIcon>
w={'auto'} </Grid.Col>
variant='subtle' <Grid.Col span={3}>
c={'var(--color-text-pri)'} <Text>Humidity</Text>
> </Grid.Col>
<WiBarometer size={32} /> <Grid.Col span={2}>
</ThemeIcon> <Text>{current.humidity}%</Text>
</Grid.Col> </Grid.Col>
<Grid.Col span={3}> </Grid>
<Text>Pressure</Text> <Grid align='center'>
</Grid.Col> <Grid.Col span={1}>
<Grid.Col span={2}> <ThemeIcon
<Text>{weather.pressure} in</Text> h={'auto'}
</Grid.Col> w={'auto'}
</Grid> variant='subtle'
c={'var(--color-text-pri)'}
>
<FaWind size={32} />
</ThemeIcon>
</Grid.Col>
<Grid.Col span={3}>
<Text>Wind</Text>
</Grid.Col>
<Grid.Col span={2}>
<Text>{current.windSpeed}mph</Text>
</Grid.Col>
</Grid>
<Grid align='center'>
<Grid.Col span={1}>
<ThemeIcon
h={'auto'}
w={'auto'}
variant='subtle'
c={'var(--color-text-pri)'}
>
<WiBarometer size={32} />
</ThemeIcon>
</Grid.Col>
<Grid.Col span={3}>
<Text>Pressure</Text>
</Grid.Col>
<Grid.Col span={2}>
<Text>{current.pressure} in</Text>
</Grid.Col>
</Grid>
</Stack>
</Group>
</Stack> </Stack>
</Group> ) : (
</Stack> <></>
)}
</>
); );
} }

View File

@@ -79,7 +79,7 @@ export function WeatherModal({
<Modal.Body m={0}> <Modal.Body m={0}>
<Center w={'100%'}> <Center w={'100%'}>
<Stack w={'100%'}> <Stack w={'100%'}>
<CurrentWeather weather={current} /> <CurrentWeather current={current} />
<WeatherGraphs hourlyForecast={hourlyForecast} /> <WeatherGraphs hourlyForecast={hourlyForecast} />
<ExtendedForecast forecast={extendedForecast} /> <ExtendedForecast forecast={extendedForecast} />
</Stack> </Stack>

View File

@@ -1,13 +1,15 @@
import { Stack } from '@mantine/core'; import { Grid, Stack } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks'; import { useDisclosure } from '@mantine/hooks';
import CurrentWeather from 'components/WeatherModal/CurrentWeather';
import { useCommonHooks, useOSMAPI, useQueryAPI, useWeatherAPI } from 'hooks'; import { useCommonHooks, useOSMAPI, useQueryAPI, useWeatherAPI } from 'hooks';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { stackClasses } from 'styles'; import { stackClasses } from 'styles';
import type { CurrentWeather, OutlookWeather } from 'types'; import type { CurrentWeather as CW, OutlookWeather } from 'types';
import type { ExtendedForecast } from 'types/weather'; import type { ExtendedForecast as EF } from 'types/weather';
import Applications from './components/Applications/Applications'; import Applications from './components/Applications/Applications';
import Bookmarks from './components/Bookmarks/Bookmarks'; import Bookmarks from './components/Bookmarks/Bookmarks';
import Header from './components/Header/Header'; import Header from './components/Header/Header';
import LargeHeader from './components/Header/LargeHeader';
import Search from './components/Search/Search'; import Search from './components/Search/Search';
import SettingsButton from './components/SettingsButton'; import SettingsButton from './components/SettingsButton';
@@ -105,7 +107,7 @@ export function Homepage() {
x: points?.properties.gridX || currentLocation.x, x: points?.properties.gridX || currentLocation.x,
y: points?.properties.gridY || currentLocation.y, y: points?.properties.gridY || currentLocation.y,
}); });
const [current, setCurrent] = useState<CurrentWeather>({ const [current, setCurrent] = useState<CW>({
icon: '', icon: '',
textDescription: '', textDescription: '',
temperature: 0, temperature: 0,
@@ -130,7 +132,7 @@ export function Homepage() {
windDirection: 'N', windDirection: 'N',
}, },
]); ]);
const [extendedForecast, setExtendedForecast] = useState<ExtendedForecast[]>([ const [extendedForecast, setExtendedForecast] = useState<EF[]>([
{ {
detailedForecast: '', detailedForecast: '',
isDaytime: true, isDaytime: true,
@@ -224,34 +226,73 @@ export function Homepage() {
}); });
} }
}, [forecast]); }, [forecast]);
return ( return (
<Stack gap={0} className={stackClasses.containerStack} justify='center'> <Stack
<Search gap={0}
current={current} h={appFilter.length > 0 || bookmarkFilter.length > 0 ? undefined : '100%'}
outlook={outlook} className={stackClasses.containerStack}
extendedForecast={extendedForecast} justify='center'
weather={weather} >
basicWeather={basicWeather} {appFilter.length > 0 || bookmarkFilter.length > 0 ? (
weatherModalOpened={weatherModalOpened} <>
closeWeatherModal={closeWeatherModal} <Search
openWeatherModal={openWeatherModal} current={current}
/> outlook={outlook}
<Header extendedForecast={extendedForecast}
date={date} weather={weather}
greet={displayedGreeting} basicWeather={basicWeather}
current={current} weatherModalOpened={weatherModalOpened}
setCurrent={setCurrent} closeWeatherModal={closeWeatherModal}
outlook={outlook} openWeatherModal={openWeatherModal}
extendedForecast={extendedForecast} />
weather={weather} <Header
basicWeather={basicWeather} date={date}
weatherModalOpened={weatherModalOpened} greet={displayedGreeting}
closeWeatherModal={closeWeatherModal} current={current}
openWeatherModal={openWeatherModal} setCurrent={setCurrent}
/> outlook={outlook}
<Applications contentType={appFilter} /> extendedForecast={extendedForecast}
<Bookmarks contentType={bookmarkFilter} /> weather={weather}
basicWeather={basicWeather}
weatherModalOpened={weatherModalOpened}
closeWeatherModal={closeWeatherModal}
openWeatherModal={openWeatherModal}
/>
<Applications contentType={appFilter} />
<Bookmarks contentType={bookmarkFilter} />
</>
) : (
<>
<Stack align='center'>
<LargeHeader
date={date}
greet={displayedGreeting}
current={current}
setCurrent={setCurrent}
outlook={outlook}
extendedForecast={extendedForecast}
weather={weather}
basicWeather={basicWeather}
weatherModalOpened={weatherModalOpened}
closeWeatherModal={closeWeatherModal}
openWeatherModal={openWeatherModal}
/>
<Grid grow columns={24} pos={'absolute'} bottom={'1rem'} w={'50%'}>
<CurrentWeather span={18} current={current} />
</Grid>
</Stack>
<Search
current={current}
outlook={outlook}
extendedForecast={extendedForecast}
weather={weather}
basicWeather={basicWeather}
weatherModalOpened={weatherModalOpened}
closeWeatherModal={closeWeatherModal}
openWeatherModal={openWeatherModal}
/>
</>
)}
<SettingsButton /> <SettingsButton />
</Stack> </Stack>
); );

View File

@@ -38,6 +38,7 @@ function Header({
if (weather !== undefined && basicWeather !== undefined) { if (weather !== undefined && basicWeather !== undefined) {
setCurrent({ setCurrent({
icon: weather.features[0]?.properties.icon?.replace('medium', 'large') || '', icon: weather.features[0]?.properties.icon?.replace('medium', 'large') || '',
textDescription: weather.features[0]?.properties.textDescription,
temperature: Math.round( temperature: Math.round(
(weather.features[0]?.properties.temperature.value * 9) / 5 + 32, (weather.features[0]?.properties.temperature.value * 9) / 5 + 32,
), ),
@@ -50,11 +51,23 @@ function Header({
precipitation: precipitation:
weather.features[0]?.properties.precipitationLastHour.value || 'N/A', weather.features[0]?.properties.precipitationLastHour.value || 'N/A',
humidity: Math.round(weather.features[0]?.properties.relativeHumidity.value), humidity: Math.round(weather.features[0]?.properties.relativeHumidity.value),
heatIndex: Math.round( heatIndex:
(weather.features[0]?.properties.heatIndex.value * 9) / 5 + 32, basicWeather.properties.heatIndex?.values[0].value === null
), ? null
: Math.round(
(basicWeather.properties.heatIndex.values[0].value * 9) / 5 + 32,
),
windChill:
basicWeather.properties.windChill?.values[0].value === null
? null
: Math.round(
(basicWeather.properties.windChill.values[0].value * 9) / 5 + 32,
),
windSpeed: Math.round(weather.features[0]?.properties.windSpeed.value / 1.60934), windSpeed: Math.round(weather.features[0]?.properties.windSpeed.value / 1.60934),
windDirection: weather.features[0]?.properties.windDirection.value, windDirection: weather.features[0]?.properties.windDirection.value,
pressure: Math.round(
weather.features[0]?.properties.barometricPressure.value / 3386.38,
),
}); });
} }
}, [weather, basicWeather]); }, [weather, basicWeather]);

View File

@@ -0,0 +1,103 @@
import { Stack, Text } from '@mantine/core';
import { useCommonHooks } from 'hooks';
import { useEffect, useState } from 'react';
import { textClasses } from 'styles';
function LargeHeader({ greet, date, setCurrent, weather, basicWeather }: any) {
const [time, setTime] = useState(new Date());
const { isMobile, currentUser } = useCommonHooks();
function fixDigits(k: any) {
if (k < 10) {
return `0${k}`;
}
return k;
}
useEffect(() => {
setInterval(() => {
const newDate = new Date();
setTime(newDate);
}, 1000);
}, []);
useEffect(() => {
if (weather !== undefined && basicWeather !== undefined) {
setCurrent({
icon: weather.features[0]?.properties.icon?.replace('medium', 'large') || '',
textDescription: weather.features[0]?.properties.textDescription,
temperature: Math.round(
(weather.features[0]?.properties.temperature.value * 9) / 5 + 32,
),
highTemp: Math.round(
(basicWeather.properties.maxTemperature.values[0].value * 9) / 5 + 32,
),
lowTemp: Math.round(
(basicWeather.properties.minTemperature.values[0].value * 9) / 5 + 32,
),
precipitation:
weather.features[0]?.properties.precipitationLastHour.value || 'N/A',
humidity: Math.round(weather.features[0]?.properties.relativeHumidity.value),
heatIndex:
basicWeather.properties.heatIndex?.values[0].value === null
? null
: Math.round(
(basicWeather.properties.heatIndex.values[0].value * 9) / 5 + 32,
),
windChill:
basicWeather.properties.windChill?.values[0].value === null
? null
: Math.round(
(basicWeather.properties.windChill.values[0].value * 9) / 5 + 32,
),
windSpeed: Math.round(weather.features[0]?.properties.windSpeed.value / 1.60934),
windDirection: weather.features[0]?.properties.windDirection.value,
pressure: Math.round(
weather.features[0]?.properties.barometricPressure.value / 3386.38,
),
});
}
}, [weather, basicWeather]);
return (
<Stack gap={0} pos={'absolute'} align='center' justify='center' top={0}>
<Text
className={textClasses.greeting}
classNames={textClasses}
fz={isMobile ? 24 : 96}
>
{greet
.replace('$firstName', currentUser.firstName)
.replace('$lastName', currentUser.lastName)
.replace('$^firstName', currentUser.firstName.toUpperCase())
.replace('$^lastName', currentUser.lastName.toUpperCase())}
</Text>
<Text
fz={48}
className={textClasses.dateTime}
classNames={textClasses}
m={0}
style={{ width: 'max-content' }}
>
{date}
</Text>
<Text
fz={96}
fw={400}
m={0}
className={textClasses.dateTime}
classNames={textClasses}
>
{`${
time.getHours() === 0
? 12
: time.getHours() > 12
? time.getHours() - 12
: time.getHours()
}:${fixDigits(time.getMinutes())} ${time.getHours() >= 12 ? 'PM' : 'AM'}`}
</Text>
</Stack>
);
}
export default LargeHeader;