This commit is contained in:
@@ -1,27 +1,63 @@
|
||||
import { Box, Card, Group, Stack, Text } from '@mantine/core';
|
||||
import { useCommonHooks, useSunStateAPI } from 'hooks';
|
||||
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 { CurrentWeather as CW, SunState } from 'types';
|
||||
import type { MeteoWeather } from 'types';
|
||||
import WeatherFeaturePill from './WeatherFeaturePill';
|
||||
import WeatherIcon from './WeatherIcon';
|
||||
|
||||
export default function CurrentWeather({ current }: { current: CW }) {
|
||||
const { currentLocation, isMobile, theme, textShadowStyle } = useCommonHooks();
|
||||
const { data: sunStateData } = useSunStateAPI({
|
||||
lat: currentLocation.lat,
|
||||
lon: currentLocation.lon,
|
||||
});
|
||||
const WeatherCodes: { [key: number]: string } = {
|
||||
0: 'Clear sky',
|
||||
|
||||
const sunStates: SunState[] =
|
||||
sunStateData?.results.map((item: SunState) => {
|
||||
return {
|
||||
date: item.date,
|
||||
sunrise: item.sunrise,
|
||||
sunset: item.sunset,
|
||||
};
|
||||
}) || [];
|
||||
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 (
|
||||
<>
|
||||
@@ -71,25 +107,11 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
opacity: 0.5,
|
||||
}}
|
||||
>
|
||||
<WeatherIcon
|
||||
size={'lg'}
|
||||
textDescription={`${
|
||||
current.textDescription.includes('and')
|
||||
? current.textDescription.substring(
|
||||
0,
|
||||
current.textDescription.indexOf('and'),
|
||||
)
|
||||
: current.textDescription.includes('then')
|
||||
? current.textDescription.substring(
|
||||
0,
|
||||
current.textDescription.indexOf('then'),
|
||||
)
|
||||
: current.textDescription
|
||||
}`}
|
||||
/>
|
||||
<WeatherIcon size={'lg'} code={current.current.weather_code} />
|
||||
</Box>
|
||||
<Text fz={isMobile ? '5rem' : '7rem'} fw={400}>
|
||||
{current.temperature}°<sup style={{ fontSize: '3rem' }}>F</sup>
|
||||
{current.current.temperature_2m?.toFixed(0)}°
|
||||
<sup style={{ fontSize: '3rem' }}>F</sup>
|
||||
</Text>
|
||||
<Box
|
||||
style={{
|
||||
@@ -108,7 +130,11 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
/>
|
||||
</Group>
|
||||
<Group
|
||||
justify={current.textDescription.length > 25 ? 'flex-start' : 'center'}
|
||||
justify={
|
||||
WeatherCodes[Number(current.current.weather_code)].length > 25
|
||||
? 'flex-start'
|
||||
: 'center'
|
||||
}
|
||||
style={{
|
||||
width: '100%',
|
||||
maxWidth: '180px',
|
||||
@@ -120,13 +146,15 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
>
|
||||
<Text
|
||||
className={
|
||||
current.textDescription.length > 25
|
||||
WeatherCodes[Number(current.current.weather_code)].length > 25
|
||||
? textClasses.autoScrollText
|
||||
: undefined
|
||||
}
|
||||
classNames={textClasses}
|
||||
>
|
||||
{current.temperature === 69 ? 'Nice' : current.textDescription}
|
||||
{current.current.temperature_2m?.toFixed(0) === '69'
|
||||
? 'Nice'
|
||||
: WeatherCodes[Number(current.current.weather_code)]}
|
||||
</Text>
|
||||
</Group>
|
||||
</Stack>
|
||||
@@ -134,8 +162,9 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
leftSide={<Text>Feels like </Text>}
|
||||
rightSide={
|
||||
<Text>
|
||||
{current.heatIndex ?? current.windChill ?? current.temperature}°
|
||||
<sup>F</sup>
|
||||
{current.current.apparent_temperature?.toFixed(0) ??
|
||||
current.current.temperature_2m?.toFixed(0)}
|
||||
°<sup>F</sup>
|
||||
</Text>
|
||||
}
|
||||
highlight='right'
|
||||
@@ -164,7 +193,7 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
}
|
||||
rightSide={
|
||||
<Text>
|
||||
{current.highTemp}°<sup>F</sup>
|
||||
{current.daily.temperature_2m_max?.[0].toFixed(0)}°<sup>F</sup>
|
||||
</Text>
|
||||
}
|
||||
highlight='right'
|
||||
@@ -178,7 +207,7 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
}
|
||||
rightSide={
|
||||
<Text>
|
||||
{current.lowTemp}°<sup>F</sup>
|
||||
{current.daily.temperature_2m_min?.[0].toFixed(0)}°<sup>F</sup>
|
||||
</Text>
|
||||
}
|
||||
highlight='right'
|
||||
@@ -205,7 +234,7 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
Humidity
|
||||
</Group>
|
||||
}
|
||||
rightSide={<Text>{current.humidity}%</Text>}
|
||||
rightSide={<Text>{current.current.relative_humidity_2m}%</Text>}
|
||||
highlight='right'
|
||||
/>
|
||||
<WeatherFeaturePill
|
||||
@@ -215,7 +244,9 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
Wind
|
||||
</Group>
|
||||
}
|
||||
rightSide={<Text>{current.windSpeed}mph</Text>}
|
||||
rightSide={
|
||||
<Text>{current.current.wind_speed_10m?.toFixed(0)}mph</Text>
|
||||
}
|
||||
highlight='right'
|
||||
/>
|
||||
<WeatherFeaturePill
|
||||
@@ -225,7 +256,9 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
Pressure
|
||||
</Group>
|
||||
}
|
||||
rightSide={<Text>{current.pressure} in</Text>}
|
||||
rightSide={
|
||||
<Text>{current.current.surface_pressure?.toFixed(0)} mbar</Text>
|
||||
}
|
||||
highlight='right'
|
||||
/>
|
||||
</Group>
|
||||
@@ -257,7 +290,7 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
/>
|
||||
</Group>
|
||||
}
|
||||
rightSide={<Text>{sunStates[0]?.sunrise}</Text>}
|
||||
rightSide={<Text>{sunrise}</Text>}
|
||||
highlight='left'
|
||||
/>
|
||||
<WeatherFeaturePill
|
||||
@@ -274,7 +307,7 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
/>
|
||||
</Group>
|
||||
}
|
||||
rightSide={<Text>{sunStates[0]?.sunset}</Text>}
|
||||
rightSide={<Text>{sunset}</Text>}
|
||||
highlight='left'
|
||||
/>
|
||||
</Group>
|
||||
|
||||
@@ -1,17 +1,78 @@
|
||||
import { Card, Group, SimpleGrid, Stack, Text } from '@mantine/core';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { textClasses } from 'styles';
|
||||
import type { ExtendedForecast } from 'types';
|
||||
import type { Daily } from 'types';
|
||||
import WeatherIcon from './WeatherIcon';
|
||||
|
||||
export default function ExtendedForecastCard({
|
||||
forecast,
|
||||
}: {
|
||||
forecast: ExtendedForecast[];
|
||||
}) {
|
||||
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 ExtendedForecastCard({ daily }: { daily: Daily | undefined }) {
|
||||
const { isMobile, theme } = useCommonHooks();
|
||||
const day = forecast.slice(2, 14).filter((item: ExtendedForecast) => item.isDaytime);
|
||||
const night = forecast.slice(2, 14).filter((item: ExtendedForecast) => !item.isDaytime);
|
||||
const forecast = daily?.time.map((_: any, index: number) => {
|
||||
const time = new Date(daily.time[index]);
|
||||
time.setMinutes(daily.time[index].getTimezoneOffset() + time.getMinutes());
|
||||
|
||||
return {
|
||||
apparentTemperatureMax: daily.apparent_temperature_max?.[index],
|
||||
apparentTemperatureMin: daily.apparent_temperature_min?.[index],
|
||||
daylightDuration: daily.daylight_duration?.[index],
|
||||
precipitationHours: daily.precipitation_hours?.[index],
|
||||
precipitationProbability: daily.precipitation_probability_max?.[index],
|
||||
precipitationSum: daily.precipitation_sum?.[index],
|
||||
sunrise: daily.sunrise[index],
|
||||
sunset: daily.sunset[index],
|
||||
sunshineDuration: daily.sunshine_duration?.[index],
|
||||
temperatureMax: daily.temperature_2m_max?.[index],
|
||||
temperatureMin: daily.temperature_2m_min?.[index],
|
||||
time: time,
|
||||
unIndexClearSkyMax: daily.uv_index_clear_sky_max?.[index],
|
||||
uvIndexMax: daily.uv_index_max?.[index],
|
||||
weatherCode: daily.weather_code?.[index],
|
||||
windDirection: daily.wind_direction_10m_dominant?.[index],
|
||||
windGusts: daily.wind_gusts_10m_max?.[index],
|
||||
windSpeed: daily.wind_speed_10m_max?.[index],
|
||||
};
|
||||
});
|
||||
return (
|
||||
<Card
|
||||
w={'100%'}
|
||||
@@ -37,13 +98,7 @@ export default function ExtendedForecastCard({
|
||||
Extended Forecast
|
||||
</Text>
|
||||
<SimpleGrid w={'100%'} pt={'.5rem'} cols={isMobile ? 3 : 6}>
|
||||
{day.map((item: ExtendedForecast, index: number) => {
|
||||
const short = item.shortForecast.includes('And')
|
||||
? item.shortForecast.substring(0, item.shortForecast.indexOf('And'))
|
||||
: item.shortForecast.includes('then')
|
||||
? item.shortForecast.substring(0, item.shortForecast.indexOf('then'))
|
||||
: item.shortForecast;
|
||||
|
||||
{forecast?.slice(1, 7).map((item: any) => {
|
||||
return (
|
||||
<Stack
|
||||
key={item.name}
|
||||
@@ -55,7 +110,11 @@ export default function ExtendedForecastCard({
|
||||
}}
|
||||
>
|
||||
<Group
|
||||
justify={item.name.length > 15 ? 'flex-start' : 'center'}
|
||||
justify={
|
||||
item.time.toLocaleDateString('en-US', { weekday: 'long' }).length > 15
|
||||
? 'flex-start'
|
||||
: 'center'
|
||||
}
|
||||
style={{
|
||||
width: '100%',
|
||||
whiteSpace: 'nowrap',
|
||||
@@ -66,16 +125,20 @@ export default function ExtendedForecastCard({
|
||||
>
|
||||
<Text
|
||||
className={
|
||||
item.name.length > 15 ? textClasses.autoScrollText : undefined
|
||||
item.time.toLocaleDateString('en-US', { weekday: 'long' }).length > 15
|
||||
? textClasses.autoScrollText
|
||||
: undefined
|
||||
}
|
||||
classNames={textClasses}
|
||||
>
|
||||
{item.name}
|
||||
{item.time.toLocaleDateString('en-US', { weekday: 'long' })}
|
||||
</Text>
|
||||
</Group>
|
||||
<WeatherIcon size='md' textDescription={short} />
|
||||
<WeatherIcon size='md' code={item.weatherCode} />
|
||||
<Group
|
||||
justify={short.length > 15 ? 'flex-start' : 'center'}
|
||||
justify={
|
||||
WeatherCodes[item.weatherCode].length > 15 ? 'flex-start' : 'center'
|
||||
}
|
||||
style={{
|
||||
width: '100%',
|
||||
whiteSpace: 'nowrap',
|
||||
@@ -85,15 +148,18 @@ export default function ExtendedForecastCard({
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
className={short.length > 15 ? textClasses.autoScrollText : undefined}
|
||||
className={
|
||||
WeatherCodes[item.weatherCode].length > 15
|
||||
? textClasses.autoScrollText
|
||||
: undefined
|
||||
}
|
||||
classNames={textClasses}
|
||||
>
|
||||
{short}
|
||||
{WeatherCodes[item.weatherCode]}
|
||||
</Text>
|
||||
</Group>
|
||||
<Text>
|
||||
{item.temperature}°{item.temperatureUnit}/{night[index].temperature}°
|
||||
{item.temperatureUnit}
|
||||
{item.temperatureMax.toFixed(0)}°F/{item.temperatureMin.toFixed(0)}°F
|
||||
</Text>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -11,16 +11,31 @@ import {
|
||||
XAxis,
|
||||
YAxis,
|
||||
} from 'recharts';
|
||||
import type { HourlyForecast } from 'types';
|
||||
import type { Hourly } from 'types';
|
||||
import WeatherTooltip from './WeatherTooltip';
|
||||
|
||||
export default function WeatherGraphs({
|
||||
hourlyForecast,
|
||||
}: {
|
||||
hourlyForecast: HourlyForecast[];
|
||||
}) {
|
||||
export default function WeatherGraphs({ hourly }: { hourly: Hourly | undefined }) {
|
||||
const colorPrecipitation = 'colorPrecipitation';
|
||||
const colorHumidity = 'colorHumidity';
|
||||
|
||||
const later = new Date();
|
||||
const now = new Date();
|
||||
later.setDate(now.getDate() + 1);
|
||||
const hourlyForecast = hourly?.time
|
||||
?.map((_: any, index: number) => {
|
||||
return {
|
||||
dewpoint: hourly.dew_point_2m?.[index].toFixed(0),
|
||||
isDaytime: hourly.is_day?.[index],
|
||||
name: hourly.time[index],
|
||||
startTime: hourly.time[index],
|
||||
endTime: hourly.time[index + 1],
|
||||
probabilityOfPrecipitation: hourly.precipitation_probability?.[index],
|
||||
temperature: hourly.temperature_2m?.[index].toFixed(0),
|
||||
relativeHumidity: hourly.relative_humidity_2m?.[index].toFixed(0),
|
||||
};
|
||||
})
|
||||
.filter((hour: any) => hour.startTime > now && hour.startTime < later);
|
||||
|
||||
return (
|
||||
<Stack
|
||||
style={{
|
||||
@@ -34,7 +49,7 @@ export default function WeatherGraphs({
|
||||
<XAxis
|
||||
type='category'
|
||||
stroke={'var(--mantine-color-primary-0)'}
|
||||
dataKey={(data: HourlyForecast) => {
|
||||
dataKey={(data) => {
|
||||
return new Date(data.startTime).toLocaleTimeString('en-US', {
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
@@ -49,7 +64,7 @@ export default function WeatherGraphs({
|
||||
}}
|
||||
/>
|
||||
<CartesianGrid stroke='#f5f5f522' />
|
||||
<Tooltip content={<WeatherTooltip />} />
|
||||
<Tooltip wrapperStyle={{ zIndex: 100 }} content={<WeatherTooltip />} />
|
||||
<Line
|
||||
unit={'°F'}
|
||||
type='monotone'
|
||||
@@ -67,9 +82,7 @@ export default function WeatherGraphs({
|
||||
unit={'°F'}
|
||||
type='monotone'
|
||||
name='Dew Point'
|
||||
dataKey={(data: HourlyForecast) => {
|
||||
return (data.dewpoint.value * 9) / 5 + 32;
|
||||
}}
|
||||
dataKey='dewpoint'
|
||||
stroke={'var(--mantine-color-accent-0)'}
|
||||
strokeWidth={2}
|
||||
dot={{
|
||||
@@ -78,7 +91,7 @@ export default function WeatherGraphs({
|
||||
fill: 'var(--mantine-color-accent-0)',
|
||||
}}
|
||||
/>
|
||||
<Legend style={{ background: 'var(--mantine-color-search-0)' }} />
|
||||
<Legend wrapperStyle={{ zIndex: 0, position: 'absolute' }} />
|
||||
</ComposedChart>
|
||||
</ResponsiveContainer>
|
||||
<ResponsiveContainer width={'100%'} height={150}>
|
||||
@@ -112,7 +125,7 @@ export default function WeatherGraphs({
|
||||
<XAxis
|
||||
type='category'
|
||||
stroke={'var(--mantine-color-primary-0)'}
|
||||
dataKey={(data: HourlyForecast) => {
|
||||
dataKey={(data) => {
|
||||
return new Date(data.startTime).toLocaleTimeString('en-US', {
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
@@ -121,14 +134,12 @@ export default function WeatherGraphs({
|
||||
/>
|
||||
<YAxis stroke={'var(--mantine-color-primary-0)'} unit={'%'} domain={[0, 100]} />
|
||||
<CartesianGrid stroke='#f5f5f522' />
|
||||
<Tooltip content={<WeatherTooltip />} />
|
||||
<Tooltip wrapperStyle={{ zIndex: 100 }} content={<WeatherTooltip />} />
|
||||
<Area
|
||||
unit={'%'}
|
||||
type='monotone'
|
||||
name='Humidity'
|
||||
dataKey={(data: HourlyForecast) => {
|
||||
return data.relativeHumidity.value;
|
||||
}}
|
||||
dataKey={'relativeHumidity'}
|
||||
stroke={'var(--mantine-color-primary-0)'}
|
||||
strokeWidth={2}
|
||||
fill={`url(#${colorPrecipitation})`}
|
||||
@@ -142,9 +153,7 @@ export default function WeatherGraphs({
|
||||
unit={'%'}
|
||||
type='monotone'
|
||||
name='Precipitation'
|
||||
dataKey={(data: HourlyForecast) => {
|
||||
return data.probabilityOfPrecipitation.value;
|
||||
}}
|
||||
dataKey={'probabilityOfPrecipitation'}
|
||||
stroke={'var(--mantine-color-accent-0)'}
|
||||
strokeWidth={2}
|
||||
fill={`url(#${colorHumidity})`}
|
||||
@@ -154,7 +163,7 @@ export default function WeatherGraphs({
|
||||
fill: 'var(--mantine-color-accent-0)',
|
||||
}}
|
||||
/>
|
||||
<Legend style={{ background: 'var(--mantine-color-search-0)' }} />
|
||||
<Legend wrapperStyle={{ zIndex: 0, position: 'absolute' }} />
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</Stack>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Group, Image } from '@mantine/core';
|
||||
import { FaArrowRight } from 'react-icons/fa';
|
||||
import { Image } from '@mantine/core';
|
||||
import CloudyIcon from '../../assets/weather/cloudy.svg';
|
||||
import HazeIcon from '../../assets/weather/haze.svg';
|
||||
import HeavyRainIcon from '../../assets/weather/heavy-rain.svg';
|
||||
@@ -9,168 +8,166 @@ import SleetIcon from '../../assets/weather/sleet.svg';
|
||||
import SnowIcon from '../../assets/weather/snow.svg';
|
||||
import SunnyIcon from '../../assets/weather/sunny.svg';
|
||||
import ThunderstormIcon from '../../assets/weather/thunderstorm.svg';
|
||||
import WindyIcon from '../../assets/weather/windy.svg';
|
||||
|
||||
export default function WeatherIcon({
|
||||
size,
|
||||
textDescription,
|
||||
code,
|
||||
}: {
|
||||
size: string;
|
||||
textDescription: string;
|
||||
code: number | undefined;
|
||||
}) {
|
||||
const icon = textDescription.includes('then')
|
||||
? [
|
||||
textDescription.substring(0, textDescription.trim().indexOf('then')),
|
||||
textDescription.substring(textDescription.trim().indexOf('then') + 4).trim(),
|
||||
]
|
||||
: [textDescription.trim()];
|
||||
|
||||
const lookupSource = (icon: any) => {
|
||||
switch (icon.trim()) {
|
||||
case 'Ash':
|
||||
const lookupSource = (code: any) => {
|
||||
switch (code) {
|
||||
case 0:
|
||||
return {
|
||||
src: HazeIcon,
|
||||
alt: 'HazeIcon',
|
||||
src: SunnyIcon,
|
||||
alt: 'SunnyIcon',
|
||||
};
|
||||
case 'Broken Clouds':
|
||||
|
||||
case 1:
|
||||
return {
|
||||
src: PartlyCloudyIcon,
|
||||
alt: 'PartlyCloudyIcon',
|
||||
};
|
||||
case 'Chance Rain Showers':
|
||||
case 2:
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
src: PartlyCloudyIcon,
|
||||
alt: 'PartlyCloudyIcon',
|
||||
};
|
||||
case 'Chance Showers':
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
case 'Slight Chance Showers':
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
case 'Cloudy':
|
||||
case 3:
|
||||
return {
|
||||
src: CloudyIcon,
|
||||
alt: 'CloudyIcon',
|
||||
};
|
||||
case 'Dust':
|
||||
|
||||
case 45:
|
||||
return {
|
||||
src: HazeIcon,
|
||||
alt: 'HazeIcon',
|
||||
};
|
||||
case 'Drizzle':
|
||||
case 48:
|
||||
return {
|
||||
src: HazeIcon,
|
||||
alt: 'HazeIcon',
|
||||
};
|
||||
|
||||
case 51:
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
case 'Fog':
|
||||
case 53:
|
||||
return {
|
||||
src: HazeIcon,
|
||||
alt: 'HazeIcon',
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
case 'Freezing Rain':
|
||||
case 55:
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
|
||||
case 56:
|
||||
return {
|
||||
src: SleetIcon,
|
||||
alt: 'SleetIcon',
|
||||
};
|
||||
case 'Haze':
|
||||
case 57:
|
||||
return {
|
||||
src: HazeIcon,
|
||||
alt: 'HazeIcon',
|
||||
src: SleetIcon,
|
||||
alt: 'SleetIcon',
|
||||
};
|
||||
case 'Heavy Rain':
|
||||
|
||||
case 61:
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
case 63:
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
case 65:
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
|
||||
case 66:
|
||||
return {
|
||||
src: SleetIcon,
|
||||
alt: 'SleetIcon',
|
||||
};
|
||||
case 67:
|
||||
return {
|
||||
src: SleetIcon,
|
||||
alt: 'SleetIcon',
|
||||
};
|
||||
|
||||
case 71:
|
||||
return {
|
||||
src: SnowIcon,
|
||||
alt: 'SnowIcon',
|
||||
};
|
||||
case 73:
|
||||
return {
|
||||
src: SnowIcon,
|
||||
alt: 'SnowIcon',
|
||||
};
|
||||
case 75:
|
||||
return {
|
||||
src: SnowIcon,
|
||||
alt: 'SnowIcon',
|
||||
};
|
||||
|
||||
case 77:
|
||||
return {
|
||||
src: SnowIcon,
|
||||
alt: 'SnowIcon',
|
||||
};
|
||||
|
||||
case 80:
|
||||
return {
|
||||
src: HeavyRainIcon,
|
||||
alt: 'HeavyRainIcon',
|
||||
};
|
||||
case 'Heavy Snow':
|
||||
case 81:
|
||||
return {
|
||||
src: HeavyRainIcon,
|
||||
alt: 'HeavyRainIcon',
|
||||
};
|
||||
case 82:
|
||||
return {
|
||||
src: HeavyRainIcon,
|
||||
alt: 'HeavyRainIcon',
|
||||
};
|
||||
|
||||
case 85:
|
||||
return {
|
||||
src: SnowIcon,
|
||||
alt: 'SnowIcon',
|
||||
};
|
||||
case 'Light Rain':
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
case 'Mist':
|
||||
return {
|
||||
src: HazeIcon,
|
||||
alt: 'HazeIcon',
|
||||
};
|
||||
case 'Moderate Rain':
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
case 'Mostly Cloudy':
|
||||
return {
|
||||
src: CloudyIcon,
|
||||
alt: 'CloudyIcon',
|
||||
};
|
||||
case 'Overcast Clouds':
|
||||
return {
|
||||
src: PartlyCloudyIcon,
|
||||
alt: 'PartlyCloudyIcon',
|
||||
};
|
||||
case 'Patchy Fog':
|
||||
return {
|
||||
src: HazeIcon,
|
||||
alt: 'HazeIcon',
|
||||
};
|
||||
case 'Partly Sunny':
|
||||
return {
|
||||
src: PartlyCloudyIcon,
|
||||
alt: 'PartlyCloudyIcon',
|
||||
};
|
||||
case 'Rain':
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
case 'Scattered Clouds':
|
||||
return {
|
||||
src: PartlyCloudyIcon,
|
||||
alt: 'PartlyCloudyIcon',
|
||||
};
|
||||
case 'Showers':
|
||||
return {
|
||||
src: RainIcon,
|
||||
alt: 'RainIcon',
|
||||
};
|
||||
case 'Sleet':
|
||||
return {
|
||||
src: SleetIcon,
|
||||
alt: 'SleetIcon',
|
||||
};
|
||||
case 'Smoke':
|
||||
return {
|
||||
src: HazeIcon,
|
||||
alt: 'HazeIcon',
|
||||
};
|
||||
case 'Snow':
|
||||
case 86:
|
||||
return {
|
||||
src: SnowIcon,
|
||||
alt: 'SnowIcon',
|
||||
};
|
||||
case 'Squall':
|
||||
return {
|
||||
src: WindyIcon,
|
||||
alt: 'WindyIcon',
|
||||
};
|
||||
case 'Thunderstorm':
|
||||
|
||||
case 95:
|
||||
return {
|
||||
src: ThunderstormIcon,
|
||||
alt: 'ThunderstormIcon',
|
||||
};
|
||||
case 'Tornado':
|
||||
case 96:
|
||||
return {
|
||||
src: WindyIcon,
|
||||
alt: 'WindyIcon',
|
||||
src: ThunderstormIcon,
|
||||
alt: 'ThunderstormIcon',
|
||||
};
|
||||
case 99:
|
||||
return {
|
||||
src: ThunderstormIcon,
|
||||
alt: 'ThunderstormIcon',
|
||||
};
|
||||
|
||||
default:
|
||||
@@ -182,61 +179,14 @@ export default function WeatherIcon({
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{icon.length === 1 ? (
|
||||
<Image
|
||||
style={
|
||||
size === 'lg'
|
||||
? { width: '150px', height: '150px' }
|
||||
: { width: '75px', height: '75px' }
|
||||
}
|
||||
src={lookupSource(icon[0]).src}
|
||||
alt={lookupSource(icon[0]).alt}
|
||||
/>
|
||||
) : (
|
||||
<Group
|
||||
pos={'relative'}
|
||||
style={
|
||||
size === 'lg'
|
||||
? { width: '150px', height: '150px' }
|
||||
: { width: '75px', height: '75px' }
|
||||
}
|
||||
align='center'
|
||||
justify='center'
|
||||
>
|
||||
<Image
|
||||
style={{
|
||||
mask: 'linear-gradient(105deg, rgba(0, 0, 0, 1) 52%, rgba(0, 0, 0, 0) 56%)',
|
||||
}}
|
||||
pos={'absolute'}
|
||||
left={-8}
|
||||
src={lookupSource(icon[0]).src}
|
||||
alt={lookupSource(icon[0]).alt}
|
||||
/>
|
||||
<Image
|
||||
style={{
|
||||
mask: 'linear-gradient(105deg, rgba(0, 0, 0, 0) 44%, rgba(0, 0, 0, 1) 48%)',
|
||||
}}
|
||||
pos={'absolute'}
|
||||
right={-8}
|
||||
src={lookupSource(icon[1]).src}
|
||||
alt={lookupSource(icon[1]).alt}
|
||||
/>
|
||||
<FaArrowRight
|
||||
size={28}
|
||||
style={{
|
||||
color: 'var(--mantine-color-background-0)',
|
||||
position: 'absolute',
|
||||
stroke: 'var(--mantine-color-primary-0)',
|
||||
strokeWidth: 16,
|
||||
backgroundColor:
|
||||
'color-mix(in srgb, var(--mantine-color-accent-0), transparent 20%)',
|
||||
borderRadius: '50%',
|
||||
padding: '5px',
|
||||
}}
|
||||
/>
|
||||
</Group>
|
||||
)}
|
||||
</>
|
||||
<Image
|
||||
style={
|
||||
size === 'lg'
|
||||
? { width: '150px', height: '150px' }
|
||||
: { width: '75px', height: '75px' }
|
||||
}
|
||||
src={lookupSource(code).src}
|
||||
alt={lookupSource(code).alt}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,34 +1,23 @@
|
||||
import { Center, Group, Modal, Stack, Text } from '@mantine/core';
|
||||
import { useCommonHooks, useWeatherAPI } from 'hooks';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { modalClasses } from 'styles';
|
||||
|
||||
import type { CurrentWeather as CW, ExtendedForecast, HourlyForecast } from 'types';
|
||||
import type { MeteoWeather } from 'types';
|
||||
import CurrentWeather from './CurrentWeather';
|
||||
import ExtendedForecastCard from './ExtendedForecastCard';
|
||||
import WeatherGraphs from './WeatherGraphs';
|
||||
|
||||
export function WeatherModal({
|
||||
current,
|
||||
extendedForecast,
|
||||
weatherModalOpened,
|
||||
handleResetSearch,
|
||||
closeWeatherModal,
|
||||
}: {
|
||||
current: CW;
|
||||
extendedForecast: ExtendedForecast[];
|
||||
current: MeteoWeather | undefined;
|
||||
weatherModalOpened: boolean;
|
||||
handleResetSearch: () => void;
|
||||
closeWeatherModal: () => void;
|
||||
}) {
|
||||
const { isMobile, currentUser, currentLocation } = useCommonHooks();
|
||||
const { data: hourly } = useWeatherAPI({
|
||||
endpoint: 'hourly',
|
||||
office: currentLocation.office,
|
||||
x: currentLocation.x,
|
||||
y: currentLocation.y,
|
||||
});
|
||||
const hourlyForecast: HourlyForecast[] =
|
||||
hourly?.properties?.periods?.slice(1, 25) || [];
|
||||
const { isMobile, currentUser } = useCommonHooks();
|
||||
|
||||
return (
|
||||
<Modal.Root
|
||||
@@ -68,8 +57,8 @@ export function WeatherModal({
|
||||
<Center w={'100%'}>
|
||||
<Stack w={'100%'}>
|
||||
<CurrentWeather current={current} />
|
||||
<WeatherGraphs hourlyForecast={hourlyForecast} />
|
||||
<ExtendedForecastCard forecast={extendedForecast} />
|
||||
<WeatherGraphs hourly={current?.hourly} />
|
||||
<ExtendedForecastCard daily={current?.daily} />
|
||||
</Stack>
|
||||
</Center>
|
||||
</Modal.Body>
|
||||
|
||||
@@ -10,6 +10,9 @@ function WeatherTooltip({ payload, active }: any) {
|
||||
borderRadius: '8px',
|
||||
}}
|
||||
>
|
||||
<Text size='md' c='var(--mantine-color-primary-0)'>
|
||||
{payload[0]?.payload.startTime?.toLocaleString()}
|
||||
</Text>
|
||||
{payload.map((item: any) => (
|
||||
<Text
|
||||
key={item.name}
|
||||
|
||||
Reference in New Issue
Block a user