diff --git a/.gitignore b/.gitignore index 3892bed..c9a9d6e 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ dist-ssr *.sw? .env +package-lock.json \ No newline at end of file diff --git a/src/components/HelpModal/HelpSection.tsx b/src/components/HelpModal/HelpSection.tsx index 9db17d2..b886287 100644 --- a/src/components/HelpModal/HelpSection.tsx +++ b/src/components/HelpModal/HelpSection.tsx @@ -1,8 +1,9 @@ import { Divider, Group } from '@mantine/core'; import { useCommonHooks } from 'hooks'; +import type { SearchShortcut } from 'types'; import HintItem from './HintItem'; -function HelpSection({ name, items }: { name: string; items: object[] }) { +function HelpSection({ name, items }: { name: string; items: SearchShortcut[] }) { const { theme } = useCommonHooks(); return ( <> @@ -30,8 +31,10 @@ function HelpSection({ name, items }: { name: string; items: object[] }) { }} > {items - ?.toSorted((a: any, b: any) => (a.command > b.command ? 1 : -1)) - .map((item: any) => ( + ?.toSorted((a: SearchShortcut, b: SearchShortcut) => + a.command > b.command ? 1 : -1, + ) + .map((item: SearchShortcut) => ( ))} diff --git a/src/components/WeatherModal/CurrentWeather.tsx b/src/components/WeatherModal/CurrentWeather.tsx index 897a4a1..5b40579 100644 --- a/src/components/WeatherModal/CurrentWeather.tsx +++ b/src/components/WeatherModal/CurrentWeather.tsx @@ -5,7 +5,7 @@ import { useEffect, useState } from 'react'; import { FaLongArrowAltDown, FaLongArrowAltUp, FaWind } from 'react-icons/fa'; import { WiBarometer, WiHumidity, WiSunrise, WiSunset } from 'react-icons/wi'; import { themeIconClasses } from 'styles'; -import type { CurrentWeather as CW } from 'types'; +import type { CurrentWeather as CW, SunState } from 'types'; import WeatherIcon from './WeatherIcon'; export default function CurrentWeather({ current }: { current: CW }) { @@ -15,12 +15,12 @@ export default function CurrentWeather({ current }: { current: CW }) { lon: currentLocation.lon, }); - const [sunStates, setSunStates] = useState([]); + const [sunStates, setSunStates] = useState([]); useEffect(() => { if (sunStateData) { setSunStates( - sunStateData.results.map((item: any) => { + sunStateData.results.map((item: SunState) => { return { date: item.date, sunrise: item.sunrise, diff --git a/src/components/WeatherModal/ExtendedForecast.tsx b/src/components/WeatherModal/ExtendedForecastCard.tsx similarity index 83% rename from src/components/WeatherModal/ExtendedForecast.tsx rename to src/components/WeatherModal/ExtendedForecastCard.tsx index c23c1de..db4c5a9 100644 --- a/src/components/WeatherModal/ExtendedForecast.tsx +++ b/src/components/WeatherModal/ExtendedForecastCard.tsx @@ -1,11 +1,15 @@ import { Group, Stack, Text } from '@mantine/core'; import { useCommonHooks } from 'hooks'; import { textClasses } from 'styles'; +import type { ExtendedForecast } from 'types'; import WeatherIcon from './WeatherIcon'; -export default function ExtendedForecast({ forecast }: any) { - const day = forecast.slice(2, 14).filter((item: any) => item.isDaytime); - const night = forecast.slice(2, 14).filter((item: any) => !item.isDaytime); +export default function ExtendedForecastCard({ + forecast, +}: { forecast: ExtendedForecast[] }) { + const day = forecast.slice(2, 14).filter((item: ExtendedForecast) => item.isDaytime); + const night = forecast.slice(2, 14).filter((item: ExtendedForecast) => !item.isDaytime); + const { isMobile } = useCommonHooks(); return ( - {day.map((item: any, index: number) => { + {day.map((item: ExtendedForecast, index: number) => { const short = item.shortForecast.includes('And') ? item.shortForecast.substring(0, item.shortForecast.indexOf('And')) : item.shortForecast.includes('then') diff --git a/src/components/WeatherModal/WeatherGraphs.tsx b/src/components/WeatherModal/WeatherGraphs.tsx index 85a2586..b61e9a7 100644 --- a/src/components/WeatherModal/WeatherGraphs.tsx +++ b/src/components/WeatherModal/WeatherGraphs.tsx @@ -10,8 +10,11 @@ import { XAxis, YAxis, } from 'recharts'; +import type { HourlyForecast } from 'types'; -export default function WeatherGraphs({ hourlyForecast }: any) { +export default function WeatherGraphs({ + hourlyForecast, +}: { hourlyForecast: HourlyForecast[] }) { function CustomTooltip({ payload, active }: any) { if (active) { return ( @@ -48,7 +51,7 @@ export default function WeatherGraphs({ hourlyForecast }: any) { { + dataKey={(data: HourlyForecast) => { return new Date(data.startTime).toLocaleTimeString('en-US', { hour: 'numeric', minute: 'numeric', @@ -74,7 +77,7 @@ export default function WeatherGraphs({ hourlyForecast }: any) { unit={'°F'} type='monotone' name='Dew Point' - dataKey={(data: any) => { + dataKey={(data: HourlyForecast) => { return (data.dewpoint.value * 9) / 5 + 32; }} stroke={'var(--color-text-acc)'} @@ -88,7 +91,7 @@ export default function WeatherGraphs({ hourlyForecast }: any) { { + dataKey={(data: HourlyForecast) => { return new Date(data.startTime).toLocaleTimeString('en-US', { hour: 'numeric', minute: 'numeric', @@ -102,7 +105,7 @@ export default function WeatherGraphs({ hourlyForecast }: any) { unit={'%'} type='monotone' name='Precipitation' - dataKey={(data: any) => { + dataKey={(data: HourlyForecast) => { return data.probabilityOfPrecipitation.value; }} stroke={'var(--color-text-pri)'} @@ -113,7 +116,7 @@ export default function WeatherGraphs({ hourlyForecast }: any) { unit={'%'} type='monotone' name='Humidity' - dataKey={(data: any) => { + dataKey={(data: HourlyForecast) => { return data.relativeHumidity.value; }} stroke={'var(--color-text-acc)'} diff --git a/src/components/WeatherModal/WeatherModal.tsx b/src/components/WeatherModal/WeatherModal.tsx index 67f516b..c28f328 100644 --- a/src/components/WeatherModal/WeatherModal.tsx +++ b/src/components/WeatherModal/WeatherModal.tsx @@ -4,9 +4,9 @@ import { modalClasses } from 'styles'; import { useCommonHooks, useWeatherAPI } from 'hooks'; import { useEffect, useState } from 'react'; -import type { CurrentWeather as CW, ExtendedForecast as EF } from 'types'; +import type { CurrentWeather as CW, ExtendedForecast, HourlyForecast } from 'types'; import CurrentWeather from './CurrentWeather'; -import ExtendedForecast from './ExtendedForecast'; +import ExtendedForecastCard from './ExtendedForecastCard'; import WeatherGraphs from './WeatherGraphs'; export function WeatherModal({ @@ -19,7 +19,7 @@ export function WeatherModal({ closeWeatherModal, }: { current: CW; - extendedForecast: EF[]; + extendedForecast: ExtendedForecast[]; weatherModalOpened: boolean; setSearchValue: (value: string) => void; setProviderLabel: (label: string) => void; @@ -33,14 +33,13 @@ export function WeatherModal({ x: currentLocation.x, y: currentLocation.y, }); - const [hourlyForecast, setHourlyForecast] = useState([]); + const [hourlyForecast, setHourlyForecast] = useState([]); useEffect(() => { if (hourly) { setHourlyForecast(hourly.properties.periods.slice(1, 25)); } }, [hourly]); - return ( - + diff --git a/src/hooks/useAPI.ts b/src/hooks/useAPI.ts index 45bf56b..44f2bc9 100644 --- a/src/hooks/useAPI.ts +++ b/src/hooks/useAPI.ts @@ -3,12 +3,12 @@ import { useRef } from 'react'; import { Flip, toast } from 'react-toastify'; const url = `${import.meta.env.PROD ? import.meta.env.VITE_DOMAIN_PROD : import.meta.env.VITE_DOMAIN_DEV}/${import.meta.env.VITE_BASE_URL}`; -const headers = { +const headers: HeadersInit = { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': '*', 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', - 'Access-Control-Allow-Credentials': true, + 'Access-Control-Allow-Credentials': 'true', 'Sec-Fetch-Mode': 'no-cors', 'Sec-Fetch-Site': 'same-site', }; @@ -49,7 +49,7 @@ export function useMutationAPI() { endpoint: string, body: object | undefined | null, ) => { - const options: any = { + const options: { method: string; headers: HeadersInit | undefined; body: string } = { method: method, headers: headers, body: JSON.stringify(body), diff --git a/src/hooks/useCommonHooks.ts b/src/hooks/useCommonHooks.ts index 8b1996f..1054826 100644 --- a/src/hooks/useCommonHooks.ts +++ b/src/hooks/useCommonHooks.ts @@ -13,7 +13,7 @@ export function useCommonHooks() { key: 'theme', defaultValue: 'blackboard', }); - const [appFilter, setAppFilter] = useLocalStorage<[string]>({ + const [appFilter, setAppFilter] = useLocalStorage({ key: 'appFilter', defaultValue: ['All'], }); @@ -29,7 +29,7 @@ export function useCommonHooks() { key: 'bookmarkSort', defaultValue: 'A>Z', }); - const [bookmarkFilter, setBookmarkFilter] = useLocalStorage<[string]>({ + const [bookmarkFilter, setBookmarkFilter] = useLocalStorage({ key: 'bookmarkFilter', defaultValue: ['All'], }); diff --git a/src/pages/homepage/Homepage.tsx b/src/pages/homepage/Homepage.tsx index b8829f2..62f9c7d 100644 --- a/src/pages/homepage/Homepage.tsx +++ b/src/pages/homepage/Homepage.tsx @@ -7,6 +7,7 @@ import { stackClasses } from 'styles'; import type { CurrentWeather as CW, ExtendedForecast as EF, + ExtendedForecast, Message, PersonalData, } from 'types'; @@ -177,7 +178,7 @@ export function Homepage() { useEffect(() => { if (forecast) { setExtendedForecast( - forecast.properties.periods.map((item: any) => ({ + forecast.properties.periods.map((item: ExtendedForecast) => ({ detailedForecast: item.detailedForecast, isDaytime: item.isDaytime, name: item.name, @@ -196,6 +197,7 @@ export function Homepage() { }); } }, [forecast]); + return ( a.enabled === 1) - .sort((a: any, b: any) => { + .sort((a: Application, b: Application) => { switch (appSort) { case 'A>Z': return a.name > b.name ? 1 : -1; case 'Z>A': return a.name < b.name ? 1 : -1; case 'Newest': - return a.id < b.id ? 1 : -1; + if (a.id && b.id) { + return a.id < b.id ? 1 : -1; + } + + return -1; case 'Oldest': - return a.id > b.id ? 1 : -1; + if (a.id && b.id) { + return a.id > b.id ? 1 : -1; + } + + return -1; case 'Custom': return a.index > b.index ? 1 : -1; } diff --git a/src/pages/homepage/components/Bookmarks/Bookmarks.tsx b/src/pages/homepage/components/Bookmarks/Bookmarks.tsx index 93eb53e..6a80c5b 100644 --- a/src/pages/homepage/components/Bookmarks/Bookmarks.tsx +++ b/src/pages/homepage/components/Bookmarks/Bookmarks.tsx @@ -5,7 +5,7 @@ import { textClasses } from 'styles'; import type { Bookmark, BookmarkGroup } from 'types'; import LinkGroups from './LinkGroups'; -function Links({ contentType }: { contentType: [string] }) { +function Links({ contentType }: { contentType: string[] }) { const { data: linkData, isFetched: linksIsFetched } = useQueryAPI({ endpoint: 'api/links', }); @@ -28,18 +28,26 @@ function Links({ contentType }: { contentType: [string] }) { return category; }); setGroups( - groupList.sort((a: any, b: any) => { + groupList.sort((a: BookmarkGroup, b: BookmarkGroup) => { switch (bookmarkSort) { case 'A>Z': return a.categoryName > b.categoryName ? 1 : -1; case 'Z>A': return a.categoryName < b.categoryName ? 1 : -1; case 'Newest': - return a.id < b.id ? 1 : -1; + if (a.id && b.id) { + return a.id < b.id ? 1 : -1; + } + + return -1; case 'Oldest': - return a.id > b.id ? 1 : -1; + if (a.id && b.id) { + return a.id > b.id ? 1 : -1; + } + + return -1; case 'Custom': - return a.index > b.index ? 1 : -1; + return a.categoryIndex > b.categoryIndex ? 1 : -1; } }), ); diff --git a/src/pages/homepage/components/Header/Header.tsx b/src/pages/homepage/components/Header/Header.tsx index ad7754c..404ad3c 100644 --- a/src/pages/homepage/components/Header/Header.tsx +++ b/src/pages/homepage/components/Header/Header.tsx @@ -2,7 +2,7 @@ import { Group, Stack, Text } from '@mantine/core'; import { useCommonHooks } from 'hooks'; import { useEffect, useState } from 'react'; import { textClasses } from 'styles'; -import type { CurrentWeather as CW } from 'types'; +import type { CurrentWeather } from 'types'; function Header({ greet, @@ -15,8 +15,8 @@ function Header({ }: { greet: string; date: string; - current: CW; - setCurrent: (current: CW) => void; + current: CurrentWeather; + setCurrent: (current: CurrentWeather) => void; weather: any; basicWeather: any; openWeatherModal: () => void; diff --git a/src/pages/homepage/components/Search/Search.tsx b/src/pages/homepage/components/Search/Search.tsx index 6dcb44a..ae1ee29 100644 --- a/src/pages/homepage/components/Search/Search.tsx +++ b/src/pages/homepage/components/Search/Search.tsx @@ -67,11 +67,11 @@ export default function Search({ const [placeholderValue, setPlaceholderValue] = useState(''); const [value, setValue] = useState(0); - const handleSearchHistoryItem = (item: any) => { + const handleSearchHistoryItem = ({ option }: { option: SearchHistoryItem }) => { const url = - providers.find((provider: Provider) => provider.prefix === item.option.prefix) - ?.url ?? 'https://www.google.com/search?q='; - open(`${url}${item.option.searchTerm}`, '_self'); + providers.find((provider: Provider) => provider.prefix === option.prefix)?.url ?? + 'https://www.google.com/search?q='; + open(`${url}${option.searchTerm}`, '_self'); }; const handleAppSearchItem = (item: any) => { @@ -425,7 +425,7 @@ export default function Search({ useEffect(() => { const splittedSearch = searchValue.toLowerCase().trim().split(' '); const filtered = searchHistory - .filter((item: any) => { + .filter((item: SearchHistoryItem) => { const option = `${item.prefix} ${item.searchTerm}`; const words = option.toLowerCase().trim().split(' '); return splittedSearch.every((searchWord) => @@ -450,7 +450,7 @@ export default function Search({