209 lines
6.5 KiB
TypeScript
209 lines
6.5 KiB
TypeScript
import { Stack } from '@mantine/core';
|
|
import { useDisclosure } from '@mantine/hooks';
|
|
import { useCommonHooks, useOSMAPI, useQueryAPI, useWeatherAPI } from 'hooks';
|
|
import { useEffect, useState } from 'react';
|
|
import { stackClasses } from 'styles';
|
|
import type { CurrentWeather, OutlookWeather } from 'types';
|
|
import Applications from './components/Applications/Applications';
|
|
import Bookmarks from './components/Bookmarks/Bookmarks';
|
|
import Header from './components/Header/Header';
|
|
import Search from './components/Search/Search';
|
|
import SettingsButton from './components/SettingsButton';
|
|
|
|
export function Homepage() {
|
|
const { data: personal, isFetched: personalIsFetched } = useQueryAPI({
|
|
endpoint: 'api/personalData',
|
|
});
|
|
const {
|
|
data: messageData,
|
|
isFetching: isMessagesFetching,
|
|
isFetched: isMessagesFetched,
|
|
} = useQueryAPI({
|
|
endpoint: 'api/messages',
|
|
});
|
|
const [personalData, setPersonalData] = useState<any>([]);
|
|
const [messages, setMessages] = useState<any>([]);
|
|
const [displayedGreeting, setDisplayedGreeting] = useState('');
|
|
const [weatherModalOpened, { open: openWeatherModal, close: closeWeatherModal }] =
|
|
useDisclosure(false);
|
|
const { appFilter, bookmarkFilter, isMobile } = useCommonHooks();
|
|
const dateOptions: Intl.DateTimeFormatOptions = !isMobile
|
|
? {
|
|
weekday: 'long',
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric',
|
|
}
|
|
: {};
|
|
const date = new Date().toLocaleDateString('en-US', dateOptions);
|
|
|
|
useEffect(() => {
|
|
if (messageData && isMessagesFetched) {
|
|
setMessages(messageData);
|
|
}
|
|
}, [messageData, isMessagesFetched]);
|
|
useEffect(() => {
|
|
if (personal && personalIsFetched) {
|
|
setPersonalData(personal);
|
|
}
|
|
}, [personal, personalIsFetched]);
|
|
|
|
useEffect(() => {
|
|
if (messages && personalData) {
|
|
setDisplayedGreeting(() => {
|
|
if (Math.floor(Math.random() * 100) > 10 || messages.length === 0) {
|
|
switch (Math.floor(new Date().getHours() / 6)) {
|
|
case 0:
|
|
return `Good night, ${personalData?.[0]?.firstName}!`;
|
|
case 1:
|
|
return `Good morning, ${personalData?.[0]?.firstName}!`;
|
|
case 2:
|
|
return `Good afternoon, ${personalData?.[0]?.firstName}!`;
|
|
case 3:
|
|
return `Good evening, ${personalData?.[0]?.firstName}!`;
|
|
}
|
|
}
|
|
return messages[Math.floor(Math.random() * messages.length)].message;
|
|
});
|
|
}
|
|
}, [messages, personalData, isMessagesFetching]);
|
|
|
|
const { data: weatherMetadata } = useOSMAPI({ address: personal?.[0].physicalAddress });
|
|
const { data: points } = useWeatherAPI({
|
|
endpoint: 'points',
|
|
lat: weatherMetadata?.[0].lat || 0,
|
|
lon: weatherMetadata?.[0].lon || 0,
|
|
});
|
|
const { data: basicWeather } = useWeatherAPI({
|
|
endpoint: 'baseline',
|
|
office: points?.properties.gridId,
|
|
x: points?.properties.gridX,
|
|
y: points?.properties.gridY,
|
|
});
|
|
const { data: stations } = useWeatherAPI({
|
|
endpoint: 'stations',
|
|
office: points?.properties.gridId,
|
|
x: points?.properties.gridX,
|
|
y: points?.properties.gridY,
|
|
});
|
|
const { data: weather } = useWeatherAPI({
|
|
endpoint: 'current',
|
|
station: stations?.features[0].properties.stationIdentifier,
|
|
});
|
|
const { data: forecast } = useWeatherAPI({
|
|
endpoint: 'forecast',
|
|
office: points?.properties.gridId,
|
|
x: points?.properties.gridX,
|
|
y: points?.properties.gridY,
|
|
});
|
|
const [current, setCurrent] = useState<CurrentWeather>({
|
|
icon: '',
|
|
temperature: 0,
|
|
highTemp: 0,
|
|
lowTemp: 0,
|
|
precipitation: 'N/A',
|
|
humidity: 0,
|
|
heatIndex: 0,
|
|
windSpeed: 0,
|
|
windDirection: 0,
|
|
});
|
|
const [outlook, setOutlook] = useState<OutlookWeather[]>([
|
|
{
|
|
name: '',
|
|
icon: '',
|
|
isDayTime: true,
|
|
temperature: 0,
|
|
precipitation: 0,
|
|
windSpeed: '0 mph',
|
|
windDirection: 'N',
|
|
},
|
|
]);
|
|
|
|
useEffect(() => {
|
|
if (weather !== undefined && basicWeather !== undefined) {
|
|
setCurrent({
|
|
icon: weather.features[0]?.properties.icon?.replace('medium', 'large') || '',
|
|
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: Math.round(
|
|
weather.features[0]?.properties.heatIndex.value !== null
|
|
? (weather.features[0]?.properties.heatIndex.value * 9) / 5 + 32
|
|
: (weather.features[0]?.properties.temperature.value * 9) / 5 + 32,
|
|
),
|
|
windSpeed: Math.round(weather.features[0]?.properties.windSpeed.value / 1.60934),
|
|
windDirection: weather.features[0]?.properties.windDirection.value,
|
|
});
|
|
}
|
|
}, [weather, basicWeather]);
|
|
|
|
useEffect(() => {
|
|
if (forecast) {
|
|
setOutlook([
|
|
{
|
|
name: forecast.properties.periods[0].name,
|
|
icon: forecast.properties.periods[0].icon.replace('medium', 'large'),
|
|
isDayTime: forecast.properties.periods[0].isDaytime,
|
|
temperature: forecast.properties.periods[0].temperature,
|
|
precipitation: Math.round(
|
|
forecast.properties.periods[0].probabilityOfPrecipitation.value,
|
|
),
|
|
windSpeed: forecast.properties.periods[0].windSpeed,
|
|
windDirection: forecast.properties.periods[0].windDirection,
|
|
},
|
|
{
|
|
name: forecast.properties.periods[1].name,
|
|
icon: forecast.properties.periods[1].icon.replace('medium', 'large'),
|
|
isDayTime: forecast.properties.periods[1].isDaytime,
|
|
temperature: forecast.properties.periods[1].temperature,
|
|
precipitation: Math.round(
|
|
forecast.properties.periods[1].probabilityOfPrecipitation.value,
|
|
),
|
|
windSpeed: forecast.properties.periods[1].windSpeed,
|
|
windDirection: forecast.properties.periods[1].windDirection,
|
|
},
|
|
]);
|
|
}
|
|
}, [forecast]);
|
|
|
|
return (
|
|
<Stack gap={0} className={stackClasses.containerStack} justify='center'>
|
|
<Search
|
|
current={current}
|
|
outlook={outlook}
|
|
weather={weather}
|
|
basicWeather={basicWeather}
|
|
points={points}
|
|
weatherModalOpened={weatherModalOpened}
|
|
closeWeatherModal={closeWeatherModal}
|
|
openWeatherModal={openWeatherModal}
|
|
/>
|
|
<Header
|
|
date={date}
|
|
greet={displayedGreeting}
|
|
current={current}
|
|
setCurrent={setCurrent}
|
|
outlook={outlook}
|
|
weather={weather}
|
|
basicWeather={basicWeather}
|
|
points={points}
|
|
weatherModalOpened={weatherModalOpened}
|
|
closeWeatherModal={closeWeatherModal}
|
|
openWeatherModal={openWeatherModal}
|
|
/>
|
|
<Applications contentType={appFilter} />
|
|
<Bookmarks contentType={bookmarkFilter} />
|
|
<SettingsButton />
|
|
</Stack>
|
|
);
|
|
}
|