Slight refactor
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Stack } from '@mantine/core';
|
||||
import { useDisclosure, useLocalStorage } from '@mantine/hooks';
|
||||
import { date, greet, useQueryAPI, useWeatherAPI } from 'hooks';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { date, greet, useCommonHooks } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { stackClasses } from 'styles';
|
||||
import type { CurrentWeather, OutlookWeather } from 'types';
|
||||
@@ -10,21 +10,18 @@ import Header from './components/Header/Header';
|
||||
import Search from './components/Search/Search';
|
||||
import SettingsButton from './components/SettingsButton';
|
||||
|
||||
export function Homepage({ theme }: any) {
|
||||
const [appFilter, setAppFilter] = useLocalStorage<[any]>({
|
||||
key: 'appFilter',
|
||||
defaultValue: ['All'],
|
||||
});
|
||||
const [bookmarkFilter, setBookmarkFilter] = useLocalStorage<[any]>({
|
||||
key: 'bookmarkFilter',
|
||||
defaultValue: ['All'],
|
||||
});
|
||||
const { data, isFetching } = useQueryAPI({ endpoint: 'api/messages' });
|
||||
const { data: basicWeather } = useWeatherAPI({ endpoint: 'baseline' });
|
||||
const { data: weather } = useWeatherAPI({ endpoint: 'current' });
|
||||
const { data: forecast } = useWeatherAPI({ endpoint: 'forecast' });
|
||||
const { data: hourly } = useWeatherAPI({ endpoint: 'hourly' });
|
||||
export function Homepage() {
|
||||
const [displayedGreeting, setDisplayedGreeting] = useState('');
|
||||
const {
|
||||
appFilter,
|
||||
bookmarkFilter,
|
||||
isMobile,
|
||||
messages,
|
||||
isMessagesFetching,
|
||||
weather,
|
||||
basicWeather,
|
||||
forecast,
|
||||
} = useCommonHooks();
|
||||
const [current, setCurrent] = useState<CurrentWeather>({
|
||||
icon: '',
|
||||
temperature: 0,
|
||||
@@ -47,17 +44,14 @@ export function Homepage({ theme }: any) {
|
||||
windDirection: 'N',
|
||||
},
|
||||
]);
|
||||
const isMobile = window.matchMedia('(max-width: 600px)').matches;
|
||||
const [weatherModalOpened, { open: openWeatherModal, close: closeWeatherModal }] =
|
||||
useDisclosure(false);
|
||||
const [providerLabel, setProviderLabel] = useState('Google Search');
|
||||
const [providerURL, setProviderURL] = useState('https://www.google.com/search?q=');
|
||||
const [value, setValue] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
setDisplayedGreeting(greet(data));
|
||||
if (messages) {
|
||||
setDisplayedGreeting(greet(messages));
|
||||
}
|
||||
}, [data, isFetching]);
|
||||
}, [messages, isMessagesFetching]);
|
||||
|
||||
useEffect(() => {
|
||||
if (weather && basicWeather) {
|
||||
@@ -119,19 +113,7 @@ export function Homepage({ theme }: any) {
|
||||
<Stack gap={0} className={stackClasses.containerStack} justify='center'>
|
||||
<Search
|
||||
current={current}
|
||||
setCurrent={setCurrent}
|
||||
outlook={outlook}
|
||||
setOutlook={setOutlook}
|
||||
weather={weather}
|
||||
basicWeather={basicWeather}
|
||||
forecast={forecast}
|
||||
hourly={hourly}
|
||||
providerLabel={providerLabel}
|
||||
setProviderLabel={setProviderLabel}
|
||||
providerURL={providerURL}
|
||||
setProviderURL={setProviderURL}
|
||||
value={value}
|
||||
setValue={setValue}
|
||||
weatherModalOpened={weatherModalOpened}
|
||||
closeWeatherModal={closeWeatherModal}
|
||||
openWeatherModal={openWeatherModal}
|
||||
@@ -139,30 +121,16 @@ export function Homepage({ theme }: any) {
|
||||
<Header
|
||||
date={date(isMobile)}
|
||||
greet={displayedGreeting}
|
||||
isMobile={isMobile}
|
||||
current={current}
|
||||
setCurrent={setCurrent}
|
||||
outlook={outlook}
|
||||
weather={weather}
|
||||
basicWeather={basicWeather}
|
||||
forecast={forecast}
|
||||
hourly={hourly}
|
||||
setProviderLabel={setProviderLabel}
|
||||
setProviderURL={setProviderURL}
|
||||
setValue={setValue}
|
||||
weatherModalOpened={weatherModalOpened}
|
||||
closeWeatherModal={closeWeatherModal}
|
||||
openWeatherModal={openWeatherModal}
|
||||
/>
|
||||
<Applications contentType={appFilter} isMobile={isMobile} />
|
||||
<Bookmarks contentType={bookmarkFilter} isMobile={isMobile} />
|
||||
<SettingsButton
|
||||
theme={theme}
|
||||
setAppFilter={setAppFilter}
|
||||
appFilter={appFilter}
|
||||
setBookmarkFilter={setBookmarkFilter}
|
||||
bookmarkFilter={bookmarkFilter}
|
||||
/>
|
||||
<Applications contentType={appFilter} />
|
||||
<Bookmarks contentType={bookmarkFilter} />
|
||||
<SettingsButton />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Icon } from '@iconify/react';
|
||||
import { Box, Stack, Text } from '@mantine/core';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { useState } from 'react';
|
||||
import { stackClasses, textClasses } from 'styles';
|
||||
|
||||
function AppItem({ url, icon, name, isMobile }: any) {
|
||||
function AppItem({ url, icon, name }: any) {
|
||||
const [textDecoration, setTextDecoration] = useState<string>('none');
|
||||
const { isMobile } = useCommonHooks();
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -15,11 +17,11 @@ function AppItem({ url, icon, name, isMobile }: any) {
|
||||
className={stackClasses.appItemBox}
|
||||
>
|
||||
<Stack
|
||||
align={isMobile && 'center'}
|
||||
justify={isMobile && 'center'}
|
||||
align={isMobile ? 'center' : undefined}
|
||||
justify={isMobile ? 'center' : undefined}
|
||||
style={{
|
||||
height: '64px',
|
||||
width: isMobile && '100%',
|
||||
width: isMobile ? '100%' : undefined,
|
||||
marginRight: isMobile ? '0' : '1em',
|
||||
marginLeft: isMobile ? '0' : '1em',
|
||||
paddingTop: isMobile ? '0' : '15px',
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
import { Stack, Text } from '@mantine/core';
|
||||
import { useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { textClasses } from 'styles';
|
||||
import AppItem from './AppItem';
|
||||
|
||||
function Applications({ contentType, isMobile }: any) {
|
||||
const { data, isFetching } = useQueryAPI({ endpoint: 'api/apps' });
|
||||
const [applications, setApplications] = useState([]);
|
||||
useEffect(() => {
|
||||
if (data && !isFetching) {
|
||||
setApplications(data);
|
||||
}
|
||||
}, [data, isFetching]);
|
||||
function Applications({ contentType }: any) {
|
||||
const { isMobile, applicationData } = useCommonHooks();
|
||||
return (
|
||||
<>
|
||||
{applications.length > 0 && contentType.length > 0 && (
|
||||
{applicationData.length > 0 && contentType.length > 0 && (
|
||||
<Stack id='apps' style={{ gap: 0 }}>
|
||||
<Text className={textClasses.sectionTitle} classNames={textClasses}>
|
||||
Applications
|
||||
@@ -32,7 +25,7 @@ function Applications({ contentType, isMobile }: any) {
|
||||
paddingBottom: 'var(--module-spacing)',
|
||||
}}
|
||||
>
|
||||
{applications?.map((application: any) => {
|
||||
{applicationData?.map((application: any) => {
|
||||
if (
|
||||
contentType.includes(application.filterName) ||
|
||||
contentType.includes('All')
|
||||
@@ -44,7 +37,6 @@ function Applications({ contentType, isMobile }: any) {
|
||||
url={application.url}
|
||||
icon={application.icon}
|
||||
category={application.category}
|
||||
isMobile={isMobile}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -1,30 +1,16 @@
|
||||
import { Stack, Text } from '@mantine/core';
|
||||
import { useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { textClasses } from 'styles';
|
||||
import LinkGroups from './LinkGroups';
|
||||
|
||||
function Links({ contentType, isMobile }: any) {
|
||||
const { data: linkData, isFetched: linksIsFetched } = useQueryAPI({
|
||||
endpoint: 'api/links',
|
||||
});
|
||||
const { data: groupData, isFetched: groupsIsFetched } = useQueryAPI({
|
||||
endpoint: 'api/categories',
|
||||
});
|
||||
const [bookmarks, setBookmarks] = useState([]);
|
||||
const [categories, setCategories] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (linksIsFetched && groupsIsFetched) {
|
||||
setBookmarks(linkData);
|
||||
setCategories(groupData);
|
||||
}
|
||||
}, [linksIsFetched, groupsIsFetched]);
|
||||
function Links({ contentType }: any) {
|
||||
const { isMobile, linksIsFetched, groupsIsFetched, groups, bookmarkData } =
|
||||
useCommonHooks();
|
||||
return (
|
||||
<>
|
||||
{groupsIsFetched &&
|
||||
linksIsFetched &&
|
||||
categories?.length > 0 &&
|
||||
groups?.length > 0 &&
|
||||
contentType.length > 0 && (
|
||||
<Stack id='links' style={{ gap: 0 }}>
|
||||
<Text className={textClasses.sectionTitle} classNames={textClasses}>
|
||||
@@ -40,19 +26,18 @@ function Links({ contentType, isMobile }: any) {
|
||||
gridTemplateRows: 'auto',
|
||||
}}
|
||||
>
|
||||
{categories.map((category: any) => {
|
||||
{groups.map((category: any) => {
|
||||
if (
|
||||
contentType.includes(category.filterName) ||
|
||||
contentType.includes('All')
|
||||
) {
|
||||
return (
|
||||
<LinkGroups
|
||||
key={category.id}
|
||||
key={category}
|
||||
category={category.categoryName}
|
||||
links={bookmarks.filter(
|
||||
(bookmark: any) => bookmark.category === category.categoryName,
|
||||
links={bookmarkData.filter(
|
||||
(bookmark: any) => bookmark.category === category,
|
||||
)}
|
||||
isMobile={isMobile}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Stack, Text } from '@mantine/core';
|
||||
import { textClasses } from 'styles';
|
||||
import LinkItem from './LinkItem';
|
||||
|
||||
function LinkGroups({ links, category, isMobile }: any) {
|
||||
function LinkGroups({ links, category }: any) {
|
||||
return (
|
||||
<Stack
|
||||
style={{
|
||||
@@ -16,7 +16,7 @@ function LinkGroups({ links, category, isMobile }: any) {
|
||||
{category}
|
||||
</Text>
|
||||
{links?.map((link: any) => (
|
||||
<LinkItem key={link.name} link={link} isMobile={isMobile} />
|
||||
<LinkItem key={link.name} link={link} />
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -1,25 +1,20 @@
|
||||
import { Group, Stack, Text } from '@mantine/core';
|
||||
import { WeatherModal } from 'components';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { textClasses } from 'styles';
|
||||
|
||||
function Header({
|
||||
greet,
|
||||
date,
|
||||
isMobile,
|
||||
current,
|
||||
setCurrent,
|
||||
weather,
|
||||
basicWeather,
|
||||
outlook,
|
||||
hourly,
|
||||
weatherModalOpened,
|
||||
closeWeatherModal,
|
||||
openWeatherModal,
|
||||
setProviderLabel,
|
||||
setProviderURL,
|
||||
setValue,
|
||||
}: any) {
|
||||
const { isMobile, weather, basicWeather } = useCommonHooks();
|
||||
const [time, setTime] = useState(new Date());
|
||||
function fixDigits(k: any) {
|
||||
if (k < 10) {
|
||||
@@ -80,7 +75,7 @@ function Header({
|
||||
<Text
|
||||
className={textClasses.greeting}
|
||||
classNames={textClasses}
|
||||
fz={isMobile && 24}
|
||||
fz={isMobile ? 24 : undefined}
|
||||
>
|
||||
{greet}
|
||||
</Text>
|
||||
@@ -152,13 +147,8 @@ function Header({
|
||||
<WeatherModal
|
||||
current={current}
|
||||
outlook={outlook}
|
||||
hourly={hourly}
|
||||
closeWeatherModal={closeWeatherModal}
|
||||
weatherModalOpened={weatherModalOpened}
|
||||
setProviderLabel={setProviderLabel}
|
||||
setProviderURL={setProviderURL}
|
||||
setValue={setValue}
|
||||
isMobile={isMobile}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
import { Stack, TextInput } from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { HelpModal } from '../../../../components/HelpModal/HelpModal';
|
||||
import { WeatherModal } from '../../../../components/WeatherModal/WeatherModal';
|
||||
import { containsProtocol, useQueryAPI, validURL } from '../../../../hooks';
|
||||
import { textInputClasses } from '../../../../styles';
|
||||
import { HelpModal, WeatherModal } from 'components';
|
||||
import { containsProtocol, useCommonHooks, validURL } from 'hooks';
|
||||
import { textInputClasses } from 'styles';
|
||||
|
||||
export default function Search({
|
||||
current,
|
||||
outlook,
|
||||
hourly,
|
||||
weatherModalOpened,
|
||||
closeWeatherModal,
|
||||
openWeatherModal,
|
||||
providerLabel,
|
||||
setProviderLabel,
|
||||
providerURL,
|
||||
setProviderURL,
|
||||
value,
|
||||
setValue,
|
||||
}: any) {
|
||||
const { data: providers } = useQueryAPI({ endpoint: 'api/providers' });
|
||||
const {
|
||||
providerLabel,
|
||||
setProviderLabel,
|
||||
providerURL,
|
||||
setProviderURL,
|
||||
searchValue,
|
||||
setSearchValue,
|
||||
providers,
|
||||
} = useCommonHooks();
|
||||
|
||||
const [providerModalOpened, { open: openProviderModal, close: closeProviderModal }] =
|
||||
useDisclosure(false);
|
||||
|
||||
@@ -72,10 +73,10 @@ export default function Search({
|
||||
classNames={textInputClasses}
|
||||
spellCheck='true'
|
||||
leftSection={providerLabel}
|
||||
value={value}
|
||||
data-active={value !== ''}
|
||||
value={searchValue}
|
||||
data-active={searchValue !== ''}
|
||||
onChange={(item: any) => {
|
||||
setValue(item.currentTarget.value);
|
||||
setSearchValue(item.currentTarget.value);
|
||||
if (
|
||||
item.target.value === '/?' ||
|
||||
item.target.value === '!help' ||
|
||||
@@ -104,22 +105,14 @@ export default function Search({
|
||||
}}
|
||||
/>
|
||||
<HelpModal
|
||||
providers={providers}
|
||||
providerModalOpened={providerModalOpened}
|
||||
closeProviderModal={closeProviderModal}
|
||||
setValue={setValue}
|
||||
setProviderLabel={setProviderLabel}
|
||||
setProviderURL={setProviderURL}
|
||||
/>
|
||||
<WeatherModal
|
||||
current={current}
|
||||
outlook={outlook}
|
||||
hourly={hourly}
|
||||
closeWeatherModal={closeWeatherModal}
|
||||
weatherModalOpened={weatherModalOpened}
|
||||
setValue={setValue}
|
||||
setProviderLabel={setProviderLabel}
|
||||
setProviderURL={setProviderURL}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
import { Button, Menu, MultiSelect, NavLink } from '@mantine/core';
|
||||
import { useQueryAPI } from 'hooks';
|
||||
import { Button, Menu, MultiSelect, NavLink, Switch } from '@mantine/core';
|
||||
import { runWakeCommand, useCommonHooks, useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FiMenu, FiMonitor } from 'react-icons/fi';
|
||||
import { FiMenu, FiMonitor, FiShuffle } from 'react-icons/fi';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { buttonClasses, menuClasses, navLinkClasses, selectClasses } from 'styles';
|
||||
|
||||
function SettingsButton({
|
||||
appFilter,
|
||||
setAppFilter,
|
||||
bookmarkFilter,
|
||||
setBookmarkFilter,
|
||||
}: any) {
|
||||
function SettingsButton() {
|
||||
const { data, isFetched } = useQueryAPI({ endpoint: 'api/appCategories' });
|
||||
const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]);
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
currentTheme,
|
||||
setCurrentTheme,
|
||||
handleThemeChange,
|
||||
theme,
|
||||
allThemes,
|
||||
appFilter,
|
||||
setAppFilter,
|
||||
bookmarkFilter,
|
||||
setBookmarkFilter,
|
||||
} = useCommonHooks();
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
const list: [any] =
|
||||
@@ -25,13 +32,6 @@ function SettingsButton({
|
||||
}
|
||||
}, [data, isFetched]);
|
||||
|
||||
function runWakeCommand() {
|
||||
const requestOptions = {
|
||||
method: 'GET',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
};
|
||||
fetch(`/${import.meta.env.VITE_BASE_URL}/api/wakeDakota`, requestOptions);
|
||||
}
|
||||
return (
|
||||
<Menu withinPortal={false} withArrow shadow='md' position='top'>
|
||||
<Menu.Target>
|
||||
@@ -59,6 +59,31 @@ function SettingsButton({
|
||||
className={navLinkClasses.defaultNavLink}
|
||||
classNames={navLinkClasses}
|
||||
/>
|
||||
<NavLink
|
||||
label='Shuffle Themes'
|
||||
leftSection={
|
||||
<Switch
|
||||
labelPosition='left'
|
||||
checked={currentTheme === 'random'}
|
||||
onChange={(e) => {
|
||||
setCurrentTheme(e.target.checked ? 'random' : theme.name);
|
||||
}}
|
||||
color={theme.primaryColor}
|
||||
/>
|
||||
}
|
||||
onClick={() => {}}
|
||||
className={navLinkClasses.defaultNavLink}
|
||||
classNames={navLinkClasses}
|
||||
/>
|
||||
<NavLink
|
||||
label='Random Theme'
|
||||
leftSection={<FiShuffle />}
|
||||
onClick={() => {
|
||||
handleThemeChange(allThemes, true);
|
||||
}}
|
||||
className={navLinkClasses.defaultNavLink}
|
||||
classNames={navLinkClasses}
|
||||
/>
|
||||
</NavLink>
|
||||
<MultiSelect
|
||||
label='App Filter'
|
||||
|
||||
Reference in New Issue
Block a user