MainLayout for theme persistence
This commit is contained in:
26
src/App.tsx
26
src/App.tsx
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
Box,
|
|
||||||
DEFAULT_THEME,
|
DEFAULT_THEME,
|
||||||
MantineProvider,
|
MantineProvider,
|
||||||
createTheme,
|
createTheme,
|
||||||
@@ -16,7 +15,7 @@ import {
|
|||||||
createBrowserRouter,
|
createBrowserRouter,
|
||||||
createRoutesFromElements,
|
createRoutesFromElements,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
import { ThemeProvider } from './components';
|
import { MainLayout, ThemeProvider } from './components';
|
||||||
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
|
||||||
@@ -57,15 +56,20 @@ function App() {
|
|||||||
const router = createBrowserRouter(
|
const router = createBrowserRouter(
|
||||||
createRoutesFromElements(
|
createRoutesFromElements(
|
||||||
<Route>
|
<Route>
|
||||||
<Route path='/' element={<Navigate to={`/${import.meta.env.VITE_BASE_URL}`} />} />
|
<Route path='' element={<MainLayout theme={theme} />}>
|
||||||
|
<Route
|
||||||
|
path='/'
|
||||||
|
element={<Navigate to={`/${import.meta.env.VITE_BASE_URL}`} />}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={`/${import.meta.env.VITE_BASE_URL}`}
|
path={`/${import.meta.env.VITE_BASE_URL}`}
|
||||||
element={<Homepage theme={theme} />}
|
element={<Homepage theme={theme} />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={`/${import.meta.env.VITE_BASE_URL}/settings`}
|
path={`/${import.meta.env.VITE_BASE_URL}/settings`}
|
||||||
element={<Settings theme={theme} />}
|
element={<Settings theme={theme} setTheme={setTheme} allThemes={data} />}
|
||||||
/>
|
/>
|
||||||
|
</Route>
|
||||||
</Route>,
|
</Route>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -82,22 +86,8 @@ function App() {
|
|||||||
<MantineProvider theme={mantineTheme}>
|
<MantineProvider theme={mantineTheme}>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<ModalsProvider>
|
<ModalsProvider>
|
||||||
<>
|
|
||||||
<Box
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
position: 'fixed',
|
|
||||||
backgroundImage: `linear-gradient(${theme.backgroundColor}33, ${theme.backgroundColor}33), url(/backgrounds/${theme.backgroundImage})`,
|
|
||||||
backgroundSize: 'cover',
|
|
||||||
backgroundRepeat: 'no-repeat',
|
|
||||||
backgroundPosition: 'center',
|
|
||||||
zIndex: -1,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
<ReactQueryDevtools initialIsOpen={false} />
|
<ReactQueryDevtools initialIsOpen={false} />
|
||||||
</>
|
|
||||||
</ModalsProvider>
|
</ModalsProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</MantineProvider>
|
</MantineProvider>
|
||||||
|
|||||||
50
src/Root.tsx
Normal file
50
src/Root.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { QueryClient } from '@tanstack/react-query';
|
||||||
|
import {
|
||||||
|
PersistQueryClientProvider,
|
||||||
|
type PersistedClient,
|
||||||
|
type Persister,
|
||||||
|
} from '@tanstack/react-query-persist-client';
|
||||||
|
import { del, get, set } from 'idb-keyval';
|
||||||
|
import React, { type ComponentType } from 'react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
|
const container = document.getElementById('root') as HTMLElement;
|
||||||
|
const root = createRoot(container);
|
||||||
|
|
||||||
|
const queryClient = new QueryClient({
|
||||||
|
defaultOptions: {
|
||||||
|
queries: {
|
||||||
|
gcTime: 1000 * 60 * 60 * 24, // 24 hours
|
||||||
|
staleTime: 1000 * 60 * 1, // 1 min
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export function createIDBPersister(idbValidKey: IDBValidKey = 'reactQuery') {
|
||||||
|
return {
|
||||||
|
persistClient: async (client: PersistedClient) => {
|
||||||
|
set(idbValidKey, client);
|
||||||
|
},
|
||||||
|
restoreClient: async () => {
|
||||||
|
return await get<PersistedClient>(idbValidKey);
|
||||||
|
},
|
||||||
|
removeClient: async () => {
|
||||||
|
await del(idbValidKey);
|
||||||
|
},
|
||||||
|
} as Persister;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render(App: ComponentType) {
|
||||||
|
root.render(
|
||||||
|
<PersistQueryClientProvider
|
||||||
|
client={queryClient}
|
||||||
|
persistOptions={{ persister: createIDBPersister() }}
|
||||||
|
>
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>
|
||||||
|
</PersistQueryClientProvider>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default render;
|
||||||
21
src/components/MainLayout.tsx
Normal file
21
src/components/MainLayout.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { Box } from '@mantine/core';
|
||||||
|
import { Outlet } from 'react-router-dom';
|
||||||
|
|
||||||
|
export function MainLayout({ theme }: any) {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
position: 'fixed',
|
||||||
|
backgroundImage: `linear-gradient(${theme.backgroundColor}33, ${theme.backgroundColor}33), url(/backgrounds/${theme.backgroundImage})`,
|
||||||
|
backgroundSize: 'cover',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'center',
|
||||||
|
zIndex: -1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Outlet />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -14,7 +14,6 @@ export function WeatherModal({
|
|||||||
hourly,
|
hourly,
|
||||||
closeWeatherModal,
|
closeWeatherModal,
|
||||||
weatherModalOpened,
|
weatherModalOpened,
|
||||||
setValue,
|
|
||||||
setProviderLabel,
|
setProviderLabel,
|
||||||
setProviderURL,
|
setProviderURL,
|
||||||
isMobile,
|
isMobile,
|
||||||
@@ -50,7 +49,6 @@ export function WeatherModal({
|
|||||||
opened={weatherModalOpened}
|
opened={weatherModalOpened}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
closeWeatherModal();
|
closeWeatherModal();
|
||||||
setValue('');
|
|
||||||
setProviderLabel('Google Search');
|
setProviderLabel('Google Search');
|
||||||
setProviderURL('https://www.google.com/search?q=');
|
setProviderURL('https://www.google.com/search?q=');
|
||||||
}}
|
}}
|
||||||
@@ -119,7 +117,9 @@ export function WeatherModal({
|
|||||||
>
|
>
|
||||||
{hourlyForecast.length > 0 &&
|
{hourlyForecast.length > 0 &&
|
||||||
hourlyForecast.map((h: any) => {
|
hourlyForecast.map((h: any) => {
|
||||||
return <HourlyCard key={h.time} weather={h} isMobile={isMobile} />;
|
return (
|
||||||
|
<HourlyCard key={h.number} weather={h} isMobile={isMobile} />
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</Box>
|
</Box>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export { HelpModal } from './HelpModal/HelpModal';
|
|||||||
export { WeatherModal } from './WeatherModal/WeatherModal';
|
export { WeatherModal } from './WeatherModal/WeatherModal';
|
||||||
export { DataTable } from './DataTable/DataTable';
|
export { DataTable } from './DataTable/DataTable';
|
||||||
export { ThemeProvider } from './ThemeProvider';
|
export { ThemeProvider } from './ThemeProvider';
|
||||||
|
export { MainLayout } from './MainLayout';
|
||||||
export { ApplicationColumns } from './DataTable/columns/ApplicationColumns';
|
export { ApplicationColumns } from './DataTable/columns/ApplicationColumns';
|
||||||
export { BookmarkColumns } from './DataTable/columns/BookmarkColumns';
|
export { BookmarkColumns } from './DataTable/columns/BookmarkColumns';
|
||||||
export { CategoryColumns } from './DataTable/columns/CategoryColumns';
|
export { CategoryColumns } from './DataTable/columns/CategoryColumns';
|
||||||
|
|||||||
27
src/main.tsx
27
src/main.tsx
@@ -1,21 +1,10 @@
|
|||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
import App from './App';
|
||||||
import React from 'react';
|
import render from './Root';
|
||||||
import ReactDOM from 'react-dom/client';
|
|
||||||
import App from './App.tsx';
|
|
||||||
|
|
||||||
const queryClient = new QueryClient({
|
Promise.all([render, App])
|
||||||
defaultOptions: {
|
.then(([render, App]) => {
|
||||||
queries: {
|
render(App);
|
||||||
gcTime: 1000 * 60 * 60 * 24, // 24 hours
|
})
|
||||||
staleTime: 1000 * 60 * 1, // 1 min
|
.catch((error) => {
|
||||||
},
|
console.error('Error loading the app:', error);
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
|
||||||
<React.StrictMode>
|
|
||||||
<QueryClientProvider client={queryClient}>
|
|
||||||
<App />
|
|
||||||
</QueryClientProvider>
|
|
||||||
</React.StrictMode>,
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export function Homepage({ theme }: any) {
|
|||||||
if (data) {
|
if (data) {
|
||||||
setDisplayedGreeting(greet(data));
|
setDisplayedGreeting(greet(data));
|
||||||
}
|
}
|
||||||
}, [isFetching]);
|
}, [data, isFetching]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (weather && basicWeather) {
|
if (weather && basicWeather) {
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ function Applications({ contentType, isMobile }: any) {
|
|||||||
const { data, isFetching } = useQueryAPI({ endpoint: 'api/apps' });
|
const { data, isFetching } = useQueryAPI({ endpoint: 'api/apps' });
|
||||||
const [applications, setApplications] = useState([]);
|
const [applications, setApplications] = useState([]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isFetching) {
|
if (data && !isFetching) {
|
||||||
setApplications(data);
|
setApplications(data);
|
||||||
}
|
}
|
||||||
}, [isFetching]);
|
}, [data, isFetching]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{applications.length > 0 && contentType.length > 0 && (
|
{applications.length > 0 && contentType.length > 0 && (
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ function Header({
|
|||||||
weatherModalOpened,
|
weatherModalOpened,
|
||||||
closeWeatherModal,
|
closeWeatherModal,
|
||||||
openWeatherModal,
|
openWeatherModal,
|
||||||
setValue,
|
|
||||||
setProviderLabel,
|
setProviderLabel,
|
||||||
setProviderURL,
|
setProviderURL,
|
||||||
}: any) {
|
}: any) {
|
||||||
@@ -155,7 +154,6 @@ function Header({
|
|||||||
hourly={hourly}
|
hourly={hourly}
|
||||||
closeWeatherModal={closeWeatherModal}
|
closeWeatherModal={closeWeatherModal}
|
||||||
weatherModalOpened={weatherModalOpened}
|
weatherModalOpened={weatherModalOpened}
|
||||||
setValue={setValue}
|
|
||||||
setProviderLabel={setProviderLabel}
|
setProviderLabel={setProviderLabel}
|
||||||
setProviderURL={setProviderURL}
|
setProviderURL={setProviderURL}
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Button, Menu, MultiSelect, NavLink } from '@mantine/core';
|
|||||||
import { useQueryAPI } from 'hooks';
|
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 { useNavigate } from 'react-router-dom';
|
||||||
import { buttonClasses, menuClasses, navLinkClasses, selectClasses } from 'styles';
|
import { buttonClasses, menuClasses, navLinkClasses, selectClasses } from 'styles';
|
||||||
|
|
||||||
function SettingsButton({
|
function SettingsButton({
|
||||||
@@ -12,7 +13,7 @@ function SettingsButton({
|
|||||||
}: 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' }]);
|
||||||
|
const navigate = useNavigate();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
const list: [any] =
|
const list: [any] =
|
||||||
@@ -42,9 +43,9 @@ function SettingsButton({
|
|||||||
<NavLink
|
<NavLink
|
||||||
label='Settings'
|
label='Settings'
|
||||||
component='a'
|
component='a'
|
||||||
href={`/${import.meta.env.VITE_BASE_URL}/settings`}
|
|
||||||
className={navLinkClasses.defaultNavLink}
|
className={navLinkClasses.defaultNavLink}
|
||||||
classNames={navLinkClasses}
|
classNames={navLinkClasses}
|
||||||
|
onClick={() => navigate(`/${import.meta.env.VITE_BASE_URL}/settings`)}
|
||||||
/>
|
/>
|
||||||
<NavLink
|
<NavLink
|
||||||
label='Quick Actions'
|
label='Quick Actions'
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
FiSearch,
|
FiSearch,
|
||||||
FiUser,
|
FiUser,
|
||||||
} from 'react-icons/fi';
|
} from 'react-icons/fi';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { actionIconClasses, tabClasses, textClasses } from 'styles';
|
import { actionIconClasses, tabClasses, textClasses } from 'styles';
|
||||||
import Applications from './components/Applications';
|
import Applications from './components/Applications';
|
||||||
import Bookmarks from './components/Bookmarks';
|
import Bookmarks from './components/Bookmarks';
|
||||||
@@ -18,8 +19,9 @@ 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';
|
||||||
|
|
||||||
export function Settings({ theme }: any) {
|
export function Settings({ theme, setTheme, allThemes }: any) {
|
||||||
const isMobile = window.matchMedia('(max-width: 600px)').matches;
|
const isMobile = window.matchMedia('(max-width: 600px)').matches;
|
||||||
|
const navigate = useNavigate();
|
||||||
return (
|
return (
|
||||||
<Stack px={'2rem'}>
|
<Stack px={'2rem'}>
|
||||||
<Group gap={0}>
|
<Group gap={0}>
|
||||||
@@ -27,7 +29,7 @@ export function Settings({ theme }: any) {
|
|||||||
className={actionIconClasses.backButton}
|
className={actionIconClasses.backButton}
|
||||||
classNames={actionIconClasses}
|
classNames={actionIconClasses}
|
||||||
component='a'
|
component='a'
|
||||||
href={`/${import.meta.env.VITE_BASE_URL}`}
|
onClick={() => navigate(`/${import.meta.env.VITE_BASE_URL}`)}
|
||||||
>
|
>
|
||||||
<FiArrowLeftCircle />
|
<FiArrowLeftCircle />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
@@ -74,7 +76,7 @@ export function Settings({ theme }: any) {
|
|||||||
<Categories />
|
<Categories />
|
||||||
</Tabs.Panel>
|
</Tabs.Panel>
|
||||||
<Tabs.Panel value='themes'>
|
<Tabs.Panel value='themes'>
|
||||||
<Themes theme={theme} />
|
<Themes theme={theme} setTheme={setTheme} allThemes={allThemes} />
|
||||||
</Tabs.Panel>
|
</Tabs.Panel>
|
||||||
<Tabs.Panel value='providers'>
|
<Tabs.Panel value='providers'>
|
||||||
<SearchProviders />
|
<SearchProviders />
|
||||||
|
|||||||
@@ -7,12 +7,15 @@ function ThemeCard({
|
|||||||
handleOpen,
|
handleOpen,
|
||||||
handleDeleteTheme,
|
handleDeleteTheme,
|
||||||
theme,
|
theme,
|
||||||
|
allThemes,
|
||||||
|
setTheme,
|
||||||
cardTheme,
|
cardTheme,
|
||||||
currentTheme,
|
currentTheme,
|
||||||
setValue,
|
setValue,
|
||||||
createTheme,
|
createTheme,
|
||||||
}: any) {
|
}: any) {
|
||||||
const [hover, setHover] = useState(false);
|
const [hover, setHover] = useState(false);
|
||||||
|
const [shift, setShift] = useState<number>(0);
|
||||||
return (
|
return (
|
||||||
<Group
|
<Group
|
||||||
gap={0}
|
gap={0}
|
||||||
@@ -51,7 +54,7 @@ function ThemeCard({
|
|||||||
backgroundColor: cardTheme.backgroundColor,
|
backgroundColor: cardTheme.backgroundColor,
|
||||||
border: `solid ${cardTheme.borderColor}`,
|
border: `solid ${cardTheme.borderColor}`,
|
||||||
}}
|
}}
|
||||||
data-cardTheme={cardTheme.name}
|
// data-cardTheme={cardTheme.name}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setValue(cardTheme.name);
|
setValue(cardTheme.name);
|
||||||
}}
|
}}
|
||||||
@@ -145,23 +148,46 @@ function ThemeCard({
|
|||||||
</Button>
|
</Button>
|
||||||
{currentTheme === 'random' && cardTheme.name === theme.name ? (
|
{currentTheme === 'random' && cardTheme.name === theme.name ? (
|
||||||
<Group
|
<Group
|
||||||
|
onMouseEnter={() => {
|
||||||
|
setShift(2);
|
||||||
|
}}
|
||||||
|
onMouseLeave={() => {
|
||||||
|
setShift(0);
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setShift(0);
|
||||||
|
}}
|
||||||
gap={0}
|
gap={0}
|
||||||
style={{
|
style={{
|
||||||
zIndex: 300,
|
zIndex: 300,
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
right: 0,
|
right: 0,
|
||||||
backgroundColor: 'white',
|
top: 27 - shift,
|
||||||
|
backgroundColor: shift === 0 ? 'white' : 'var(--color-background)',
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
padding: '8px',
|
padding: '8px',
|
||||||
margin: '4px',
|
margin: '4px',
|
||||||
border: 'solid 2px black',
|
border: 'solid 2px',
|
||||||
|
borderColor: shift === 0 ? 'black' : 'var(--color-text-pri)',
|
||||||
|
transition: 'all 0.2s',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FiShuffle
|
<FiShuffle
|
||||||
|
onClick={() => {
|
||||||
|
const enabled = allThemes
|
||||||
|
.filter((t: any) => t.randomEnabled)
|
||||||
|
.filter((t: any) => t.name !== theme.name);
|
||||||
|
if (enabled.length === 0) {
|
||||||
|
setTheme(allThemes[0]);
|
||||||
|
} else {
|
||||||
|
const index = Math.floor(Math.random() * enabled.length);
|
||||||
|
setTheme(enabled[index]);
|
||||||
|
}
|
||||||
|
}}
|
||||||
style={{
|
style={{
|
||||||
fontSize: '2em',
|
fontSize: '2em',
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
color: 'black',
|
color: shift === 0 ? 'black' : 'var(--color-text-pri)',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { modals } from '@mantine/modals';
|
|||||||
import { buttonClasses, textClasses } from 'styles';
|
import { buttonClasses, textClasses } from 'styles';
|
||||||
import ThemeCard from './ThemeCard';
|
import ThemeCard from './ThemeCard';
|
||||||
import ThemeModal from './ThemeModal';
|
import ThemeModal from './ThemeModal';
|
||||||
function ThemesSettings({ theme }: any) {
|
function ThemesSettings({ theme, setTheme, allThemes }: 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>('');
|
||||||
@@ -18,23 +18,14 @@ function ThemesSettings({ theme }: any) {
|
|||||||
key: 'theme',
|
key: 'theme',
|
||||||
defaultValue: 'blackboard',
|
defaultValue: 'blackboard',
|
||||||
});
|
});
|
||||||
const { data, isFetched } = useQueryAPI({
|
|
||||||
endpoint: 'api/themes',
|
|
||||||
});
|
|
||||||
const { data: backgrounds, isFetched: isBackgroundFetched } = useQueryAPI({
|
const { data: backgrounds, isFetched: isBackgroundFetched } = useQueryAPI({
|
||||||
endpoint: 'api/backgrounds',
|
endpoint: 'api/backgrounds',
|
||||||
});
|
});
|
||||||
const [themesList, setThemesList] = useState([]);
|
|
||||||
const [backgroundList, setBackgroundList] = useState<any>(['None']);
|
const [backgroundList, setBackgroundList] = useState<any>(['None']);
|
||||||
const [selectedTheme, setSelectedTheme] = useState<any>({});
|
const [selectedTheme, setSelectedTheme] = useState<any>({});
|
||||||
const { mutateAsync: createTheme } = useMutationAPI();
|
const { mutateAsync: createTheme } = useMutationAPI();
|
||||||
const { mutateAsync: deleteTheme } = useMutationAPI();
|
const { mutateAsync: deleteTheme } = useMutationAPI();
|
||||||
|
const isMobile = window.matchMedia('(max-width: 600px)').matches;
|
||||||
useEffect(() => {
|
|
||||||
if (isFetched) {
|
|
||||||
setThemesList(data);
|
|
||||||
}
|
|
||||||
}, [data, isFetched]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (backgrounds && isBackgroundFetched) {
|
if (backgrounds && isBackgroundFetched) {
|
||||||
@@ -128,7 +119,7 @@ function ThemesSettings({ theme }: any) {
|
|||||||
color={theme.primaryColor}
|
color={theme.primaryColor}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
<Group justify='center' pos={'relative'}>
|
<Group justify='center' align='center' pos={'relative'}>
|
||||||
<Overlay
|
<Overlay
|
||||||
display={currentTheme === 'random' ? 'flex' : 'none'}
|
display={currentTheme === 'random' ? 'flex' : 'none'}
|
||||||
blur={5}
|
blur={5}
|
||||||
@@ -136,10 +127,12 @@ function ThemesSettings({ theme }: any) {
|
|||||||
borderRadius: '10px',
|
borderRadius: '10px',
|
||||||
marginTop: '-15px',
|
marginTop: '-15px',
|
||||||
marginBottom: '-10px',
|
marginBottom: '-10px',
|
||||||
|
marginRight: isMobile ? '0' : '50px',
|
||||||
|
marginLeft: isMobile ? '0' : '50px',
|
||||||
}}
|
}}
|
||||||
pos={'absolute'}
|
pos={'absolute'}
|
||||||
/>
|
/>
|
||||||
{themesList.map((cardTheme: any) => (
|
{allThemes?.map((cardTheme: any) => (
|
||||||
<Group key={cardTheme.name} pos={'relative'}>
|
<Group key={cardTheme.name} pos={'relative'}>
|
||||||
{cardTheme.name === currentTheme && (
|
{cardTheme.name === currentTheme && (
|
||||||
<FiChevronRight
|
<FiChevronRight
|
||||||
@@ -166,6 +159,8 @@ function ThemesSettings({ theme }: any) {
|
|||||||
>
|
>
|
||||||
<ThemeCard
|
<ThemeCard
|
||||||
theme={theme}
|
theme={theme}
|
||||||
|
allThemes={allThemes}
|
||||||
|
setTheme={setTheme}
|
||||||
cardTheme={cardTheme}
|
cardTheme={cardTheme}
|
||||||
currentTheme={currentTheme}
|
currentTheme={currentTheme}
|
||||||
handleOpen={handleOpen}
|
handleOpen={handleOpen}
|
||||||
|
|||||||
Reference in New Issue
Block a user