~ format project files using prettier local configuration
				
					
				
			This commit is contained in:
		
							
								
								
									
										110
									
								
								src/App.tsx
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								src/App.tsx
									
									
									
									
									
								
							| @@ -1,48 +1,22 @@ | |||||||
| import { | import {Refine, GitHubBanner, WelcomePage, Authenticated} from '@refinedev/core' | ||||||
|   Refine, | import {DevtoolsPanel, DevtoolsProvider} from '@refinedev/devtools' | ||||||
|   GitHubBanner, | import {RefineKbar, RefineKbarProvider} from '@refinedev/kbar' | ||||||
|   WelcomePage, |  | ||||||
|   Authenticated, |  | ||||||
| } from "@refinedev/core"; |  | ||||||
| import { DevtoolsPanel, DevtoolsProvider } from "@refinedev/devtools"; |  | ||||||
| import { RefineKbar, RefineKbarProvider } from "@refinedev/kbar"; |  | ||||||
|  |  | ||||||
| import { | import {AuthPage, ErrorComponent, useNotificationProvider, RefineSnackbarProvider, ThemedLayoutV2} from '@refinedev/mui' | ||||||
|   AuthPage, |  | ||||||
|   ErrorComponent, |  | ||||||
|   useNotificationProvider, |  | ||||||
|   RefineSnackbarProvider, |  | ||||||
|   ThemedLayoutV2, |  | ||||||
| } from "@refinedev/mui"; |  | ||||||
|  |  | ||||||
| import dataProvider from "@refinedev/simple-rest"; | import dataProvider from '@refinedev/simple-rest' | ||||||
| import CssBaseline from "@mui/material/CssBaseline"; | import CssBaseline from '@mui/material/CssBaseline' | ||||||
| import GlobalStyles from "@mui/material/GlobalStyles"; | import GlobalStyles from '@mui/material/GlobalStyles' | ||||||
| import { BrowserRouter, Route, Routes, Outlet } from "react-router"; | import {BrowserRouter, Route, Routes, Outlet} from 'react-router' | ||||||
| import routerBindings, { | import routerBindings, {NavigateToResource, CatchAllNavigate, UnsavedChangesNotifier, DocumentTitleHandler} from '@refinedev/react-router' | ||||||
|   NavigateToResource, | import {BlogPostList, BlogPostCreate, BlogPostEdit, BlogPostShow} from './pages/blog-posts' | ||||||
|   CatchAllNavigate, | import {CategoryList, CategoryCreate, CategoryEdit, CategoryShow} from './pages/categories' | ||||||
|   UnsavedChangesNotifier, | import {ColorModeContextProvider} from './contexts/color-mode' | ||||||
|   DocumentTitleHandler, | import {Header} from './components/header' | ||||||
| } from "@refinedev/react-router"; | import {Login} from './pages/login' | ||||||
| import { | import {Register} from './pages/register' | ||||||
|   BlogPostList, | import {ForgotPassword} from './pages/forgotPassword' | ||||||
|   BlogPostCreate, | import {authProvider} from './authProvider' | ||||||
|   BlogPostEdit, |  | ||||||
|   BlogPostShow, |  | ||||||
| } from "./pages/blog-posts"; |  | ||||||
| import { |  | ||||||
|   CategoryList, |  | ||||||
|   CategoryCreate, |  | ||||||
|   CategoryEdit, |  | ||||||
|   CategoryShow, |  | ||||||
| } from "./pages/categories"; |  | ||||||
| import { ColorModeContextProvider } from "./contexts/color-mode"; |  | ||||||
| import { Header } from "./components/header"; |  | ||||||
| import { Login } from "./pages/login"; |  | ||||||
| import { Register } from "./pages/register"; |  | ||||||
| import { ForgotPassword } from "./pages/forgotPassword"; |  | ||||||
| import { authProvider } from "./authProvider"; |  | ||||||
|  |  | ||||||
| function App() { | function App() { | ||||||
|   return ( |   return ( | ||||||
| @@ -51,31 +25,31 @@ function App() { | |||||||
|       <RefineKbarProvider> |       <RefineKbarProvider> | ||||||
|         <ColorModeContextProvider> |         <ColorModeContextProvider> | ||||||
|           <CssBaseline /> |           <CssBaseline /> | ||||||
|           <GlobalStyles styles={{ html: { WebkitFontSmoothing: "auto" } }} /> |           <GlobalStyles styles={{html: {WebkitFontSmoothing: 'auto'}}} /> | ||||||
|           <RefineSnackbarProvider> |           <RefineSnackbarProvider> | ||||||
|             <DevtoolsProvider> |             <DevtoolsProvider> | ||||||
|               <Refine |               <Refine | ||||||
|                 dataProvider={dataProvider("https://api.fake-rest.refine.dev")} |                 dataProvider={dataProvider('https://api.fake-rest.refine.dev')} | ||||||
|                 notificationProvider={useNotificationProvider} |                 notificationProvider={useNotificationProvider} | ||||||
|                 routerProvider={routerBindings} |                 routerProvider={routerBindings} | ||||||
|                 authProvider={authProvider} |                 authProvider={authProvider} | ||||||
|                 resources={[ |                 resources={[ | ||||||
|                   { |                   { | ||||||
|                     name: "blog_posts", |                     name: 'blog_posts', | ||||||
|                     list: "/blog-posts", |                     list: '/blog-posts', | ||||||
|                     create: "/blog-posts/create", |                     create: '/blog-posts/create', | ||||||
|                     edit: "/blog-posts/edit/:id", |                     edit: '/blog-posts/edit/:id', | ||||||
|                     show: "/blog-posts/show/:id", |                     show: '/blog-posts/show/:id', | ||||||
|                     meta: { |                     meta: { | ||||||
|                       canDelete: true, |                       canDelete: true, | ||||||
|                     }, |                     }, | ||||||
|                   }, |                   }, | ||||||
|                   { |                   { | ||||||
|                     name: "categories", |                     name: 'categories', | ||||||
|                     list: "/categories", |                     list: '/categories', | ||||||
|                     create: "/categories/create", |                     create: '/categories/create', | ||||||
|                     edit: "/categories/edit/:id", |                     edit: '/categories/edit/:id', | ||||||
|                     show: "/categories/show/:id", |                     show: '/categories/show/:id', | ||||||
|                     meta: { |                     meta: { | ||||||
|                       canDelete: true, |                       canDelete: true, | ||||||
|                     }, |                     }, | ||||||
| @@ -85,26 +59,20 @@ function App() { | |||||||
|                   syncWithLocation: true, |                   syncWithLocation: true, | ||||||
|                   warnWhenUnsavedChanges: true, |                   warnWhenUnsavedChanges: true, | ||||||
|                   useNewQueryKeys: true, |                   useNewQueryKeys: true, | ||||||
|                   projectId: "Wv044J-t53S3s-PcbJGe", |                   projectId: 'Wv044J-t53S3s-PcbJGe', | ||||||
|                 }} |                 }} | ||||||
|               > |               > | ||||||
|                 <Routes> |                 <Routes> | ||||||
|                   <Route |                   <Route | ||||||
|                     element={ |                     element={ | ||||||
|                       <Authenticated |                       <Authenticated key="authenticated-inner" fallback={<CatchAllNavigate to="/login" />}> | ||||||
|                         key="authenticated-inner" |  | ||||||
|                         fallback={<CatchAllNavigate to="/login" />} |  | ||||||
|                       > |  | ||||||
|                         <ThemedLayoutV2 Header={Header}> |                         <ThemedLayoutV2 Header={Header}> | ||||||
|                           <Outlet /> |                           <Outlet /> | ||||||
|                         </ThemedLayoutV2> |                         </ThemedLayoutV2> | ||||||
|                       </Authenticated> |                       </Authenticated> | ||||||
|                     } |                     } | ||||||
|                   > |                   > | ||||||
|                     <Route |                     <Route index element={<NavigateToResource resource="blog_posts" />} /> | ||||||
|                       index |  | ||||||
|                       element={<NavigateToResource resource="blog_posts" />} |  | ||||||
|                     /> |  | ||||||
|                     <Route path="/blog-posts"> |                     <Route path="/blog-posts"> | ||||||
|                       <Route index element={<BlogPostList />} /> |                       <Route index element={<BlogPostList />} /> | ||||||
|                       <Route path="create" element={<BlogPostCreate />} /> |                       <Route path="create" element={<BlogPostCreate />} /> | ||||||
| @@ -121,20 +89,14 @@ function App() { | |||||||
|                   </Route> |                   </Route> | ||||||
|                   <Route |                   <Route | ||||||
|                     element={ |                     element={ | ||||||
|                       <Authenticated |                       <Authenticated key="authenticated-outer" fallback={<Outlet />}> | ||||||
|                         key="authenticated-outer" |  | ||||||
|                         fallback={<Outlet />} |  | ||||||
|                       > |  | ||||||
|                         <NavigateToResource /> |                         <NavigateToResource /> | ||||||
|                       </Authenticated> |                       </Authenticated> | ||||||
|                     } |                     } | ||||||
|                   > |                   > | ||||||
|                     <Route path="/login" element={<Login />} /> |                     <Route path="/login" element={<Login />} /> | ||||||
|                     <Route path="/register" element={<Register />} /> |                     <Route path="/register" element={<Register />} /> | ||||||
|                     <Route |                     <Route path="/forgot-password" element={<ForgotPassword />} /> | ||||||
|                       path="/forgot-password" |  | ||||||
|                       element={<ForgotPassword />} |  | ||||||
|                     /> |  | ||||||
|                   </Route> |                   </Route> | ||||||
|                 </Routes> |                 </Routes> | ||||||
|  |  | ||||||
| @@ -148,7 +110,7 @@ function App() { | |||||||
|         </ColorModeContextProvider> |         </ColorModeContextProvider> | ||||||
|       </RefineKbarProvider> |       </RefineKbarProvider> | ||||||
|     </BrowserRouter> |     </BrowserRouter> | ||||||
|   ); |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
| export default App; | export default App | ||||||
|   | |||||||
| @@ -1,59 +1,59 @@ | |||||||
| import type { AuthProvider } from "@refinedev/core"; | import type {AuthProvider} from '@refinedev/core' | ||||||
|  |  | ||||||
| export const TOKEN_KEY = "refine-auth"; | export const TOKEN_KEY = 'refine-auth' | ||||||
|  |  | ||||||
| export const authProvider: AuthProvider = { | export const authProvider: AuthProvider = { | ||||||
|   login: async ({ username, email, password }) => { |   login: async ({username, email, password}) => { | ||||||
|     if ((username || email) && password) { |     if ((username || email) && password) { | ||||||
|       localStorage.setItem(TOKEN_KEY, username); |       localStorage.setItem(TOKEN_KEY, username) | ||||||
|       return { |       return { | ||||||
|         success: true, |         success: true, | ||||||
|         redirectTo: "/", |         redirectTo: '/', | ||||||
|       }; |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return { |     return { | ||||||
|       success: false, |       success: false, | ||||||
|       error: { |       error: { | ||||||
|         name: "LoginError", |         name: 'LoginError', | ||||||
|         message: "Invalid username or password", |         message: 'Invalid username or password', | ||||||
|       }, |       }, | ||||||
|     }; |     } | ||||||
|   }, |   }, | ||||||
|   logout: async () => { |   logout: async () => { | ||||||
|     localStorage.removeItem(TOKEN_KEY); |     localStorage.removeItem(TOKEN_KEY) | ||||||
|     return { |     return { | ||||||
|       success: true, |       success: true, | ||||||
|       redirectTo: "/login", |       redirectTo: '/login', | ||||||
|     }; |     } | ||||||
|   }, |   }, | ||||||
|   check: async () => { |   check: async () => { | ||||||
|     const token = localStorage.getItem(TOKEN_KEY); |     const token = localStorage.getItem(TOKEN_KEY) | ||||||
|     if (token) { |     if (token) { | ||||||
|       return { |       return { | ||||||
|         authenticated: true, |         authenticated: true, | ||||||
|       }; |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return { |     return { | ||||||
|       authenticated: false, |       authenticated: false, | ||||||
|       redirectTo: "/login", |       redirectTo: '/login', | ||||||
|     }; |     } | ||||||
|   }, |   }, | ||||||
|   getPermissions: async () => null, |   getPermissions: async () => null, | ||||||
|   getIdentity: async () => { |   getIdentity: async () => { | ||||||
|     const token = localStorage.getItem(TOKEN_KEY); |     const token = localStorage.getItem(TOKEN_KEY) | ||||||
|     if (token) { |     if (token) { | ||||||
|       return { |       return { | ||||||
|         id: 1, |         id: 1, | ||||||
|         name: "John Doe", |         name: 'John Doe', | ||||||
|         avatar: "https://i.pravatar.cc/300", |         avatar: 'https://i.pravatar.cc/300', | ||||||
|       }; |       } | ||||||
|     } |     } | ||||||
|     return null; |     return null | ||||||
|   }, |   }, | ||||||
|   onError: async (error) => { |   onError: async (error) => { | ||||||
|     console.error(error); |     console.error(error) | ||||||
|     return { error }; |     return {error} | ||||||
|   }, |   }, | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,67 +1,50 @@ | |||||||
| import DarkModeOutlined from "@mui/icons-material/DarkModeOutlined"; | import DarkModeOutlined from '@mui/icons-material/DarkModeOutlined' | ||||||
| import LightModeOutlined from "@mui/icons-material/LightModeOutlined"; | import LightModeOutlined from '@mui/icons-material/LightModeOutlined' | ||||||
| import AppBar from "@mui/material/AppBar"; | import AppBar from '@mui/material/AppBar' | ||||||
| import Avatar from "@mui/material/Avatar"; | import Avatar from '@mui/material/Avatar' | ||||||
| import IconButton from "@mui/material/IconButton"; | import IconButton from '@mui/material/IconButton' | ||||||
| import Stack from "@mui/material/Stack"; | import Stack from '@mui/material/Stack' | ||||||
| import Toolbar from "@mui/material/Toolbar"; | import Toolbar from '@mui/material/Toolbar' | ||||||
| import Typography from "@mui/material/Typography"; | import Typography from '@mui/material/Typography' | ||||||
| import { useGetIdentity } from "@refinedev/core"; | import {useGetIdentity} from '@refinedev/core' | ||||||
| import { HamburgerMenu, RefineThemedLayoutV2HeaderProps } from "@refinedev/mui"; | import {HamburgerMenu, RefineThemedLayoutV2HeaderProps} from '@refinedev/mui' | ||||||
| import React, { useContext } from "react"; | import React, {useContext} from 'react' | ||||||
| import { ColorModeContext } from "../../contexts/color-mode"; | import {ColorModeContext} from '../../contexts/color-mode' | ||||||
|  |  | ||||||
| type IUser = { | type IUser = { | ||||||
|   id: number; |   id: number | ||||||
|   name: string; |   name: string | ||||||
|   avatar: string; |   avatar: string | ||||||
| }; | } | ||||||
|  |  | ||||||
| export const Header: React.FC<RefineThemedLayoutV2HeaderProps> = ({ | export const Header: React.FC<RefineThemedLayoutV2HeaderProps> = ({sticky = true}) => { | ||||||
|   sticky = true, |   const {mode, setMode} = useContext(ColorModeContext) | ||||||
| }) => { |  | ||||||
|   const { mode, setMode } = useContext(ColorModeContext); |  | ||||||
|  |  | ||||||
|   const { data: user } = useGetIdentity<IUser>(); |   const {data: user} = useGetIdentity<IUser>() | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <AppBar position={sticky ? "sticky" : "relative"}> |     <AppBar position={sticky ? 'sticky' : 'relative'}> | ||||||
|       <Toolbar> |       <Toolbar> | ||||||
|         <Stack |         <Stack direction="row" width="100%" justifyContent="flex-end" alignItems="center"> | ||||||
|           direction="row" |  | ||||||
|           width="100%" |  | ||||||
|           justifyContent="flex-end" |  | ||||||
|           alignItems="center" |  | ||||||
|         > |  | ||||||
|           <HamburgerMenu /> |           <HamburgerMenu /> | ||||||
|           <Stack |           <Stack direction="row" width="100%" justifyContent="flex-end" alignItems="center"> | ||||||
|             direction="row" |  | ||||||
|             width="100%" |  | ||||||
|             justifyContent="flex-end" |  | ||||||
|             alignItems="center" |  | ||||||
|           > |  | ||||||
|             <IconButton |             <IconButton | ||||||
|               color="inherit" |               color="inherit" | ||||||
|               onClick={() => { |               onClick={() => { | ||||||
|                 setMode(); |                 setMode() | ||||||
|               }} |               }} | ||||||
|             > |             > | ||||||
|               {mode === "dark" ? <LightModeOutlined /> : <DarkModeOutlined />} |               {mode === 'dark' ? <LightModeOutlined /> : <DarkModeOutlined />} | ||||||
|             </IconButton> |             </IconButton> | ||||||
|  |  | ||||||
|             {(user?.avatar || user?.name) && ( |             {(user?.avatar || user?.name) && ( | ||||||
|               <Stack |               <Stack direction="row" gap="16px" alignItems="center" justifyContent="center"> | ||||||
|                 direction="row" |  | ||||||
|                 gap="16px" |  | ||||||
|                 alignItems="center" |  | ||||||
|                 justifyContent="center" |  | ||||||
|               > |  | ||||||
|                 {user?.name && ( |                 {user?.name && ( | ||||||
|                   <Typography |                   <Typography | ||||||
|                     sx={{ |                     sx={{ | ||||||
|                       display: { |                       display: { | ||||||
|                         xs: "none", |                         xs: 'none', | ||||||
|                         sm: "inline-block", |                         sm: 'inline-block', | ||||||
|                       }, |                       }, | ||||||
|                     }} |                     }} | ||||||
|                     variant="subtitle2" |                     variant="subtitle2" | ||||||
| @@ -76,5 +59,5 @@ export const Header: React.FC<RefineThemedLayoutV2HeaderProps> = ({ | |||||||
|         </Stack> |         </Stack> | ||||||
|       </Toolbar> |       </Toolbar> | ||||||
|     </AppBar> |     </AppBar> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| export { Header } from "./header"; | export {Header} from './header' | ||||||
|   | |||||||
| @@ -1,45 +1,32 @@ | |||||||
| import React, { | import React, {PropsWithChildren, createContext, useEffect, useState} from 'react' | ||||||
|   PropsWithChildren, | import {ThemeProvider} from '@mui/material/styles' | ||||||
|   createContext, | import {RefineThemes} from '@refinedev/mui' | ||||||
|   useEffect, |  | ||||||
|   useState, |  | ||||||
| } from "react"; |  | ||||||
| import { ThemeProvider } from "@mui/material/styles"; |  | ||||||
| import { RefineThemes } from "@refinedev/mui"; |  | ||||||
|  |  | ||||||
| type ColorModeContextType = { | type ColorModeContextType = { | ||||||
|   mode: string; |   mode: string | ||||||
|   setMode: () => void; |   setMode: () => void | ||||||
| }; | } | ||||||
|  |  | ||||||
| export const ColorModeContext = createContext<ColorModeContextType>( | export const ColorModeContext = createContext<ColorModeContextType>({} as ColorModeContextType) | ||||||
|   {} as ColorModeContextType |  | ||||||
| ); |  | ||||||
|  |  | ||||||
| export const ColorModeContextProvider: React.FC<PropsWithChildren> = ({ | export const ColorModeContextProvider: React.FC<PropsWithChildren> = ({children}) => { | ||||||
|   children, |   const colorModeFromLocalStorage = localStorage.getItem('colorMode') | ||||||
| }) => { |   const isSystemPreferenceDark = window?.matchMedia('(prefers-color-scheme: dark)').matches | ||||||
|   const colorModeFromLocalStorage = localStorage.getItem("colorMode"); |  | ||||||
|   const isSystemPreferenceDark = window?.matchMedia( |  | ||||||
|     "(prefers-color-scheme: dark)" |  | ||||||
|   ).matches; |  | ||||||
|  |  | ||||||
|   const systemPreference = isSystemPreferenceDark ? "dark" : "light"; |   const systemPreference = isSystemPreferenceDark ? 'dark' : 'light' | ||||||
|   const [mode, setMode] = useState( |   const [mode, setMode] = useState(colorModeFromLocalStorage || systemPreference) | ||||||
|     colorModeFromLocalStorage || systemPreference |  | ||||||
|   ); |  | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     window.localStorage.setItem("colorMode", mode); |     window.localStorage.setItem('colorMode', mode) | ||||||
|   }, [mode]); |   }, [mode]) | ||||||
|  |  | ||||||
|   const setColorMode = () => { |   const setColorMode = () => { | ||||||
|     if (mode === "light") { |     if (mode === 'light') { | ||||||
|       setMode("dark"); |       setMode('dark') | ||||||
|     } else { |     } else { | ||||||
|       setMode("light"); |       setMode('light') | ||||||
|     } |     } | ||||||
|   }; |   } | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <ColorModeContext.Provider |     <ColorModeContext.Provider | ||||||
| @@ -50,10 +37,10 @@ export const ColorModeContextProvider: React.FC<PropsWithChildren> = ({ | |||||||
|     > |     > | ||||||
|       <ThemeProvider |       <ThemeProvider | ||||||
|         // you can change the theme colors here. example: mode === "light" ? RefineThemes.Magenta : RefineThemes.MagentaDark |         // you can change the theme colors here. example: mode === "light" ? RefineThemes.Magenta : RefineThemes.MagentaDark | ||||||
|         theme={mode === "light" ? RefineThemes.Blue : RefineThemes.BlueDark} |         theme={mode === 'light' ? RefineThemes.Blue : RefineThemes.BlueDark} | ||||||
|       > |       > | ||||||
|         {children} |         {children} | ||||||
|       </ThemeProvider> |       </ThemeProvider> | ||||||
|     </ColorModeContext.Provider> |     </ColorModeContext.Provider> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
| import React from "react"; | import React from 'react' | ||||||
| import { createRoot } from "react-dom/client"; | import {createRoot} from 'react-dom/client' | ||||||
|  |  | ||||||
| import App from "./App"; | import App from './App' | ||||||
|  |  | ||||||
| const container = document.getElementById("root") as HTMLElement; | const container = document.getElementById('root') as HTMLElement | ||||||
| const root = createRoot(container); | const root = createRoot(container) | ||||||
|  |  | ||||||
| root.render( | root.render( | ||||||
|   <React.StrictMode> |   <React.StrictMode> | ||||||
|     <App /> |     <App /> | ||||||
|   </React.StrictMode> |   </React.StrictMode>, | ||||||
| ); | ) | ||||||
|   | |||||||
| @@ -1,120 +1,96 @@ | |||||||
| import { Autocomplete, Box, MenuItem, Select, TextField } from "@mui/material"; | import {Autocomplete, Box, MenuItem, Select, TextField} from '@mui/material' | ||||||
| import { Create, useAutocomplete } from "@refinedev/mui"; | import {Create, useAutocomplete} from '@refinedev/mui' | ||||||
| import { useForm } from "@refinedev/react-hook-form"; | import {useForm} from '@refinedev/react-hook-form' | ||||||
| import React from "react"; | import React from 'react' | ||||||
| import { Controller } from "react-hook-form"; | import {Controller} from 'react-hook-form' | ||||||
|  |  | ||||||
| export const BlogPostCreate = () => { | export const BlogPostCreate = () => { | ||||||
|   const { |   const { | ||||||
|     saveButtonProps, |     saveButtonProps, | ||||||
|     refineCore: { formLoading }, |     refineCore: {formLoading}, | ||||||
|     register, |     register, | ||||||
|     control, |     control, | ||||||
|     formState: { errors }, |     formState: {errors}, | ||||||
|   } = useForm({}); |   } = useForm({}) | ||||||
|  |  | ||||||
|   const { autocompleteProps: categoryAutocompleteProps } = useAutocomplete({ |   const {autocompleteProps: categoryAutocompleteProps} = useAutocomplete({ | ||||||
|     resource: "categories", |     resource: 'categories', | ||||||
|   }); |   }) | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <Create isLoading={formLoading} saveButtonProps={saveButtonProps}> |     <Create isLoading={formLoading} saveButtonProps={saveButtonProps}> | ||||||
|       <Box |       <Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off"> | ||||||
|         component="form" |  | ||||||
|         sx={{ display: "flex", flexDirection: "column" }} |  | ||||||
|         autoComplete="off" |  | ||||||
|       > |  | ||||||
|         <TextField |         <TextField | ||||||
|           {...register("title", { |           {...register('title', { | ||||||
|             required: "This field is required", |             required: 'This field is required', | ||||||
|           })} |           })} | ||||||
|           error={!!(errors as any)?.title} |           error={!!(errors as any)?.title} | ||||||
|           helperText={(errors as any)?.title?.message} |           helperText={(errors as any)?.title?.message} | ||||||
|           margin="normal" |           margin="normal" | ||||||
|           fullWidth |           fullWidth | ||||||
|           InputLabelProps={{ shrink: true }} |           InputLabelProps={{shrink: true}} | ||||||
|           type="text" |           type="text" | ||||||
|           label={"Title"} |           label={'Title'} | ||||||
|           name="title" |           name="title" | ||||||
|         /> |         /> | ||||||
|         <TextField |         <TextField | ||||||
|           {...register("content", { |           {...register('content', { | ||||||
|             required: "This field is required", |             required: 'This field is required', | ||||||
|           })} |           })} | ||||||
|           error={!!(errors as any)?.content} |           error={!!(errors as any)?.content} | ||||||
|           helperText={(errors as any)?.content?.message} |           helperText={(errors as any)?.content?.message} | ||||||
|           margin="normal" |           margin="normal" | ||||||
|           fullWidth |           fullWidth | ||||||
|           InputLabelProps={{ shrink: true }} |           InputLabelProps={{shrink: true}} | ||||||
|           multiline |           multiline | ||||||
|           label={"Content"} |           label={'Content'} | ||||||
|           name="content" |           name="content" | ||||||
|         /> |         /> | ||||||
|         <Controller |         <Controller | ||||||
|           control={control} |           control={control} | ||||||
|           name={"category.id"} |           name={'category.id'} | ||||||
|           rules={{ required: "This field is required" }} |           rules={{required: 'This field is required'}} | ||||||
|           // eslint-disable-next-line |           // eslint-disable-next-line | ||||||
|           defaultValue={null as any} |           defaultValue={null as any} | ||||||
|           render={({ field }) => ( |           render={({field}) => ( | ||||||
|             <Autocomplete |             <Autocomplete | ||||||
|               {...categoryAutocompleteProps} |               {...categoryAutocompleteProps} | ||||||
|               {...field} |               {...field} | ||||||
|               onChange={(_, value) => { |               onChange={(_, value) => { | ||||||
|                 field.onChange(value.id); |                 field.onChange(value.id) | ||||||
|               }} |               }} | ||||||
|               getOptionLabel={(item) => { |               getOptionLabel={(item) => { | ||||||
|                 return ( |                 return ( | ||||||
|                   categoryAutocompleteProps?.options?.find((p) => { |                   categoryAutocompleteProps?.options?.find((p) => { | ||||||
|                     const itemId = |                     const itemId = typeof item === 'object' ? item?.id?.toString() : item?.toString() | ||||||
|                       typeof item === "object" |                     const pId = p?.id?.toString() | ||||||
|                         ? item?.id?.toString() |                     return itemId === pId | ||||||
|                         : item?.toString(); |                   })?.title ?? '' | ||||||
|                     const pId = p?.id?.toString(); |                 ) | ||||||
|                     return itemId === pId; |  | ||||||
|                   })?.title ?? "" |  | ||||||
|                 ); |  | ||||||
|               }} |               }} | ||||||
|               isOptionEqualToValue={(option, value) => { |               isOptionEqualToValue={(option, value) => { | ||||||
|                 const optionId = option?.id?.toString(); |                 const optionId = option?.id?.toString() | ||||||
|                 const valueId = |                 const valueId = typeof value === 'object' ? value?.id?.toString() : value?.toString() | ||||||
|                   typeof value === "object" |                 return value === undefined || optionId === valueId | ||||||
|                     ? value?.id?.toString() |  | ||||||
|                     : value?.toString(); |  | ||||||
|                 return value === undefined || optionId === valueId; |  | ||||||
|               }} |               }} | ||||||
|               renderInput={(params) => ( |               renderInput={(params) => <TextField {...params} label={'Category'} margin="normal" variant="outlined" error={!!(errors as any)?.category?.id} helperText={(errors as any)?.category?.id?.message} required />} | ||||||
|                 <TextField |  | ||||||
|                   {...params} |  | ||||||
|                   label={"Category"} |  | ||||||
|                   margin="normal" |  | ||||||
|                   variant="outlined" |  | ||||||
|                   error={!!(errors as any)?.category?.id} |  | ||||||
|                   helperText={(errors as any)?.category?.id?.message} |  | ||||||
|                   required |  | ||||||
|                 /> |  | ||||||
|               )} |  | ||||||
|             /> |             /> | ||||||
|           )} |           )} | ||||||
|         /> |         /> | ||||||
|         <Controller |         <Controller | ||||||
|           name="status" |           name="status" | ||||||
|           control={control} |           control={control} | ||||||
|           render={({ field }) => { |           render={({field}) => { | ||||||
|             return ( |             return ( | ||||||
|               <Select |               <Select {...field} value={field?.value || 'draft'} label={'Status'}> | ||||||
|                 {...field} |  | ||||||
|                 value={field?.value || "draft"} |  | ||||||
|                 label={"Status"} |  | ||||||
|               > |  | ||||||
|                 <MenuItem value="draft">Draft</MenuItem> |                 <MenuItem value="draft">Draft</MenuItem> | ||||||
|                 <MenuItem value="published">Published</MenuItem> |                 <MenuItem value="published">Published</MenuItem> | ||||||
|                 <MenuItem value="rejected">Rejected</MenuItem> |                 <MenuItem value="rejected">Rejected</MenuItem> | ||||||
|               </Select> |               </Select> | ||||||
|             ); |             ) | ||||||
|           }} |           }} | ||||||
|         /> |         /> | ||||||
|       </Box> |       </Box> | ||||||
|     </Create> |     </Create> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,125 +1,101 @@ | |||||||
| import { Autocomplete, Box, Select, TextField } from "@mui/material"; | import {Autocomplete, Box, Select, TextField} from '@mui/material' | ||||||
| import MenuItem from "@mui/material/MenuItem"; | import MenuItem from '@mui/material/MenuItem' | ||||||
| import { Edit, useAutocomplete } from "@refinedev/mui"; | import {Edit, useAutocomplete} from '@refinedev/mui' | ||||||
| import { useForm } from "@refinedev/react-hook-form"; | import {useForm} from '@refinedev/react-hook-form' | ||||||
| import React from "react"; | import React from 'react' | ||||||
| import { Controller } from "react-hook-form"; | import {Controller} from 'react-hook-form' | ||||||
|  |  | ||||||
| export const BlogPostEdit = () => { | export const BlogPostEdit = () => { | ||||||
|   const { |   const { | ||||||
|     saveButtonProps, |     saveButtonProps, | ||||||
|     refineCore: { queryResult, formLoading }, |     refineCore: {queryResult, formLoading}, | ||||||
|     register, |     register, | ||||||
|     control, |     control, | ||||||
|     formState: { errors }, |     formState: {errors}, | ||||||
|   } = useForm({}); |   } = useForm({}) | ||||||
|  |  | ||||||
|   const blogPostsData = queryResult?.data?.data; |   const blogPostsData = queryResult?.data?.data | ||||||
|  |  | ||||||
|   const { autocompleteProps: categoryAutocompleteProps } = useAutocomplete({ |   const {autocompleteProps: categoryAutocompleteProps} = useAutocomplete({ | ||||||
|     resource: "categories", |     resource: 'categories', | ||||||
|     defaultValue: blogPostsData?.category?.id, |     defaultValue: blogPostsData?.category?.id, | ||||||
|   }); |   }) | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <Edit isLoading={formLoading} saveButtonProps={saveButtonProps}> |     <Edit isLoading={formLoading} saveButtonProps={saveButtonProps}> | ||||||
|       <Box |       <Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off"> | ||||||
|         component="form" |  | ||||||
|         sx={{ display: "flex", flexDirection: "column" }} |  | ||||||
|         autoComplete="off" |  | ||||||
|       > |  | ||||||
|         <TextField |         <TextField | ||||||
|           {...register("title", { |           {...register('title', { | ||||||
|             required: "This field is required", |             required: 'This field is required', | ||||||
|           })} |           })} | ||||||
|           error={!!(errors as any)?.title} |           error={!!(errors as any)?.title} | ||||||
|           helperText={(errors as any)?.title?.message} |           helperText={(errors as any)?.title?.message} | ||||||
|           margin="normal" |           margin="normal" | ||||||
|           fullWidth |           fullWidth | ||||||
|           InputLabelProps={{ shrink: true }} |           InputLabelProps={{shrink: true}} | ||||||
|           type="text" |           type="text" | ||||||
|           label={"Title"} |           label={'Title'} | ||||||
|           name="title" |           name="title" | ||||||
|         /> |         /> | ||||||
|         <TextField |         <TextField | ||||||
|           {...register("content", { |           {...register('content', { | ||||||
|             required: "This field is required", |             required: 'This field is required', | ||||||
|           })} |           })} | ||||||
|           error={!!(errors as any)?.content} |           error={!!(errors as any)?.content} | ||||||
|           helperText={(errors as any)?.content?.message} |           helperText={(errors as any)?.content?.message} | ||||||
|           margin="normal" |           margin="normal" | ||||||
|           fullWidth |           fullWidth | ||||||
|           InputLabelProps={{ shrink: true }} |           InputLabelProps={{shrink: true}} | ||||||
|           multiline |           multiline | ||||||
|           label={"Content"} |           label={'Content'} | ||||||
|           name="content" |           name="content" | ||||||
|           rows={4} |           rows={4} | ||||||
|         /> |         /> | ||||||
|         <Controller |         <Controller | ||||||
|           control={control} |           control={control} | ||||||
|           name={"category.id"} |           name={'category.id'} | ||||||
|           rules={{ required: "This field is required" }} |           rules={{required: 'This field is required'}} | ||||||
|           // eslint-disable-next-line |           // eslint-disable-next-line | ||||||
|           defaultValue={null as any} |           defaultValue={null as any} | ||||||
|           render={({ field }) => ( |           render={({field}) => ( | ||||||
|             <Autocomplete |             <Autocomplete | ||||||
|               {...categoryAutocompleteProps} |               {...categoryAutocompleteProps} | ||||||
|               {...field} |               {...field} | ||||||
|               onChange={(_, value) => { |               onChange={(_, value) => { | ||||||
|                 field.onChange(value.id); |                 field.onChange(value.id) | ||||||
|               }} |               }} | ||||||
|               getOptionLabel={(item) => { |               getOptionLabel={(item) => { | ||||||
|                 return ( |                 return ( | ||||||
|                   categoryAutocompleteProps?.options?.find((p) => { |                   categoryAutocompleteProps?.options?.find((p) => { | ||||||
|                     const itemId = |                     const itemId = typeof item === 'object' ? item?.id?.toString() : item?.toString() | ||||||
|                       typeof item === "object" |                     const pId = p?.id?.toString() | ||||||
|                         ? item?.id?.toString() |                     return itemId === pId | ||||||
|                         : item?.toString(); |                   })?.title ?? '' | ||||||
|                     const pId = p?.id?.toString(); |                 ) | ||||||
|                     return itemId === pId; |  | ||||||
|                   })?.title ?? "" |  | ||||||
|                 ); |  | ||||||
|               }} |               }} | ||||||
|               isOptionEqualToValue={(option, value) => { |               isOptionEqualToValue={(option, value) => { | ||||||
|                 const optionId = option?.id?.toString(); |                 const optionId = option?.id?.toString() | ||||||
|                 const valueId = |                 const valueId = typeof value === 'object' ? value?.id?.toString() : value?.toString() | ||||||
|                   typeof value === "object" |                 return value === undefined || optionId === valueId | ||||||
|                     ? value?.id?.toString() |  | ||||||
|                     : value?.toString(); |  | ||||||
|                 return value === undefined || optionId === valueId; |  | ||||||
|               }} |               }} | ||||||
|               renderInput={(params) => ( |               renderInput={(params) => <TextField {...params} label={'Category'} margin="normal" variant="outlined" error={!!(errors as any)?.category?.id} helperText={(errors as any)?.category?.id?.message} required />} | ||||||
|                 <TextField |  | ||||||
|                   {...params} |  | ||||||
|                   label={"Category"} |  | ||||||
|                   margin="normal" |  | ||||||
|                   variant="outlined" |  | ||||||
|                   error={!!(errors as any)?.category?.id} |  | ||||||
|                   helperText={(errors as any)?.category?.id?.message} |  | ||||||
|                   required |  | ||||||
|                 /> |  | ||||||
|               )} |  | ||||||
|             /> |             /> | ||||||
|           )} |           )} | ||||||
|         /> |         /> | ||||||
|         <Controller |         <Controller | ||||||
|           name="status" |           name="status" | ||||||
|           control={control} |           control={control} | ||||||
|           render={({ field }) => { |           render={({field}) => { | ||||||
|             return ( |             return ( | ||||||
|               <Select |               <Select {...field} value={field?.value || 'draft'} label={'Status'}> | ||||||
|                 {...field} |  | ||||||
|                 value={field?.value || "draft"} |  | ||||||
|                 label={"Status"} |  | ||||||
|               > |  | ||||||
|                 <MenuItem value="draft">Draft</MenuItem> |                 <MenuItem value="draft">Draft</MenuItem> | ||||||
|                 <MenuItem value="published">Published</MenuItem> |                 <MenuItem value="published">Published</MenuItem> | ||||||
|                 <MenuItem value="rejected">Rejected</MenuItem> |                 <MenuItem value="rejected">Rejected</MenuItem> | ||||||
|               </Select> |               </Select> | ||||||
|             ); |             ) | ||||||
|           }} |           }} | ||||||
|         /> |         /> | ||||||
|       </Box> |       </Box> | ||||||
|     </Edit> |     </Edit> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| export * from "./create"; | export * from './create' | ||||||
| export * from "./edit"; | export * from './edit' | ||||||
| export * from "./list"; | export * from './list' | ||||||
| export * from "./show"; | export * from './show' | ||||||
|   | |||||||
| @@ -1,124 +1,105 @@ | |||||||
| import { DataGrid, type GridColDef } from "@mui/x-data-grid"; | import {DataGrid, type GridColDef} from '@mui/x-data-grid' | ||||||
| import { useMany } from "@refinedev/core"; | import {useMany} from '@refinedev/core' | ||||||
| import { | import {DateField, DeleteButton, EditButton, List, ShowButton, useDataGrid} from '@refinedev/mui' | ||||||
|   DateField, | import {Typography} from '@mui/material' | ||||||
|   DeleteButton, | import React from 'react' | ||||||
|   EditButton, |  | ||||||
|   List, |  | ||||||
|   ShowButton, |  | ||||||
|   useDataGrid, |  | ||||||
| } from "@refinedev/mui"; |  | ||||||
| import { Typography } from "@mui/material"; |  | ||||||
| import React from "react"; |  | ||||||
|  |  | ||||||
| export const BlogPostList = () => { | export const BlogPostList = () => { | ||||||
|   const { dataGridProps } = useDataGrid({}); |   const {dataGridProps} = useDataGrid({}) | ||||||
|  |  | ||||||
|   const { data: categoryData, isLoading: categoryIsLoading } = useMany({ |   const {data: categoryData, isLoading: categoryIsLoading} = useMany({ | ||||||
|     resource: "categories", |     resource: 'categories', | ||||||
|     ids: |     ids: dataGridProps?.rows?.map((item: any) => item?.category?.id).filter(Boolean) ?? [], | ||||||
|       dataGridProps?.rows |  | ||||||
|         ?.map((item: any) => item?.category?.id) |  | ||||||
|         .filter(Boolean) ?? [], |  | ||||||
|     queryOptions: { |     queryOptions: { | ||||||
|       enabled: !!dataGridProps?.rows, |       enabled: !!dataGridProps?.rows, | ||||||
|     }, |     }, | ||||||
|   }); |   }) | ||||||
|  |  | ||||||
|   const columns = React.useMemo<GridColDef[]>( |   const columns = React.useMemo<GridColDef[]>( | ||||||
|     () => [ |     () => [ | ||||||
|       { |       { | ||||||
|         field: "id", |         field: 'id', | ||||||
|         headerName: "ID", |         headerName: 'ID', | ||||||
|         type: "number", |         type: 'number', | ||||||
|         minWidth: 50, |         minWidth: 50, | ||||||
|         display: "flex", |         display: 'flex', | ||||||
|         align: "left", |         align: 'left', | ||||||
|         headerAlign: "left", |         headerAlign: 'left', | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         field: "title", |         field: 'title', | ||||||
|         headerName: "Title", |         headerName: 'Title', | ||||||
|         minWidth: 200, |         minWidth: 200, | ||||||
|         display: "flex", |         display: 'flex', | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         field: "content", |         field: 'content', | ||||||
|         flex: 1, |         flex: 1, | ||||||
|         headerName: "Content", |         headerName: 'Content', | ||||||
|         minWidth: 250, |         minWidth: 250, | ||||||
|         display: "flex", |         display: 'flex', | ||||||
|         renderCell: function render({ value }) { |         renderCell: function render({value}) { | ||||||
|           if (!value) return "-"; |           if (!value) return '-' | ||||||
|           return ( |           return ( | ||||||
|             <Typography |             <Typography component="p" whiteSpace="pre" overflow="hidden" textOverflow="ellipsis"> | ||||||
|               component="p" |  | ||||||
|               whiteSpace="pre" |  | ||||||
|               overflow="hidden" |  | ||||||
|               textOverflow="ellipsis" |  | ||||||
|             > |  | ||||||
|               {value} |               {value} | ||||||
|             </Typography> |             </Typography> | ||||||
|           ); |           ) | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         field: "category", |         field: 'category', | ||||||
|         headerName: "Category", |         headerName: 'Category', | ||||||
|         minWidth: 160, |         minWidth: 160, | ||||||
|         display: "flex", |         display: 'flex', | ||||||
|         valueGetter: (_, row) => { |         valueGetter: (_, row) => { | ||||||
|           const value = row?.category; |           const value = row?.category | ||||||
|           return value; |           return value | ||||||
|         }, |         }, | ||||||
|         renderCell: function render({ value }) { |         renderCell: function render({value}) { | ||||||
|           return categoryIsLoading ? ( |           return categoryIsLoading ? <>Loading...</> : categoryData?.data?.find((item) => item.id === value?.id)?.title | ||||||
|             <>Loading...</> |  | ||||||
|           ) : ( |  | ||||||
|             categoryData?.data?.find((item) => item.id === value?.id)?.title |  | ||||||
|           ); |  | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         field: "status", |         field: 'status', | ||||||
|         headerName: "Status", |         headerName: 'Status', | ||||||
|         minWidth: 80, |         minWidth: 80, | ||||||
|         display: "flex", |         display: 'flex', | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         field: "createdAt", |         field: 'createdAt', | ||||||
|         headerName: "Created at", |         headerName: 'Created at', | ||||||
|         minWidth: 120, |         minWidth: 120, | ||||||
|         display: "flex", |         display: 'flex', | ||||||
|         renderCell: function render({ value }) { |         renderCell: function render({value}) { | ||||||
|           return <DateField value={value} />; |           return <DateField value={value} /> | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         field: "actions", |         field: 'actions', | ||||||
|         headerName: "Actions", |         headerName: 'Actions', | ||||||
|         align: "right", |         align: 'right', | ||||||
|         headerAlign: "right", |         headerAlign: 'right', | ||||||
|         minWidth: 120, |         minWidth: 120, | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         display: "flex", |         display: 'flex', | ||||||
|         renderCell: function render({ row }) { |         renderCell: function render({row}) { | ||||||
|           return ( |           return ( | ||||||
|             <> |             <> | ||||||
|               <EditButton hideText recordItemId={row.id} /> |               <EditButton hideText recordItemId={row.id} /> | ||||||
|               <ShowButton hideText recordItemId={row.id} /> |               <ShowButton hideText recordItemId={row.id} /> | ||||||
|               <DeleteButton hideText recordItemId={row.id} /> |               <DeleteButton hideText recordItemId={row.id} /> | ||||||
|             </> |             </> | ||||||
|           ); |           ) | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|     ], |     ], | ||||||
|     [categoryData, categoryIsLoading] |     [categoryData, categoryIsLoading], | ||||||
|   ); |   ) | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <List> |     <List> | ||||||
|       <DataGrid {...dataGridProps} columns={columns} /> |       <DataGrid {...dataGridProps} columns={columns} /> | ||||||
|     </List> |     </List> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,59 +1,53 @@ | |||||||
| import { Stack, Typography } from "@mui/material"; | import {Stack, Typography} from '@mui/material' | ||||||
| import { useOne, useShow } from "@refinedev/core"; | import {useOne, useShow} from '@refinedev/core' | ||||||
| import { | import {DateField, MarkdownField, NumberField, Show, TextFieldComponent as TextField} from '@refinedev/mui' | ||||||
|   DateField, |  | ||||||
|   MarkdownField, |  | ||||||
|   NumberField, |  | ||||||
|   Show, |  | ||||||
|   TextFieldComponent as TextField, |  | ||||||
| } from "@refinedev/mui"; |  | ||||||
|  |  | ||||||
| export const BlogPostShow = () => { | export const BlogPostShow = () => { | ||||||
|   const { query } = useShow({}); |   const {query} = useShow({}) | ||||||
|  |  | ||||||
|   const { data, isLoading } = query; |   const {data, isLoading} = query | ||||||
|  |  | ||||||
|   const record = data?.data; |   const record = data?.data | ||||||
|  |  | ||||||
|   const { data: categoryData, isLoading: categoryIsLoading } = useOne({ |   const {data: categoryData, isLoading: categoryIsLoading} = useOne({ | ||||||
|     resource: "categories", |     resource: 'categories', | ||||||
|     id: record?.category?.id || "", |     id: record?.category?.id || '', | ||||||
|     queryOptions: { |     queryOptions: { | ||||||
|       enabled: !!record, |       enabled: !!record, | ||||||
|     }, |     }, | ||||||
|   }); |   }) | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <Show isLoading={isLoading}> |     <Show isLoading={isLoading}> | ||||||
|       <Stack gap={1}> |       <Stack gap={1}> | ||||||
|         <Typography variant="body1" fontWeight="bold"> |         <Typography variant="body1" fontWeight="bold"> | ||||||
|           {"ID"} |           {'ID'} | ||||||
|         </Typography> |         </Typography> | ||||||
|         <TextField value={record?.id} /> |         <TextField value={record?.id} /> | ||||||
|  |  | ||||||
|         <Typography variant="body1" fontWeight="bold"> |         <Typography variant="body1" fontWeight="bold"> | ||||||
|           {"Title"} |           {'Title'} | ||||||
|         </Typography> |         </Typography> | ||||||
|         <TextField value={record?.title} /> |         <TextField value={record?.title} /> | ||||||
|  |  | ||||||
|         <Typography variant="body1" fontWeight="bold"> |         <Typography variant="body1" fontWeight="bold"> | ||||||
|           {"Content"} |           {'Content'} | ||||||
|         </Typography> |         </Typography> | ||||||
|         <MarkdownField value={record?.content} /> |         <MarkdownField value={record?.content} /> | ||||||
|  |  | ||||||
|         <Typography variant="body1" fontWeight="bold"> |         <Typography variant="body1" fontWeight="bold"> | ||||||
|           {"Category"} |           {'Category'} | ||||||
|         </Typography> |         </Typography> | ||||||
|         {categoryIsLoading ? <>Loading...</> : <>{categoryData?.data?.title}</>} |         {categoryIsLoading ? <>Loading...</> : <>{categoryData?.data?.title}</>} | ||||||
|         <Typography variant="body1" fontWeight="bold"> |         <Typography variant="body1" fontWeight="bold"> | ||||||
|           {"Status"} |           {'Status'} | ||||||
|         </Typography> |         </Typography> | ||||||
|         <TextField value={record?.status} /> |         <TextField value={record?.status} /> | ||||||
|         <Typography variant="body1" fontWeight="bold"> |         <Typography variant="body1" fontWeight="bold"> | ||||||
|           {"CreatedAt"} |           {'CreatedAt'} | ||||||
|         </Typography> |         </Typography> | ||||||
|         <DateField value={record?.createdAt} /> |         <DateField value={record?.createdAt} /> | ||||||
|       </Stack> |       </Stack> | ||||||
|     </Show> |     </Show> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,36 +1,32 @@ | |||||||
| import { Box, TextField } from "@mui/material"; | import {Box, TextField} from '@mui/material' | ||||||
| import { Create } from "@refinedev/mui"; | import {Create} from '@refinedev/mui' | ||||||
| import { useForm } from "@refinedev/react-hook-form"; | import {useForm} from '@refinedev/react-hook-form' | ||||||
|  |  | ||||||
| export const CategoryCreate = () => { | export const CategoryCreate = () => { | ||||||
|   const { |   const { | ||||||
|     saveButtonProps, |     saveButtonProps, | ||||||
|     refineCore: { formLoading }, |     refineCore: {formLoading}, | ||||||
|     register, |     register, | ||||||
|     formState: { errors }, |     formState: {errors}, | ||||||
|   } = useForm({}); |   } = useForm({}) | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <Create isLoading={formLoading} saveButtonProps={saveButtonProps}> |     <Create isLoading={formLoading} saveButtonProps={saveButtonProps}> | ||||||
|       <Box |       <Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off"> | ||||||
|         component="form" |  | ||||||
|         sx={{ display: "flex", flexDirection: "column" }} |  | ||||||
|         autoComplete="off" |  | ||||||
|       > |  | ||||||
|         <TextField |         <TextField | ||||||
|           {...register("title", { |           {...register('title', { | ||||||
|             required: "This field is required", |             required: 'This field is required', | ||||||
|           })} |           })} | ||||||
|           error={!!(errors as any)?.title} |           error={!!(errors as any)?.title} | ||||||
|           helperText={(errors as any)?.title?.message} |           helperText={(errors as any)?.title?.message} | ||||||
|           margin="normal" |           margin="normal" | ||||||
|           fullWidth |           fullWidth | ||||||
|           InputLabelProps={{ shrink: true }} |           InputLabelProps={{shrink: true}} | ||||||
|           type="text" |           type="text" | ||||||
|           label={"Title"} |           label={'Title'} | ||||||
|           name="title" |           name="title" | ||||||
|         /> |         /> | ||||||
|       </Box> |       </Box> | ||||||
|     </Create> |     </Create> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,35 +1,31 @@ | |||||||
| import { Box, TextField } from "@mui/material"; | import {Box, TextField} from '@mui/material' | ||||||
| import { Edit } from "@refinedev/mui"; | import {Edit} from '@refinedev/mui' | ||||||
| import { useForm } from "@refinedev/react-hook-form"; | import {useForm} from '@refinedev/react-hook-form' | ||||||
|  |  | ||||||
| export const CategoryEdit = () => { | export const CategoryEdit = () => { | ||||||
|   const { |   const { | ||||||
|     saveButtonProps, |     saveButtonProps, | ||||||
|     register, |     register, | ||||||
|     formState: { errors }, |     formState: {errors}, | ||||||
|   } = useForm({}); |   } = useForm({}) | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <Edit saveButtonProps={saveButtonProps}> |     <Edit saveButtonProps={saveButtonProps}> | ||||||
|       <Box |       <Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off"> | ||||||
|         component="form" |  | ||||||
|         sx={{ display: "flex", flexDirection: "column" }} |  | ||||||
|         autoComplete="off" |  | ||||||
|       > |  | ||||||
|         <TextField |         <TextField | ||||||
|           {...register("title", { |           {...register('title', { | ||||||
|             required: "This field is required", |             required: 'This field is required', | ||||||
|           })} |           })} | ||||||
|           error={!!(errors as any)?.title} |           error={!!(errors as any)?.title} | ||||||
|           helperText={(errors as any)?.title?.message} |           helperText={(errors as any)?.title?.message} | ||||||
|           margin="normal" |           margin="normal" | ||||||
|           fullWidth |           fullWidth | ||||||
|           InputLabelProps={{ shrink: true }} |           InputLabelProps={{shrink: true}} | ||||||
|           type="text" |           type="text" | ||||||
|           label={"Title"} |           label={'Title'} | ||||||
|           name="title" |           name="title" | ||||||
|         /> |         /> | ||||||
|       </Box> |       </Box> | ||||||
|     </Edit> |     </Edit> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| export * from "./create"; | export * from './create' | ||||||
| export * from "./edit"; | export * from './edit' | ||||||
| export * from "./list"; | export * from './list' | ||||||
| export * from "./show"; | export * from './show' | ||||||
|   | |||||||
| @@ -1,59 +1,53 @@ | |||||||
| import { DataGrid, type GridColDef } from "@mui/x-data-grid"; | import {DataGrid, type GridColDef} from '@mui/x-data-grid' | ||||||
| import { | import {DeleteButton, EditButton, List, ShowButton, useDataGrid} from '@refinedev/mui' | ||||||
|   DeleteButton, | import React from 'react' | ||||||
|   EditButton, |  | ||||||
|   List, |  | ||||||
|   ShowButton, |  | ||||||
|   useDataGrid, |  | ||||||
| } from "@refinedev/mui"; |  | ||||||
| import React from "react"; |  | ||||||
|  |  | ||||||
| export const CategoryList = () => { | export const CategoryList = () => { | ||||||
|   const { dataGridProps } = useDataGrid({}); |   const {dataGridProps} = useDataGrid({}) | ||||||
|  |  | ||||||
|   const columns = React.useMemo<GridColDef[]>( |   const columns = React.useMemo<GridColDef[]>( | ||||||
|     () => [ |     () => [ | ||||||
|       { |       { | ||||||
|         field: "id", |         field: 'id', | ||||||
|         headerName: "ID", |         headerName: 'ID', | ||||||
|         type: "number", |         type: 'number', | ||||||
|         minWidth: 50, |         minWidth: 50, | ||||||
|         display: "flex", |         display: 'flex', | ||||||
|         align: "left", |         align: 'left', | ||||||
|         headerAlign: "left", |         headerAlign: 'left', | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         field: "title", |         field: 'title', | ||||||
|         flex: 1, |         flex: 1, | ||||||
|         headerName: "Title", |         headerName: 'Title', | ||||||
|         minWidth: 200, |         minWidth: 200, | ||||||
|         display: "flex", |         display: 'flex', | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         field: "actions", |         field: 'actions', | ||||||
|         headerName: "Actions", |         headerName: 'Actions', | ||||||
|         align: "right", |         align: 'right', | ||||||
|         headerAlign: "right", |         headerAlign: 'right', | ||||||
|         minWidth: 120, |         minWidth: 120, | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         display: "flex", |         display: 'flex', | ||||||
|         renderCell: function render({ row }) { |         renderCell: function render({row}) { | ||||||
|           return ( |           return ( | ||||||
|             <> |             <> | ||||||
|               <EditButton hideText recordItemId={row.id} /> |               <EditButton hideText recordItemId={row.id} /> | ||||||
|               <ShowButton hideText recordItemId={row.id} /> |               <ShowButton hideText recordItemId={row.id} /> | ||||||
|               <DeleteButton hideText recordItemId={row.id} /> |               <DeleteButton hideText recordItemId={row.id} /> | ||||||
|             </> |             </> | ||||||
|           ); |           ) | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|     ], |     ], | ||||||
|     [] |     [], | ||||||
|   ); |   ) | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <List> |     <List> | ||||||
|       <DataGrid {...dataGridProps} columns={columns} /> |       <DataGrid {...dataGridProps} columns={columns} /> | ||||||
|     </List> |     </List> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,29 +1,25 @@ | |||||||
| import { Stack, Typography } from "@mui/material"; | import {Stack, Typography} from '@mui/material' | ||||||
| import { useShow } from "@refinedev/core"; | import {useShow} from '@refinedev/core' | ||||||
| import { | import {NumberField, Show, TextFieldComponent as TextField} from '@refinedev/mui' | ||||||
|   NumberField, |  | ||||||
|   Show, |  | ||||||
|   TextFieldComponent as TextField, |  | ||||||
| } from "@refinedev/mui"; |  | ||||||
|  |  | ||||||
| export const CategoryShow = () => { | export const CategoryShow = () => { | ||||||
|   const { query } = useShow({}); |   const {query} = useShow({}) | ||||||
|   const { data, isLoading } = query; |   const {data, isLoading} = query | ||||||
|  |  | ||||||
|   const record = data?.data; |   const record = data?.data | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <Show isLoading={isLoading}> |     <Show isLoading={isLoading}> | ||||||
|       <Stack gap={1}> |       <Stack gap={1}> | ||||||
|         <Typography variant="body1" fontWeight="bold"> |         <Typography variant="body1" fontWeight="bold"> | ||||||
|           {"ID"} |           {'ID'} | ||||||
|         </Typography> |         </Typography> | ||||||
|         <TextField value={record?.id} /> |         <TextField value={record?.id} /> | ||||||
|         <Typography variant="body1" fontWeight="bold"> |         <Typography variant="body1" fontWeight="bold"> | ||||||
|           {"Title"} |           {'Title'} | ||||||
|         </Typography> |         </Typography> | ||||||
|         <TextField value={record?.title} /> |         <TextField value={record?.title} /> | ||||||
|       </Stack> |       </Stack> | ||||||
|     </Show> |     </Show> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import { AuthPage } from "@refinedev/mui"; | import {AuthPage} from '@refinedev/mui' | ||||||
|  |  | ||||||
| export const ForgotPassword = () => { | export const ForgotPassword = () => { | ||||||
|   return <AuthPage type="forgotPassword" />; |   return <AuthPage type="forgotPassword" /> | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| import { AuthPage } from "@refinedev/mui"; | import {AuthPage} from '@refinedev/mui' | ||||||
|  |  | ||||||
| export const Login = () => { | export const Login = () => { | ||||||
|   return ( |   return ( | ||||||
|     <AuthPage |     <AuthPage | ||||||
|       type="login" |       type="login" | ||||||
|       formProps={{ |       formProps={{ | ||||||
|         defaultValues: { email: "demo@refine.dev", password: "demodemo" }, |         defaultValues: {email: 'demo@refine.dev', password: 'demodemo'}, | ||||||
|       }} |       }} | ||||||
|     /> |     /> | ||||||
|   ); |   ) | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import { AuthPage } from "@refinedev/mui"; | import {AuthPage} from '@refinedev/mui' | ||||||
|  |  | ||||||
| export const Register = () => { | export const Register = () => { | ||||||
|   return <AuthPage type="register" />; |   return <AuthPage type="register" /> | ||||||
| }; | } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import { defineConfig } from "vite"; | import {defineConfig} from 'vite' | ||||||
| import react from "@vitejs/plugin-react"; | import react from '@vitejs/plugin-react' | ||||||
|  |  | ||||||
| export default defineConfig({ | export default defineConfig({ | ||||||
|   plugins: [react()], |   plugins: [react()], | ||||||
| }); | }) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user