More typing and fixes
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -25,3 +25,4 @@ dist-ssr
|
|||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
.env
|
.env
|
||||||
|
package-lock.json
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Divider, Group } from '@mantine/core';
|
import { Divider, Group } from '@mantine/core';
|
||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
|
import type { SearchShortcut } from 'types';
|
||||||
import HintItem from './HintItem';
|
import HintItem from './HintItem';
|
||||||
|
|
||||||
function HelpSection({ name, items }: { name: string; items: object[] }) {
|
function HelpSection({ name, items }: { name: string; items: SearchShortcut[] }) {
|
||||||
const { theme } = useCommonHooks();
|
const { theme } = useCommonHooks();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -30,8 +31,10 @@ function HelpSection({ name, items }: { name: string; items: object[] }) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{items
|
{items
|
||||||
?.toSorted((a: any, b: any) => (a.command > b.command ? 1 : -1))
|
?.toSorted((a: SearchShortcut, b: SearchShortcut) =>
|
||||||
.map((item: any) => (
|
a.command > b.command ? 1 : -1,
|
||||||
|
)
|
||||||
|
.map((item: SearchShortcut) => (
|
||||||
<HintItem key={item.command} command={item.command} name={item.name} />
|
<HintItem key={item.command} command={item.command} name={item.name} />
|
||||||
))}
|
))}
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useEffect, useState } from 'react';
|
|||||||
import { FaLongArrowAltDown, FaLongArrowAltUp, FaWind } from 'react-icons/fa';
|
import { FaLongArrowAltDown, FaLongArrowAltUp, FaWind } from 'react-icons/fa';
|
||||||
import { WiBarometer, WiHumidity, WiSunrise, WiSunset } from 'react-icons/wi';
|
import { WiBarometer, WiHumidity, WiSunrise, WiSunset } from 'react-icons/wi';
|
||||||
import { themeIconClasses } from 'styles';
|
import { themeIconClasses } from 'styles';
|
||||||
import type { CurrentWeather as CW } from 'types';
|
import type { CurrentWeather as CW, SunState } from 'types';
|
||||||
import WeatherIcon from './WeatherIcon';
|
import WeatherIcon from './WeatherIcon';
|
||||||
|
|
||||||
export default function CurrentWeather({ current }: { current: CW }) {
|
export default function CurrentWeather({ current }: { current: CW }) {
|
||||||
@@ -15,12 +15,12 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
|||||||
lon: currentLocation.lon,
|
lon: currentLocation.lon,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [sunStates, setSunStates] = useState<any>([]);
|
const [sunStates, setSunStates] = useState<SunState[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (sunStateData) {
|
if (sunStateData) {
|
||||||
setSunStates(
|
setSunStates(
|
||||||
sunStateData.results.map((item: any) => {
|
sunStateData.results.map((item: SunState) => {
|
||||||
return {
|
return {
|
||||||
date: item.date,
|
date: item.date,
|
||||||
sunrise: item.sunrise,
|
sunrise: item.sunrise,
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import { Group, Stack, Text } from '@mantine/core';
|
import { Group, Stack, Text } from '@mantine/core';
|
||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { textClasses } from 'styles';
|
import { textClasses } from 'styles';
|
||||||
|
import type { ExtendedForecast } from 'types';
|
||||||
import WeatherIcon from './WeatherIcon';
|
import WeatherIcon from './WeatherIcon';
|
||||||
|
|
||||||
export default function ExtendedForecast({ forecast }: any) {
|
export default function ExtendedForecastCard({
|
||||||
const day = forecast.slice(2, 14).filter((item: any) => item.isDaytime);
|
forecast,
|
||||||
const night = forecast.slice(2, 14).filter((item: any) => !item.isDaytime);
|
}: { 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();
|
const { isMobile } = useCommonHooks();
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
@@ -30,7 +34,7 @@ export default function ExtendedForecast({ forecast }: any) {
|
|||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Group w={'100%'} align='center' justify='space-between'>
|
<Group w={'100%'} align='center' justify='space-between'>
|
||||||
{day.map((item: any, index: number) => {
|
{day.map((item: ExtendedForecast, index: number) => {
|
||||||
const short = item.shortForecast.includes('And')
|
const short = item.shortForecast.includes('And')
|
||||||
? item.shortForecast.substring(0, item.shortForecast.indexOf('And'))
|
? item.shortForecast.substring(0, item.shortForecast.indexOf('And'))
|
||||||
: item.shortForecast.includes('then')
|
: item.shortForecast.includes('then')
|
||||||
@@ -10,8 +10,11 @@ import {
|
|||||||
XAxis,
|
XAxis,
|
||||||
YAxis,
|
YAxis,
|
||||||
} from 'recharts';
|
} 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) {
|
function CustomTooltip({ payload, active }: any) {
|
||||||
if (active) {
|
if (active) {
|
||||||
return (
|
return (
|
||||||
@@ -48,7 +51,7 @@ export default function WeatherGraphs({ hourlyForecast }: any) {
|
|||||||
<XAxis
|
<XAxis
|
||||||
type='category'
|
type='category'
|
||||||
stroke={'var(--color-text-pri)'}
|
stroke={'var(--color-text-pri)'}
|
||||||
dataKey={(data: any) => {
|
dataKey={(data: HourlyForecast) => {
|
||||||
return new Date(data.startTime).toLocaleTimeString('en-US', {
|
return new Date(data.startTime).toLocaleTimeString('en-US', {
|
||||||
hour: 'numeric',
|
hour: 'numeric',
|
||||||
minute: 'numeric',
|
minute: 'numeric',
|
||||||
@@ -74,7 +77,7 @@ export default function WeatherGraphs({ hourlyForecast }: any) {
|
|||||||
unit={'°F'}
|
unit={'°F'}
|
||||||
type='monotone'
|
type='monotone'
|
||||||
name='Dew Point'
|
name='Dew Point'
|
||||||
dataKey={(data: any) => {
|
dataKey={(data: HourlyForecast) => {
|
||||||
return (data.dewpoint.value * 9) / 5 + 32;
|
return (data.dewpoint.value * 9) / 5 + 32;
|
||||||
}}
|
}}
|
||||||
stroke={'var(--color-text-acc)'}
|
stroke={'var(--color-text-acc)'}
|
||||||
@@ -88,7 +91,7 @@ export default function WeatherGraphs({ hourlyForecast }: any) {
|
|||||||
<XAxis
|
<XAxis
|
||||||
type='category'
|
type='category'
|
||||||
stroke={'var(--color-text-pri)'}
|
stroke={'var(--color-text-pri)'}
|
||||||
dataKey={(data: any) => {
|
dataKey={(data: HourlyForecast) => {
|
||||||
return new Date(data.startTime).toLocaleTimeString('en-US', {
|
return new Date(data.startTime).toLocaleTimeString('en-US', {
|
||||||
hour: 'numeric',
|
hour: 'numeric',
|
||||||
minute: 'numeric',
|
minute: 'numeric',
|
||||||
@@ -102,7 +105,7 @@ export default function WeatherGraphs({ hourlyForecast }: any) {
|
|||||||
unit={'%'}
|
unit={'%'}
|
||||||
type='monotone'
|
type='monotone'
|
||||||
name='Precipitation'
|
name='Precipitation'
|
||||||
dataKey={(data: any) => {
|
dataKey={(data: HourlyForecast) => {
|
||||||
return data.probabilityOfPrecipitation.value;
|
return data.probabilityOfPrecipitation.value;
|
||||||
}}
|
}}
|
||||||
stroke={'var(--color-text-pri)'}
|
stroke={'var(--color-text-pri)'}
|
||||||
@@ -113,7 +116,7 @@ export default function WeatherGraphs({ hourlyForecast }: any) {
|
|||||||
unit={'%'}
|
unit={'%'}
|
||||||
type='monotone'
|
type='monotone'
|
||||||
name='Humidity'
|
name='Humidity'
|
||||||
dataKey={(data: any) => {
|
dataKey={(data: HourlyForecast) => {
|
||||||
return data.relativeHumidity.value;
|
return data.relativeHumidity.value;
|
||||||
}}
|
}}
|
||||||
stroke={'var(--color-text-acc)'}
|
stroke={'var(--color-text-acc)'}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import { modalClasses } from 'styles';
|
|||||||
import { useCommonHooks, useWeatherAPI } from 'hooks';
|
import { useCommonHooks, useWeatherAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
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 CurrentWeather from './CurrentWeather';
|
||||||
import ExtendedForecast from './ExtendedForecast';
|
import ExtendedForecastCard from './ExtendedForecastCard';
|
||||||
import WeatherGraphs from './WeatherGraphs';
|
import WeatherGraphs from './WeatherGraphs';
|
||||||
|
|
||||||
export function WeatherModal({
|
export function WeatherModal({
|
||||||
@@ -19,7 +19,7 @@ export function WeatherModal({
|
|||||||
closeWeatherModal,
|
closeWeatherModal,
|
||||||
}: {
|
}: {
|
||||||
current: CW;
|
current: CW;
|
||||||
extendedForecast: EF[];
|
extendedForecast: ExtendedForecast[];
|
||||||
weatherModalOpened: boolean;
|
weatherModalOpened: boolean;
|
||||||
setSearchValue: (value: string) => void;
|
setSearchValue: (value: string) => void;
|
||||||
setProviderLabel: (label: string) => void;
|
setProviderLabel: (label: string) => void;
|
||||||
@@ -33,14 +33,13 @@ export function WeatherModal({
|
|||||||
x: currentLocation.x,
|
x: currentLocation.x,
|
||||||
y: currentLocation.y,
|
y: currentLocation.y,
|
||||||
});
|
});
|
||||||
const [hourlyForecast, setHourlyForecast] = useState<any>([]);
|
const [hourlyForecast, setHourlyForecast] = useState<HourlyForecast[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hourly) {
|
if (hourly) {
|
||||||
setHourlyForecast(hourly.properties.periods.slice(1, 25));
|
setHourlyForecast(hourly.properties.periods.slice(1, 25));
|
||||||
}
|
}
|
||||||
}, [hourly]);
|
}, [hourly]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal.Root
|
<Modal.Root
|
||||||
fullScreen={isMobile}
|
fullScreen={isMobile}
|
||||||
@@ -79,7 +78,7 @@ export function WeatherModal({
|
|||||||
<Stack w={'100%'}>
|
<Stack w={'100%'}>
|
||||||
<CurrentWeather current={current} />
|
<CurrentWeather current={current} />
|
||||||
<WeatherGraphs hourlyForecast={hourlyForecast} />
|
<WeatherGraphs hourlyForecast={hourlyForecast} />
|
||||||
<ExtendedForecast forecast={extendedForecast} />
|
<ExtendedForecastCard forecast={extendedForecast} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</Center>
|
</Center>
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ import { useRef } from 'react';
|
|||||||
import { Flip, toast } from 'react-toastify';
|
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 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',
|
'Content-Type': 'application/json',
|
||||||
'Access-Control-Allow-Origin': '*',
|
'Access-Control-Allow-Origin': '*',
|
||||||
'Access-Control-Allow-Headers': '*',
|
'Access-Control-Allow-Headers': '*',
|
||||||
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
||||||
'Access-Control-Allow-Credentials': true,
|
'Access-Control-Allow-Credentials': 'true',
|
||||||
'Sec-Fetch-Mode': 'no-cors',
|
'Sec-Fetch-Mode': 'no-cors',
|
||||||
'Sec-Fetch-Site': 'same-site',
|
'Sec-Fetch-Site': 'same-site',
|
||||||
};
|
};
|
||||||
@@ -49,7 +49,7 @@ export function useMutationAPI() {
|
|||||||
endpoint: string,
|
endpoint: string,
|
||||||
body: object | undefined | null,
|
body: object | undefined | null,
|
||||||
) => {
|
) => {
|
||||||
const options: any = {
|
const options: { method: string; headers: HeadersInit | undefined; body: string } = {
|
||||||
method: method,
|
method: method,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function useCommonHooks() {
|
|||||||
key: 'theme',
|
key: 'theme',
|
||||||
defaultValue: 'blackboard',
|
defaultValue: 'blackboard',
|
||||||
});
|
});
|
||||||
const [appFilter, setAppFilter] = useLocalStorage<[string]>({
|
const [appFilter, setAppFilter] = useLocalStorage<string[]>({
|
||||||
key: 'appFilter',
|
key: 'appFilter',
|
||||||
defaultValue: ['All'],
|
defaultValue: ['All'],
|
||||||
});
|
});
|
||||||
@@ -29,7 +29,7 @@ export function useCommonHooks() {
|
|||||||
key: 'bookmarkSort',
|
key: 'bookmarkSort',
|
||||||
defaultValue: 'A>Z',
|
defaultValue: 'A>Z',
|
||||||
});
|
});
|
||||||
const [bookmarkFilter, setBookmarkFilter] = useLocalStorage<[string]>({
|
const [bookmarkFilter, setBookmarkFilter] = useLocalStorage<string[]>({
|
||||||
key: 'bookmarkFilter',
|
key: 'bookmarkFilter',
|
||||||
defaultValue: ['All'],
|
defaultValue: ['All'],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { stackClasses } from 'styles';
|
|||||||
import type {
|
import type {
|
||||||
CurrentWeather as CW,
|
CurrentWeather as CW,
|
||||||
ExtendedForecast as EF,
|
ExtendedForecast as EF,
|
||||||
|
ExtendedForecast,
|
||||||
Message,
|
Message,
|
||||||
PersonalData,
|
PersonalData,
|
||||||
} from 'types';
|
} from 'types';
|
||||||
@@ -177,7 +178,7 @@ export function Homepage() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (forecast) {
|
if (forecast) {
|
||||||
setExtendedForecast(
|
setExtendedForecast(
|
||||||
forecast.properties.periods.map((item: any) => ({
|
forecast.properties.periods.map((item: ExtendedForecast) => ({
|
||||||
detailedForecast: item.detailedForecast,
|
detailedForecast: item.detailedForecast,
|
||||||
isDaytime: item.isDaytime,
|
isDaytime: item.isDaytime,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
@@ -196,6 +197,7 @@ export function Homepage() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [forecast]);
|
}, [forecast]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
gap={0}
|
gap={0}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { textClasses } from 'styles';
|
|||||||
import type { Application } from 'types';
|
import type { Application } from 'types';
|
||||||
import AppItem from './AppItem';
|
import AppItem from './AppItem';
|
||||||
|
|
||||||
function Applications({ contentType }: { contentType: [string] }) {
|
function Applications({ contentType }: { contentType: string[] }) {
|
||||||
const { data: apps, isFetching: isAppsFetching } = useQueryAPI({
|
const { data: apps, isFetching: isAppsFetching } = useQueryAPI({
|
||||||
endpoint: 'api/apps',
|
endpoint: 'api/apps',
|
||||||
});
|
});
|
||||||
@@ -17,16 +17,24 @@ function Applications({ contentType }: { contentType: [string] }) {
|
|||||||
setApplicationData(
|
setApplicationData(
|
||||||
apps
|
apps
|
||||||
.filter((a: Application) => a.enabled === 1)
|
.filter((a: Application) => a.enabled === 1)
|
||||||
.sort((a: any, b: any) => {
|
.sort((a: Application, b: Application) => {
|
||||||
switch (appSort) {
|
switch (appSort) {
|
||||||
case 'A>Z':
|
case 'A>Z':
|
||||||
return a.name > b.name ? 1 : -1;
|
return a.name > b.name ? 1 : -1;
|
||||||
case 'Z>A':
|
case 'Z>A':
|
||||||
return a.name < b.name ? 1 : -1;
|
return a.name < b.name ? 1 : -1;
|
||||||
case 'Newest':
|
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':
|
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':
|
case 'Custom':
|
||||||
return a.index > b.index ? 1 : -1;
|
return a.index > b.index ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { textClasses } from 'styles';
|
|||||||
import type { Bookmark, BookmarkGroup } from 'types';
|
import type { Bookmark, BookmarkGroup } from 'types';
|
||||||
import LinkGroups from './LinkGroups';
|
import LinkGroups from './LinkGroups';
|
||||||
|
|
||||||
function Links({ contentType }: { contentType: [string] }) {
|
function Links({ contentType }: { contentType: string[] }) {
|
||||||
const { data: linkData, isFetched: linksIsFetched } = useQueryAPI({
|
const { data: linkData, isFetched: linksIsFetched } = useQueryAPI({
|
||||||
endpoint: 'api/links',
|
endpoint: 'api/links',
|
||||||
});
|
});
|
||||||
@@ -28,18 +28,26 @@ function Links({ contentType }: { contentType: [string] }) {
|
|||||||
return category;
|
return category;
|
||||||
});
|
});
|
||||||
setGroups(
|
setGroups(
|
||||||
groupList.sort((a: any, b: any) => {
|
groupList.sort((a: BookmarkGroup, b: BookmarkGroup) => {
|
||||||
switch (bookmarkSort) {
|
switch (bookmarkSort) {
|
||||||
case 'A>Z':
|
case 'A>Z':
|
||||||
return a.categoryName > b.categoryName ? 1 : -1;
|
return a.categoryName > b.categoryName ? 1 : -1;
|
||||||
case 'Z>A':
|
case 'Z>A':
|
||||||
return a.categoryName < b.categoryName ? 1 : -1;
|
return a.categoryName < b.categoryName ? 1 : -1;
|
||||||
case 'Newest':
|
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':
|
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':
|
case 'Custom':
|
||||||
return a.index > b.index ? 1 : -1;
|
return a.categoryIndex > b.categoryIndex ? 1 : -1;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Group, Stack, Text } from '@mantine/core';
|
|||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { textClasses } from 'styles';
|
import { textClasses } from 'styles';
|
||||||
import type { CurrentWeather as CW } from 'types';
|
import type { CurrentWeather } from 'types';
|
||||||
|
|
||||||
function Header({
|
function Header({
|
||||||
greet,
|
greet,
|
||||||
@@ -15,8 +15,8 @@ function Header({
|
|||||||
}: {
|
}: {
|
||||||
greet: string;
|
greet: string;
|
||||||
date: string;
|
date: string;
|
||||||
current: CW;
|
current: CurrentWeather;
|
||||||
setCurrent: (current: CW) => void;
|
setCurrent: (current: CurrentWeather) => void;
|
||||||
weather: any;
|
weather: any;
|
||||||
basicWeather: any;
|
basicWeather: any;
|
||||||
openWeatherModal: () => void;
|
openWeatherModal: () => void;
|
||||||
|
|||||||
@@ -67,11 +67,11 @@ export default function Search({
|
|||||||
const [placeholderValue, setPlaceholderValue] = useState('');
|
const [placeholderValue, setPlaceholderValue] = useState('');
|
||||||
const [value, setValue] = useState(0);
|
const [value, setValue] = useState(0);
|
||||||
|
|
||||||
const handleSearchHistoryItem = (item: any) => {
|
const handleSearchHistoryItem = ({ option }: { option: SearchHistoryItem }) => {
|
||||||
const url =
|
const url =
|
||||||
providers.find((provider: Provider) => provider.prefix === item.option.prefix)
|
providers.find((provider: Provider) => provider.prefix === option.prefix)?.url ??
|
||||||
?.url ?? 'https://www.google.com/search?q=';
|
'https://www.google.com/search?q=';
|
||||||
open(`${url}${item.option.searchTerm}`, '_self');
|
open(`${url}${option.searchTerm}`, '_self');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAppSearchItem = (item: any) => {
|
const handleAppSearchItem = (item: any) => {
|
||||||
@@ -425,7 +425,7 @@ export default function Search({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const splittedSearch = searchValue.toLowerCase().trim().split(' ');
|
const splittedSearch = searchValue.toLowerCase().trim().split(' ');
|
||||||
const filtered = searchHistory
|
const filtered = searchHistory
|
||||||
.filter((item: any) => {
|
.filter((item: SearchHistoryItem) => {
|
||||||
const option = `${item.prefix} ${item.searchTerm}`;
|
const option = `${item.prefix} ${item.searchTerm}`;
|
||||||
const words = option.toLowerCase().trim().split(' ');
|
const words = option.toLowerCase().trim().split(' ');
|
||||||
return splittedSearch.every((searchWord) =>
|
return splittedSearch.every((searchWord) =>
|
||||||
@@ -450,7 +450,7 @@ export default function Search({
|
|||||||
<Select
|
<Select
|
||||||
classNames={selectClasses}
|
classNames={selectClasses}
|
||||||
className={selectClasses.search}
|
className={selectClasses.search}
|
||||||
data={searchHistory.map((item: any) => ({
|
data={searchHistory.map((item: SearchHistoryItem) => ({
|
||||||
label: `${item.provider}`,
|
label: `${item.provider}`,
|
||||||
value: `${item.prefix} ${item.searchTerm} ${item.dateTimeStamp}`,
|
value: `${item.prefix} ${item.searchTerm} ${item.dateTimeStamp}`,
|
||||||
...item,
|
...item,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Button,
|
Button,
|
||||||
|
type ComboboxItem,
|
||||||
Group,
|
Group,
|
||||||
Menu,
|
Menu,
|
||||||
MultiSelect,
|
MultiSelect,
|
||||||
@@ -169,7 +170,9 @@ function SettingsButton() {
|
|||||||
macAddress: wolClient.macAddress,
|
macAddress: wolClient.macAddress,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.toSorted((a: any, b: any) => a.label.localeCompare(b.label)) || []
|
.toSorted((a: ComboboxItem, b: ComboboxItem) =>
|
||||||
|
a.label.localeCompare(b.label),
|
||||||
|
) ?? []
|
||||||
}
|
}
|
||||||
w='92%'
|
w='92%'
|
||||||
classNames={{
|
classNames={{
|
||||||
@@ -179,8 +182,6 @@ function SettingsButton() {
|
|||||||
option: selectClasses.menuSelectOption,
|
option: selectClasses.menuSelectOption,
|
||||||
}}
|
}}
|
||||||
comboboxProps={{ withinPortal: false }}
|
comboboxProps={{ withinPortal: false }}
|
||||||
onChange={(_value, option: any) => setSelectedClient(option)}
|
|
||||||
onLoad={(option: any) => setSelectedClient(option)}
|
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack
|
<Stack
|
||||||
@@ -252,7 +253,9 @@ function SettingsButton() {
|
|||||||
label: playlist.name,
|
label: playlist.name,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.toSorted((a: any, b: any) => a.label.localeCompare(b.label)) ?? []
|
.toSorted((a: ComboboxItem, b: ComboboxItem) =>
|
||||||
|
a.label.localeCompare(b.label),
|
||||||
|
) ?? []
|
||||||
}
|
}
|
||||||
w='92%'
|
w='92%'
|
||||||
classNames={{
|
classNames={{
|
||||||
@@ -262,7 +265,7 @@ function SettingsButton() {
|
|||||||
option: selectClasses.menuSelectOption,
|
option: selectClasses.menuSelectOption,
|
||||||
}}
|
}}
|
||||||
comboboxProps={{ withinPortal: false }}
|
comboboxProps={{ withinPortal: false }}
|
||||||
onChange={(_value, option: any) => {
|
onChange={(_value, option: ComboboxItem) => {
|
||||||
setCurrentThemePlaylist(option.value);
|
setCurrentThemePlaylist(option.value);
|
||||||
if (option.value !== 'Time of Day') {
|
if (option.value !== 'Time of Day') {
|
||||||
setThemeName('random');
|
setThemeName('random');
|
||||||
@@ -281,7 +284,6 @@ function SettingsButton() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onLoad={(option: any) => setCurrentThemePlaylist(option)}
|
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -329,7 +331,7 @@ function SettingsButton() {
|
|||||||
<MultiSelect
|
<MultiSelect
|
||||||
label='Filter'
|
label='Filter'
|
||||||
data={
|
data={
|
||||||
categories.toSorted((a: any, b: any) =>
|
categories.toSorted((a: ComboboxItem, b: ComboboxItem) =>
|
||||||
a.label.localeCompare(b.label),
|
a.label.localeCompare(b.label),
|
||||||
) ?? []
|
) ?? []
|
||||||
}
|
}
|
||||||
@@ -341,7 +343,7 @@ function SettingsButton() {
|
|||||||
: 'No apps selected'
|
: 'No apps selected'
|
||||||
}
|
}
|
||||||
defaultValue={appFilter}
|
defaultValue={appFilter}
|
||||||
onChange={(data: any) => {
|
onChange={(data: string[]) => {
|
||||||
setAppFilter(data);
|
setAppFilter(data);
|
||||||
}}
|
}}
|
||||||
classNames={multiSelectClasses}
|
classNames={multiSelectClasses}
|
||||||
@@ -359,7 +361,7 @@ function SettingsButton() {
|
|||||||
option: selectClasses.menuSelectOption,
|
option: selectClasses.menuSelectOption,
|
||||||
}}
|
}}
|
||||||
comboboxProps={{ withinPortal: false }}
|
comboboxProps={{ withinPortal: false }}
|
||||||
onChange={(_value, option: any) => {
|
onChange={(_value, option: ComboboxItem) => {
|
||||||
setAppSort(option.value);
|
setAppSort(option.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -408,7 +410,7 @@ function SettingsButton() {
|
|||||||
<MultiSelect
|
<MultiSelect
|
||||||
label='Filter'
|
label='Filter'
|
||||||
data={
|
data={
|
||||||
categories.toSorted((a: any, b: any) =>
|
categories.toSorted((a: ComboboxItem, b: ComboboxItem) =>
|
||||||
a.label.localeCompare(b.label),
|
a.label.localeCompare(b.label),
|
||||||
) ?? []
|
) ?? []
|
||||||
}
|
}
|
||||||
@@ -420,7 +422,7 @@ function SettingsButton() {
|
|||||||
: 'No bookmarks selected'
|
: 'No bookmarks selected'
|
||||||
}
|
}
|
||||||
defaultValue={bookmarkFilter}
|
defaultValue={bookmarkFilter}
|
||||||
onChange={(data: any) => {
|
onChange={(data: string[]) => {
|
||||||
setBookmarkFilter(data);
|
setBookmarkFilter(data);
|
||||||
}}
|
}}
|
||||||
classNames={multiSelectClasses}
|
classNames={multiSelectClasses}
|
||||||
@@ -438,7 +440,7 @@ function SettingsButton() {
|
|||||||
option: selectClasses.menuSelectOption,
|
option: selectClasses.menuSelectOption,
|
||||||
}}
|
}}
|
||||||
comboboxProps={{ withinPortal: false }}
|
comboboxProps={{ withinPortal: false }}
|
||||||
onChange={(_value, option: any) => {
|
onChange={(_value, option: ComboboxItem) => {
|
||||||
setBookmarkSort(option.value);
|
setBookmarkSort(option.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import {
|
|||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
|
type ComboboxItem,
|
||||||
|
type ComboboxLikeRenderOptionInput,
|
||||||
Divider,
|
Divider,
|
||||||
Grid,
|
Grid,
|
||||||
GridCol,
|
GridCol,
|
||||||
@@ -179,13 +181,13 @@ const ApplicationSettings = () => {
|
|||||||
zIndex: 3000,
|
zIndex: 3000,
|
||||||
withinPortal: false,
|
withinPortal: false,
|
||||||
}}
|
}}
|
||||||
onChange={(event: any) => {
|
onChange={(value: string | null) => {
|
||||||
setNewApplication({
|
setNewApplication({
|
||||||
...newApplication,
|
...newApplication,
|
||||||
icon: event,
|
icon: value ?? '',
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
renderOption={(item: any) => {
|
renderOption={(item: ComboboxLikeRenderOptionInput<ComboboxItem>) => {
|
||||||
const Icon = allIcons[item.option.value];
|
const Icon = allIcons[item.option.value];
|
||||||
return (
|
return (
|
||||||
<Group>
|
<Group>
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import {
|
|||||||
ActionIcon,
|
ActionIcon,
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
|
type ComboboxItem,
|
||||||
|
type ComboboxLikeRenderOptionInput,
|
||||||
Group,
|
Group,
|
||||||
Select,
|
Select,
|
||||||
Stack,
|
Stack,
|
||||||
@@ -194,13 +196,13 @@ function DebouncedApplication({
|
|||||||
zIndex: 3000,
|
zIndex: 3000,
|
||||||
withinPortal: false,
|
withinPortal: false,
|
||||||
}}
|
}}
|
||||||
onChange={(event: any) => {
|
onChange={(value: string | null) => {
|
||||||
setUpdate({
|
setUpdate({
|
||||||
...app,
|
...app,
|
||||||
icon: event,
|
icon: value,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
renderOption={(item: any) => {
|
renderOption={(item: ComboboxLikeRenderOptionInput<ComboboxItem>) => {
|
||||||
const Icon = allIcons[item.option.value];
|
const Icon = allIcons[item.option.value];
|
||||||
return (
|
return (
|
||||||
<Group>
|
<Group>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import SettingsHeader from '../Shared/SettingsHeader';
|
|||||||
import DebouncedGroupSettingsItem from './DebouncedGroupSettingsItem';
|
import DebouncedGroupSettingsItem from './DebouncedGroupSettingsItem';
|
||||||
const BookmarkSettings = () => {
|
const BookmarkSettings = () => {
|
||||||
const defaultGroup = {
|
const defaultGroup = {
|
||||||
id: undefined,
|
id: null,
|
||||||
categoryName: '',
|
categoryName: '',
|
||||||
categoryIndex: 0,
|
categoryIndex: 0,
|
||||||
filterName: '',
|
filterName: '',
|
||||||
|
|||||||
@@ -29,10 +29,14 @@ function SettingsHeader({
|
|||||||
setSearchValue,
|
setSearchValue,
|
||||||
searchPlaceholder,
|
searchPlaceholder,
|
||||||
}: {
|
}: {
|
||||||
setDragging: any;
|
setDragging: undefined | ((dragging: boolean) => void);
|
||||||
openModal: () => void;
|
openModal: () => void;
|
||||||
title: string;
|
title: string;
|
||||||
tooltip: any;
|
tooltip: {
|
||||||
|
title: string;
|
||||||
|
highlightList: string[];
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
searchValue: string | undefined;
|
searchValue: string | undefined;
|
||||||
setSearchValue: (searchValue: string) => void;
|
setSearchValue: (searchValue: string) => void;
|
||||||
searchPlaceholder: string | undefined;
|
searchPlaceholder: string | undefined;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ function ThemeCard({
|
|||||||
cardTheme: Theme;
|
cardTheme: Theme;
|
||||||
handleOpen: (cardTheme: Theme) => void;
|
handleOpen: (cardTheme: Theme) => void;
|
||||||
allThemes: Theme[];
|
allThemes: Theme[];
|
||||||
themePlaylists: any;
|
themePlaylists: ThemePlaylist[];
|
||||||
}) {
|
}) {
|
||||||
const [hover, setHover] = useState(false);
|
const [hover, setHover] = useState(false);
|
||||||
const [shiftEdit, setShiftEdit] = useState<number>(0);
|
const [shiftEdit, setShiftEdit] = useState<number>(0);
|
||||||
@@ -274,8 +274,8 @@ function ThemeCard({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
const themeList = JSON.parse(
|
const themeList = JSON.parse(
|
||||||
themePlaylists?.find(
|
themePlaylists?.find(
|
||||||
(t: ThemePlaylist) => t.name === currentThemePlaylist,
|
(t: ThemePlaylist) => t?.name === currentThemePlaylist,
|
||||||
).themeList,
|
)?.themeList ?? '[]',
|
||||||
);
|
);
|
||||||
const filteredThemes = allThemes.filter((t: Theme) =>
|
const filteredThemes = allThemes.filter((t: Theme) =>
|
||||||
themeList.includes(t.id),
|
themeList.includes(t.id),
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ function ThemeModal({
|
|||||||
<Modal.Content>
|
<Modal.Content>
|
||||||
<Modal.Header style={{ justifyContent: 'center' }}>
|
<Modal.Header style={{ justifyContent: 'center' }}>
|
||||||
<Group pos={'absolute'}>
|
<Group pos={'absolute'}>
|
||||||
<Text>Name:</Text>
|
<Text c={theme.backgroundColor}>Name:</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
className={textInputClasses.default}
|
className={textInputClasses.default}
|
||||||
classNames={textInputClasses}
|
classNames={textInputClasses}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ function ThemePlaylistCard({
|
|||||||
const themeList = JSON.parse(
|
const themeList = JSON.parse(
|
||||||
cardPlaylist.themeList.name === 'Time of Day' ? '[]' : cardPlaylist.themeList,
|
cardPlaylist.themeList.name === 'Time of Day' ? '[]' : cardPlaylist.themeList,
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group
|
<Group
|
||||||
gap={0}
|
gap={0}
|
||||||
@@ -253,7 +252,7 @@ function ThemePlaylistCard({
|
|||||||
<Stack gap={4}>
|
<Stack gap={4}>
|
||||||
{themeList.length > 0 &&
|
{themeList.length > 0 &&
|
||||||
themeList
|
themeList
|
||||||
.sort((a: any, b: any) => (a > b ? 1 : -1))
|
.sort((a: number, b: number) => (a > b ? 1 : -1))
|
||||||
.map((item: number) => {
|
.map((item: number) => {
|
||||||
return (
|
return (
|
||||||
<ThemeMiniCard key={item} item={item} allThemes={allThemes} />
|
<ThemeMiniCard key={item} item={item} allThemes={allThemes} />
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { modalClasses, textInputClasses } from 'styles';
|
import { modalClasses, textInputClasses } from 'styles';
|
||||||
import type { Theme } from 'types';
|
import type { Theme, ThemePlaylist } from 'types';
|
||||||
import ThemeMiniCard from './ThemeMiniCard';
|
import ThemeMiniCard from './ThemeMiniCard';
|
||||||
import TimeOfDay from './TimeOfDay';
|
import TimeOfDay from './TimeOfDay';
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@ function ThemePlaylistModal({
|
|||||||
handleClose,
|
handleClose,
|
||||||
createPlaylist,
|
createPlaylist,
|
||||||
selectedPlaylist,
|
selectedPlaylist,
|
||||||
|
defaultPlaylist,
|
||||||
setSelectedPlaylist,
|
setSelectedPlaylist,
|
||||||
handleSavePlaylist,
|
handleSavePlaylist,
|
||||||
allThemes,
|
allThemes,
|
||||||
@@ -26,13 +27,15 @@ function ThemePlaylistModal({
|
|||||||
opened: boolean;
|
opened: boolean;
|
||||||
handleClose: () => void;
|
handleClose: () => void;
|
||||||
createPlaylist: any;
|
createPlaylist: any;
|
||||||
selectedPlaylist: any;
|
selectedPlaylist: ThemePlaylist;
|
||||||
setSelectedPlaylist: (selectedPlaylist: any) => void;
|
defaultPlaylist: ThemePlaylist;
|
||||||
|
setSelectedPlaylist: (selectedPlaylist: ThemePlaylist) => void;
|
||||||
handleSavePlaylist: () => void;
|
handleSavePlaylist: () => void;
|
||||||
allThemes: Theme[];
|
allThemes: Theme[];
|
||||||
}) {
|
}) {
|
||||||
const { theme, isMobile, modalStyle } = useCommonHooks();
|
const { theme, isMobile, modalStyle } = useCommonHooks();
|
||||||
const [themeList, setThemeList] = useState<any>('[]');
|
const [themeList, setThemeList] = useState<any>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedPlaylist?.themeList) {
|
if (selectedPlaylist?.themeList) {
|
||||||
setThemeList(JSON.parse(selectedPlaylist?.themeList));
|
setThemeList(JSON.parse(selectedPlaylist?.themeList));
|
||||||
@@ -40,12 +43,8 @@ function ThemePlaylistModal({
|
|||||||
}, [selectedPlaylist]);
|
}, [selectedPlaylist]);
|
||||||
|
|
||||||
if (selectedPlaylist?.name === undefined) {
|
if (selectedPlaylist?.name === undefined) {
|
||||||
setSelectedPlaylist({
|
setSelectedPlaylist(defaultPlaylist);
|
||||||
name: 'New Playlist',
|
|
||||||
themeList: '[]',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal.Root
|
<Modal.Root
|
||||||
size={'50%'}
|
size={'50%'}
|
||||||
@@ -64,7 +63,7 @@ function ThemePlaylistModal({
|
|||||||
<Modal.Content>
|
<Modal.Content>
|
||||||
<Modal.Header style={{ justifyContent: 'center' }}>
|
<Modal.Header style={{ justifyContent: 'center' }}>
|
||||||
<Group pos={'absolute'}>
|
<Group pos={'absolute'}>
|
||||||
<Text>Name:</Text>
|
<Text c={theme.backgroundColor}>Name:</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
className={textInputClasses.default}
|
className={textInputClasses.default}
|
||||||
classNames={textInputClasses}
|
classNames={textInputClasses}
|
||||||
@@ -145,7 +144,7 @@ function ThemePlaylistModal({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleClose();
|
handleClose();
|
||||||
setThemeList('[]');
|
setThemeList('[]');
|
||||||
setSelectedPlaylist({});
|
setSelectedPlaylist(defaultPlaylist);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@@ -18,9 +18,16 @@ function ThemePlaylists() {
|
|||||||
const { data: themePlaylists } = useQueryAPI({
|
const { data: themePlaylists } = useQueryAPI({
|
||||||
endpoint: themePlaylistsEndpoint,
|
endpoint: themePlaylistsEndpoint,
|
||||||
});
|
});
|
||||||
|
const defaultPlaylist = {
|
||||||
|
id: undefined,
|
||||||
|
default: 0,
|
||||||
|
name: 'New Playlist',
|
||||||
|
themeList: '[]',
|
||||||
|
};
|
||||||
const { mutateAsync } = useMutationAPI();
|
const { mutateAsync } = useMutationAPI();
|
||||||
const [opened, { open, close }] = useDisclosure(false);
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
const [selectedPlaylist, setSelectedPlaylist] = useState<ThemePlaylist | undefined>();
|
const [selectedPlaylist, setSelectedPlaylist] =
|
||||||
|
useState<ThemePlaylist>(defaultPlaylist);
|
||||||
const { currentThemePlaylist, theme, isMobile } = useCommonHooks();
|
const { currentThemePlaylist, theme, isMobile } = useCommonHooks();
|
||||||
const [searchValue, setSearchValue] = useState('');
|
const [searchValue, setSearchValue] = useState('');
|
||||||
const [debouncedSearch] = useDebouncedValue(searchValue, 500);
|
const [debouncedSearch] = useDebouncedValue(searchValue, 500);
|
||||||
@@ -31,7 +38,7 @@ function ThemePlaylists() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setSelectedPlaylist(undefined);
|
setSelectedPlaylist(defaultPlaylist);
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,6 +57,7 @@ function ThemePlaylists() {
|
|||||||
opened={opened}
|
opened={opened}
|
||||||
handleClose={handleClose}
|
handleClose={handleClose}
|
||||||
selectedPlaylist={selectedPlaylist}
|
selectedPlaylist={selectedPlaylist}
|
||||||
|
defaultPlaylist={defaultPlaylist}
|
||||||
setSelectedPlaylist={setSelectedPlaylist}
|
setSelectedPlaylist={setSelectedPlaylist}
|
||||||
handleSavePlaylist={handleSavePlaylist}
|
handleSavePlaylist={handleSavePlaylist}
|
||||||
allThemes={allThemes}
|
allThemes={allThemes}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import { Group, Select, Text } from '@mantine/core';
|
import {
|
||||||
import type { Theme } from 'types';
|
type ComboboxItem,
|
||||||
|
type ComboboxLikeRenderOptionInput,
|
||||||
|
Group,
|
||||||
|
Select,
|
||||||
|
Text,
|
||||||
|
} from '@mantine/core';
|
||||||
|
import type { Theme, ThemePlaylist } from 'types';
|
||||||
|
|
||||||
function ThemeSelect({
|
function ThemeSelect({
|
||||||
allThemes,
|
allThemes,
|
||||||
@@ -10,14 +16,15 @@ function ThemeSelect({
|
|||||||
timeIndex,
|
timeIndex,
|
||||||
}: {
|
}: {
|
||||||
allThemes: Theme[];
|
allThemes: Theme[];
|
||||||
createPlaylist: any;
|
createPlaylist: (arg0: object) => void;
|
||||||
themeList: any;
|
themeList: Array<string>;
|
||||||
selectedPlaylist: any;
|
selectedPlaylist: ThemePlaylist;
|
||||||
index: string;
|
index: number;
|
||||||
timeIndex: string;
|
timeIndex: string;
|
||||||
}) {
|
}) {
|
||||||
const theme = allThemes.find((theme: Theme) => `${theme.id}` === themeList[index]);
|
const theme: Theme | undefined = allThemes.find(
|
||||||
|
(theme: Theme) => `${theme.id}` === themeList[index],
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<Group>
|
<Group>
|
||||||
<Text w={'100px'}>{timeIndex}</Text>
|
<Text w={'100px'}>{timeIndex}</Text>
|
||||||
@@ -34,7 +41,7 @@ function ThemeSelect({
|
|||||||
})}
|
})}
|
||||||
onChange={(data) => {
|
onChange={(data) => {
|
||||||
const newThemeList = themeList;
|
const newThemeList = themeList;
|
||||||
newThemeList[index] = data;
|
newThemeList[index] = data as string;
|
||||||
createPlaylist({
|
createPlaylist({
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
endpoint: 'api/themePlaylists',
|
endpoint: 'api/themePlaylists',
|
||||||
@@ -60,8 +67,10 @@ function ThemeSelect({
|
|||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
renderOption={({ option }: any) => {
|
renderOption={(item: ComboboxLikeRenderOptionInput<ComboboxItem>) => {
|
||||||
const theme = allThemes?.find((theme: Theme) => `${theme.id}` === option.value);
|
const theme = allThemes?.find(
|
||||||
|
(theme: Theme) => `${theme.id}` === item.option.value,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<Group
|
<Group
|
||||||
gap={0}
|
gap={0}
|
||||||
@@ -86,7 +95,10 @@ function ThemeSelect({
|
|||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{allThemes.find((theme: Theme) => `${theme.id}` === option.value)?.name}
|
{
|
||||||
|
allThemes.find((theme: Theme) => `${theme.id}` === item.option.value)
|
||||||
|
?.name
|
||||||
|
}
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useEffect, useState } from 'react';
|
|||||||
import { FaDice } from 'react-icons/fa';
|
import { FaDice } from 'react-icons/fa';
|
||||||
import { FiChevronRight } from 'react-icons/fi';
|
import { FiChevronRight } from 'react-icons/fi';
|
||||||
import { switchClasses } from 'styles';
|
import { switchClasses } from 'styles';
|
||||||
import type { Theme } from 'types';
|
import type { Theme, ThemePlaylist } from 'types';
|
||||||
import SettingsHeader from '../Shared/SettingsHeader';
|
import SettingsHeader from '../Shared/SettingsHeader';
|
||||||
import ThemeCard from './ThemeCard';
|
import ThemeCard from './ThemeCard';
|
||||||
import ThemeModal from './ThemeModal';
|
import ThemeModal from './ThemeModal';
|
||||||
@@ -19,9 +19,10 @@ function ThemesSettings() {
|
|||||||
const { data: backgroundData, isFetched: isBackgroundFetched } = useQueryAPI({
|
const { data: backgroundData, isFetched: isBackgroundFetched } = useQueryAPI({
|
||||||
endpoint: backgroundsEndpoint,
|
endpoint: backgroundsEndpoint,
|
||||||
});
|
});
|
||||||
const { data: themePlaylists } = useQueryAPI({
|
const { data: themePlaylistData } = useQueryAPI({
|
||||||
endpoint: 'api/themePlaylists',
|
endpoint: 'api/themePlaylists',
|
||||||
});
|
});
|
||||||
|
const [themePlaylists, setThemePlaylists] = useState<ThemePlaylist[]>([]);
|
||||||
const { mutateAsync } = useMutationAPI();
|
const { mutateAsync } = useMutationAPI();
|
||||||
const [opened, { open, close }] = useDisclosure(false);
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
const [colorId, setColorId] = useState<string>('');
|
const [colorId, setColorId] = useState<string>('');
|
||||||
@@ -79,6 +80,13 @@ function ThemesSettings() {
|
|||||||
setBackgroundList(['None', ...backgroundData]);
|
setBackgroundList(['None', ...backgroundData]);
|
||||||
}
|
}
|
||||||
}, [backgroundData, isBackgroundFetched]);
|
}, [backgroundData, isBackgroundFetched]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (themePlaylistData) {
|
||||||
|
setThemePlaylists(themePlaylistData);
|
||||||
|
}
|
||||||
|
}, [themePlaylistData]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack w={'100%'} align='center'>
|
<Stack w={'100%'} align='center'>
|
||||||
<ThemeModal
|
<ThemeModal
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Stack } from '@mantine/core';
|
import { Stack } from '@mantine/core';
|
||||||
import type { Theme } from 'types';
|
import type { Theme, ThemePlaylist } from 'types';
|
||||||
import ThemeSelect from './ThemeSelect';
|
import ThemeSelect from './ThemeSelect';
|
||||||
|
|
||||||
function TimeOfDay({
|
function TimeOfDay({
|
||||||
@@ -7,7 +7,12 @@ function TimeOfDay({
|
|||||||
themeList,
|
themeList,
|
||||||
allThemes,
|
allThemes,
|
||||||
selectedPlaylist,
|
selectedPlaylist,
|
||||||
}: { createPlaylist: any; themeList: any; allThemes: Theme[]; selectedPlaylist: any }) {
|
}: {
|
||||||
|
createPlaylist: () => void;
|
||||||
|
themeList: Array<string>;
|
||||||
|
allThemes: Theme[];
|
||||||
|
selectedPlaylist: ThemePlaylist;
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
<ThemeSelect
|
<ThemeSelect
|
||||||
@@ -15,7 +20,7 @@ function TimeOfDay({
|
|||||||
createPlaylist={createPlaylist}
|
createPlaylist={createPlaylist}
|
||||||
themeList={themeList}
|
themeList={themeList}
|
||||||
selectedPlaylist={selectedPlaylist}
|
selectedPlaylist={selectedPlaylist}
|
||||||
index='0'
|
index={0}
|
||||||
timeIndex='00:00 - 05:59'
|
timeIndex='00:00 - 05:59'
|
||||||
/>
|
/>
|
||||||
<ThemeSelect
|
<ThemeSelect
|
||||||
@@ -23,7 +28,7 @@ function TimeOfDay({
|
|||||||
createPlaylist={createPlaylist}
|
createPlaylist={createPlaylist}
|
||||||
themeList={themeList}
|
themeList={themeList}
|
||||||
selectedPlaylist={selectedPlaylist}
|
selectedPlaylist={selectedPlaylist}
|
||||||
index='1'
|
index={1}
|
||||||
timeIndex='06:00 - 11:59'
|
timeIndex='06:00 - 11:59'
|
||||||
/>
|
/>
|
||||||
<ThemeSelect
|
<ThemeSelect
|
||||||
@@ -31,7 +36,7 @@ function TimeOfDay({
|
|||||||
createPlaylist={createPlaylist}
|
createPlaylist={createPlaylist}
|
||||||
themeList={themeList}
|
themeList={themeList}
|
||||||
selectedPlaylist={selectedPlaylist}
|
selectedPlaylist={selectedPlaylist}
|
||||||
index='2'
|
index={2}
|
||||||
timeIndex='12:00 - 17:59'
|
timeIndex='12:00 - 17:59'
|
||||||
/>
|
/>
|
||||||
<ThemeSelect
|
<ThemeSelect
|
||||||
@@ -39,7 +44,7 @@ function TimeOfDay({
|
|||||||
createPlaylist={createPlaylist}
|
createPlaylist={createPlaylist}
|
||||||
themeList={themeList}
|
themeList={themeList}
|
||||||
selectedPlaylist={selectedPlaylist}
|
selectedPlaylist={selectedPlaylist}
|
||||||
index='3'
|
index={3}
|
||||||
timeIndex='18:00 - 23:59'
|
timeIndex='18:00 - 23:59'
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export interface BookmarkGroup {
|
export interface BookmarkGroup {
|
||||||
id: number | undefined;
|
id: number | null;
|
||||||
categoryName: string;
|
categoryName: string;
|
||||||
categoryIndex: number;
|
categoryIndex: number;
|
||||||
filterName: string;
|
filterName: string;
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
export type { CurrentWeather, OutlookWeather, ExtendedForecast } from './weather';
|
export type {
|
||||||
|
CurrentWeather,
|
||||||
|
OutlookWeather,
|
||||||
|
ExtendedForecast,
|
||||||
|
HourlyForecast,
|
||||||
|
SunState,
|
||||||
|
} from './weather';
|
||||||
export type { Application, AppCategory } from './application';
|
export type { Application, AppCategory } from './application';
|
||||||
export type { Bookmark } from './bookmark';
|
export type { Bookmark } from './bookmark';
|
||||||
export type { BookmarkGroup } from './bookmarkGroup';
|
export type { BookmarkGroup } from './bookmarkGroup';
|
||||||
@@ -7,6 +13,6 @@ export type { Message } from './message';
|
|||||||
export type { Provider } from './provider';
|
export type { Provider } from './provider';
|
||||||
export type { Theme, ThemePlaylist } from './theme';
|
export type { Theme, ThemePlaylist } from './theme';
|
||||||
export type { WolClient } from './wolClient';
|
export type { WolClient } from './wolClient';
|
||||||
export type { SearchHistoryItem } from './searchHistory';
|
export type { SearchHistoryItem, SearchShortcut } from './search';
|
||||||
export type { User } from './user';
|
export type { User } from './user';
|
||||||
export type { Location } from './location';
|
export type { Location } from './location';
|
||||||
|
|||||||
@@ -5,3 +5,8 @@ export interface SearchHistoryItem {
|
|||||||
searchTerm: string;
|
searchTerm: string;
|
||||||
dateTimeStamp: string;
|
dateTimeStamp: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SearchShortcut {
|
||||||
|
name: string;
|
||||||
|
command: string;
|
||||||
|
}
|
||||||
@@ -14,5 +14,5 @@ export interface ThemePlaylist {
|
|||||||
id: number | undefined;
|
id: number | undefined;
|
||||||
name: string;
|
name: string;
|
||||||
default: number;
|
default: number;
|
||||||
themeList: number[];
|
themeList: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,3 +31,43 @@ export interface ExtendedForecast {
|
|||||||
temperature: number;
|
temperature: number;
|
||||||
temperatureUnit: string;
|
temperatureUnit: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HourlyForecast {
|
||||||
|
detailedForecast: string;
|
||||||
|
dewpoint: DewPoint;
|
||||||
|
endTime: string;
|
||||||
|
icon: string;
|
||||||
|
isDaytime: boolean;
|
||||||
|
name: string;
|
||||||
|
number: number;
|
||||||
|
probabilityOfPrecipitation: ProbabilityOfPrecipitation;
|
||||||
|
relativeHumidity: RelativeHumidity;
|
||||||
|
shortForecast: string;
|
||||||
|
startTime: string;
|
||||||
|
temperature: number;
|
||||||
|
temperatureTrend: string;
|
||||||
|
temperatureUnit: string;
|
||||||
|
windDirection: string;
|
||||||
|
windSpeed: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProbabilityOfPrecipitation {
|
||||||
|
unitCode: string;
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RelativeHumidity {
|
||||||
|
unitCode: string;
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DewPoint {
|
||||||
|
unitCode: string;
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SunState {
|
||||||
|
date: string;
|
||||||
|
sunrise: string;
|
||||||
|
sunset: string;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user