This commit is contained in:
35
package-lock.json
generated
35
package-lock.json
generated
@@ -21,7 +21,7 @@
|
|||||||
"@tanstack/react-query-persist-client": "^5.101.2",
|
"@tanstack/react-query-persist-client": "^5.101.2",
|
||||||
"@tanstack/react-table": "^8.21.3",
|
"@tanstack/react-table": "^8.21.3",
|
||||||
"idb-keyval": "^6.3.0",
|
"idb-keyval": "^6.3.0",
|
||||||
"jotai": "^2.20.1",
|
"jotai": "^2.20.2",
|
||||||
"openmeteo": "^1.2.3",
|
"openmeteo": "^1.2.3",
|
||||||
"react": "^19.2.7",
|
"react": "^19.2.7",
|
||||||
"react-dom": "^19.2.7",
|
"react-dom": "^19.2.7",
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
"@vitest/coverage-v8": "^4.1.10",
|
"@vitest/coverage-v8": "^4.1.10",
|
||||||
"@vitest/ui": "^4.1.10",
|
"@vitest/ui": "^4.1.10",
|
||||||
"typescript": "^7.0.2",
|
"typescript": "^7.0.2",
|
||||||
"vite": "^8.1.4",
|
"vite": "^8.1.5",
|
||||||
"vite-plugin-dts": "~5.0.3",
|
"vite-plugin-dts": "~5.0.3",
|
||||||
"vite-tsconfig-paths": "^6.1.1",
|
"vite-tsconfig-paths": "^6.1.1",
|
||||||
"vitest": "^4.1.10"
|
"vitest": "^4.1.10"
|
||||||
@@ -1918,9 +1918,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jotai": {
|
"node_modules/jotai": {
|
||||||
"version": "2.20.1",
|
"version": "2.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/jotai/-/jotai-2.20.1.tgz",
|
"resolved": "https://registry.npmjs.org/jotai/-/jotai-2.20.2.tgz",
|
||||||
"integrity": "sha512-dnuKfU/GLi8B28RRMjQ3AfoN7kfzP8o41+AX2FmITZqEMY8PHnjABq+VkEooomLwYaGjda+pgy0yFSjaHX/ZPg==",
|
"integrity": "sha512-aHB4CNb9qRcyf0mwSB6EO5bCGAjx8cTwFgOFCE2leOnTzqACbnSWG8XoWB3LxCT1Qoj03I1OWAHszDmN4uHb/w==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.20.0"
|
"node": ">=12.20.0"
|
||||||
},
|
},
|
||||||
@@ -3097,15 +3097,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "8.1.4",
|
"version": "8.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz",
|
||||||
"integrity": "sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==",
|
"integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lightningcss": "^1.32.0",
|
"lightningcss": "^1.32.0",
|
||||||
"picomatch": "^4.0.5",
|
"picomatch": "^4.0.5",
|
||||||
"postcss": "^8.5.16",
|
"postcss": "^8.5.17",
|
||||||
"rolldown": "~1.1.4",
|
"rolldown": "~1.1.5",
|
||||||
"tinyglobby": "^0.2.17"
|
"tinyglobby": "^0.2.17"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -3233,6 +3233,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vite-tsconfig-paths/node_modules/typescript": {
|
||||||
|
"version": "5.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||||
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"bin": {
|
||||||
|
"tsc": "bin/tsc",
|
||||||
|
"tsserver": "bin/tsserver"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vitest": {
|
"node_modules/vitest": {
|
||||||
"version": "4.1.10",
|
"version": "4.1.10",
|
||||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz",
|
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz",
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
"@tanstack/react-query-persist-client": "^5.101.2",
|
"@tanstack/react-query-persist-client": "^5.101.2",
|
||||||
"@tanstack/react-table": "^8.21.3",
|
"@tanstack/react-table": "^8.21.3",
|
||||||
"idb-keyval": "^6.3.0",
|
"idb-keyval": "^6.3.0",
|
||||||
"jotai": "^2.20.1",
|
"jotai": "^2.20.2",
|
||||||
"openmeteo": "^1.2.3",
|
"openmeteo": "^1.2.3",
|
||||||
"react": "^19.2.7",
|
"react": "^19.2.7",
|
||||||
"react-dom": "^19.2.7",
|
"react-dom": "^19.2.7",
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
"@vitest/coverage-v8": "^4.1.10",
|
"@vitest/coverage-v8": "^4.1.10",
|
||||||
"@vitest/ui": "^4.1.10",
|
"@vitest/ui": "^4.1.10",
|
||||||
"typescript": "^7.0.2",
|
"typescript": "^7.0.2",
|
||||||
"vite": "^8.1.4",
|
"vite": "^8.1.5",
|
||||||
"vite-plugin-dts": "~5.0.3",
|
"vite-plugin-dts": "~5.0.3",
|
||||||
"vite-tsconfig-paths": "^6.1.1",
|
"vite-tsconfig-paths": "^6.1.1",
|
||||||
"vitest": "^4.1.10"
|
"vitest": "^4.1.10"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { datePickerInputClasses, selectClasses } from 'styles';
|
|||||||
|
|
||||||
declare module '@tanstack/react-table' {
|
declare module '@tanstack/react-table' {
|
||||||
//allows us to define custom properties for our columns
|
//allows us to define custom properties for our columns
|
||||||
interface ColumnMeta<TData extends RowData, TValue> {
|
interface ColumnMeta<_TData extends RowData, _TValue> {
|
||||||
filterVariant?:
|
filterVariant?:
|
||||||
| 'text'
|
| 'text'
|
||||||
| 'range'
|
| 'range'
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ export default function CurrentWeather({
|
|||||||
? textClasses.autoScrollText
|
? textClasses.autoScrollText
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
fz={isMobile ? 12 : 18}
|
||||||
classNames={textClasses}
|
classNames={textClasses}
|
||||||
style={{ lineHeight: 1 }}
|
style={{ lineHeight: 1 }}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,18 +1,26 @@
|
|||||||
import { ActionIcon, Box, Card, Group, Stack, Text } from '@mantine/core';
|
import { ActionIcon, Box, Card, Group, Stack, Text } from '@mantine/core';
|
||||||
import { FaArrowDown, FaArrowUp, FaLocationArrow, FaSun, FaWind } from 'react-icons/fa';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { FaX } from 'react-icons/fa6';
|
import { FaLocationArrow, FaSun, FaWind } from 'react-icons/fa';
|
||||||
|
import { FaDroplet, FaX } from 'react-icons/fa6';
|
||||||
import { WiRain, WiSunrise, WiSunset } from 'react-icons/wi';
|
import { WiRain, WiSunrise, WiSunset } from 'react-icons/wi';
|
||||||
|
import { textClasses } from 'styles';
|
||||||
import { WeatherCodes } from 'types';
|
import { WeatherCodes } from 'types';
|
||||||
import WeatherFeaturePill from './WeatherFeaturePill';
|
import WeatherFeaturePill from './WeatherFeaturePill';
|
||||||
|
import WeatherGraphs from './WeatherGraphs';
|
||||||
import WeatherIcon from './WeatherIcon';
|
import WeatherIcon from './WeatherIcon';
|
||||||
|
|
||||||
export default function ExtendedForecastDetails({
|
export default function ExtendedForecastDetails({
|
||||||
selectedDay,
|
selectedDay,
|
||||||
setSelectedDay,
|
setSelectedDay,
|
||||||
|
selectedHourly,
|
||||||
|
setSelectedHourly,
|
||||||
}: {
|
}: {
|
||||||
selectedDay: any;
|
selectedDay: any;
|
||||||
setSelectedDay: (day: any) => void;
|
setSelectedDay: (day: any) => void;
|
||||||
|
selectedHourly: any;
|
||||||
|
setSelectedHourly: (hourly: any) => void;
|
||||||
}) {
|
}) {
|
||||||
|
const { isMobile } = useCommonHooks();
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
h={'100%'}
|
h={'100%'}
|
||||||
@@ -24,7 +32,8 @@ export default function ExtendedForecastDetails({
|
|||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
overflow: 'visible',
|
overflow: 'visible',
|
||||||
cursor: 'default',
|
cursor: 'default',
|
||||||
boxShadow: '15px 15px 3px var(--mantine-color-border-0)',
|
boxShadow:
|
||||||
|
'15px 15px 2px color-mix(in srgb, var(--mantine-color-border-0), transparent 50%)',
|
||||||
}}
|
}}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -41,6 +50,7 @@ export default function ExtendedForecastDetails({
|
|||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedDay(undefined);
|
setSelectedDay(undefined);
|
||||||
|
setSelectedHourly(undefined);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FaX />
|
<FaX />
|
||||||
@@ -64,10 +74,96 @@ export default function ExtendedForecastDetails({
|
|||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Stack align='center' p={16}>
|
<Stack align='center' p={16}>
|
||||||
<WeatherIcon size={'xl'} code={selectedDay.weatherCode} />
|
<Group>
|
||||||
<Text fz={'1rem'} fw={600} mt={'-32px'}>
|
<Stack
|
||||||
{WeatherCodes[Number(selectedDay.weatherCode)]}
|
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>
|
</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>
|
||||||
<Group justify='space-between'>
|
<Group justify='space-between'>
|
||||||
<Stack gap={4}>
|
<Stack gap={4}>
|
||||||
@@ -173,76 +269,27 @@ export default function ExtendedForecastDetails({
|
|||||||
</Stack>
|
</Stack>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<Group w={'100%'} gap={4} justify='space-between'>
|
<Group justify='space-between'>
|
||||||
<Box w={'48%'}>
|
<Stack align='center' justify='center' gap={0}>
|
||||||
<WeatherFeaturePill
|
<Box
|
||||||
leftSide={
|
style={{
|
||||||
<Group gap={2}>
|
border: '2px solid var(--mantine-color-primary-0)',
|
||||||
<FaArrowUp size={16} />
|
borderRadius: '100%',
|
||||||
<Text>High Temp</Text>
|
aspectRatio: 1,
|
||||||
</Group>
|
width: 'fit-content',
|
||||||
}
|
padding: '.75rem',
|
||||||
rightSide={
|
display: 'flex',
|
||||||
<Text>
|
backgroundColor: 'var(--mantine-color-background-0)',
|
||||||
{selectedDay.temperatureMax.toFixed(0)}°<sup>F</sup>
|
}}
|
||||||
</Text>
|
>
|
||||||
}
|
<FaDroplet
|
||||||
highlight='right'
|
style={{
|
||||||
|
color: 'var(--mantine-color-accent-0)',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box w={'48%'}>
|
</Stack>
|
||||||
<WeatherFeaturePill
|
<Stack gap={4}>
|
||||||
leftSide={
|
|
||||||
<Group gap={2}>
|
|
||||||
<FaArrowDown size={16} />
|
|
||||||
<Text>Low Temp</Text>
|
|
||||||
</Group>
|
|
||||||
}
|
|
||||||
rightSide={
|
|
||||||
<Text>
|
|
||||||
{selectedDay.temperatureMin.toFixed(0)}°<sup>F</sup>
|
|
||||||
</Text>
|
|
||||||
}
|
|
||||||
highlight='right'
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Group>
|
|
||||||
<Group w={'100%'} gap={4} justify='space-between'>
|
|
||||||
<Box w={'48%'}>
|
|
||||||
<WeatherFeaturePill
|
|
||||||
leftSide={
|
|
||||||
<Group gap={2}>
|
|
||||||
<FaArrowUp size={16} />
|
|
||||||
<Text>Feels Like High</Text>
|
|
||||||
</Group>
|
|
||||||
}
|
|
||||||
rightSide={
|
|
||||||
<Text>
|
|
||||||
{selectedDay.apparentTemperatureMax.toFixed(0)}°<sup>F</sup>
|
|
||||||
</Text>
|
|
||||||
}
|
|
||||||
highlight='right'
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<Box w={'48%'}>
|
|
||||||
<WeatherFeaturePill
|
|
||||||
leftSide={
|
|
||||||
<Group gap={2}>
|
|
||||||
<FaArrowDown size={16} />
|
|
||||||
<Text>Feels Like Temp</Text>
|
|
||||||
</Group>
|
|
||||||
}
|
|
||||||
rightSide={
|
|
||||||
<Text>
|
|
||||||
{selectedDay.apparentTemperatureMin.toFixed(0)}°<sup>F</sup>
|
|
||||||
</Text>
|
|
||||||
}
|
|
||||||
highlight='right'
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Group>
|
|
||||||
<Group w={'100%'} gap={4} justify='space-between'>
|
|
||||||
<Box w={'48%'}>
|
|
||||||
<WeatherFeaturePill
|
<WeatherFeaturePill
|
||||||
leftSide={
|
leftSide={
|
||||||
<Group gap={2}>
|
<Group gap={2}>
|
||||||
@@ -253,8 +300,6 @@ export default function ExtendedForecastDetails({
|
|||||||
rightSide={<Text>{selectedDay.precipitationProbability}%</Text>}
|
rightSide={<Text>{selectedDay.precipitationProbability}%</Text>}
|
||||||
highlight='right'
|
highlight='right'
|
||||||
/>
|
/>
|
||||||
</Box>
|
|
||||||
<Box w={'48%'}>
|
|
||||||
<WeatherFeaturePill
|
<WeatherFeaturePill
|
||||||
leftSide={
|
leftSide={
|
||||||
<Group gap={2}>
|
<Group gap={2}>
|
||||||
@@ -265,8 +310,9 @@ export default function ExtendedForecastDetails({
|
|||||||
rightSide={<Text>{selectedDay.precipitationSum.toFixed(2)} in.</Text>}
|
rightSide={<Text>{selectedDay.precipitationSum.toFixed(2)} in.</Text>}
|
||||||
highlight='right'
|
highlight='right'
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Stack>
|
||||||
</Group>
|
</Group>
|
||||||
|
<WeatherGraphs hourly={selectedHourly} formatted />
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,18 +13,24 @@ import {
|
|||||||
YAxis,
|
YAxis,
|
||||||
} from 'recharts';
|
} from 'recharts';
|
||||||
import { selectClasses } from 'styles';
|
import { selectClasses } from 'styles';
|
||||||
import type { Hourly } from 'types';
|
|
||||||
import WeatherTooltip from './WeatherTooltip';
|
import WeatherTooltip from './WeatherTooltip';
|
||||||
|
|
||||||
export default function WeatherGraphs({ hourly }: { hourly: Hourly | undefined }) {
|
export default function WeatherGraphs({
|
||||||
|
hourly,
|
||||||
|
formatted,
|
||||||
|
}: {
|
||||||
|
hourly: any;
|
||||||
|
formatted?: boolean;
|
||||||
|
}) {
|
||||||
const colorPrecipitation = 'colorPrecipitation';
|
const colorPrecipitation = 'colorPrecipitation';
|
||||||
const colorHumidity = 'colorHumidity';
|
const colorHumidity = 'colorHumidity';
|
||||||
const [timeFrame, setTimeFrame] = useState(24);
|
const [timeFrame, setTimeFrame] = useState(24);
|
||||||
const later = new Date();
|
const later = new Date();
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
later.setTime(now.getTime() + timeFrame * 60 * 60 * 1000);
|
later.setTime(now.getTime() + timeFrame * 60 * 60 * 1000);
|
||||||
const hourlyForecast = hourly?.time
|
const hourlyForecast = formatted
|
||||||
|
? hourly
|
||||||
|
: hourly?.time
|
||||||
?.map((_: any, index: number) => {
|
?.map((_: any, index: number) => {
|
||||||
return {
|
return {
|
||||||
dewpoint: hourly.dew_point_2m?.[index].toFixed(0),
|
dewpoint: hourly.dew_point_2m?.[index].toFixed(0),
|
||||||
@@ -39,8 +45,10 @@ export default function WeatherGraphs({ hourly }: { hourly: Hourly | undefined }
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter((hour: any) => hour.startTime > now && hour.startTime < later);
|
.filter((hour: any) => hour.startTime > now && hour.startTime < later);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
|
w={'100%'}
|
||||||
style={{
|
style={{
|
||||||
background: 'var(--mantine-color-search-0)',
|
background: 'var(--mantine-color-search-0)',
|
||||||
padding: '.5rem',
|
padding: '.5rem',
|
||||||
@@ -49,6 +57,7 @@ export default function WeatherGraphs({ hourly }: { hourly: Hourly | undefined }
|
|||||||
marginTop: '.5rem',
|
marginTop: '.5rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{!formatted && (
|
||||||
<Group m={0} p={0} mt={'-1.5rem'}>
|
<Group m={0} p={0} mt={'-1.5rem'}>
|
||||||
<Select
|
<Select
|
||||||
classNames={{
|
classNames={{
|
||||||
@@ -71,6 +80,7 @@ export default function WeatherGraphs({ hourly }: { hourly: Hourly | undefined }
|
|||||||
onChange={(value: any) => setTimeFrame(value)}
|
onChange={(value: any) => setTimeFrame(value)}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
|
)}
|
||||||
<ResponsiveContainer width={'100%'} height={150}>
|
<ResponsiveContainer width={'100%'} height={150}>
|
||||||
<ComposedChart data={hourlyForecast}>
|
<ComposedChart data={hourlyForecast}>
|
||||||
<XAxis
|
<XAxis
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Group, Modal, Overlay, Stack, Text } from '@mantine/core';
|
import { Group, Modal, Overlay, Stack, Text } from '@mantine/core';
|
||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { modalClasses } from 'styles';
|
import { modalClasses } from 'styles';
|
||||||
import type { MeteoWeather } from 'types';
|
import type { MeteoWeather } from 'types';
|
||||||
import CurrentWeather from './CurrentWeather';
|
import CurrentWeather from './CurrentWeather';
|
||||||
@@ -21,6 +21,35 @@ export function WeatherModal({
|
|||||||
}) {
|
}) {
|
||||||
const { isMobile, currentUser } = useCommonHooks();
|
const { isMobile, currentUser } = useCommonHooks();
|
||||||
const [selectedDay, setSelectedDay] = useState<any>(undefined);
|
const [selectedDay, setSelectedDay] = useState<any>(undefined);
|
||||||
|
const [selectedHourly, setSelectedHourly] = useState<any>(undefined);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedDay && current) {
|
||||||
|
const later = new Date().setTime(selectedDay.time.getTime() + 24 * 60 * 60 * 1000);
|
||||||
|
setSelectedHourly(
|
||||||
|
current?.hourly.time
|
||||||
|
?.map((_: any, index: number) => {
|
||||||
|
return {
|
||||||
|
dewpoint: current?.hourly.dew_point_2m?.[index].toFixed(0),
|
||||||
|
isDaytime: current?.hourly.is_day?.[index],
|
||||||
|
name: current?.hourly.time[index].toLocaleString('en-us'),
|
||||||
|
startTime: current?.hourly.time[index],
|
||||||
|
endTime: current?.hourly.time[index + 1],
|
||||||
|
probabilityOfPrecipitation:
|
||||||
|
current?.hourly.precipitation_probability?.[index],
|
||||||
|
temperature: current?.hourly.temperature_2m?.[index].toFixed(0),
|
||||||
|
apparentTemperature:
|
||||||
|
current?.hourly.apparent_temperature?.[index].toFixed(0),
|
||||||
|
relativeHumidity: current?.hourly.relative_humidity_2m?.[index].toFixed(0),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(
|
||||||
|
(hour: any) => hour.startTime >= selectedDay.time && hour.startTime < later,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [selectedDay]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal.Root
|
<Modal.Root
|
||||||
fullScreen={isMobile}
|
fullScreen={isMobile}
|
||||||
@@ -80,6 +109,8 @@ export function WeatherModal({
|
|||||||
<ExtendedForecastDetails
|
<ExtendedForecastDetails
|
||||||
selectedDay={selectedDay}
|
selectedDay={selectedDay}
|
||||||
setSelectedDay={setSelectedDay}
|
setSelectedDay={setSelectedDay}
|
||||||
|
selectedHourly={selectedHourly}
|
||||||
|
setSelectedHourly={setSelectedHourly}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|||||||
Reference in New Issue
Block a user