Clean up and typing

This commit is contained in:
Sean Edmunds
2025-03-27 16:22:34 -05:00
parent b46d89721e
commit 67293b20ca
47 changed files with 450 additions and 540 deletions

View File

@@ -4,8 +4,13 @@ import CurrentWeather from 'components/WeatherModal/CurrentWeather';
import { useCommonHooks, useOSMAPI, useQueryAPI, useWeatherAPI } from 'hooks';
import { useEffect, useState } from 'react';
import { stackClasses } from 'styles';
import type { CurrentWeather as CW, OutlookWeather } from 'types';
import type { ExtendedForecast as EF } from 'types/weather';
import type {
CurrentWeather as CW,
ExtendedForecast as EF,
Message,
OutlookWeather,
PersonalData,
} from 'types';
import Applications from './components/Applications/Applications';
import Bookmarks from './components/Bookmarks/Bookmarks';
import Header from './components/Header/Header';
@@ -24,11 +29,6 @@ export function Homepage() {
} = useQueryAPI({
endpoint: 'api/messages',
});
const [personalData, setPersonalData] = useState<any>(null);
const [messages, setMessages] = useState<any>(null);
const [displayedGreeting, setDisplayedGreeting] = useState('');
const [weatherModalOpened, { open: openWeatherModal, close: closeWeatherModal }] =
useDisclosure(false);
const {
appFilter,
bookmarkFilter,
@@ -37,6 +37,11 @@ export function Homepage() {
currentLocation,
setCurrentLocation,
} = useCommonHooks();
const [personalData, setPersonalData] = useState<PersonalData>();
const [messages, setMessages] = useState<Message[]>([]);
const [displayedGreeting, setDisplayedGreeting] = useState('');
const [weatherModalOpened, { open: openWeatherModal, close: closeWeatherModal }] =
useDisclosure(false);
const dateOptions: Intl.DateTimeFormatOptions = !isMobile
? {
weekday: 'long',
@@ -54,23 +59,22 @@ export function Homepage() {
useEffect(() => {
if (personal && personalIsFetched) {
setCurrentUser(personal[0]);
setPersonalData(personal);
setPersonalData(personal[0]);
}
}, [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}!`;
return `Good night, ${personalData?.firstName}!`;
case 1:
return `Good morning, ${personalData?.[0]?.firstName}!`;
return `Good morning, ${personalData?.firstName}!`;
case 2:
return `Good afternoon, ${personalData?.[0]?.firstName}!`;
return `Good afternoon, ${personalData?.firstName}!`;
case 3:
return `Good evening, ${personalData?.[0]?.firstName}!`;
return `Good evening, ${personalData?.firstName}!`;
}
}
return messages[Math.floor(Math.random() * messages.length)].message;

View File

@@ -5,9 +5,9 @@ import { useState } from 'react';
import { stackClasses, textClasses } from 'styles';
function AppItem({ url, icon, name }: any) {
const { isMobile } = useCommonHooks();
const [textDecoration, setTextDecoration] = useState<string>('none');
const [hover, setHover] = useState<boolean>(false);
const { isMobile } = useCommonHooks();
const validUrl =
url.startsWith('http://') || url.startsWith('https://') ? url : `http://${url}`;
return (

View File

@@ -2,14 +2,15 @@ import { Stack, Text } from '@mantine/core';
import { useCommonHooks, useQueryAPI } from 'hooks';
import { useEffect, useState } from 'react';
import { textClasses } from 'styles';
import type { Application } from 'types';
import AppItem from './AppItem';
function Applications({ contentType }: any) {
const { data: apps, isFetching: isAppsFetching } = useQueryAPI({
endpoint: 'api/apps',
});
const [applicationData, setApplicationData] = useState<any>([]);
const { isMobile } = useCommonHooks();
const [applicationData, setApplicationData] = useState<Application[]>([]);
useEffect(() => {
if (apps && !isAppsFetching) {

View File

@@ -2,6 +2,7 @@ import { Stack, Text } from '@mantine/core';
import { useCommonHooks, useQueryAPI } from 'hooks';
import { useEffect, useState } from 'react';
import { textClasses } from 'styles';
import type { Bookmark, BookmarkGroup } from 'types';
import LinkGroups from './LinkGroups';
function Links({ contentType }: any) {
@@ -11,9 +12,9 @@ function Links({ contentType }: any) {
const { data: groupData, isFetched: groupsIsFetched } = useQueryAPI({
endpoint: 'api/categories',
});
const [bookmarkData, setBookmarkData] = useState<any>([]);
const [groups, setGroups] = useState([]);
const { isMobile } = useCommonHooks();
const [bookmarkData, setBookmarkData] = useState<Bookmark[]>([]);
const [groups, setGroups] = useState<BookmarkGroup[]>([]);
useEffect(() => {
if (linkData && linksIsFetched) {
@@ -23,10 +24,14 @@ function Links({ contentType }: any) {
useEffect(() => {
if (groupData && groupsIsFetched) {
const groupList = groupData?.map((category: any) => {
const groupList = groupData?.map((category: BookmarkGroup) => {
return category;
});
setGroups(groupList);
setGroups(
groupList.sort((a: BookmarkGroup, b: BookmarkGroup) =>
a.categoryIndex > b.categoryIndex ? 1 : -1,
),
);
}
}, [groupData, groupsIsFetched]);
@@ -50,24 +55,23 @@ function Links({ contentType }: any) {
gridTemplateRows: 'auto',
}}
>
{groups
.sort((a: any, b: any) => (a.categoryIndex > b.categoryIndex ? 1 : -1))
.map((category: any) => {
if (
contentType.includes(category.filterName) ||
contentType.includes('All')
) {
return (
<LinkGroups
key={category.categoryName}
category={category.categoryName}
links={bookmarkData.filter(
(bookmark: any) => bookmark.category === category.categoryName,
)}
/>
);
}
})}
{groups.map((category: BookmarkGroup) => {
if (
contentType.includes(category.filterName) ||
contentType.includes('All')
) {
return (
<LinkGroups
key={category.categoryName}
category={category.categoryName}
links={bookmarkData.filter(
(bookmark: Bookmark) =>
bookmark.category === category.categoryName,
)}
/>
);
}
})}
</Stack>
</Stack>
)}

View File

@@ -8,8 +8,6 @@ function LinkItem({ link }: any) {
classNames={textClasses}
component='a'
href={link.url}
style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}
w={'min-content'}
>
{link.name}
</Text>

View File

@@ -18,14 +18,7 @@ function Header({
openWeatherModal,
}: any) {
const [time, setTime] = useState(new Date());
const { isMobile, currentUser } = useCommonHooks();
function fixDigits(k: any) {
if (k < 10) {
return `0${k}`;
}
return k;
}
const { isMobile, currentUser, fixDigits } = useCommonHooks();
useEffect(() => {
setInterval(() => {

View File

@@ -5,14 +5,7 @@ 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;
}
const { isMobile, currentUser, fixDigits } = useCommonHooks();
useEffect(() => {
setInterval(() => {

View File

@@ -12,6 +12,7 @@ import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
import { useEffect, useState } from 'react';
import { FiEdit, FiTrash } from 'react-icons/fi';
import { actionIconClasses, selectClasses } from 'styles';
import type { Application, Provider } from 'types';
export default function Search({
current,
@@ -24,7 +25,7 @@ export default function Search({
const { data: providers, isFetched: providersIsFetched } = useQueryAPI({
endpoint: 'api/providers',
});
const [providerData, setProviderData] = useState<any>([]);
const [providerData, setProviderData] = useState<Provider[]>([]);
const { data: apps, isFetching: isAppsFetching } = useQueryAPI({
endpoint: 'api/apps',
});
@@ -42,6 +43,7 @@ export default function Search({
const [listIndex, setListIndex] = useState(0);
const {
theme,
urlPattern,
providerLabel,
setProviderLabel,
providerURL,
@@ -53,15 +55,6 @@ export default function Search({
} = useCommonHooks();
const [placeholderValue, setPlaceholderValue] = useState('');
const [value, setValue] = useState(0);
const urlPattern = new RegExp(
'^(https?:\\/\\/)?' + // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
'(\\#[-a-z\\d_]*)?$',
'i',
); // fragment locator
const handleSearchHistoryItem = (item: any) => {
const url =
@@ -104,7 +97,7 @@ export default function Search({
openWeatherModal();
} else if (providerLabel.startsWith('Launch')) {
open(
`https://${applicationData?.find((app: any) => app.baseUrl.substr(1).toLowerCase() === item.target.value.substr(1)).url}`,
`https://${applicationData ?? applicationData.find((app: Application) => app.baseUrl.substring(1).toLowerCase() === item.target.value.substr(1)).url}`,
'_self',
);
} else if (urlPattern.test(item.target.value)) {
@@ -213,11 +206,11 @@ export default function Search({
setProviderPrefix('/g');
} else if (item.target.value.startsWith('/')) {
const provider = providerData?.find(
(p: any) => p.prefix === item.target.value.split(' ')[0],
(p: Provider) => p.prefix === item.target.value.split(' ')[0],
);
setProviderLabel(provider?.name || 'Invalid Search');
setProviderURL(provider?.url);
setProviderPrefix(provider?.prefix);
setProviderLabel(provider?.name ?? 'Invalid Search');
setProviderURL(provider?.url ?? '');
setProviderPrefix(provider?.prefix ?? '');
} else if (item.target.value.startsWith('!')) {
if (item.target.value === '!w' || item.target.value === '!weather') {
setProviderLabel('Show weather');
@@ -255,9 +248,12 @@ export default function Search({
}
return options
.filter((option: any) => {
const words = option.value.toLowerCase().trim().split(' ');
return splittedSearch.every((searchWord) =>
words.some((word: any) => word.includes(searchWord)),
option.value
.toLowerCase()
.trim()
.split(' ')
.some((word: any) => word.includes(searchWord)),
);
})
.slice(0, 10);

View File

@@ -24,13 +24,14 @@ import {
selectClasses,
stackClasses,
} from 'styles';
import type { AppCategory, Theme, ThemePlaylist, WolClient } from 'types';
function SettingsButton() {
const { data, isFetched } = useQueryAPI({ endpoint: 'api/appCategories' });
const { data: wolClients, isFetched: wolClientsIsFetched } = useQueryAPI({
endpoint: 'api/wolClients',
});
const [wolClientsData, setWolClientsData] = useState<any>([]);
const [wolClientsData, setWolClientsData] = useState<WolClient[]>([]);
const { data: allThemes, isFetched: isAllThemesFetched } = useQueryAPI({
endpoint: 'api/themes',
});
@@ -38,9 +39,9 @@ function SettingsButton() {
endpoint: 'api/themePlaylists',
});
const { mutateAsync: wakeRequest } = useMutationAPI();
const [allThemeData, setAllThemeData] = useState<any>([]);
const [allThemeData, setAllThemeData] = useState<Theme[]>([]);
const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]);
const [selectedClient, setSelectedClient] = useState<any>(wolClients?.[0]);
const [selectedClient, setSelectedClient] = useState<WolClient>(wolClients?.[0]);
const [overlayOpened, setOverlayOpened] = useState(false);
const navigate = useNavigate();
const notify = (notification: any) => toast(notification, { position: 'bottom-right' });
@@ -50,7 +51,6 @@ function SettingsButton() {
setThemeName,
handleThemeChange,
theme,
setTheme,
appFilter,
setAppFilter,
bookmarkFilter,
@@ -69,7 +69,7 @@ function SettingsButton() {
useEffect(() => {
if (data) {
const list: [any] = data.map((category: any) => {
const list: [any] = data.map((category: AppCategory) => {
return { value: category.filterName, label: category.filterName };
});
list.unshift({ value: 'All', label: 'All' });
@@ -232,7 +232,7 @@ function SettingsButton() {
value={currentThemePlaylist}
data={
themePlaylists
?.map((playlist: any) => {
?.map((playlist: ThemePlaylist) => {
return {
value: playlist.name,
label: playlist.name,
@@ -254,12 +254,13 @@ function SettingsButton() {
setThemeName('random');
} else {
const themeList = JSON.parse(
themePlaylists.find((t: any) => t.name === 'Time of Day')
.themeList,
themePlaylists.find(
(t: ThemePlaylist) => t.name === 'Time of Day',
).themeList,
);
setThemeName(
allThemes.find(
(t: any) =>
(t: Theme) =>
t.id ===
Number(themeList[Math.floor(new Date().getHours() / 6)]),
).name,