Refactor
This commit is contained in:
@@ -4,5 +4,3 @@
|
|||||||
- Create actions section
|
- Create actions section
|
||||||
|
|
||||||
- Fix all query/setState problems
|
- Fix all query/setState problems
|
||||||
|
|
||||||
- Random "feeling lucky" or subreddit button
|
|
||||||
|
|||||||
1934
package-lock.json
generated
1934
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,12 @@
|
|||||||
"eslint-plugin-react-hooks": "^4.6.2",
|
"eslint-plugin-react-hooks": "^4.6.2",
|
||||||
"eslint-plugin-react-refresh": "^0.4.9",
|
"eslint-plugin-react-refresh": "^0.4.9",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"vite": "^5.4.0"
|
"vite": "^5.4.0",
|
||||||
|
"vite-plugin-dts": "~4.0.1",
|
||||||
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
|
"vite-tsconfig-paths": "^4.3.2",
|
||||||
|
"vitest": "^2.0.5",
|
||||||
|
"@vitest/coverage-v8": "^2.0.5",
|
||||||
|
"@vitest/ui": "^2.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/App.tsx
11
src/App.tsx
@@ -7,6 +7,7 @@ import {
|
|||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useLocalStorage } from '@mantine/hooks';
|
import { useLocalStorage } from '@mantine/hooks';
|
||||||
import { ModalsProvider } from '@mantine/modals';
|
import { ModalsProvider } from '@mantine/modals';
|
||||||
|
import { useQueryAPI } from 'hooks';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import {
|
import {
|
||||||
Route,
|
Route,
|
||||||
@@ -14,24 +15,22 @@ import {
|
|||||||
createBrowserRouter,
|
createBrowserRouter,
|
||||||
createRoutesFromElements,
|
createRoutesFromElements,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
import ThemeProvider from './components/ThemeProvider';
|
import { ThemeProvider } from './components';
|
||||||
import { useQueryAPI } from './hooks/useAPI';
|
|
||||||
import Homepage from './pages/homepage/Homepage';
|
|
||||||
import Settings from './pages/settings/Settings';
|
|
||||||
import '@mantine/core/styles.css'; //import Mantine V7 styles needed by MRT
|
import '@mantine/core/styles.css'; //import Mantine V7 styles needed by MRT
|
||||||
import '@mantine/dates/styles.css'; //if using mantine date picker features
|
import '@mantine/dates/styles.css'; //if using mantine date picker features
|
||||||
import 'mantine-react-table/styles.css'; //import MRT styles
|
import 'mantine-react-table/styles.css'; //import MRT styles
|
||||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
||||||
|
import { appTheme } from 'contexts';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { appTheme } from './contexts/theme';
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
import { Homepage, Settings } from 'pages';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const { data, isFetched } = useQueryAPI({
|
const { data, isFetched } = useQueryAPI({
|
||||||
endpoint: 'api/themes',
|
endpoint: 'api/themes',
|
||||||
});
|
});
|
||||||
|
|
||||||
const [themeName, setThemeName] = useLocalStorage<any>({
|
const [themeName, _] = useLocalStorage<any>({
|
||||||
key: 'theme',
|
key: 'theme',
|
||||||
defaultValue: 'blackboard',
|
defaultValue: 'blackboard',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ import {
|
|||||||
useMantineReactTable,
|
useMantineReactTable,
|
||||||
} from 'mantine-react-table';
|
} from 'mantine-react-table';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import '../dataTableStyles.css';
|
import '../../../src/dataTableStyles.css';
|
||||||
import { ActionIcon, Button, Flex, Text } from '@mantine/core';
|
import { ActionIcon, Button, Flex, Text } from '@mantine/core';
|
||||||
import { modals } from '@mantine/modals';
|
import { modals } from '@mantine/modals';
|
||||||
import { IconEdit, IconTrash } from '@tabler/icons-react';
|
import { IconEdit, IconTrash } from '@tabler/icons-react';
|
||||||
|
import { appTheme } from 'contexts';
|
||||||
|
import { useMutationAPI } from 'hooks';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { FiPlus } from 'react-icons/fi';
|
import { FiPlus } from 'react-icons/fi';
|
||||||
import { appTheme } from '../contexts/theme';
|
import { actionIconClasses, buttonClasses } from 'styles';
|
||||||
import { useMutationAPI } from '../hooks/useAPI';
|
|
||||||
import { actionIconClasses, buttonClasses } from '../styles';
|
|
||||||
|
|
||||||
export function DataTableComponent({
|
export function DataTableComponent({
|
||||||
tableName,
|
tableName,
|
||||||
@@ -22,7 +22,6 @@ export function DataTableComponent({
|
|||||||
isFetching,
|
isFetching,
|
||||||
isLoading,
|
isLoading,
|
||||||
endpoint,
|
endpoint,
|
||||||
grouping,
|
|
||||||
}: {
|
}: {
|
||||||
tableName: string;
|
tableName: string;
|
||||||
columns: any;
|
columns: any;
|
||||||
@@ -30,9 +29,8 @@ export function DataTableComponent({
|
|||||||
isFetching: boolean;
|
isFetching: boolean;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
grouping?: string;
|
|
||||||
}) {
|
}) {
|
||||||
const [theme, setTheme] = useAtom(appTheme);
|
const [theme, _] = useAtom(appTheme);
|
||||||
const { mutateAsync: createRow } = useMutationAPI();
|
const { mutateAsync: createRow } = useMutationAPI();
|
||||||
const { mutateAsync: editRow } = useMutationAPI();
|
const { mutateAsync: editRow } = useMutationAPI();
|
||||||
const { mutateAsync: deleteRow } = useMutationAPI();
|
const { mutateAsync: deleteRow } = useMutationAPI();
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { MRT_ColumnDef } from 'mantine-react-table';
|
import type { MRT_ColumnDef } from 'mantine-react-table';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
export default function ApplicationColumns() {
|
export function ApplicationColumns() {
|
||||||
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -15,7 +15,7 @@ export default function ApplicationColumns() {
|
|||||||
id: 'id',
|
id: 'id',
|
||||||
header: 'ID',
|
header: 'ID',
|
||||||
size: 50,
|
size: 50,
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -27,7 +27,7 @@ export default function ApplicationColumns() {
|
|||||||
},
|
},
|
||||||
id: 'name',
|
id: 'name',
|
||||||
header: 'Name',
|
header: 'Name',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -39,7 +39,7 @@ export default function ApplicationColumns() {
|
|||||||
},
|
},
|
||||||
id: 'url',
|
id: 'url',
|
||||||
header: 'Url',
|
header: 'Url',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -51,7 +51,7 @@ export default function ApplicationColumns() {
|
|||||||
},
|
},
|
||||||
id: 'icon',
|
id: 'icon',
|
||||||
header: 'Icon',
|
header: 'Icon',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,7 @@ export default function ApplicationColumns() {
|
|||||||
},
|
},
|
||||||
id: 'baseUrl',
|
id: 'baseUrl',
|
||||||
header: 'Base Url',
|
header: 'Base Url',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -75,7 +75,7 @@ export default function ApplicationColumns() {
|
|||||||
},
|
},
|
||||||
id: 'filterName',
|
id: 'filterName',
|
||||||
header: 'Filter Name',
|
header: 'Filter Name',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { MRT_ColumnDef } from 'mantine-react-table';
|
import type { MRT_ColumnDef } from 'mantine-react-table';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
export default function ApplicationColumns(groups: any) {
|
export function BookmarkColumns(groups: any) {
|
||||||
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -15,7 +15,7 @@ export default function ApplicationColumns(groups: any) {
|
|||||||
id: 'id',
|
id: 'id',
|
||||||
header: 'ID',
|
header: 'ID',
|
||||||
size: 50,
|
size: 50,
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -27,7 +27,7 @@ export default function ApplicationColumns(groups: any) {
|
|||||||
},
|
},
|
||||||
id: 'name',
|
id: 'name',
|
||||||
header: 'Name',
|
header: 'Name',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -39,7 +39,7 @@ export default function ApplicationColumns(groups: any) {
|
|||||||
},
|
},
|
||||||
id: 'url',
|
id: 'url',
|
||||||
header: 'Url',
|
header: 'Url',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { MRT_ColumnDef } from 'mantine-react-table';
|
import type { MRT_ColumnDef } from 'mantine-react-table';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
export default function CategoryColumns() {
|
export function CategoryColumns() {
|
||||||
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -15,7 +15,7 @@ export default function CategoryColumns() {
|
|||||||
id: 'id',
|
id: 'id',
|
||||||
header: 'ID',
|
header: 'ID',
|
||||||
size: 50,
|
size: 50,
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -28,7 +28,7 @@ export default function CategoryColumns() {
|
|||||||
id: 'categoryName',
|
id: 'categoryName',
|
||||||
header: 'Name',
|
header: 'Name',
|
||||||
size: 50,
|
size: 50,
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -42,7 +42,7 @@ export default function CategoryColumns() {
|
|||||||
id: 'categoryIndex',
|
id: 'categoryIndex',
|
||||||
header: 'Index',
|
header: 'Index',
|
||||||
size: 50,
|
size: 50,
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -55,7 +55,7 @@ export default function CategoryColumns() {
|
|||||||
id: 'filterName',
|
id: 'filterName',
|
||||||
header: 'Filter Name',
|
header: 'Filter Name',
|
||||||
size: 50,
|
size: 50,
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { MRT_ColumnDef } from 'mantine-react-table';
|
import type { MRT_ColumnDef } from 'mantine-react-table';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
export default function MessagesColumns() {
|
export function MessagesColumns() {
|
||||||
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -15,7 +15,7 @@ export default function MessagesColumns() {
|
|||||||
id: 'id',
|
id: 'id',
|
||||||
header: 'ID',
|
header: 'ID',
|
||||||
size: 50,
|
size: 50,
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -27,7 +27,7 @@ export default function MessagesColumns() {
|
|||||||
},
|
},
|
||||||
id: 'message',
|
id: 'message',
|
||||||
header: 'Message',
|
header: 'Message',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { MRT_ColumnDef } from 'mantine-react-table';
|
import type { MRT_ColumnDef } from 'mantine-react-table';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
export default function PersonalizationColumns() {
|
export function PersonalizationColumns() {
|
||||||
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -14,7 +14,7 @@ export default function PersonalizationColumns() {
|
|||||||
id: 'firstName',
|
id: 'firstName',
|
||||||
header: 'First Name',
|
header: 'First Name',
|
||||||
size: 50,
|
size: 50,
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -26,7 +26,7 @@ export default function PersonalizationColumns() {
|
|||||||
},
|
},
|
||||||
id: 'lastName',
|
id: 'lastName',
|
||||||
header: 'Last Name',
|
header: 'Last Name',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,7 @@ export default function PersonalizationColumns() {
|
|||||||
},
|
},
|
||||||
id: 'email',
|
id: 'email',
|
||||||
header: 'Email',
|
header: 'Email',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { MRT_ColumnDef } from 'mantine-react-table';
|
import type { MRT_ColumnDef } from 'mantine-react-table';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
export default function SearchProviderColumns() {
|
export function SearchProviderColumns() {
|
||||||
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
const columns = useMemo<MRT_ColumnDef<any>[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -15,7 +15,7 @@ export default function SearchProviderColumns() {
|
|||||||
id: 'id',
|
id: 'id',
|
||||||
header: 'ID',
|
header: 'ID',
|
||||||
size: 50,
|
size: 50,
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -27,7 +27,7 @@ export default function SearchProviderColumns() {
|
|||||||
},
|
},
|
||||||
id: 'name',
|
id: 'name',
|
||||||
header: 'Name',
|
header: 'Name',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -39,7 +39,7 @@ export default function SearchProviderColumns() {
|
|||||||
},
|
},
|
||||||
id: 'url',
|
id: 'url',
|
||||||
header: 'Url',
|
header: 'Url',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -51,7 +51,7 @@ export default function SearchProviderColumns() {
|
|||||||
},
|
},
|
||||||
id: 'prefix',
|
id: 'prefix',
|
||||||
header: 'Prefix',
|
header: 'Prefix',
|
||||||
Cell: ({ renderedCellValue, row }) => renderedCellValue,
|
Cell: ({ renderedCellValue }) => renderedCellValue,
|
||||||
Header: ({ column }) => column.columnDef.header,
|
Header: ({ column }) => column.columnDef.header,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Divider, Group, Modal, Stack, Text } from '@mantine/core';
|
import { Divider, Group, Modal, Stack, Text } from '@mantine/core';
|
||||||
|
import { appTheme } from 'contexts';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { appTheme } from '../../../contexts/theme';
|
import { modalClasses } from 'styles';
|
||||||
import { modalClasses } from '../../../styles';
|
|
||||||
|
|
||||||
export default function HelpModal({
|
export function HelpModal({
|
||||||
setValue,
|
setValue,
|
||||||
setProviderLabel,
|
setProviderLabel,
|
||||||
setProviderURL,
|
setProviderURL,
|
||||||
@@ -11,7 +11,7 @@ export default function HelpModal({
|
|||||||
providerModalOpened,
|
providerModalOpened,
|
||||||
closeProviderModal,
|
closeProviderModal,
|
||||||
}: any) {
|
}: any) {
|
||||||
const [theme, setTheme] = useAtom(appTheme);
|
const [theme, _] = useAtom(appTheme);
|
||||||
return (
|
return (
|
||||||
<Modal.Root
|
<Modal.Root
|
||||||
size={'60%'}
|
size={'60%'}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Box } from '@mantine/core';
|
import { Box } from '@mantine/core';
|
||||||
|
|
||||||
export default function ThemeProvider({
|
export function ThemeProvider({
|
||||||
theme,
|
theme,
|
||||||
children,
|
children,
|
||||||
}: { theme: any; children: React.ReactNode }) {
|
}: { theme: any; children: React.ReactNode }) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Stack, Text } from '@mantine/core';
|
import { Stack, Text } from '@mantine/core';
|
||||||
import { stackClasses } from '../styles';
|
import { stackClasses } from 'styles';
|
||||||
|
|
||||||
export function ToastError({ err }: { err: any }) {
|
export function ToastError({ err }: { err: any }) {
|
||||||
const errorResponse = JSON.parse(err.message);
|
const errorResponse = JSON.parse(err.message);
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export default function HourlyCard({ weather }: any) {
|
|||||||
transform: `rotate(${WindDirection[weather.windDirection]}deg)`,
|
transform: `rotate(${WindDirection[weather.windDirection]}deg)`,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{`${weather.probabilityOfPrecipitation.value * 10}`}%
|
{`${weather.probabilityOfPrecipitation.value}`}%
|
||||||
</Group>
|
</Group>
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import { Center, Divider, Group, Modal, Stack } from '@mantine/core';
|
import { Center, Divider, Group, Modal, Stack } from '@mantine/core';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { modalClasses } from '../../../styles';
|
import { modalClasses } from 'styles';
|
||||||
import SmallOutlookCard from './SmallOutlookCard';
|
import SmallOutlookCard from './SmallOutlookCard';
|
||||||
import SmallWeatherCard from './SmallWeatherCard';
|
import SmallWeatherCard from './SmallWeatherCard';
|
||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { appTheme } from '../../../contexts/theme';
|
import { appTheme } from '../../contexts/theme';
|
||||||
import HourlyCard from './HourlyCard';
|
import HourlyCard from './HourlyCard';
|
||||||
|
|
||||||
export default function WeatherModal({
|
export function WeatherModal({
|
||||||
current,
|
current,
|
||||||
outlook,
|
outlook,
|
||||||
hourly,
|
hourly,
|
||||||
@@ -18,7 +18,7 @@ export default function WeatherModal({
|
|||||||
setProviderLabel,
|
setProviderLabel,
|
||||||
setProviderURL,
|
setProviderURL,
|
||||||
}: any) {
|
}: any) {
|
||||||
const [theme, setTheme] = useAtom(appTheme);
|
const [theme, _] = useAtom(appTheme);
|
||||||
const [hourlyForecast, setHourlyForecast] = useState<any>([]);
|
const [hourlyForecast, setHourlyForecast] = useState<any>([]);
|
||||||
const [sunset, setSunset] = useState(100);
|
const [sunset, setSunset] = useState(100);
|
||||||
|
|
||||||
@@ -30,8 +30,13 @@ export default function WeatherModal({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hourlyForecast) {
|
if (hourlyForecast) {
|
||||||
setSunset(
|
hourlyForecast[0]?.isDaytime
|
||||||
(hourlyForecast.findIndex((item: any) => item.isDaytime === false) / 12) * 100,
|
? setSunset(
|
||||||
|
(hourlyForecast.findIndex((item: any) => item.isDaytime === false) / 12) *
|
||||||
|
100,
|
||||||
|
)
|
||||||
|
: setSunset(
|
||||||
|
(hourlyForecast.findIndex((item: any) => item.isDaytime === true) / 12) * 100,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [hourlyForecast]);
|
}, [hourlyForecast]);
|
||||||
10
src/components/index.ts
Normal file
10
src/components/index.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export { HelpModal } from './HelpModal/HelpModal';
|
||||||
|
export { WeatherModal } from './WeatherModal/WeatherModal';
|
||||||
|
export { DataTable } from './DataTable/DataTable';
|
||||||
|
export { ThemeProvider } from './ThemeProvider';
|
||||||
|
export { ApplicationColumns } from './DataTable/columns/ApplicationColumns';
|
||||||
|
export { BookmarkColumns } from './DataTable/columns/BookmarkColumns';
|
||||||
|
export { CategoryColumns } from './DataTable/columns/CategoryColumns';
|
||||||
|
export { MessagesColumns } from './DataTable/columns/MessagesColumns';
|
||||||
|
export { PersonalizationColumns } from './DataTable/columns/PersonalizationColumns';
|
||||||
|
export { SearchProviderColumns } from './DataTable/columns/SearchProviderColumns';
|
||||||
2
src/contexts/index.ts
Normal file
2
src/contexts/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export { HomepageFilters } from './HomepageFilters';
|
||||||
|
export { appTheme } from './theme';
|
||||||
47
src/hooks/helpers.ts
Normal file
47
src/hooks/helpers.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
export function date(isMobile: boolean) {
|
||||||
|
const currentDate = new Date();
|
||||||
|
const dateOptions: Intl.DateTimeFormatOptions = !isMobile
|
||||||
|
? {
|
||||||
|
weekday: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric',
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
const date = currentDate.toLocaleDateString('en-US', dateOptions);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
export function greet(list: any) {
|
||||||
|
const currentTime = new Date();
|
||||||
|
const greet = Math.floor(currentTime.getHours() / 6);
|
||||||
|
const easterEggChance = Math.floor(Math.random() * 100);
|
||||||
|
let timeBased: any = [];
|
||||||
|
let customGreetings: any = [];
|
||||||
|
for (const l of list) {
|
||||||
|
if (l.customGreeting === 0) {
|
||||||
|
timeBased = timeBased.concat(l);
|
||||||
|
} else {
|
||||||
|
customGreetings = customGreetings.concat(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (easterEggChance > 10 || customGreetings.length === 0) {
|
||||||
|
return timeBased[greet].message;
|
||||||
|
}
|
||||||
|
return customGreetings[Math.floor(Math.random() * customGreetings.length)].message;
|
||||||
|
}
|
||||||
|
export function validURL(str: any) {
|
||||||
|
const pattern = 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
|
||||||
|
return !!pattern.test(str);
|
||||||
|
}
|
||||||
|
export function containsProtocol(str: any) {
|
||||||
|
const pattern = /^(https?:\/\/).*/i;
|
||||||
|
return !!pattern.test(str);
|
||||||
|
}
|
||||||
@@ -1 +1,3 @@
|
|||||||
export { useQueryAPI, useWeatherAPI } from './useAPI';
|
export { useQueryAPI, useWeatherAPI, useMutationAPI } from './useAPI';
|
||||||
|
export { date, greet } from './helpers';
|
||||||
|
export { validURL, containsProtocol } from './helpers';
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
import {
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
useInfiniteQuery,
|
|
||||||
useMutation,
|
|
||||||
useQuery,
|
|
||||||
useQueryClient,
|
|
||||||
} from '@tanstack/react-query';
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
@@ -48,19 +43,7 @@ export function useWeatherAPI({ endpoint }: { endpoint: string }) {
|
|||||||
} else if (endpoint === 'hourly') {
|
} else if (endpoint === 'hourly') {
|
||||||
url = 'https://api.weather.gov/gridpoints/HGX/55,96/forecast/hourly';
|
url = 'https://api.weather.gov/gridpoints/HGX/55,96/forecast/hourly';
|
||||||
}
|
}
|
||||||
const callEndpoint = async (endpoint: string) => {
|
const callEndpoint = async () => {
|
||||||
const options: object = {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/geo+json',
|
|
||||||
'Access-Control-Allow-Origin': '*',
|
|
||||||
'Access-Control-Allow-Headers': '*',
|
|
||||||
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
|
||||||
'Access-Control-Allow-Credentials': true,
|
|
||||||
'Sec-Fetch-Mode': 'no-cors',
|
|
||||||
'Sec-Fetch-Site': 'same-site',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`${response.status} ${response.statusText}`);
|
throw new Error(`${response.status} ${response.statusText}`);
|
||||||
@@ -70,7 +53,7 @@ export function useWeatherAPI({ endpoint }: { endpoint: string }) {
|
|||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ['GET', url],
|
queryKey: ['GET', url],
|
||||||
queryFn: () => callEndpoint(endpoint),
|
queryFn: () => callEndpoint(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,8 +326,7 @@ interface DownloadFileOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useDownloadFile() {
|
export function useDownloadFile() {
|
||||||
const downloadFile = useCallback(
|
const downloadFile = useCallback(async ({ file_name }: DownloadFileOptions) => {
|
||||||
async ({ endpoint, file_name }: DownloadFileOptions) => {
|
|
||||||
const options: any = {
|
const options: any = {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
@@ -408,64 +390,7 @@ export function useDownloadFile() {
|
|||||||
closeButton: null,
|
closeButton: null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}, []);
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
return downloadFile;
|
return downloadFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useFetchInfiniteQuery = ({
|
|
||||||
endpoint,
|
|
||||||
pageSize = 10,
|
|
||||||
}: {
|
|
||||||
endpoint: string;
|
|
||||||
pageSize?: number;
|
|
||||||
}) => {
|
|
||||||
const queryKey = ['GET', endpoint];
|
|
||||||
|
|
||||||
const fetchInfiniteQuery = async (endpoint: string) => {
|
|
||||||
const requestOptions: any = {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Access-Control-Allow-Origin': '*',
|
|
||||||
'Access-Control-Allow-Headers': '*',
|
|
||||||
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
|
||||||
'Access-Control-Allow-Credentials': true,
|
|
||||||
'Sec-Fetch-Mode': 'no-cors',
|
|
||||||
'Sec-Fetch-Site': 'same-site',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
const response = await fetch(url, requestOptions);
|
|
||||||
return await response.json();
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching transactions:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const queryFn = ({ pageParam = 1 }) =>
|
|
||||||
fetchInfiniteQuery(`${endpoint}&page=${pageParam}&size=${pageSize}`);
|
|
||||||
const getNextPageParam = (lastPage: any, allPages: any) => {
|
|
||||||
if (lastPage.items.length < pageSize) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return allPages.length + 1;
|
|
||||||
};
|
|
||||||
const { data, isLoading, isFetchingNextPage, fetchNextPage, isError, isFetching } =
|
|
||||||
useInfiniteQuery({
|
|
||||||
queryKey,
|
|
||||||
queryFn,
|
|
||||||
getNextPageParam,
|
|
||||||
initialPageParam: 1,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
data,
|
|
||||||
isLoading,
|
|
||||||
isFetchingNextPage,
|
|
||||||
fetchNextPage,
|
|
||||||
isError,
|
|
||||||
isFetching,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
import { Stack } from '@mantine/core';
|
import { Stack } from '@mantine/core';
|
||||||
import { useDisclosure, useLocalStorage } from '@mantine/hooks';
|
import { useDisclosure, useLocalStorage } from '@mantine/hooks';
|
||||||
|
import { date, greet, useQueryAPI, useWeatherAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useQueryAPI, useWeatherAPI } from '../../hooks/useAPI';
|
import { stackClasses } from 'styles';
|
||||||
import stackClasses from '../../styles/Stack.module.css';
|
import type { CurrentWeather, OutlookWeather } from 'types';
|
||||||
import Applications from './components/Applications';
|
import Applications from './components/Applications/Applications';
|
||||||
import Bookmarks from './components/Bookmarks';
|
import Bookmarks from './components/Bookmarks/Bookmarks';
|
||||||
import Header from './components/Header';
|
import Header from './components/Header/Header';
|
||||||
import Search from './components/Search';
|
import Search from './components/Search/Search';
|
||||||
import SettingsButton from './components/SettingsButton';
|
import SettingsButton from './components/SettingsButton';
|
||||||
import type { CurrentWeather, OutlookWeather } from './types/weather';
|
|
||||||
|
|
||||||
export default function Homepage({ theme }: any) {
|
export function Homepage({ theme }: any) {
|
||||||
const { data, isFetching } = useQueryAPI({ endpoint: 'api/messages' });
|
|
||||||
const [displayedGreeting, setDisplayedGreeting] = useState('');
|
|
||||||
const [appFilter, setAppFilter] = useLocalStorage<[any]>({
|
const [appFilter, setAppFilter] = useLocalStorage<[any]>({
|
||||||
key: 'appFilter',
|
key: 'appFilter',
|
||||||
defaultValue: ['All'],
|
defaultValue: ['All'],
|
||||||
@@ -21,8 +19,12 @@ export default function Homepage({ theme }: any) {
|
|||||||
key: 'bookmarkFilter',
|
key: 'bookmarkFilter',
|
||||||
defaultValue: ['All'],
|
defaultValue: ['All'],
|
||||||
});
|
});
|
||||||
|
const { data, isFetching } = useQueryAPI({ endpoint: 'api/messages' });
|
||||||
const { data: basicWeather } = useWeatherAPI({ endpoint: 'baseline' });
|
const { data: basicWeather } = useWeatherAPI({ endpoint: 'baseline' });
|
||||||
const { data: weather } = useWeatherAPI({ endpoint: 'current' });
|
const { data: weather } = useWeatherAPI({ endpoint: 'current' });
|
||||||
|
const { data: forecast } = useWeatherAPI({ endpoint: 'forecast' });
|
||||||
|
const { data: hourly } = useWeatherAPI({ endpoint: 'hourly' });
|
||||||
|
const [displayedGreeting, setDisplayedGreeting] = useState('');
|
||||||
const [current, setCurrent] = useState<CurrentWeather>({
|
const [current, setCurrent] = useState<CurrentWeather>({
|
||||||
icon: '',
|
icon: '',
|
||||||
temperature: 0,
|
temperature: 0,
|
||||||
@@ -45,42 +47,9 @@ export default function Homepage({ theme }: any) {
|
|||||||
windDirection: 'N',
|
windDirection: 'N',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
const { data: forecast } = useWeatherAPI({ endpoint: 'forecast' });
|
const isMobile = window.matchMedia('(max-width: 600px)').matches;
|
||||||
const { data: hourly } = useWeatherAPI({ endpoint: 'hourly' });
|
|
||||||
const [weatherModalOpened, { open: openWeatherModal, close: closeWeatherModal }] =
|
const [weatherModalOpened, { open: openWeatherModal, close: closeWeatherModal }] =
|
||||||
useDisclosure(false);
|
useDisclosure(false);
|
||||||
const isMobile = window.matchMedia('(max-width: 600px)').matches;
|
|
||||||
function date() {
|
|
||||||
const currentDate = new Date();
|
|
||||||
const dateOptions: Intl.DateTimeFormatOptions = !isMobile
|
|
||||||
? {
|
|
||||||
weekday: 'long',
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric',
|
|
||||||
}
|
|
||||||
: {};
|
|
||||||
const date = currentDate.toLocaleDateString('en-US', dateOptions);
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
function greet(list: any) {
|
|
||||||
const currentTime = new Date();
|
|
||||||
const greet = Math.floor(currentTime.getHours() / 6);
|
|
||||||
const easterEggChance = Math.floor(Math.random() * 100);
|
|
||||||
let timeBased: any = [];
|
|
||||||
let customGreetings: any = [];
|
|
||||||
for (const l of list) {
|
|
||||||
if (l.customGreeting === 0) {
|
|
||||||
timeBased = timeBased.concat(l);
|
|
||||||
} else {
|
|
||||||
customGreetings = customGreetings.concat(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (easterEggChance > 10 || customGreetings.length === 0) {
|
|
||||||
return timeBased[greet].message;
|
|
||||||
}
|
|
||||||
return customGreetings[Math.floor(Math.random() * customGreetings.length)].message;
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
@@ -160,12 +129,12 @@ export default function Homepage({ theme }: any) {
|
|||||||
openWeatherModal={openWeatherModal}
|
openWeatherModal={openWeatherModal}
|
||||||
/>
|
/>
|
||||||
<Header
|
<Header
|
||||||
date={date()}
|
date={date(isMobile)}
|
||||||
greet={displayedGreeting}
|
greet={displayedGreeting}
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
current={current}
|
current={current}
|
||||||
outlook={outlook}
|
|
||||||
setCurrent={setCurrent}
|
setCurrent={setCurrent}
|
||||||
|
outlook={outlook}
|
||||||
weather={weather}
|
weather={weather}
|
||||||
basicWeather={basicWeather}
|
basicWeather={basicWeather}
|
||||||
forecast={forecast}
|
forecast={forecast}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import { Box, Stack, Text } from '@mantine/core';
|
import { Box, Stack, Text } from '@mantine/core';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import stacks from '../../../styles/Stack.module.css';
|
import { stackClasses, textClasses } from 'styles';
|
||||||
import texts from '../../../styles/Text.module.css';
|
|
||||||
|
|
||||||
function AppItem({ url, icon, name, isMobile }: any) {
|
function AppItem({ url, icon, name, isMobile }: any) {
|
||||||
const [textDecoration, setTextDecoration] = useState<string>('none');
|
const [textDecoration, setTextDecoration] = useState<string>('none');
|
||||||
@@ -13,7 +12,7 @@ function AppItem({ url, icon, name, isMobile }: any) {
|
|||||||
href={`https://${url}`}
|
href={`https://${url}`}
|
||||||
onMouseOver={() => setTextDecoration('underline')}
|
onMouseOver={() => setTextDecoration('underline')}
|
||||||
onMouseOut={() => setTextDecoration('none')}
|
onMouseOut={() => setTextDecoration('none')}
|
||||||
className={stacks.appItemBox}
|
className={stackClasses.appItemBox}
|
||||||
>
|
>
|
||||||
<Stack
|
<Stack
|
||||||
align={isMobile && 'center'}
|
align={isMobile && 'center'}
|
||||||
@@ -38,12 +37,12 @@ function AppItem({ url, icon, name, isMobile }: any) {
|
|||||||
gap: 0,
|
gap: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text className={texts.appName} classNames={texts}>
|
<Text className={textClasses.appName} classNames={textClasses}>
|
||||||
{name}
|
{name}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
className={texts.appUrl}
|
className={textClasses.appUrl}
|
||||||
classNames={texts}
|
classNames={textClasses}
|
||||||
style={{
|
style={{
|
||||||
textDecoration: textDecoration,
|
textDecoration: textDecoration,
|
||||||
}}
|
}}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Stack, Text } from '@mantine/core';
|
import { Stack, Text } from '@mantine/core';
|
||||||
|
import { useQueryAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useQueryAPI } from '../../../hooks/useAPI';
|
import { textClasses } from 'styles';
|
||||||
import texts from '../../../styles/Text.module.css';
|
|
||||||
import AppItem from './AppItem';
|
import AppItem from './AppItem';
|
||||||
|
|
||||||
function Applications({ contentType, isMobile }: any) {
|
function Applications({ contentType, isMobile }: any) {
|
||||||
@@ -16,7 +16,7 @@ function Applications({ contentType, isMobile }: any) {
|
|||||||
<>
|
<>
|
||||||
{applications.length > 0 && contentType.length > 0 && (
|
{applications.length > 0 && contentType.length > 0 && (
|
||||||
<Stack id='apps' style={{ gap: 0 }}>
|
<Stack id='apps' style={{ gap: 0 }}>
|
||||||
<Text className={texts.sectionTitle} classNames={texts}>
|
<Text className={textClasses.sectionTitle} classNames={textClasses}>
|
||||||
Applications
|
Applications
|
||||||
</Text>
|
</Text>
|
||||||
<Stack
|
<Stack
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Stack, Text } from '@mantine/core';
|
import { Stack, Text } from '@mantine/core';
|
||||||
|
import { useQueryAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useQueryAPI } from '../../../hooks/useAPI';
|
import { textClasses } from 'styles';
|
||||||
import texts from '../../../styles/Text.module.css';
|
|
||||||
import LinkGroups from './LinkGroups';
|
import LinkGroups from './LinkGroups';
|
||||||
|
|
||||||
function Links({ contentType, isMobile }: any) {
|
function Links({ contentType, isMobile }: any) {
|
||||||
@@ -27,7 +27,7 @@ function Links({ contentType, isMobile }: any) {
|
|||||||
categories?.length > 0 &&
|
categories?.length > 0 &&
|
||||||
contentType.length > 0 && (
|
contentType.length > 0 && (
|
||||||
<Stack id='links' style={{ gap: 0 }}>
|
<Stack id='links' style={{ gap: 0 }}>
|
||||||
<Text className={texts.sectionTitle} classNames={texts}>
|
<Text className={textClasses.sectionTitle} classNames={textClasses}>
|
||||||
Bookmarks
|
Bookmarks
|
||||||
</Text>
|
</Text>
|
||||||
<Stack
|
<Stack
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Stack, Text } from '@mantine/core';
|
import { Stack, Text } from '@mantine/core';
|
||||||
import texts from '../../../styles/Text.module.css';
|
import { textClasses } from 'styles';
|
||||||
import LinkItem from './LinkItem';
|
import LinkItem from './LinkItem';
|
||||||
|
|
||||||
function LinkGroups({ links, category, isMobile }: any) {
|
function LinkGroups({ links, category, isMobile }: any) {
|
||||||
@@ -12,7 +12,7 @@ function LinkGroups({ links, category, isMobile }: any) {
|
|||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text className={texts.linkCategory} classNames={texts}>
|
<Text className={textClasses.linkCategory} classNames={textClasses}>
|
||||||
{category}
|
{category}
|
||||||
</Text>
|
</Text>
|
||||||
{links?.map((link: any) => (
|
{links?.map((link: any) => (
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Text } from '@mantine/core';
|
import { Text } from '@mantine/core';
|
||||||
import texts from '../../../styles/Text.module.css';
|
import { textClasses } from 'styles';
|
||||||
|
|
||||||
function LinkItem({ link, isMobile }: any) {
|
function LinkItem({ link }: any) {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
className={texts.linkItem}
|
className={textClasses.linkItem}
|
||||||
classNames={texts}
|
classNames={textClasses}
|
||||||
component='a'
|
component='a'
|
||||||
href={link.url}
|
href={link.url}
|
||||||
style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}
|
style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Group, Stack, Text } from '@mantine/core';
|
import { Group, Stack, Text } from '@mantine/core';
|
||||||
|
import { WeatherModal } from 'components';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { textClasses } from '../../../styles';
|
import { textClasses } from 'styles';
|
||||||
import WeatherModal from './WeatherModal';
|
|
||||||
|
|
||||||
function Header({
|
function Header({
|
||||||
greet,
|
greet,
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import { useEffect, useState } from 'react';
|
|
||||||
import Messages from '../../../components/Messages';
|
|
||||||
import useQueryAPI from '../../../hooks/useAPI';
|
|
||||||
|
|
||||||
function MessageInfo() {
|
|
||||||
const messageData = useQueryAPI({ endpoint: 'api/messages' });
|
|
||||||
const [greetings, setGreetings] = useState([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!messageData.isFetching) {
|
|
||||||
setGreetings(messageData.data);
|
|
||||||
}
|
|
||||||
}, [messageData.isFetching]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{greetings && (
|
|
||||||
<div id='messageForm'>
|
|
||||||
{greetings.map((greeting, index) => (
|
|
||||||
<Messages
|
|
||||||
key={greeting.id}
|
|
||||||
group={index + 1}
|
|
||||||
index={greeting.index}
|
|
||||||
greeting={greeting.message}
|
|
||||||
easterEgg={greeting.customGreeting}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MessageInfo;
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
function Provider(props) {
|
|
||||||
return (
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<a href={props.provider.url}>{props.provider.name}</a>
|
|
||||||
</td>
|
|
||||||
<td>{props.provider.prefix}</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Provider;
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Stack, TextInput } from '@mantine/core';
|
import { Stack, TextInput } from '@mantine/core';
|
||||||
import { useDisclosure } from '@mantine/hooks';
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useQueryAPI } from '../../../hooks';
|
import { HelpModal } from '../../../../components/HelpModal/HelpModal';
|
||||||
import { textInputClasses } from '../../../styles';
|
import { WeatherModal } from '../../../../components/WeatherModal/WeatherModal';
|
||||||
import HelpModal from './HelpModal';
|
import { containsProtocol, useQueryAPI, validURL } from '../../../../hooks';
|
||||||
import WeatherModal from './WeatherModal';
|
import { textInputClasses } from '../../../../styles';
|
||||||
|
|
||||||
export default function Search({
|
export default function Search({
|
||||||
current,
|
current,
|
||||||
@@ -52,23 +52,6 @@ export default function Search({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function validURL(str: any) {
|
|
||||||
const pattern = 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
|
|
||||||
return !!pattern.test(str);
|
|
||||||
}
|
|
||||||
function containsProtocol(str: any) {
|
|
||||||
const pattern = /^(https?:\/\/).*/i;
|
|
||||||
return !!pattern.test(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
style={{
|
style={{
|
||||||
@@ -1,18 +1,14 @@
|
|||||||
import { Button, Menu, MultiSelect, NavLink } from '@mantine/core';
|
import { Button, Menu, MultiSelect, NavLink } from '@mantine/core';
|
||||||
|
import { useQueryAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { FiMenu, FiMonitor } from 'react-icons/fi';
|
import { FiMenu, FiMonitor } from 'react-icons/fi';
|
||||||
import { useQueryAPI } from '../../../hooks/useAPI';
|
import { buttonClasses, menuClasses, navLinkClasses, selectClasses } from 'styles';
|
||||||
import button from '../../../styles/Button.module.css';
|
|
||||||
import menu from '../../../styles/Menu.module.css';
|
|
||||||
import navLink from '../../../styles/NavLink.module.css';
|
|
||||||
import selectClasses from '../../../styles/Select.module.css';
|
|
||||||
|
|
||||||
function SettingsButton({
|
function SettingsButton({
|
||||||
appFilter,
|
appFilter,
|
||||||
setAppFilter,
|
setAppFilter,
|
||||||
bookmarkFilter,
|
bookmarkFilter,
|
||||||
setBookmarkFilter,
|
setBookmarkFilter,
|
||||||
theme,
|
|
||||||
}: any) {
|
}: any) {
|
||||||
const { data, isFetched } = useQueryAPI({ endpoint: 'api/appCategories' });
|
const { data, isFetched } = useQueryAPI({ endpoint: 'api/appCategories' });
|
||||||
const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]);
|
const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]);
|
||||||
@@ -38,29 +34,29 @@ function SettingsButton({
|
|||||||
return (
|
return (
|
||||||
<Menu withinPortal={false} withArrow shadow='md' position='top'>
|
<Menu withinPortal={false} withArrow shadow='md' position='top'>
|
||||||
<Menu.Target>
|
<Menu.Target>
|
||||||
<Button className={button.settingsButton} classNames={button}>
|
<Button className={buttonClasses.settingsButton} classNames={buttonClasses}>
|
||||||
<FiMenu />
|
<FiMenu />
|
||||||
</Button>
|
</Button>
|
||||||
</Menu.Target>
|
</Menu.Target>
|
||||||
<Menu.Dropdown className={menu.dropdown}>
|
<Menu.Dropdown className={menuClasses.dropdown}>
|
||||||
<NavLink
|
<NavLink
|
||||||
label='Settings'
|
label='Settings'
|
||||||
component='a'
|
component='a'
|
||||||
href={`/${import.meta.env.VITE_BASE_URL}/settings`}
|
href={`/${import.meta.env.VITE_BASE_URL}/settings`}
|
||||||
className={navLink.defaultNavLink}
|
className={navLinkClasses.defaultNavLink}
|
||||||
classNames={navLink}
|
classNames={navLinkClasses}
|
||||||
/>
|
/>
|
||||||
<NavLink
|
<NavLink
|
||||||
label='Quick Actions'
|
label='Quick Actions'
|
||||||
className={navLink.defaultNavLink}
|
className={navLinkClasses.defaultNavLink}
|
||||||
classNames={navLink}
|
classNames={navLinkClasses}
|
||||||
>
|
>
|
||||||
<NavLink
|
<NavLink
|
||||||
label='Wake Dakota'
|
label='Wake Dakota'
|
||||||
leftSection={<FiMonitor />}
|
leftSection={<FiMonitor />}
|
||||||
onClick={() => runWakeCommand()}
|
onClick={() => runWakeCommand()}
|
||||||
className={navLink.defaultNavLink}
|
className={navLinkClasses.defaultNavLink}
|
||||||
classNames={navLink}
|
classNames={navLinkClasses}
|
||||||
/>
|
/>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
|
|||||||
2
src/pages/index.ts
Normal file
2
src/pages/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export { Homepage } from './homepage/Homepage';
|
||||||
|
export { Settings } from './settings/Settings';
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import { ActionIcon, Group, Stack, Tabs, Text } from '@mantine/core';
|
import { ActionIcon, Group, Stack, Tabs, Text } from '@mantine/core';
|
||||||
import { FiArrowLeftCircle } from 'react-icons/fi';
|
import { FiArrowLeftCircle } from 'react-icons/fi';
|
||||||
import { actionIconClasses, textClasses } from '../../styles';
|
import { actionIconClasses, tabClasses, textClasses } from 'styles';
|
||||||
import tabClasses from '../../styles/Tabs.module.css';
|
|
||||||
import Applications from './components/Applications';
|
import Applications from './components/Applications';
|
||||||
import Bookmarks from './components/Bookmarks';
|
import Bookmarks from './components/Bookmarks';
|
||||||
import Categories from './components/Categories';
|
import Categories from './components/Categories';
|
||||||
@@ -10,7 +9,7 @@ import Personalization from './components/Personalization';
|
|||||||
import SearchProviders from './components/SearchProviders';
|
import SearchProviders from './components/SearchProviders';
|
||||||
import Themes from './components/Themes';
|
import Themes from './components/Themes';
|
||||||
|
|
||||||
function Settings({ theme }: any) {
|
export function Settings({ theme }: any) {
|
||||||
return (
|
return (
|
||||||
<Stack h={'100vh'} px={'2rem'}>
|
<Stack h={'100vh'} px={'2rem'}>
|
||||||
<Group gap={0}>
|
<Group gap={0}>
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { Stack, Text } from '@mantine/core';
|
import { Stack, Text } from '@mantine/core';
|
||||||
|
import { ApplicationColumns, DataTable } from 'components';
|
||||||
|
import { useQueryAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { DataTable } from '../../../DataTable/DataTable';
|
import { textClasses } from 'styles';
|
||||||
import ApplicationColumns from '../../../DataTable/columns/ApplicationColumns';
|
|
||||||
import { useQueryAPI } from '../../../hooks/useAPI';
|
|
||||||
import { textClasses } from '../../../styles';
|
|
||||||
|
|
||||||
const ApplicationSettings = () => {
|
const ApplicationSettings = () => {
|
||||||
const endpoint = 'api/apps';
|
const endpoint = 'api/apps';
|
||||||
|
|||||||
@@ -1,23 +1,16 @@
|
|||||||
import { Stack, Text } from '@mantine/core';
|
import { Stack, Text } from '@mantine/core';
|
||||||
|
import { BookmarkColumns, DataTable } from 'components';
|
||||||
|
import { useQueryAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { DataTable } from '../../../DataTable/DataTable';
|
import { textClasses } from 'styles';
|
||||||
import BookmarkColumns from '../../../DataTable/columns/BookmarkColumns';
|
|
||||||
import { useQueryAPI } from '../../../hooks/useAPI';
|
|
||||||
import { textClasses } from '../../../styles';
|
|
||||||
const BookmarkSettings = () => {
|
const BookmarkSettings = () => {
|
||||||
const endpoint = 'api/links';
|
const endpoint = 'api/links';
|
||||||
const { data, isFetching, isLoading, isFetched } = useQueryAPI({
|
const { data, isFetching, isLoading, isFetched } = useQueryAPI({
|
||||||
endpoint: endpoint,
|
endpoint: endpoint,
|
||||||
});
|
});
|
||||||
const {
|
const { data: groupData } = useQueryAPI({ endpoint: 'api/categories' });
|
||||||
data: groupData,
|
|
||||||
isFetching: groupDataIsFetching,
|
|
||||||
isLoading: groupDataIsLoading,
|
|
||||||
isFetched: groupDataIsFetched,
|
|
||||||
} = useQueryAPI({ endpoint: 'api/categories' });
|
|
||||||
const [bookmarkData, setBookmarkData] = useState<any>([]);
|
const [bookmarkData, setBookmarkData] = useState<any>([]);
|
||||||
const [groups, setGroups] = useState([]);
|
const [groups, setGroups] = useState([]);
|
||||||
const [fullyFetched, setFullyFetched] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isFetched) {
|
if (isFetched) {
|
||||||
@@ -31,7 +24,6 @@ const BookmarkSettings = () => {
|
|||||||
return category.categoryName;
|
return category.categoryName;
|
||||||
});
|
});
|
||||||
setGroups(groupList);
|
setGroups(groupList);
|
||||||
setFullyFetched(true);
|
|
||||||
}
|
}
|
||||||
}, [groupData]);
|
}, [groupData]);
|
||||||
return (
|
return (
|
||||||
@@ -46,7 +38,6 @@ const BookmarkSettings = () => {
|
|||||||
isFetching={isFetching}
|
isFetching={isFetching}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
endpoint={endpoint}
|
endpoint={endpoint}
|
||||||
grouping='category'
|
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Stack, Text } from '@mantine/core';
|
import { Stack, Text } from '@mantine/core';
|
||||||
|
import { CategoryColumns, DataTable } from 'components';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { DataTable } from '../../../DataTable/DataTable';
|
|
||||||
import CategoryColumns from '../../../DataTable/columns/CategoryColumns';
|
|
||||||
import { useQueryAPI } from '../../../hooks/useAPI';
|
import { useQueryAPI } from '../../../hooks/useAPI';
|
||||||
import { textClasses } from '../../../styles';
|
import { textClasses } from '../../../styles';
|
||||||
const CategorySettings = () => {
|
const CategorySettings = () => {
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { Stack, Text } from '@mantine/core';
|
import { Stack, Text } from '@mantine/core';
|
||||||
|
import { DataTable, MessagesColumns } from 'components';
|
||||||
|
import { useQueryAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { DataTable } from '../../../DataTable/DataTable';
|
import { textClasses } from 'styles';
|
||||||
import MessagesColumns from '../../../DataTable/columns/MessagesColumns';
|
|
||||||
import { useQueryAPI } from '../../../hooks/useAPI';
|
|
||||||
import { textClasses } from '../../../styles';
|
|
||||||
const MessageSettings = () => {
|
const MessageSettings = () => {
|
||||||
const endpoint = 'api/messages';
|
const endpoint = 'api/messages';
|
||||||
const { data, isFetching, isLoading, isFetched } = useQueryAPI({
|
const { data, isFetching, isLoading, isFetched } = useQueryAPI({
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { Text } from '@mantine/core';
|
import { Text } from '@mantine/core';
|
||||||
|
import { DataTable, PersonalizationColumns } from 'components';
|
||||||
|
import { useQueryAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { DataTable } from '../../../DataTable/DataTable';
|
import { textClasses } from 'styles';
|
||||||
import PersonalizationColumns from '../../../DataTable/columns/PersonalizationColumns';
|
|
||||||
import { useQueryAPI } from '../../../hooks/useAPI';
|
|
||||||
import { textClasses } from '../../../styles';
|
|
||||||
const PersonalizationSettings = () => {
|
const PersonalizationSettings = () => {
|
||||||
const endpoint = 'api/personalData';
|
const endpoint = 'api/personalData';
|
||||||
const { data, isFetching, isLoading, isFetched } = useQueryAPI({
|
const { data, isFetching, isLoading, isFetched } = useQueryAPI({
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Stack, Text } from '@mantine/core';
|
import { Stack, Text } from '@mantine/core';
|
||||||
|
import { DataTable, SearchProviderColumns } from 'components';
|
||||||
|
import { useQueryAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { DataTable } from '../../../DataTable/DataTable';
|
import { textClasses } from 'styles';
|
||||||
import SearchProviderColumns from '../../../DataTable/columns/SearchProviderColumns';
|
|
||||||
import { useQueryAPI } from '../../../hooks/useAPI';
|
|
||||||
import { textClasses } from '../../../styles';
|
|
||||||
const SearchProviderSettings = () => {
|
const SearchProviderSettings = () => {
|
||||||
const endpoint = 'api/providers';
|
const endpoint = 'api/providers';
|
||||||
const { data, isFetching, isLoading, isFetched } = useQueryAPI({
|
const { data, isFetching, isLoading, isFetched } = useQueryAPI({
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Icon } from '@iconify/react/dist/iconify.js';
|
import { Icon } from '@iconify/react/dist/iconify.js';
|
||||||
import { Box, Group, Stack, Text } from '@mantine/core';
|
import { Box, Group, Stack, Text } from '@mantine/core';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { stackClasses } from '../../../styles';
|
import { stackClasses } from 'styles';
|
||||||
|
|
||||||
export default function ThemeModalContent({ selectedTheme }: any) {
|
export default function ThemeModalContent({ selectedTheme }: any) {
|
||||||
const ExampleApp = (previewTheme: any) => {
|
const ExampleApp = (previewTheme: any) => {
|
||||||
|
|||||||
@@ -12,25 +12,20 @@ import {
|
|||||||
TextInput,
|
TextInput,
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useDisclosure, useLocalStorage } from '@mantine/hooks';
|
import { useDisclosure, useLocalStorage } from '@mantine/hooks';
|
||||||
|
import { useMutationAPI, useQueryAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { FiEdit, FiPlus, FiSave, FiTrash, FiX } from 'react-icons/fi';
|
import { FiEdit, FiPlus, FiSave, FiTrash, FiX } from 'react-icons/fi';
|
||||||
import { useMutationAPI, useQueryAPI } from '../../../hooks/useAPI';
|
|
||||||
import '@mantine/core/styles/ModalBase.css';
|
import '@mantine/core/styles/ModalBase.css';
|
||||||
import '@mantine/core/styles/Modal.css';
|
import '@mantine/core/styles/Modal.css';
|
||||||
import { modals } from '@mantine/modals';
|
import { modals } from '@mantine/modals';
|
||||||
import {
|
import { actionIconClasses, buttonClasses, modalClasses, textClasses } from 'styles';
|
||||||
actionIconClasses,
|
|
||||||
buttonClasses,
|
|
||||||
modalClasses,
|
|
||||||
textClasses,
|
|
||||||
} from '../../../styles';
|
|
||||||
import ThemeModalContent from './ThemeModalContent';
|
import ThemeModalContent from './ThemeModalContent';
|
||||||
function ThemesSettings({ theme }: any) {
|
function ThemesSettings({ theme }: any) {
|
||||||
const [opened, { open, close }] = useDisclosure(false);
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
const [pickerOpen, { open: openPicker, close: closePicker }] = useDisclosure(false);
|
const [pickerOpen, { open: openPicker, close: closePicker }] = useDisclosure(false);
|
||||||
const [colorId, setColorId] = useState<string>('');
|
const [colorId, setColorId] = useState<string>('');
|
||||||
const [colorValue, setColorValue] = useState('#000000');
|
const [colorValue, setColorValue] = useState('#000000');
|
||||||
const [value, setValue] = useLocalStorage<any>({
|
const [_, setValue] = useLocalStorage<any>({
|
||||||
key: 'theme',
|
key: 'theme',
|
||||||
defaultValue: 'blackboard',
|
defaultValue: 'blackboard',
|
||||||
});
|
});
|
||||||
@@ -39,8 +34,8 @@ function ThemesSettings({ theme }: any) {
|
|||||||
});
|
});
|
||||||
const [themesList, setThemesList] = useState([]);
|
const [themesList, setThemesList] = useState([]);
|
||||||
const [selectedTheme, setSelectedTheme] = useState<any>({});
|
const [selectedTheme, setSelectedTheme] = useState<any>({});
|
||||||
const { mutateAsync: createTheme, isPending: isCreatingTheme } = useMutationAPI();
|
const { mutateAsync: createTheme } = useMutationAPI();
|
||||||
const { mutateAsync: deleteTheme, isPending: isDeletingTheme } = useMutationAPI();
|
const { mutateAsync: deleteTheme } = useMutationAPI();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isFetched) {
|
if (isFetched) {
|
||||||
setThemesList(data);
|
setThemesList(data);
|
||||||
|
|||||||
1
src/types/index.ts
Normal file
1
src/types/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { type CurrentWeather, type OutlookWeather } from './weather';
|
||||||
@@ -2,12 +2,18 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
"baseUrl": "./src",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"allowJs": false,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"types": ["vite/client", "vitest"],
|
||||||
|
|
||||||
/* Bundler mode */
|
/* Bundler mode */
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "node",
|
||||||
"allowImportingTsExtensions": true,
|
"allowImportingTsExtensions": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
@@ -18,7 +24,15 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"paths": {
|
||||||
|
"components": ["./components/index.ts"],
|
||||||
|
"contexts": ["./contexts/index.ts"],
|
||||||
|
"hooks": ["./hooks/index.ts"],
|
||||||
|
"pages": ["./pages/index.ts"],
|
||||||
|
"styles": ["./styles/index.ts"],
|
||||||
|
"types": ["./types/index.ts"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import path from 'node:path';
|
||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
import { defineConfig, loadEnv } from 'vite';
|
import { defineConfig, loadEnv } from 'vite';
|
||||||
|
|
||||||
@@ -28,5 +29,15 @@ export default defineConfig(({ mode }) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
components: path.resolve(__dirname, './src/components'),
|
||||||
|
hooks: path.resolve(__dirname, './src/hooks'),
|
||||||
|
pages: path.resolve(__dirname, './src/pages'),
|
||||||
|
styles: path.resolve(__dirname, './src/styles'),
|
||||||
|
types: path.resolve(__dirname, './src/types'),
|
||||||
|
contexts: path.resolve(__dirname, './src/contexts'),
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user