diff --git a/src/App.tsx b/src/App.tsx index 853a732..5cd6b2a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,6 @@ import ScrollToTop from '@/components/default/scroll-to-top'; import '@/config/firebase'; import routes from '@/config/routes'; -import { FirebaseAuthProvider } from '@/libs/auth'; import LocalStorageDataSource from '@/libs/data-sources/data-sources/LocalStorageDataSource'; import theme from '@/theme/paperbase/theme'; @@ -9,6 +8,7 @@ import './App.css'; import config from './config'; import { getPath } from './config/paths'; import Dashboard from './Dashboard'; +import FirebaseAuthProvider from './libs/auth/auth-providers/FirebaseAuthProvider'; const firebaseProvider = new FirebaseAuthProvider({ login: getPath('login').to, diff --git a/src/Dashboard.tsx b/src/Dashboard.tsx index 6e0b892..8936c7d 100644 --- a/src/Dashboard.tsx +++ b/src/Dashboard.tsx @@ -2,7 +2,6 @@ import { Seo, setPageTitleSuffix } from '@/components/default/seo'; import { SplashScreen } from '@/components/default/splash-screen'; import config from '@/config'; import useHttpsRedirect from '@/hooks/use-https-redirect'; -import { AuthConsumer, AuthProvider } from '@/libs/auth'; import '@/libs/i18n'; import defaultRoutes from '@/routes/defaultRoutes'; import { Theme, ThemeProvider } from '@mui/material'; @@ -15,6 +14,7 @@ import { QueryParamProvider } from 'use-query-params'; import { ReactRouter6Adapter } from 'use-query-params/adapters/react-router-6'; import ErrorBoundary from './components/default/error-boundary'; import useRouter from './hooks/use-router'; +import { AuthConsumer, AuthProvider } from './libs/auth/context'; import { DataProvider, DataSourceObject } from './libs/data-sources'; interface DashboardProps { diff --git a/src/components/default/json-editor.tsx b/src/components/default/json-editor.tsx index bc5a8b3..a953a16 100644 --- a/src/components/default/json-editor.tsx +++ b/src/components/default/json-editor.tsx @@ -34,7 +34,7 @@ const JsonEditor = (props: { data: any; options?: Partial }) => const { validationSchema, ...jsonEditorOptions } = { ...defaultProps, ...options }; const handleAdd = (data: InteractionProps) => { - //validationSchema.validate(data) + validationSchema?.validate(data); console.log('handleAdd', data); }; diff --git a/src/components/default/layout/user-menu.tsx b/src/components/default/layout/user-menu.tsx index 9526ecb..1596abc 100644 --- a/src/components/default/layout/user-menu.tsx +++ b/src/components/default/layout/user-menu.tsx @@ -1,7 +1,7 @@ import { getPath } from '@/config/paths'; import { usePopover } from '@/hooks/use-popover'; import useRouter from '@/hooks/use-router'; -import { useAuth } from '@/libs/auth'; +import useAuth from '@/libs/auth/use-auth'; import AccountCircleIcon from '@mui/icons-material/AccountCircle'; import LogoutIcon from '@mui/icons-material/Logout'; import SettingsIcon from '@mui/icons-material/Settings'; diff --git a/src/config/routes.tsx b/src/config/routes.tsx index 76a0983..d06ff95 100644 --- a/src/config/routes.tsx +++ b/src/config/routes.tsx @@ -7,6 +7,7 @@ import SignIn from '@/pages/default/SignIn'; import TestAuthProviders from '@/pages/default/test/auth-providers'; import DataSources from '@/pages/default/test/data-sources/index'; import FileUploads from '@/pages/default/test/file-uploads'; +import FiltersPage from '@/pages/default/test/filters-page'; import Forms from '@/pages/default/test/forms'; import Translations from '@/pages/default/test/translations'; import { CustomRouteObject, routes as routesImport } from './routing'; @@ -20,33 +21,12 @@ const routeElements: { [key: string]: JSX.Element } = { ), homeIndex: <>Home, - // Recipe pages - // homeIndex: , - // recipesIndex: , - // myRecipes: , - // myRecipesIndex: , - // recipeDetails: , - // myRecipeDetails: , - // Satisfactory pages - // satisfactoryIndex: <>TEST, - // products: , - // recipes: , - // rawData: , - // generators: , - // buildables: , - // buildings: , - // schematics: , - // belts: , - // miners: , - // resources: , - // calculator: , - // games: , - // Test pages testDataSources: , testFileUploads: , testAuthProviders: , testForms: , testTranslations: , + testFilters: , // Default pages login: , signup: , diff --git a/src/config/routing.tsx b/src/config/routing.tsx index f66e9bc..a8a13b0 100644 --- a/src/config/routing.tsx +++ b/src/config/routing.tsx @@ -1,14 +1,6 @@ -// import { Outlet, RouteObject } from 'react-router-dom'; - -// import PaperbaseLayout from '@/layouts/paperbase/Layout'; -// import HomePage from '@/pages/home'; -// import MyRecipeOverviewPage from '@/pages/recipes/my-recipe-overview'; -// import RecipeDetailsPage from '@/pages/recipes/recipe-details'; -// import RecipeOverviewPage from '@/pages/recipes/recipe-overview'; import appRoutes from '@/routes/appRoutes'; import { Home as HomeIcon } from '@mui/icons-material'; import { RouteObject } from 'react-router-dom'; -//import { PathItem } from './paths'; export type CustomRouteObject = RouteObject & { id: string; @@ -30,173 +22,12 @@ export const routes: CustomRouteObject[] = [ id: 'homeIndex', index: true, }, - // { - // id: 'recipes', - // label: 'Recipes', - // translationKey: 'foodhub:menu.allrecipes', - // Icon: , - // category: 'recipes', - // path: 'recipes', - // element: , - // children: [ - // { - // id: 'recipesIndex', - // index: true, - // }, - // { - // id: 'myRecipes', - // label: 'My recipes', - // translationKey: 'foodhub:menu.myRecipes', - // Icon: , - // category: 'recipes', - // path: 'my', - // element: , - // children: [ - // { - // id: 'myRecipesIndex', - // index: true, - // }, - // { - // id: 'myRecipeDetails', - // label: 'Recipe details', - // Icon: , - // path: ':id', - // }, - // ], - // }, - // { - // id: 'recipeDetails', - // label: 'Recipe details', - // Icon: , - // path: ':id', - // }, - // ], - // }, - // { - // id: 'satisfactory', - // label: 'Satisfactory', - // Icon: , - // // category: 'satisfactory', - // path: 'satisfactory', - // element: , - // children: [ - // { - // id: 'satisfactoryIndex', - // index: true, - // }, - // { - // id: 'satisfactoryCodex', - // label: 'Codex', - // Icon: , - // // category: 'satisfactory', - // path: 'codex', - // element: , - // children: [ - // { - // id: 'codexIndex', - // index: true, - // }, - // { - // id: 'products', - // label: 'Products', - // Icon: , - // path: 'products', - // category: 'satisfactory', - // }, - // { - // id: 'recipes', - // label: 'Recipes', - // Icon: , - // path: 'recipes', - // category: 'satisfactory', - // }, - // { - // id: 'generators', - // label: 'Generators', - // Icon: , - // path: 'generators', - // category: 'satisfactory', - // }, - // { - // id: 'buildables', - // label: 'Buildables', - // Icon: , - // path: 'buildables', - // category: 'satisfactory', - // }, - // { - // id: 'buildings', - // label: 'Buildings', - // Icon: , - // path: 'buildings', - // category: 'satisfactory', - // }, - // { - // id: 'schematics', - // label: 'Schematics', - // Icon: , - // path: 'schematics', - // category: 'satisfactory', - // }, - // { - // id: 'belts', - // label: 'Belts', - // Icon: , - // path: 'belts', - // category: 'satisfactory', - // }, - // { - // id: 'miners', - // label: 'Miners', - // Icon: , - // path: 'miners', - // category: 'satisfactory', - // }, - // { - // id: 'resources', - // label: 'Resources', - // Icon: , - // path: 'resources', - // category: 'satisfactory', - // }, - // ], - // }, - // { - // id: 'calculator', - // label: 'Calculator', - // Icon: , - // path: 'calculator', - // category: 'satisfactory', - // }, - // { - // id: 'games', - // label: 'Games', - // Icon: , - // path: 'games', - // category: 'satisfactory', - // }, - // { - // id: 'rawData', - // label: 'Raw data', - // Icon: , - // path: 'raw-data', - // category: 'satisfactory', - // }, - // ], - // }, - // { - // path: 'recipes/:id', - // element: , - // }, ...appRoutes, ], }, // ...defaultRoutes, ]; -// const routes2 = generateRouteObjects(routes); -// console.log('ROUTES', routes2); - export const paths = getAllPaths(routes); // Function to create a flat list of all paths with custom properties diff --git a/src/guards/auth-guard.tsx b/src/guards/auth-guard.tsx index a756d9a..631c57d 100644 --- a/src/guards/auth-guard.tsx +++ b/src/guards/auth-guard.tsx @@ -2,7 +2,7 @@ import { useCallback, useEffect, useState } from 'react'; import config from '@/config'; import useRouter from '@/hooks/use-router'; -import { useAuth } from '@/libs/auth'; +import useAuth from '@/libs/auth/use-auth'; interface AuthGuardProps { children: React.ReactNode; diff --git a/src/hooks/use-deep-compare-memo.ts b/src/hooks/use-deep-compare-memo.ts new file mode 100644 index 0000000..6376f4c --- /dev/null +++ b/src/hooks/use-deep-compare-memo.ts @@ -0,0 +1,14 @@ +import { isEqual } from 'lodash'; +import { useRef } from 'react'; + +function useDeepCompareMemo(value: T | undefined) { + const ref = useRef(); + + if (!isEqual(ref.current, value)) { + ref.current = value; + } + + return ref.current; +} + +export default useDeepCompareMemo; diff --git a/src/hooks/use-dialog.ts b/src/hooks/use-dialog.ts index 9880a45..49e24a4 100644 --- a/src/hooks/use-dialog.ts +++ b/src/hooks/use-dialog.ts @@ -45,17 +45,20 @@ const useDialog = (options?: UseDialogOptionsProps): UseDialogReturn => { } }, [isOpen, dialogDataParam]); - const setData = useCallback((data: any | null) => { - if (queryKeyRef.current) { - if (data) { - setDialogDataParam(data); + const setData = useCallback( + (data: any | null) => { + if (queryKeyRef.current && setDialogDataParam) { + if (data) { + setDialogDataParam(data); + } else { + setDialogDataParam(undefined); + } } else { - setDialogDataParam(undefined); + setDialogData(data); } - } else { - setDialogData(data); - } - }, []); + }, + [setDialogDataParam] + ); // Respond to changes in the query value useEffect(() => { diff --git a/src/hooks/use-param-item.ts b/src/hooks/use-param-item.ts index 83fcf9c..f2bde0c 100644 --- a/src/hooks/use-param-item.ts +++ b/src/hooks/use-param-item.ts @@ -1,5 +1,6 @@ import { useMemo } from 'react'; import { useParams } from 'react-router-dom'; +import useDeepCompareMemo from './use-deep-compare-memo'; interface UseParamItemProps { id?: string; @@ -15,6 +16,7 @@ const useParamItem = >({ defaultValue, }: UseParamItemProps) => { const params = useParams(); + const stableDefaultValue = useDeepCompareMemo(defaultValue); const item = useMemo(() => { const idParam = params[id]; if (!idParam) { @@ -22,10 +24,10 @@ const useParamItem = >({ } const foundItem = items.find((item: T) => item[field] === idParam); if (!foundItem) { - return defaultValue; + return stableDefaultValue; } return foundItem; - }, [items, params]); + }, [items, params, id, field, stableDefaultValue]); return item; }; diff --git a/src/hooks/use-query-param-action.ts b/src/hooks/use-query-param-action.ts index 5f4518a..0bff94e 100644 --- a/src/hooks/use-query-param-action.ts +++ b/src/hooks/use-query-param-action.ts @@ -25,13 +25,13 @@ const useQueryParamAction = ( navigate(`${location.pathname}?${searchParams.toString()}`, { replace: true }); } } - }, [location.search, queryParamName, callback, navigate, options.removeAfterAction]); + }, [location, queryParamName, callback, navigate, options.removeAfterAction]); const clearQueryParam = useCallback(() => { const searchParams = new URLSearchParams(location.search); searchParams.delete(queryParamName); navigate(`${location.pathname}?${searchParams.toString()}`, { replace: true }); - }, [location.search, queryParamName, navigate]); + }, [location, queryParamName, navigate]); return { clearQueryParam, // Provide a function to manually clear the query parameter diff --git a/src/hooks/use-tabs.ts b/src/hooks/use-tabs.ts index fa733d8..1a44743 100644 --- a/src/hooks/use-tabs.ts +++ b/src/hooks/use-tabs.ts @@ -42,18 +42,24 @@ const useTabs = (tabsData: TabData[], options?: TabOptions) => { }, [queryParamName, searchParams, currentTab, tabsData]); // Update query param on tab change - const setTab = (newTab: string) => { - setCurrentTab(newTab); - if (queryParamName) { - const newSearchParams = new URLSearchParams(searchParams.toString()); - newSearchParams.set(queryParamName, newTab); - setSearchParams(newSearchParams); - } - }; + const setTab = useCallback( + (newTab: string) => { + setCurrentTab(newTab); + if (queryParamName && setSearchParams && searchParams) { + const newSearchParams = new URLSearchParams(searchParams.toString()); + newSearchParams.set(queryParamName, newTab); + setSearchParams(newSearchParams); + } + }, + [queryParamName, searchParams, setSearchParams] + ); - const handleTabChange = useCallback((_e: any, newValue: any) => { - setTab(newValue); - }, []); + const handleTabChange = useCallback( + (_e: any, newValue: any) => { + setTab?.(newValue); + }, + [setTab] + ); // const getValue = () => { // if (queryParamName) { diff --git a/src/layouts/paperbase/Header.jsx b/src/layouts/paperbase/Header.jsx index 4869b6a..70cdd0b 100644 --- a/src/layouts/paperbase/Header.jsx +++ b/src/layouts/paperbase/Header.jsx @@ -1,7 +1,7 @@ import LanguageSwitch from '@/components/default/layout/language-switch'; import UserMenu from '@/components/default/layout/user-menu'; import useRouter from '@/hooks/use-router'; -import { useAuth } from '@/libs/auth'; +import useAuth from '@/libs/auth/use-auth'; import IssueDialog from '@/sections/default/issue-dialog'; import MenuIcon from '@mui/icons-material/Menu'; import NotificationsIcon from '@mui/icons-material/Notifications'; diff --git a/src/layouts/paperbase/Navigator.jsx b/src/layouts/paperbase/Navigator.jsx index a4c756b..58a89bc 100644 --- a/src/layouts/paperbase/Navigator.jsx +++ b/src/layouts/paperbase/Navigator.jsx @@ -23,7 +23,7 @@ import ListItemText from '@mui/material/ListItemText'; import config from '@/config'; import { getPath, menu } from '@/config/paths'; import useRouter from '@/hooks/use-router'; -import { useAuth } from '@/libs/auth'; +import useAuth from '@/libs/auth/use-auth'; import { Collapse } from '@mui/material'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/src/layouts/simple/layout.tsx b/src/layouts/simple/layout.tsx index 7684619..2423fe3 100644 --- a/src/layouts/simple/layout.tsx +++ b/src/layouts/simple/layout.tsx @@ -1,5 +1,3 @@ -// @ts-nocheck - import { AccountCircle, RssFeed as BlogIcon, diff --git a/src/layouts/simple/theme.tsx b/src/layouts/simple/theme.tsx index 587f1b0..64b70d9 100644 --- a/src/layouts/simple/theme.tsx +++ b/src/layouts/simple/theme.tsx @@ -1,7 +1,17 @@ -// @ts-nocheck - import { createTheme } from '@mui/material'; +// Extend the BreakpointOverrides to include 'menu' +declare module '@mui/material/styles' { + interface BreakpointOverrides { + xs: true; + sm: true; + md: true; + lg: true; + xl: true; + menu: true; // add custom breakpoint + } +} + const theme = createTheme({ breakpoints: { values: { diff --git a/src/libs/auth/context.tsx b/src/libs/auth/context.tsx index 82114d0..bdb7246 100644 --- a/src/libs/auth/context.tsx +++ b/src/libs/auth/context.tsx @@ -1,35 +1,9 @@ import PropTypes from 'prop-types'; -import { createContext, useCallback, useEffect, useReducer } from 'react'; -import { AuthState, User } from '.'; +import { useCallback, useEffect, useReducer } from 'react'; +import { AuthContext, initialState } from './contextState'; //const TemplateProvider = new IAuthProvider({ login: '/login', logout: '/logout' }); -export const initialState: AuthState = { - isAuthenticated: false, - isInitialized: false, - user: null, - raw: null, - options: { login: null }, - provider: null, - signIn: async () => ({}) as User, - signUp: async () => ({}) as User, - signOut: async () => {}, - //...TemplateProvider - // signUp: (_email: string, _password: string) => Promise, - // signInWithEmailAndPassword: async () => Promise, - // signInWithGoogle: async () => Promise, - // signOut: async () => any, -}; - -export const AuthContext = createContext({ - ...initialState, - // provider: 'FIREBASE', - // createUserWithEmailAndPassword: () => Promise.resolve(), - // signInWithEmailAndPassword: () => Promise.resolve(), - // signInWithGoogle: () => Promise.resolve(), - // signOut: () => Promise.resolve(), -}); - export const AuthConsumer = AuthContext.Consumer; const reducer = (state: any, action: any) => { diff --git a/src/libs/auth/contextState.ts b/src/libs/auth/contextState.ts new file mode 100644 index 0000000..f5609fc --- /dev/null +++ b/src/libs/auth/contextState.ts @@ -0,0 +1,28 @@ +import { createContext } from 'react'; +import { AuthState, User } from '.'; + +export const initialState: AuthState = { + isAuthenticated: false, + isInitialized: false, + user: null, + raw: null, + options: { login: null }, + provider: null, + signIn: async () => ({}) as User, + signUp: async () => ({}) as User, + signOut: async () => {}, + //...TemplateProvider + // signUp: (_email: string, _password: string) => Promise, + // signInWithEmailAndPassword: async () => Promise, + // signInWithGoogle: async () => Promise, + // signOut: async () => any, +}; + +export const AuthContext = createContext({ + ...initialState, + // provider: 'FIREBASE', + // createUserWithEmailAndPassword: () => Promise.resolve(), + // signInWithEmailAndPassword: () => Promise.resolve(), + // signInWithGoogle: () => Promise.resolve(), + // signOut: () => Promise.resolve(), +}); diff --git a/src/libs/auth/index.tsx b/src/libs/auth/index.tsx index 93d8eb1..f8fcf96 100644 --- a/src/libs/auth/index.tsx +++ b/src/libs/auth/index.tsx @@ -1,18 +1,3 @@ -import CompositeAuthProvider from './auth-providers/CompositeAuthProvider'; -import FirebaseAuthProvider from './auth-providers/FirebaseAuthProvider'; -import { AuthConsumer, AuthProvider } from './context'; -import useAuth from './use-auth'; -import useLoginForm from './use-login-form'; - -export { - AuthConsumer, - AuthProvider, - CompositeAuthProvider, - FirebaseAuthProvider, - useAuth, - useLoginForm, -}; - export interface User { id: string; email?: string; diff --git a/src/libs/auth/use-auth.ts b/src/libs/auth/use-auth.ts index ce25a34..2652b9c 100644 --- a/src/libs/auth/use-auth.ts +++ b/src/libs/auth/use-auth.ts @@ -1,6 +1,7 @@ +import useDeepCompareMemo from '@/hooks/use-deep-compare-memo'; import { useContext, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; -import { AuthContext } from './context'; +import { AuthContext } from './contextState'; interface UseAuthOptions { redirectUnauthenticated?: boolean; @@ -8,13 +9,14 @@ interface UseAuthOptions { const useAuth = (options?: UseAuthOptions) => { const context = useContext(AuthContext); + const stableOptions = useDeepCompareMemo(options); const navigate = useNavigate(); useEffect(() => { - if (!context.isAuthenticated && options?.redirectUnauthenticated) { + if (!context.isAuthenticated && stableOptions?.redirectUnauthenticated) { navigate(context.options?.login); } - }, [context]); + }, [context, navigate, stableOptions]); return context; }; diff --git a/src/libs/data-sources/DataProvider.tsx b/src/libs/data-sources/DataProvider.tsx index a325425..6080420 100644 --- a/src/libs/data-sources/DataProvider.tsx +++ b/src/libs/data-sources/DataProvider.tsx @@ -18,6 +18,7 @@ import { DataSource, DataSourceObject } from '.'; // } // TODO: implement? // Create a context for the data +// eslint-disable-next-line react-refresh/only-export-components export const DataContext = createContext(undefined); interface DataProviderProps { @@ -154,6 +155,7 @@ const DataProvider: React.FC = ({ dataSources, children }) => return () => { Object.values(subscriptions).forEach((unsubscribe) => unsubscribe()); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { diff --git a/src/libs/data-sources/index.tsx b/src/libs/data-sources/index.tsx index 5792b47..9cdec78 100644 --- a/src/libs/data-sources/index.tsx +++ b/src/libs/data-sources/index.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-refresh/only-export-components */ import { useContext } from 'react'; import * as Yup from 'yup'; import DataProvider, { DataContext } from './DataProvider'; diff --git a/src/libs/filters/use-filter.ts b/src/libs/filters/use-filter.ts index cc88423..8f7441d 100644 --- a/src/libs/filters/use-filter.ts +++ b/src/libs/filters/use-filter.ts @@ -68,6 +68,7 @@ const useFilter = (initialData: T[] = [], options: Options = {}): UseFi }, [initialData, updateInitialData]); // Debounced search query handler + // eslint-disable-next-line react-hooks/exhaustive-deps const debouncedSetSearchQuery = useCallback( debounce((query: string) => { setSearchQuery(query); @@ -106,21 +107,24 @@ const useFilter = (initialData: T[] = [], options: Options = {}): UseFi }); }, []); - const applySort = (data: any[]): any[] => { - if (!sortField) return data; + const applySort = useCallback( + (data: any[]): any[] => { + if (!sortField) return data; - return _.orderBy( - data, - (item) => { - const value = item[sortField as string]; - if (typeof value === 'string') { - return value.toLowerCase(); - } - return value === undefined || value === null ? '' : value; - }, - [sortDirection] - ); - }; + return _.orderBy( + data, + (item) => { + const value = item[sortField as string]; + if (typeof value === 'string') { + return value.toLowerCase(); + } + return value === undefined || value === null ? '' : value; + }, + [sortDirection] + ); + }, + [sortDirection, sortField] + ); // const applyFilters = (data: T[]) => { // return data.filter((item: T) => { @@ -134,77 +138,86 @@ const useFilter = (initialData: T[] = [], options: Options = {}): UseFi // }); // }; //TODO: replace - const applyFilters = (data: T[]): T[] => { - return data.filter((item) => - filters.every((filter) => { - if ( - filter.value === null || - filter.value === undefined || - (Array.isArray(filter.value) && filter.value.length === 0) - ) { - return true; // Skip unset filters - } + const applyFilters = useCallback( + (data: T[]): T[] => { + return data.filter((item) => + filters.every((filter) => { + if ( + filter.value === null || + filter.value === undefined || + (Array.isArray(filter.value) && filter.value.length === 0) + ) { + return true; // Skip unset filters + } - switch (filter.type) { - case 'range': { - const rangeValue = filter.value; - return ( - (rangeValue[0] === undefined || - (item as Record)[filter.id] >= rangeValue[0]) && - (rangeValue[1] === undefined || - (item as Record)[filter.id] <= rangeValue[1]) - ); - // return ( - // (rangeValue.min === undefined || - // (item as Record)[filter.id] >= rangeValue.min) && - // (rangeValue.max === undefined || - // (item as Record)[filter.id] <= rangeValue.max) - // ); + switch (filter.type) { + case 'range': { + const rangeValue = filter.value; + return ( + (rangeValue[0] === undefined || + (item as Record)[filter.id] >= rangeValue[0]) && + (rangeValue[1] === undefined || + (item as Record)[filter.id] <= rangeValue[1]) + ); + // return ( + // (rangeValue.min === undefined || + // (item as Record)[filter.id] >= rangeValue.min) && + // (rangeValue.max === undefined || + // (item as Record)[filter.id] <= rangeValue.max) + // ); + } + case 'multi-select': + return filter.value.includes((item as Record)[filter.id]); + case 'boolean': + return ( + filter.value === null || (item as Record)[filter.id] === filter.value + ); + default: + return true; } - case 'multi-select': - return filter.value.includes((item as Record)[filter.id]); - case 'boolean': - return ( - filter.value === null || (item as Record)[filter.id] === filter.value - ); - default: - return true; - } - }) - ); - }; + }) + ); + }, + [filters] + ); - const applyTextSearch = (data: any[]) => { - if (!searchQuery) return data; // If no search query, return data unchanged + const applyTextSearch = useCallback( + (data: any[]) => { + if (!searchQuery) return data; // If no search query, return data unchanged - const lowerCaseQuery = searchQuery.toLowerCase(); + const lowerCaseQuery = searchQuery.toLowerCase(); - return data.filter((item) => { - // Use all fields if `searchableFields` is null - const fieldsToSearch = searchableFields || Object.keys(item); + return data.filter((item) => { + // Use all fields if `searchableFields` is null + const fieldsToSearch = searchableFields || Object.keys(item); - return fieldsToSearch.some((field) => { - const fieldValue = item[field]; - if (fieldValue) { - return fieldValue.toString().toLowerCase().includes(lowerCaseQuery); - } - return false; + return fieldsToSearch.some((field) => { + const fieldValue = item[field]; + if (fieldValue) { + return fieldValue.toString().toLowerCase().includes(lowerCaseQuery); + } + return false; + }); }); - }); - }; + }, + [searchQuery, searchableFields] + ); - const applyPagination = (data: any[]) => { - const startIndex = (page - 1) * rowsPerPage; // Start index for the current page (1-based) - const endIndex = Math.min(startIndex + rowsPerPage, limit); // Ensure no more than `limit` items are returned - return data.slice(startIndex, endIndex); - }; + const applyPagination = useCallback( + (data: any[]) => { + const startIndex = (page - 1) * rowsPerPage; // Start index for the current page (1-based) + const endIndex = Math.min(startIndex + rowsPerPage, limit); // Ensure no more than `limit` items are returned + return data.slice(startIndex, endIndex); + }, + [limit, page, rowsPerPage] + ); const totalFilteredItems = useMemo(() => { let processedData = applyFilters(data); processedData = applyTextSearch(processedData); processedData = applySort(processedData); return Math.min(processedData.length, limit); // Respect hard limit for total count - }, [data, filters, searchQuery, sortField, sortDirection, limit]); + }, [applyFilters, data, applyTextSearch, applySort, limit]); // Memoized computation of filtered, sorted, searched, and paginated data const filteredData = useMemo(() => { @@ -212,12 +225,13 @@ const useFilter = (initialData: T[] = [], options: Options = {}): UseFi processedData = applyTextSearch(processedData); processedData = applySort(processedData); return applyPagination(processedData); - }, [data, filters, searchQuery, sortField, sortDirection, page, rowsPerPage, limit]); + }, [applyFilters, data, applyTextSearch, applySort, applyPagination]); useEffect(() => { if (page !== 1) { setPage(1); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [filters, searchQuery, sortField, sortDirection]); const updateRowsPerPage = (newRowsPerPage: number) => { diff --git a/src/libs/forms/components/Image.tsx b/src/libs/forms/components/Image.tsx index d8a4901..9d61c47 100644 --- a/src/libs/forms/components/Image.tsx +++ b/src/libs/forms/components/Image.tsx @@ -28,21 +28,7 @@ interface ImageProps { cropImage?: (url: string) => Promise; } -const Image = ({ - name, - field: fieldConfig, - // favorite: { - // get: getFavorite, - // set: setFavorite - // }, - uploadImage, - deleteImage, - postProcess, - getFavorite, - setFavorite, - cropImage, - ...props -}: ImageProps) => { +const Image = ({ name, field: fieldConfig, deleteImage, cropImage, ...props }: ImageProps) => { if (!name && !fieldConfig) { throw new Error('Either name or field must be provided'); } diff --git a/src/libs/forms/components/Images.tsx b/src/libs/forms/components/Images.tsx index ca61bf1..bdce08d 100644 --- a/src/libs/forms/components/Images.tsx +++ b/src/libs/forms/components/Images.tsx @@ -33,13 +33,7 @@ interface ImagesProps { const Images = ({ name, field: fieldConfig, - // favorite: { - // get: getFavorite, - // set: setFavorite - // }, - uploadImage, deleteImage, - postProcess, getFavorite, setFavorite, cropImage, diff --git a/src/libs/forms/custom-form.tsx b/src/libs/forms/custom-form.tsx index 7e5003c..1ef202a 100644 --- a/src/libs/forms/custom-form.tsx +++ b/src/libs/forms/custom-form.tsx @@ -8,6 +8,7 @@ import { FieldOptions } from '.'; // Create a context for global options const FormOptionsContext = createContext({}); +// eslint-disable-next-line react-refresh/only-export-components export const useFormOptions = (): FieldOptions => useContext(FormOptionsContext); interface CustomFormProps { diff --git a/src/libs/forms/index.tsx b/src/libs/forms/index.tsx index 960e773..ea0baad 100644 --- a/src/libs/forms/index.tsx +++ b/src/libs/forms/index.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-refresh/only-export-components */ import { AutocompleteProps, TextFieldProps } from '@mui/material'; export interface FieldConfig { @@ -20,28 +21,6 @@ type MuiProps = { }; interface TableProps { - // columns?: { - // config: FieldConfig; - // label: string; - // key: string; - // render?: (value: any) => any; - // defaultValue?: any; - // type?: - // | 'text' - // | 'number' - // | 'date' - // | 'datetime' - // | 'time' - // | 'currency' - // | 'select' - // | 'boolean' - // | 'autocomplete'; - // options?: { - // key: string; - // value: any; - // }[]; - // fieldDefinition?: FieldConfig; - // }[]; columns: { [key: string]: FieldConfig; }; diff --git a/src/libs/forms/use-custom-formik.tsx b/src/libs/forms/use-custom-formik.tsx index e9f3fa0..618f0e0 100644 --- a/src/libs/forms/use-custom-formik.tsx +++ b/src/libs/forms/use-custom-formik.tsx @@ -46,6 +46,7 @@ const useCustomFormik = (props: UseCustomFormikProps) => { }; return values; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [fields, formikProps.initialValues, validationSchema]); const formik = useFormik({ diff --git a/src/libs/forms/use-form-field.tsx b/src/libs/forms/use-form-field.tsx index 5ecaa6e..b3c3e99 100644 --- a/src/libs/forms/use-form-field.tsx +++ b/src/libs/forms/use-form-field.tsx @@ -37,6 +37,7 @@ const useFormField = (name: string, fieldConfig?: FieldConfig): UseFormFieldsRet if (field.value && field.value !== inputValue) { setInputValue(field.value); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [field?.value]); // Check for debounce setting. If set, debounce the change handler @@ -46,6 +47,7 @@ const useFormField = (name: string, fieldConfig?: FieldConfig): UseFormFieldsRet debounce((value) => { helpers.setValue(value); }, debounceValue), // Adjust delay as needed + // eslint-disable-next-line react-hooks/exhaustive-deps [field.name, helpers] ); diff --git a/src/libs/tabs/context.ts b/src/libs/tabs/context.ts new file mode 100644 index 0000000..1e772d2 --- /dev/null +++ b/src/libs/tabs/context.ts @@ -0,0 +1,11 @@ +import { createContext } from 'react'; +import { TabData } from '.'; + +// Context to share current tab information +interface CurrentTabContextProps { + tabs: TabData[]; + currentTab: string; + handleTabChange: (event: React.ChangeEvent, newValue: string) => void; + setTab: (tab: string) => void; +} +export const CurrentTabContext = createContext(undefined); diff --git a/src/libs/tabs/index.tsx b/src/libs/tabs/index.tsx index 112c7aa..2a32cf8 100644 --- a/src/libs/tabs/index.tsx +++ b/src/libs/tabs/index.tsx @@ -1,23 +1,15 @@ -import { createContext } from 'react'; import Tabs from './tabs'; // Tabs data export interface TabData { label: string; value: string; - component?: JSX.Element; + component: JSX.Element; } -// Context to share current tab information -interface CurrentTabContextProps { - tabs: TabData[]; - currentTab: string; - handleTabChange: (event: React.ChangeEvent, newValue: string) => void; - setTab: (tab: string) => void; -} -export const CurrentTabContext = createContext(undefined); - +// eslint-disable-next-line react-refresh/only-export-components export { default as useCurrentTab } from './use-current-tab'; +// eslint-disable-next-line react-refresh/only-export-components export { default as useTabs } from './use-tabs'; export default Tabs; diff --git a/src/libs/tabs/tabs.tsx b/src/libs/tabs/tabs.tsx index 1639ebe..a660207 100644 --- a/src/libs/tabs/tabs.tsx +++ b/src/libs/tabs/tabs.tsx @@ -1,6 +1,7 @@ import useTabs, { TabOptions } from '@/hooks/use-tabs'; import { Box, BoxProps, TabsProps as DTabsProps, TabProps, useTheme } from '@mui/material'; -import { CurrentTabContext, TabData } from '.'; +import { TabData } from '.'; +import { CurrentTabContext } from './context'; import TabPanel from './tab-panel'; import TabsHeader from './tabs-header'; diff --git a/src/libs/tabs/use-tabs.tsx b/src/libs/tabs/use-tabs.tsx index 04eeb63..841ee7e 100644 --- a/src/libs/tabs/use-tabs.tsx +++ b/src/libs/tabs/use-tabs.tsx @@ -38,18 +38,24 @@ const useTabs = (tabsData: TabData[], options?: TabOptions) => { }, [queryParamName, searchParams, currentTab, tabsData]); // Update query param on tab change - const setTab = (newTab: string) => { - setCurrentTab(newTab); - if (queryParamName) { - const newSearchParams = new URLSearchParams(searchParams.toString()); - newSearchParams.set(queryParamName, newTab); - setSearchParams(newSearchParams); - } - }; + const setTab = useCallback( + (newTab: string) => { + setCurrentTab(newTab); + if (queryParamName) { + const newSearchParams = new URLSearchParams(searchParams.toString()); + newSearchParams.set(queryParamName, newTab); + setSearchParams(newSearchParams); + } + }, + [queryParamName, searchParams, setSearchParams] + ); - const handleTabChange = useCallback((_e: any, newValue: any) => { - setTab(newValue); - }, []); + const handleTabChange = useCallback( + (_e: any, newValue: any) => { + setTab?.(newValue); + }, + [setTab] + ); // const newTabsData = useMemo(() => { // return tabsData.map((tab, index) => ({ diff --git a/src/pages/default/AccountOld.jsx b/src/pages/default/AccountOld.jsx index 62489fd..ea0c8ee 100644 --- a/src/pages/default/AccountOld.jsx +++ b/src/pages/default/AccountOld.jsx @@ -1,6 +1,5 @@ +import useAuth from '@/libs/auth/use-auth'; import { Box, Button, Paper } from '@mui/material'; -// import { useState } from 'react'; -import { useAuth } from '@/libs/auth'; import DefaultPaperbasePage from './DefaultPaperbasePage'; const Account = () => { diff --git a/src/pages/default/SignIn.jsx b/src/pages/default/SignIn.jsx index 755bd87..f9c39ca 100644 --- a/src/pages/default/SignIn.jsx +++ b/src/pages/default/SignIn.jsx @@ -20,7 +20,8 @@ import config from '@/config'; import useMounted from '@/hooks/use-mounted'; import useRouter from '@/hooks/use-router'; import useSearchParams from '@/hooks/use-search-params'; -import { useAuth, useLoginForm } from '@/libs/auth'; +import useAuth from '@/libs/auth/use-auth'; +import useLoginForm from '@/libs/auth/use-login-form'; const Card = styled(MuiCard)(({ theme }) => ({ display: 'flex', diff --git a/src/pages/default/account/components/debug-card.tsx b/src/pages/default/account/components/debug-card.tsx index 04fc7a4..1e122a2 100644 --- a/src/pages/default/account/components/debug-card.tsx +++ b/src/pages/default/account/components/debug-card.tsx @@ -12,8 +12,8 @@ const DebugCard = ({ ); useEffect(() => { - setDebug(logLevel); - }, [logLevel]); + setDebug?.(logLevel); + }, [logLevel, setDebug]); return ( diff --git a/src/pages/default/account/index.tsx b/src/pages/default/account/index.tsx index f9034a9..67f3938 100644 --- a/src/pages/default/account/index.tsx +++ b/src/pages/default/account/index.tsx @@ -1,7 +1,5 @@ -// @ts-nocheck - import { AppConfig, setLogLevel } from '@/config'; -import { useAuth } from '@/libs/auth'; +import useAuth from '@/libs/auth/use-auth'; import useCustomFormik from '@/libs/forms/use-custom-formik'; import { Button, Card, CardContent, CardHeader, Grid } from '@mui/material'; import DefaultPage from '../DefaultPage'; diff --git a/src/pages/default/test/auth-providers/index.tsx b/src/pages/default/test/auth-providers/index.tsx index e258396..3c52370 100644 --- a/src/pages/default/test/auth-providers/index.tsx +++ b/src/pages/default/test/auth-providers/index.tsx @@ -1,5 +1,6 @@ import config from '@/config'; -import { FirebaseAuthProvider, useLoginForm } from '@/libs/auth'; +import FirebaseAuthProvider from '@/libs/auth/auth-providers/FirebaseAuthProvider'; +import useLoginForm from '@/libs/auth/use-login-form'; import { Button, Card, CardActions, CardContent, CardHeader, Grid, TextField } from '@mui/material'; import DefaultPage from '../../DefaultPage'; diff --git a/src/pages/default/test/data-sources/index.tsx b/src/pages/default/test/data-sources/index.tsx index a693293..260ef91 100644 --- a/src/pages/default/test/data-sources/index.tsx +++ b/src/pages/default/test/data-sources/index.tsx @@ -5,7 +5,7 @@ import LocalStorageDataSource from '@/libs/data-sources/data-sources/LocalStorag import MockDataSource from '@/libs/data-sources/data-sources/MockDataSource'; import useData from '@/libs/data-sources/useData'; import Tabs, { useCurrentTab } from '@/libs/tabs'; -import { Dummy, dummyConverter, dummyMockSchema, dummyYupSchema } from '@/schemas/dummy'; +import { Dummy, dummyMockSchema, dummyYupSchema } from '@/schemas/dummy'; import { Button, Card, CardActions, CardContent, CardHeader, Grid } from '@mui/material'; import DefaultPage from '../../DefaultPage'; @@ -60,24 +60,24 @@ const datasources = { }, { db } ), - 'Collection - With Converter': new FirestoreDataSource( - { - target: 'dummy', - targetMode: 'collection', - subscribe: true, - YupValidationSchema: dummyYupSchema, - }, - { db, converter: dummyConverter } - ), - 'Document - With Converter': new FirestoreDataSource( - { - target: 'dummy/01iQznR3TyhzhI5ct5cQ', - targetMode: 'document', - subscribe: true, - YupValidationSchema: dummyYupSchema, - }, - { db, converter: dummyConverter } - ), + // 'Collection - With Converter': new FirestoreDataSource( + // { + // target: 'dummy', + // targetMode: 'collection', + // subscribe: true, + // YupValidationSchema: dummyYupSchema, + // }, + // { db, converter: dummyConverter } + // ), + // 'Document - With Converter': new FirestoreDataSource( + // { + // target: 'dummy/01iQznR3TyhzhI5ct5cQ', + // targetMode: 'document', + // subscribe: true, + // YupValidationSchema: dummyYupSchema, + // }, + // { db, converter: dummyConverter } + // ), }, LocalStorage: { Realtime: new LocalStorageDataSource({ diff --git a/src/pages/default/test/file-uploads/_components/simple-cropper.tsx b/src/pages/default/test/file-uploads/_components/simple-cropper.tsx index 31956f6..7674e5a 100644 --- a/src/pages/default/test/file-uploads/_components/simple-cropper.tsx +++ b/src/pages/default/test/file-uploads/_components/simple-cropper.tsx @@ -1,6 +1,6 @@ import ImageCropper from '@/components/default/images/image-cropper'; import useDialog from '@/hooks/use-dialog'; -import { useAuth } from '@/libs/auth'; +import useAuth from '@/libs/auth/use-auth'; import FirebaseStorageProvider from '@/libs/storage-providers/providers/FirebaseStorageProvider'; import { Box, Button, TextField, Typography } from '@mui/material'; import { useState } from 'react'; diff --git a/src/pages/default/test/file-uploads/index.tsx b/src/pages/default/test/file-uploads/index.tsx index 3a5ee65..6cd7feb 100644 --- a/src/pages/default/test/file-uploads/index.tsx +++ b/src/pages/default/test/file-uploads/index.tsx @@ -1,13 +1,16 @@ -// @ts-nocheck - -import { useAuth } from '@/libs/auth'; +import useAuth from '@/libs/auth/use-auth'; import FirebaseStorageProvider from '@/libs/storage-providers/providers/FirebaseStorageProvider'; import DefaultPage from '@/pages/default/DefaultPage'; import ImageUploaderCard from '@/pages/default/test/file-uploads/_components/image-uploader-card'; import SimpleCropper from '@/pages/default/test/file-uploads/_components/simple-cropper'; import { Card, CardContent, CardHeader, Grid } from '@mui/material'; -const CardLayout = ({ title, children }) => { +interface CardLayoutProps { + title: string; + children: React.ReactNode; +} + +const CardLayout = ({ title, children }: CardLayoutProps) => { return ( diff --git a/src/pages/default/test/filters-page.tsx b/src/pages/default/test/filters-page.tsx new file mode 100644 index 0000000..5159a72 --- /dev/null +++ b/src/pages/default/test/filters-page.tsx @@ -0,0 +1,49 @@ +import { createDummySchema, Dummy } from '@/schemas/dummy'; +import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from '@mui/material'; +import { useMemo } from 'react'; +import DefaultPage from '../DefaultPage'; + +const columns = [ + { + id: 'name', + accessor: 'name', + label: 'Name', + }, + { + id: 'string', + accessor: 'string', + label: 'String', + }, +]; + +const FiltersPage = () => { + const data = useMemo(() => createDummySchema().getTestData(20), []) as Dummy[]; + + return ( + +
{JSON.stringify(data, null, 2)}
+ + + + + {columns.map((column) => ( + {column.label} + ))} + + + + {data.map((row: Dummy) => ( + + {columns.map((column) => ( + {row[column.accessor]} + ))} + + ))} + +
+
+
+ ); +}; + +export default FiltersPage; diff --git a/src/routes/appRoutes.tsx b/src/routes/appRoutes.tsx index 7d2d47b..72f8828 100644 --- a/src/routes/appRoutes.tsx +++ b/src/routes/appRoutes.tsx @@ -77,6 +77,14 @@ const appRoutes: CustomRouteObject[] = [ path: 'translations', // element: , }, + + { + id: 'testFilters', + label: 'Filters', + Icon: , + category: 'test', + path: 'filters', + }, ], }, { diff --git a/src/schemas/dummy.ts b/src/schemas/dummy.ts index 3299b74..87c2816 100644 --- a/src/schemas/dummy.ts +++ b/src/schemas/dummy.ts @@ -1,14 +1,7 @@ import generateTestData from '@/utils/generate-test-data'; import { faker } from '@faker-js/faker'; import * as Yup from 'yup'; -// import { Schema } from '.'; -// export const dummySchema: Schema = { -// name: { -// type: 'string', -// required: true, -// minLength: 3, -// }, -// }; +import { createDefaultSchema } from '.'; export const dummyYupSchema = Yup.object().shape({ name: Yup.string().required('Name is required').min(3, 'Minimum 3 characters'), @@ -31,99 +24,118 @@ export const dummyYupSchema = Yup.object().shape({ export type Dummy = Yup.InferType; -export interface DummyWithId extends Dummy { - id: string; -} - -export default interface DummyBackup { - name: string; - number?: number; - date?: Date; - boolean?: boolean; - array?: string[]; - object?: { - stringKey: string; - numberKey: number; - booleanKey: boolean; +export const createDummySchema = () => { + const defaultSchema = createDefaultSchema(dummyYupSchema); + return { + ...defaultSchema, + getTemplate: () => { + return { + ...defaultSchema.getTemplate(), + name: faker.word.verb() + ' ' + faker.word.noun(), + }; + }, + generateTestData: () => { + return { + ...generateTestData(dummyYupSchema), + name: faker.word.verb() + ' ' + faker.word.noun(), + }; + }, }; -} +}; + +// export interface DummyWithId extends Dummy { +// id: string; +// } + +// export default interface DummyBackup { +// name: string; +// number?: number; +// date?: Date; +// boolean?: boolean; +// array?: string[]; +// object?: { +// stringKey: string; +// numberKey: number; +// booleanKey: boolean; +// }; +// } export const dummyMockSchema = { name: () => faker.word.verb() + ' ' + faker.word.noun(), }; -export const getDummyTestData = (count: number): Dummy | Dummy[] => { - // If number is 1, return a single object - if (count === 1) { - return { - ...generateTestData(dummyYupSchema), - name: faker.word.verb() + ' ' + faker.word.noun(), - }; - } else if (count > 1) { - return Array.from({ length: count }, () => { - return { - ...generateTestData(dummyYupSchema), - name: faker.word.verb() + ' ' + faker.word.noun(), - }; - }); - } else { - throw new Error('Count must be greater than 0'); - } -}; +// export const getDummyTestData = (count: number): Dummy | Dummy[] => { +// // If number is 1, return a single object +// if (count === 1) { +// return { +// ...generateTestData(dummyYupSchema), +// name: faker.word.verb() + ' ' + faker.word.noun(), +// }; +// } else if (count > 1) { +// return Array.from({ length: count }, () => { +// return { +// ...generateTestData(dummyYupSchema), +// name: faker.word.verb() + ' ' + faker.word.noun(), +// }; +// }); +// } else { +// throw new Error('Count must be greater than 0'); +// } +// }; -// Or the other way around: -// let schema: Yup.ObjectSchema = dummyYupSchema; +// // Or the other way around: +// // let schema: Yup.ObjectSchema = dummyYupSchema; -export const DummyClass = class DummyClass implements Dummy { - id: string; - name: string; - string?: string; - number?: number; - date?: Date; - boolean?: boolean; - array?: string[]; - object?: { - stringKey: string; - numberKey: number; - booleanKey: boolean; - }; +// export const DummyClass = class DummyClass implements Dummy { +// id: string; +// name: string; +// string?: string; +// number?: number; +// date?: Date; +// boolean?: boolean; +// array?: string[]; +// object?: { +// stringKey: string; +// numberKey: number; +// booleanKey: boolean; +// }; - constructor(dummy: DummyWithId) { - this.id = dummy.id; - this.name = dummy.name; - this.string = dummy.string; - this.number = dummy.number; - this.date = dummy.date; - this.boolean = dummy.boolean; - this.array = dummy.array; - this.object = dummy.object; - } +// constructor(dummy: DummyWithId) { +// this.id = dummy.id; +// this.name = dummy.name; +// this.string = dummy.string; +// this.number = dummy.number; +// this.date = dummy.date; +// this.boolean = dummy.boolean; +// this.array = dummy.array; +// this.object = dummy.object; +// } - toString = () => { - return this.name; - }; +// toString = () => { +// return this.name; +// }; - toObject = () => { - return { - id: this.id, - name: this.name, - string: this.string, - number: this.number, - date: this.date, - boolean: this.boolean, - array: this.array, - object: this.object, - }; - }; -}; +// toObject = () => { +// return { +// id: this.id, +// name: this.name, +// string: this.string, +// number: this.number, +// date: this.date, +// boolean: this.boolean, +// array: this.array, +// object: this.object, +// }; +// }; +// }; -export const dummyConverter = { - fromFirestore: (snapshot: any) => { - const data = snapshot.data(); - return new DummyClass({ ...data, id: snapshot.id }); - }, - toFirestore: (dummy: Dummy) => { - const { name, string, number, date, boolean, array, object } = dummy; - return { name, string, number, date, boolean, array, object }; - }, -}; +// export const dummyConverter = { +// fromFirestore: (snapshot: any) => { +// const data = snapshot.data(); +// return new DummyClass({ ...data, id: snapshot.id }); +// }, +// toFirestore: (dummy: Dummy) => { +// const { name, string, number, date, boolean, array, object } = dummy; +// return { name, string, number, date, boolean, array, object }; +// }, +// }; diff --git a/src/schemas/index.ts b/src/schemas/index.ts index 81e6274..21ebe12 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -105,7 +105,7 @@ export const createDefaultSchema = ( getCustomFieldDefinitions: () => { return {}; }, - generateTestData, + generateTestData: () => generateTestData(schema), generateObjectName: () => { return faker.word.noun(); }, diff --git a/src/types/index.tsx b/src/types/index.tsx deleted file mode 100644 index 2941335..0000000 --- a/src/types/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from './recipe'; diff --git a/src/types/recipe.ts b/src/types/recipe.ts deleted file mode 100644 index 660d89f..0000000 --- a/src/types/recipe.ts +++ /dev/null @@ -1,41 +0,0 @@ -// export default interface Recipe { -// id?: string; -// name: string; -// description?: string; -// time?: { -// prep?: number; -// cooking?: number; -// total?: number; -// }; -// prepTime?: number; //todelete -// cookingTime?: number; //todelete -// totalTime?: number; //todelete -// yields?: { -// quantity?: number; -// unit?: string; -// }; -// yieldsText?: string; -// nutrients?: { -// [key: string]: string; -// }; -// image?: string; -// images?: string[]; -// ingredients?: string[]; -// instructions?: string[]; -// comments?: string; -// score?: number; -// url?: string; -// // new -// nutrition?: number; -// category?: string; -// keywords?: string[]; -// numberOfServings?: number; //todelete - -// cuisine?: string[]; -// // date fields -// createdAt?: string; -// updatedAt?: string; -// // Add raw data -// site?: string; -// raw?: any; -// } diff --git a/tsconfig.app.tsbuildinfo b/tsconfig.app.tsbuildinfo index e8b1f22..8b253e4 100644 --- a/tsconfig.app.tsbuildinfo +++ b/tsconfig.app.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/app.tsx","./src/dashboard.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/default/colormodeselect.jsx","./src/components/default/custom-breadcrumbs.tsx","./src/components/default/custom-dialog.tsx","./src/components/default/custom-popover.tsx","./src/components/default/custom-table.jsx","./src/components/default/error-boundary.tsx","./src/components/default/floating-button.tsx","./src/components/default/guest-avatar.tsx","./src/components/default/json-editor.tsx","./src/components/default/notepad.tsx","./src/components/default/scroll-to-top.tsx","./src/components/default/scrollbar.jsx","./src/components/default/seo.jsx","./src/components/default/severity-pill.jsx","./src/components/default/splash-screen.jsx","./src/components/default/tab-section.tsx","./src/components/default/auth/customicons.jsx","./src/components/default/auth/forgotpassword.jsx","./src/components/default/filters/sort-options.tsx","./src/components/default/images/image-cropper.tsx","./src/components/default/images/image-uploader.tsx","./src/components/default/images/image-viewer-dialog.tsx","./src/components/default/images/no-image-available.tsx","./src/components/default/layout/language-switch.tsx","./src/components/default/layout/user-menu.tsx","./src/components/default/ui/grid-layout.tsx","./src/components/default/ui/horizontal-scroll-card-list.tsx","./src/components/default/ui/image-list.tsx","./src/components/default/ui/loading-button.tsx","./src/components/default/ui/search-bar.tsx","./src/config/firebase.tsx","./src/config/index.tsx","./src/config/locales.tsx","./src/config/paths.tsx","./src/config/routes.tsx","./src/config/routing.tsx","./src/config/theme.tsx","./src/data/backend.ts","./src/data/recipe-data.tsx","./src/guards/auth-guard.tsx","./src/guards/guest-guard.jsx","./src/guards/issuer-guard.jsx","./src/hooks/use-dialog.ts","./src/hooks/use-fetch.ts","./src/hooks/use-guid.ts","./src/hooks/use-https-redirect.ts","./src/hooks/use-is-mobile.ts","./src/hooks/use-keyboard-shortcut.ts","./src/hooks/use-mounted.ts","./src/hooks/use-navigation-guard.tsx","./src/hooks/use-param-item.ts","./src/hooks/use-path-router.ts","./src/hooks/use-popover.ts","./src/hooks/use-query-param-action.ts","./src/hooks/use-query-tabs.ts","./src/hooks/use-router.ts","./src/hooks/use-search-params.ts","./src/hooks/use-tabs.ts","./src/layouts/paperbase/content.jsx","./src/layouts/paperbase/header.jsx","./src/layouts/paperbase/layout.jsx","./src/layouts/paperbase/navigator.jsx","./src/layouts/simple/layout.tsx","./src/layouts/simple/theme.tsx","./src/libs/auth/context.tsx","./src/libs/auth/index.tsx","./src/libs/auth/permissions-abac.ts","./src/libs/auth/permissions-rbac.ts","./src/libs/auth/use-auth.ts","./src/libs/auth/use-login-form.tsx","./src/libs/auth/auth-providers/compositeauthprovider.jsx","./src/libs/auth/auth-providers/firebaseauthprovider.tsx","./src/libs/auth/auth-providers/iauthprovider.ts","./src/libs/automation/index.tsx","./src/libs/data-sources/dataprovider.tsx","./src/libs/data-sources/index.tsx","./src/libs/data-sources/usedata.tsx","./src/libs/data-sources/data-sources/appwritedatasource.jsx","./src/libs/data-sources/data-sources/basedatasource.tsx","./src/libs/data-sources/data-sources/firebasedatasource.jsx","./src/libs/data-sources/data-sources/firebasedatasourcenorealtime.jsx","./src/libs/data-sources/data-sources/firestoredatasource.tsx","./src/libs/data-sources/data-sources/localstoragedatasource.tsx","./src/libs/data-sources/data-sources/mockdatasource.tsx","./src/libs/data-sources/data-sources/supabasedatasource.jsx","./src/libs/feature-flags/index.ts","./src/libs/feature-flags/murmurhash.ts","./src/libs/filters/index.tsx","./src/libs/filters/use-filter.ts","./src/libs/filters/components/boolean-filter.tsx","./src/libs/filters/components/mult-select-filter.tsx","./src/libs/filters/components/pagination.tsx","./src/libs/filters/components/range-filter.tsx","./src/libs/filters/components/search-bar.tsx","./src/libs/filters/components/select-filter.tsx","./src/libs/filters/components/sort-options.tsx","./src/libs/forms/custom-form.tsx","./src/libs/forms/index.tsx","./src/libs/forms/use-custom-formik.tsx","./src/libs/forms/use-form-button.tsx","./src/libs/forms/use-form-field.tsx","./src/libs/forms/components/autocomplete.tsx","./src/libs/forms/components/autocompletechiplist.tsx","./src/libs/forms/components/cancelbutton.tsx","./src/libs/forms/components/checkboxlist.tsx","./src/libs/forms/components/errors.tsx","./src/libs/forms/components/image.tsx","./src/libs/forms/components/images.tsx","./src/libs/forms/components/imagesform.tsx","./src/libs/forms/components/list.tsx","./src/libs/forms/components/notepad.tsx","./src/libs/forms/components/rating.tsx","./src/libs/forms/components/select.tsx","./src/libs/forms/components/submitbutton.tsx","./src/libs/forms/components/table.tsx","./src/libs/forms/components/textfield.tsx","./src/libs/i18n/index.ts","./src/libs/storage-providers/index.ts","./src/libs/storage-providers/providers/appwritestorageprovider.tsx","./src/libs/storage-providers/providers/basestorageprovider.tsx","./src/libs/storage-providers/providers/firebasestorageprovider.tsx","./src/libs/tabs/index.tsx","./src/libs/tabs/tab-panel.tsx","./src/libs/tabs/tabs-header.tsx","./src/libs/tabs/tabs.tsx","./src/libs/tabs/use-current-tab.tsx","./src/libs/tabs/use-tabs.tsx","./src/pages/default/404.tsx","./src/pages/default/accountold.jsx","./src/pages/default/defaultpage.tsx","./src/pages/default/defaultpaperbasepage.jsx","./src/pages/default/settings.tsx","./src/pages/default/signin.jsx","./src/pages/default/profile.tsx","./src/pages/default/account/index.tsx","./src/pages/default/account/components/debug-card.tsx","./src/pages/default/account/components/password-card.tsx","./src/pages/default/account/components/profile-card.tsx","./src/pages/default/test/translations.tsx","./src/pages/default/test/auth-providers/index.tsx","./src/pages/default/test/data/index.tsx","./src/pages/default/test/data-sources/index.tsx","./src/pages/default/test/file-uploads/index.tsx","./src/pages/default/test/file-uploads/_components/image-uploader-card.tsx","./src/pages/default/test/file-uploads/_components/simple-cropper.tsx","./src/pages/default/test/forms/index.tsx","./src/routes/approutes.tsx","./src/routes/defaultroutes.tsx","./src/routes/index.ts","./src/schemas/dummy.ts","./src/schemas/external-recipe.ts","./src/schemas/index.ts","./src/schemas/issue.ts","./src/sections/default/issue-dialog.tsx","./src/theme/paperbase/theme.jsx","./src/types/index.tsx","./src/types/recipe.ts","./src/utils/create-guid.ts","./src/utils/generate-test-data.ts","./src/utils/is-equal.ts","./src/utils/random-name-generator.ts","./src/utils/images/create-thumbnail.ts","./src/utils/images/get-next-filename.ts","./src/utils/images/resize-image.ts","./src/utils/images/save-external-image.ts"],"version":"5.6.3"} \ No newline at end of file +{"root":["./src/app.tsx","./src/dashboard.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/default/colormodeselect.jsx","./src/components/default/custom-breadcrumbs.tsx","./src/components/default/custom-dialog.tsx","./src/components/default/custom-popover.tsx","./src/components/default/custom-table.jsx","./src/components/default/error-boundary.tsx","./src/components/default/floating-button.tsx","./src/components/default/guest-avatar.tsx","./src/components/default/json-editor.tsx","./src/components/default/notepad.tsx","./src/components/default/scroll-to-top.tsx","./src/components/default/scrollbar.jsx","./src/components/default/seo.jsx","./src/components/default/severity-pill.jsx","./src/components/default/splash-screen.jsx","./src/components/default/tab-section.tsx","./src/components/default/auth/customicons.jsx","./src/components/default/auth/forgotpassword.jsx","./src/components/default/filters/sort-options.tsx","./src/components/default/images/image-cropper.tsx","./src/components/default/images/image-uploader.tsx","./src/components/default/images/image-viewer-dialog.tsx","./src/components/default/images/no-image-available.tsx","./src/components/default/layout/language-switch.tsx","./src/components/default/layout/user-menu.tsx","./src/components/default/ui/grid-layout.tsx","./src/components/default/ui/horizontal-scroll-card-list.tsx","./src/components/default/ui/image-list.tsx","./src/components/default/ui/loading-button.tsx","./src/components/default/ui/search-bar.tsx","./src/config/firebase.tsx","./src/config/index.tsx","./src/config/locales.tsx","./src/config/paths.tsx","./src/config/routes.tsx","./src/config/routing.tsx","./src/config/theme.tsx","./src/data/backend.ts","./src/data/recipe-data.tsx","./src/guards/auth-guard.tsx","./src/guards/guest-guard.jsx","./src/guards/issuer-guard.jsx","./src/hooks/use-deep-compare-memo.ts","./src/hooks/use-dialog.ts","./src/hooks/use-fetch.ts","./src/hooks/use-guid.ts","./src/hooks/use-https-redirect.ts","./src/hooks/use-is-mobile.ts","./src/hooks/use-keyboard-shortcut.ts","./src/hooks/use-mounted.ts","./src/hooks/use-navigation-guard.tsx","./src/hooks/use-param-item.ts","./src/hooks/use-path-router.ts","./src/hooks/use-popover.ts","./src/hooks/use-query-param-action.ts","./src/hooks/use-query-tabs.ts","./src/hooks/use-router.ts","./src/hooks/use-search-params.ts","./src/hooks/use-tabs.ts","./src/layouts/paperbase/content.jsx","./src/layouts/paperbase/header.jsx","./src/layouts/paperbase/layout.jsx","./src/layouts/paperbase/navigator.jsx","./src/layouts/simple/layout.tsx","./src/layouts/simple/theme.tsx","./src/libs/auth/context.tsx","./src/libs/auth/contextstate.ts","./src/libs/auth/index.tsx","./src/libs/auth/permissions-abac.ts","./src/libs/auth/permissions-rbac.ts","./src/libs/auth/use-auth.ts","./src/libs/auth/use-login-form.tsx","./src/libs/auth/auth-providers/compositeauthprovider.jsx","./src/libs/auth/auth-providers/firebaseauthprovider.tsx","./src/libs/auth/auth-providers/iauthprovider.ts","./src/libs/automation/index.tsx","./src/libs/data-sources/dataprovider.tsx","./src/libs/data-sources/index.tsx","./src/libs/data-sources/usedata.tsx","./src/libs/data-sources/data-sources/appwritedatasource.jsx","./src/libs/data-sources/data-sources/basedatasource.tsx","./src/libs/data-sources/data-sources/firebasedatasource.jsx","./src/libs/data-sources/data-sources/firebasedatasourcenorealtime.jsx","./src/libs/data-sources/data-sources/firestoredatasource.tsx","./src/libs/data-sources/data-sources/localstoragedatasource.tsx","./src/libs/data-sources/data-sources/mockdatasource.tsx","./src/libs/data-sources/data-sources/supabasedatasource.jsx","./src/libs/feature-flags/index.ts","./src/libs/feature-flags/murmurhash.ts","./src/libs/filters/index.tsx","./src/libs/filters/use-filter.ts","./src/libs/filters/components/boolean-filter.tsx","./src/libs/filters/components/mult-select-filter.tsx","./src/libs/filters/components/pagination.tsx","./src/libs/filters/components/range-filter.tsx","./src/libs/filters/components/search-bar.tsx","./src/libs/filters/components/select-filter.tsx","./src/libs/filters/components/sort-options.tsx","./src/libs/forms/custom-form.tsx","./src/libs/forms/index.tsx","./src/libs/forms/use-custom-formik.tsx","./src/libs/forms/use-form-button.tsx","./src/libs/forms/use-form-field.tsx","./src/libs/forms/components/autocomplete.tsx","./src/libs/forms/components/autocompletechiplist.tsx","./src/libs/forms/components/cancelbutton.tsx","./src/libs/forms/components/checkboxlist.tsx","./src/libs/forms/components/errors.tsx","./src/libs/forms/components/image.tsx","./src/libs/forms/components/images.tsx","./src/libs/forms/components/imagesform.tsx","./src/libs/forms/components/list.tsx","./src/libs/forms/components/notepad.tsx","./src/libs/forms/components/rating.tsx","./src/libs/forms/components/select.tsx","./src/libs/forms/components/submitbutton.tsx","./src/libs/forms/components/table.tsx","./src/libs/forms/components/textfield.tsx","./src/libs/i18n/index.ts","./src/libs/storage-providers/index.ts","./src/libs/storage-providers/providers/appwritestorageprovider.tsx","./src/libs/storage-providers/providers/basestorageprovider.tsx","./src/libs/storage-providers/providers/firebasestorageprovider.tsx","./src/libs/tabs/context.ts","./src/libs/tabs/index.tsx","./src/libs/tabs/tab-panel.tsx","./src/libs/tabs/tabs-header.tsx","./src/libs/tabs/tabs.tsx","./src/libs/tabs/use-current-tab.tsx","./src/libs/tabs/use-tabs.tsx","./src/pages/default/404.tsx","./src/pages/default/accountold.jsx","./src/pages/default/defaultpage.tsx","./src/pages/default/defaultpaperbasepage.jsx","./src/pages/default/settings.tsx","./src/pages/default/signin.jsx","./src/pages/default/profile.tsx","./src/pages/default/account/index.tsx","./src/pages/default/account/components/debug-card.tsx","./src/pages/default/account/components/password-card.tsx","./src/pages/default/account/components/profile-card.tsx","./src/pages/default/test/filters-page.tsx","./src/pages/default/test/translations.tsx","./src/pages/default/test/auth-providers/index.tsx","./src/pages/default/test/data/index.tsx","./src/pages/default/test/data-sources/index.tsx","./src/pages/default/test/file-uploads/index.tsx","./src/pages/default/test/file-uploads/_components/image-uploader-card.tsx","./src/pages/default/test/file-uploads/_components/simple-cropper.tsx","./src/pages/default/test/forms/index.tsx","./src/routes/approutes.tsx","./src/routes/defaultroutes.tsx","./src/routes/index.ts","./src/schemas/dummy.ts","./src/schemas/external-recipe.ts","./src/schemas/index.ts","./src/schemas/issue.ts","./src/sections/default/issue-dialog.tsx","./src/theme/paperbase/theme.jsx","./src/utils/create-guid.ts","./src/utils/generate-test-data.ts","./src/utils/is-equal.ts","./src/utils/random-name-generator.ts","./src/utils/images/create-thumbnail.ts","./src/utils/images/get-next-filename.ts","./src/utils/images/resize-image.ts","./src/utils/images/save-external-image.ts"],"errors":true,"version":"5.6.3"} \ No newline at end of file