Merge branch 'feature/remove_tel_number' into 'develop'
complete role page with show/store/update and delete actions and remove tel number from login page and add it to user page and add prettier to format the code as code formatter See merge request witel-front-end/crm-app!45
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -31,7 +31,7 @@ yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env*
|
||||
.env
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
47
.idea/codeStyles/Project.xml
generated
Normal file
47
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,47 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<option name="LINE_SEPARATOR" value=" " />
|
||||
<HTMLCodeStyleSettings>
|
||||
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||
</HTMLCodeStyleSettings>
|
||||
<JSCodeStyleSettings version="0">
|
||||
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
|
||||
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||
</JSCodeStyleSettings>
|
||||
<TypeScriptCodeStyleSettings version="0">
|
||||
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
|
||||
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||
</TypeScriptCodeStyleSettings>
|
||||
<VueCodeStyleSettings>
|
||||
<option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
|
||||
<option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
|
||||
</VueCodeStyleSettings>
|
||||
<codeStyleSettings language="HTML">
|
||||
<option name="SOFT_MARGINS" value="120" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="JavaScript">
|
||||
<option name="SOFT_MARGINS" value="120" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="TypeScript">
|
||||
<option name="SOFT_MARGINS" value="120" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="Vue">
|
||||
<option name="SOFT_MARGINS" value="120" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="4" />
|
||||
<option name="TAB_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
12
.idea/crm-app.iml
generated
Normal file
12
.idea/crm-app.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
7
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
7
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="JSAnnotator" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||
</profile>
|
||||
</component>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/crm-app.iml" filepath="$PROJECT_DIR$/.idea/crm-app.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
12
.prettierrc
Normal file
12
.prettierrc
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"printWidth": 120,
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": false,
|
||||
"arrowParens": "always",
|
||||
"endOfLine": "crlf"
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
version: '3.8'
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
nextjs:
|
||||
@@ -13,5 +13,5 @@ services:
|
||||
ports:
|
||||
- "3000:3000"
|
||||
env_file:
|
||||
- .env.local
|
||||
- .env
|
||||
restart: unless-stopped
|
||||
@@ -7,7 +7,7 @@
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,html,css,scss}\""
|
||||
"format": "npx prettier . --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/cache": "^11.14.0",
|
||||
|
||||
4894
pnpm-lock.yaml
generated
4894
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
16
src/app/(withAuth)/(dashboardLayout)/dashboard/roles/page.js
Normal file
16
src/app/(withAuth)/(dashboardLayout)/dashboard/roles/page.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import RolesPage from "@/components/dashboard/Roles";
|
||||
import WithPermission from "@/core/middlewares/withPermission";
|
||||
|
||||
export const metadata = {
|
||||
title: "نقش ها",
|
||||
};
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<WithPermission permission_name={["manage_roles"]}>
|
||||
<RolesPage />
|
||||
</WithPermission>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -9,9 +9,7 @@ import { SWRConfig } from "swr";
|
||||
|
||||
const Layout = ({ children }) => {
|
||||
const { data: permissions } = usePermissions();
|
||||
const isCallWidgetEnabled = permissions?.some(
|
||||
(permission) => permission === "manage_calls",
|
||||
);
|
||||
const isCallWidgetEnabled = permissions?.some((permission) => permission === "manage_calls");
|
||||
|
||||
return (
|
||||
<SocketProvider>
|
||||
|
||||
@@ -18,10 +18,7 @@ export default function RootLayout({ children }) {
|
||||
<link rel="icon" href={favicon.src} type="image/png" sizes="any" />
|
||||
</head>
|
||||
<body style={{ height: "100vh", width: "100vw" }}>
|
||||
<AppRouterCacheProvider
|
||||
CacheProvider={Rtl}
|
||||
options={{ enableCssLayer: true }}
|
||||
>
|
||||
<AppRouterCacheProvider CacheProvider={Rtl} options={{ enableCssLayer: true }}>
|
||||
<AuthProvider>
|
||||
<TableSettingProvider>{children}</TableSettingProvider>
|
||||
</AuthProvider>
|
||||
|
||||
@@ -4,12 +4,7 @@ import SvgNotFound from "@/core/components/svgs/SvgNotFound";
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<Stack
|
||||
sx={{ height: "100%" }}
|
||||
justifyContent={"center"}
|
||||
alignItems={"center"}
|
||||
spacing={2}
|
||||
>
|
||||
<Stack sx={{ height: "100%" }} justifyContent={"center"} alignItems={"center"} spacing={2}>
|
||||
<Box>
|
||||
<SvgNotFound width={200} height={200} />
|
||||
</Box>
|
||||
|
||||
@@ -4,14 +4,10 @@
|
||||
font-weight: 900;
|
||||
src: url("../fonts/eot/IRANSansWeb(FaNum)_Black.eot");
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb(FaNum)_Black.eot?#iefix")
|
||||
format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum)_Black.woff2")
|
||||
format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/
|
||||
url("../fonts/woff/IRANSansWeb(FaNum)_Black.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url("../fonts/ttf/IRANSansWeb(FaNum)_Black.ttf") format("truetype");
|
||||
url("../fonts/eot/IRANSansWeb(FaNum)_Black.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum)_Black.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb(FaNum)_Black.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb(FaNum)_Black.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -20,14 +16,10 @@
|
||||
font-weight: bold;
|
||||
src: url("../fonts/eot/IRANSansWeb(FaNum)_Bold.eot");
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb(FaNum)_Bold.eot?#iefix")
|
||||
format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum)_Bold.woff2")
|
||||
format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/
|
||||
url("../fonts/woff/IRANSansWeb(FaNum)_Bold.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url("../fonts/ttf/IRANSansWeb(FaNum)_Bold.ttf") format("truetype");
|
||||
url("../fonts/eot/IRANSansWeb(FaNum)_Bold.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum)_Bold.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb(FaNum)_Bold.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb(FaNum)_Bold.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -36,14 +28,10 @@
|
||||
font-weight: 500;
|
||||
src: url("../fonts/eot/IRANSansWeb(FaNum)_Medium.eot");
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb(FaNum)_Medium.eot?#iefix")
|
||||
format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum)_Medium.woff2")
|
||||
format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/
|
||||
url("../fonts/woff/IRANSansWeb(FaNum)_Medium.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url("../fonts/ttf/IRANSansWeb(FaNum)_Medium.ttf") format("truetype");
|
||||
url("../fonts/eot/IRANSansWeb(FaNum)_Medium.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum)_Medium.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb(FaNum)_Medium.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb(FaNum)_Medium.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -52,14 +40,10 @@
|
||||
font-weight: 300;
|
||||
src: url("../fonts/eot/IRANSansWeb(FaNum)_Light.eot");
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb(FaNum)_Light.eot?#iefix")
|
||||
format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum)_Light.woff2")
|
||||
format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/
|
||||
url("../fonts/woff/IRANSansWeb(FaNum)_Light.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url("../fonts/ttf/IRANSansWeb(FaNum)_Light.ttf") format("truetype");
|
||||
url("../fonts/eot/IRANSansWeb(FaNum)_Light.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum)_Light.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb(FaNum)_Light.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb(FaNum)_Light.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -68,14 +52,10 @@
|
||||
font-weight: 200;
|
||||
src: url("../fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot");
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot?#iefix")
|
||||
format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum)_UltraLight.woff2")
|
||||
format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/
|
||||
url("../fonts/woff/IRANSansWeb(FaNum)_UltraLight.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url("../fonts/ttf/IRANSansWeb(FaNum)_UltraLight.ttf") format("truetype");
|
||||
url("../fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum)_UltraLight.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb(FaNum)_UltraLight.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb(FaNum)_UltraLight.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -84,13 +64,10 @@
|
||||
font-weight: normal;
|
||||
src: url("../fonts/eot/IRANSansWeb(FaNum).eot");
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb(FaNum).eot?#iefix")
|
||||
format("embedded-opentype"),
|
||||
url("../fonts/eot/IRANSansWeb(FaNum).eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb(FaNum).woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb(FaNum).woff")
|
||||
format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url("../fonts/ttf/IRANSansWeb(FaNum).ttf") format("truetype");
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb(FaNum).woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb(FaNum).ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -101,10 +78,8 @@
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb_Black.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb_Black.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb_Black.woff")
|
||||
format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url("../fonts/ttf/IRANSansWeb_Black.ttf") format("truetype");
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb_Black.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb_Black.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -115,10 +90,8 @@
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb_Bold.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb_Bold.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb_Bold.woff")
|
||||
format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb_Bold.ttf")
|
||||
format("truetype");
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb_Bold.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb_Bold.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -127,13 +100,10 @@
|
||||
font-weight: 500;
|
||||
src: url("../fonts/eot/IRANSansWeb_Medium.eot");
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb_Medium.eot?#iefix")
|
||||
format("embedded-opentype"),
|
||||
url("../fonts/eot/IRANSansWeb_Medium.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb_Medium.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb_Medium.woff")
|
||||
format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url("../fonts/ttf/IRANSansWeb_Medium.ttf") format("truetype");
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb_Medium.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb_Medium.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -144,10 +114,8 @@
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb_Light.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb_Light.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb_Light.woff")
|
||||
format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url("../fonts/ttf/IRANSansWeb_Light.ttf") format("truetype");
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb_Light.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb_Light.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -156,14 +124,10 @@
|
||||
font-weight: 200;
|
||||
src: url("../fonts/eot/IRANSansWeb_UltraLight.eot");
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb_UltraLight.eot?#iefix")
|
||||
format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb_UltraLight.woff2")
|
||||
format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/
|
||||
url("../fonts/woff/IRANSansWeb_UltraLight.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url("../fonts/ttf/IRANSansWeb_UltraLight.ttf") format("truetype");
|
||||
url("../fonts/eot/IRANSansWeb_UltraLight.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb_UltraLight.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb_UltraLight.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb_UltraLight.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -174,10 +138,8 @@
|
||||
src:
|
||||
url("../fonts/eot/IRANSansWeb.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff2/IRANSansWeb.woff2") format("woff2"),
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb.woff")
|
||||
format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb.ttf")
|
||||
format("truetype");
|
||||
/* FF39+,Chrome36+, Opera24+*/ url("../fonts/woff/IRANSansWeb.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/IRANSansWeb.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -188,8 +150,7 @@
|
||||
src:
|
||||
url("../fonts/eot/Parastoo.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff/Parastoo.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/Parastoo.ttf")
|
||||
format("truetype");
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/Parastoo.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -200,8 +161,7 @@
|
||||
src:
|
||||
url("../fonts/eot/Parastoo-Bold.eot?#iefix") format("embedded-opentype"),
|
||||
/* IE6-8 */ url("../fonts/woff/Parastoo-Bold.woff") format("woff"),
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/Parastoo-Bold.ttf")
|
||||
format("truetype");
|
||||
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/ url("../fonts/ttf/Parastoo-Bold.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
|
||||
@@ -5,21 +5,8 @@ import { GET_USER_LOGIN_ROUTE } from "@/core/utils/routes";
|
||||
import { useAuth } from "@/lib/contexts/auth";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import {
|
||||
Lock,
|
||||
Person,
|
||||
PhoneCallback,
|
||||
Visibility,
|
||||
VisibilityOff,
|
||||
} from "@mui/icons-material";
|
||||
import {
|
||||
Button,
|
||||
Container,
|
||||
IconButton,
|
||||
InputAdornment,
|
||||
Stack,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { Lock, Person, PhoneCallback, Visibility, VisibilityOff } from "@mui/icons-material";
|
||||
import { Button, Container, IconButton, InputAdornment, Stack, Typography } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { object, string } from "yup";
|
||||
@@ -31,13 +18,11 @@ const LoginForm = () => {
|
||||
const defaultValues = {
|
||||
username: "",
|
||||
password: "",
|
||||
telephone_id: "",
|
||||
};
|
||||
|
||||
const validationSchema = object({
|
||||
username: string().required("لطفا نام کاربری را وارد کنید!"),
|
||||
password: string().required("لطفا رمز عبور را وارد کنید!"),
|
||||
telephone_id: string().required("لطفا شماره تماس داخلی را وارد کنید!"),
|
||||
});
|
||||
|
||||
const {
|
||||
@@ -57,7 +42,6 @@ const LoginForm = () => {
|
||||
const formData = new FormData();
|
||||
formData.append("username", data.username);
|
||||
formData.append("password", data.password);
|
||||
formData.append("telephone_id", data.telephone_id);
|
||||
await requestServer(GET_USER_LOGIN_ROUTE, "post", {
|
||||
data: formData,
|
||||
});
|
||||
@@ -67,27 +51,10 @@ const LoginForm = () => {
|
||||
|
||||
return (
|
||||
<Container maxWidth="xs" sx={{ flex: 1 }}>
|
||||
<StyledForm
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
>
|
||||
<Stack
|
||||
sx={{ width: "100%", height: "100%" }}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
spacing={6}
|
||||
>
|
||||
<Stack
|
||||
sx={{ width: "100%", mb: 2 }}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<Typography
|
||||
variant="h4"
|
||||
color="primary"
|
||||
fontWeight={600}
|
||||
textAlign="center"
|
||||
>
|
||||
<StyledForm onSubmit={handleSubmit(onSubmit)} style={{ width: "100%", height: "100%" }}>
|
||||
<Stack sx={{ width: "100%", height: "100%" }} justifyContent="center" alignItems="center" spacing={6}>
|
||||
<Stack sx={{ width: "100%", mb: 2 }} justifyContent="center" alignItems="center">
|
||||
<Typography variant="h4" color="primary" fontWeight={600} textAlign="center">
|
||||
ورود به سامانه CRM
|
||||
</Typography>
|
||||
</Stack>
|
||||
@@ -132,11 +99,7 @@ const LoginForm = () => {
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<IconButton onClick={handleClickShowPassword}>
|
||||
{showPassword ? (
|
||||
<VisibilityOff />
|
||||
) : (
|
||||
<Visibility />
|
||||
)}
|
||||
{showPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
@@ -155,32 +118,6 @@ const LoginForm = () => {
|
||||
}}
|
||||
name={"password"}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<LtrTextField
|
||||
{...field}
|
||||
label="شماره تماس داخلی"
|
||||
variant="outlined"
|
||||
type="tel"
|
||||
slotProps={{
|
||||
input: {
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<PhoneCallback />
|
||||
</InputAdornment>
|
||||
),
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
error={!!error}
|
||||
helperText={!!error && error.message}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"telephone_id"}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<Button
|
||||
|
||||
90
src/components/dashboard/Roles/DataTable.jsx
Normal file
90
src/components/dashboard/Roles/DataTable.jsx
Normal file
@@ -0,0 +1,90 @@
|
||||
"use client";
|
||||
import DataTableWithAuth from "@/core/components/DataTableWithAuth";
|
||||
import { GET_ROLE_LIST } from "@/core/utils/routes";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import { useMemo } from "react";
|
||||
import Toolbar from "./Toolbar";
|
||||
import moment from "jalali-moment";
|
||||
import RowActions from "./RowAcctions";
|
||||
|
||||
const DataTable = () => {
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
{
|
||||
accessorKey: "id",
|
||||
header: "کد یکتا",
|
||||
id: "id",
|
||||
enableColumnFilter: true,
|
||||
datatype: "text",
|
||||
filterMode: "equals",
|
||||
sortDescFirst: false,
|
||||
columnFilterModeOptions: ["equals", "contains"],
|
||||
grow: false,
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
accessorKey: "name_fa",
|
||||
header: "نام",
|
||||
id: "name_fa",
|
||||
enableColumnFilter: true,
|
||||
datatype: "text",
|
||||
filterMode: "equals",
|
||||
sortDescFirst: false,
|
||||
columnFilterModeOptions: ["equals", "contains"],
|
||||
grow: false,
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
accessorKey: "created_at",
|
||||
header: "تاریخ ساخت",
|
||||
id: "created_at",
|
||||
enableColumnFilter: false,
|
||||
datatype: "date",
|
||||
filterMode: "equals",
|
||||
grow: false,
|
||||
size: 100,
|
||||
Cell: ({ renderedCellValue }) => (
|
||||
<Typography variant="body2">
|
||||
{renderedCellValue ? moment(renderedCellValue).locale("fa").format("HH:mm | YYYY/MM/DD") : "-"}
|
||||
</Typography>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "updated_at",
|
||||
header: "تاریخ آخرین بروزرسانی",
|
||||
id: "updated_at",
|
||||
enableColumnFilter: false,
|
||||
datatype: "date",
|
||||
filterMode: "equals",
|
||||
grow: false,
|
||||
size: 100,
|
||||
Cell: ({ renderedCellValue }) => (
|
||||
<Typography variant="body2">
|
||||
{renderedCellValue ? moment(renderedCellValue).locale("fa").format("HH:mm | YYYY/MM/DD") : "-"}
|
||||
</Typography>
|
||||
),
|
||||
},
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ p: 1, border: 1, borderColor: "divider", borderRadius: 1 }}>
|
||||
<DataTableWithAuth
|
||||
need_filter={true}
|
||||
columns={columns}
|
||||
sorting={[{ id: "id", desc: true }]}
|
||||
table_url={GET_ROLE_LIST}
|
||||
page_name={"rolesPage"}
|
||||
table_name={"rolesList"}
|
||||
TableToolbar={Toolbar}
|
||||
enableRowActions
|
||||
positionActionsColumn={"last"}
|
||||
RowActions={RowActions}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default DataTable;
|
||||
@@ -0,0 +1,39 @@
|
||||
import { DELETE_ROLE } from "@/core/utils/routes";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { Button, DialogActions, DialogContent, Stack, Typography } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
|
||||
const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => {
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const requestServer = useRequest({ notificationSuccess: true });
|
||||
const handleClick = async () => {
|
||||
setSubmitting(true);
|
||||
try {
|
||||
await requestServer(`${DELETE_ROLE}/${rowId}`, "delete");
|
||||
mutate();
|
||||
setOpenDeleteDialog(false);
|
||||
} catch (error) {
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<DialogContent>
|
||||
<Stack alignItems="center" spacing={2}>
|
||||
<Typography mt={2}>آیا از حذف کاربر اطمینان دارید؟</Typography>
|
||||
</Stack>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ justifyContent: "center", paddingBottom: 2, width: "100%" }}>
|
||||
<Button onClick={() => setOpenDeleteDialog(false)} variant="outlined" color="secondary">
|
||||
خیر !
|
||||
</Button>
|
||||
<Button onClick={handleClick} variant="contained" color="error" disabled={submitting}>
|
||||
{submitting ? "درحال حذف..." : "بله اطمینان دارم"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteContent;
|
||||
32
src/components/dashboard/Roles/RowAcctions/Delete/index.jsx
Normal file
32
src/components/dashboard/Roles/RowAcctions/Delete/index.jsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import DeleteContent from "./DeleteContent";
|
||||
const Delete = ({ rowId, mutate }) => {
|
||||
const [openDeleteDialog, setOpenDeleteDialog] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title="حذف">
|
||||
<IconButton color="error" onClick={() => setOpenDeleteDialog(true)}>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Dialog
|
||||
open={openDeleteDialog}
|
||||
onClose={() => setOpenDeleteDialog(false)}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
|
||||
},
|
||||
}}
|
||||
dir="rtl"
|
||||
maxWidth={"md"}
|
||||
>
|
||||
<DialogTitle>حذف</DialogTitle>
|
||||
<DeleteContent rowId={rowId} mutate={mutate} setOpenDeleteDialog={setOpenDeleteDialog} />
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default Delete;
|
||||
186
src/components/dashboard/Roles/RowAcctions/Edit/Form/index.jsx
Normal file
186
src/components/dashboard/Roles/RowAcctions/Edit/Form/index.jsx
Normal file
@@ -0,0 +1,186 @@
|
||||
import LtrTextField from "@/core/components/LtrTextField";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import { CREATE_ROLE } from "@/core/utils/routes";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
Chip,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
Divider,
|
||||
FormControlLabel,
|
||||
FormHelperText,
|
||||
Grid,
|
||||
Skeleton,
|
||||
Stack,
|
||||
} from "@mui/material";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { array, object, string } from "yup";
|
||||
import usePermissionsList from "@/lib/hooks/usePermissionsList";
|
||||
|
||||
const validationSchema = object().shape({
|
||||
name: string().required("نام فارسی نقش را وارد کنید"),
|
||||
name_fa: string().required("نام انگلیسی نقش را وارد کنید"),
|
||||
permissions: array().min(1, "حداقل یک دسترسی را انتخاب نمایید")
|
||||
});
|
||||
|
||||
const UpdateRoleForm = ({ values, setOpen, mutate }) => {
|
||||
const requestServer = useRequest({ notificationSuccess: true });
|
||||
const { permissions, loadingPermissions } = usePermissionsList();
|
||||
|
||||
const defaultValues = {
|
||||
name: values.name,
|
||||
name_fa: values.name_fa,
|
||||
permissions: values.permissions?.map(p => p.id) || []
|
||||
};
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { isSubmitting, errors },
|
||||
} = useForm({ defaultValues, resolver: yupResolver(validationSchema) });
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
try {
|
||||
await requestServer(`${CREATE_ROLE}/${values.id}`, "post", {
|
||||
data: {
|
||||
permissions: data.permissions,
|
||||
name: data.name,
|
||||
name_fa: data.name_fa,
|
||||
},
|
||||
});
|
||||
setOpen(false);
|
||||
mutate();
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DialogContent dividers>
|
||||
<Divider sx={{ mb: 3 }}>
|
||||
<Chip color="primary" variant="outlined" label="کاربر جدید" />
|
||||
</Divider>
|
||||
<StyledForm
|
||||
id="UpdateRoleForm"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
>
|
||||
<Stack spacing={2}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<LtrTextField
|
||||
{...field}
|
||||
label="نام انگلیسی نقش"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
error={!!error}
|
||||
helperText={!!error && error.message}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"name"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<LtrTextField
|
||||
{...field}
|
||||
label="نام فارسی نقش"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
error={!!error}
|
||||
helperText={!!error && error.message}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"name_fa"}
|
||||
/>
|
||||
</Grid>
|
||||
<Box sx={{width: "100%"}}>
|
||||
<Divider>
|
||||
<Chip label="سطوح دسترسی" size="medium" />
|
||||
</Divider>
|
||||
</Box>
|
||||
<Grid container spacing={1} sx={{width: "100%"}}>
|
||||
{!loadingPermissions ? (
|
||||
<Controller
|
||||
control={control}
|
||||
name="permissions"
|
||||
render={({ field, fieldState: {error} }) => (
|
||||
<>
|
||||
{permissions.map((permission) => (
|
||||
<Grid key={permission.id} size={{ xs: 12, md: 4 }}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
value={permission.id}
|
||||
checked={field.value.includes(permission.id)}
|
||||
onChange={(e) => {
|
||||
const value = parseInt(e.target.value, 10);
|
||||
if (e.target.checked) {
|
||||
field.onChange([...field.value, value]);
|
||||
} else {
|
||||
field.onChange(field.value.filter((id) => id !== value));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={permission.name_fa}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
<FormHelperText sx={{color: "error.main"}}>{!!error && error.message}</FormHelperText>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<Grid container spacing={2} width="100%">
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Stack>
|
||||
</StyledForm>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="large"
|
||||
onClick={() => setOpen(false)}
|
||||
>
|
||||
بستن
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
form="UpdateRoleForm"
|
||||
size="large"
|
||||
autoFocus
|
||||
variant="contained"
|
||||
>
|
||||
{isSubmitting ? "در حال ویرایش کاربر..." : "ویرایش کاربر"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UpdateRoleForm;
|
||||
27
src/components/dashboard/Roles/RowAcctions/Edit/index.jsx
Normal file
27
src/components/dashboard/Roles/RowAcctions/Edit/index.jsx
Normal file
@@ -0,0 +1,27 @@
|
||||
"use client";
|
||||
import { Edit } from "@mui/icons-material";
|
||||
import { Dialog, IconButton, Tooltip } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import UpdateUserForm from "./Form";
|
||||
|
||||
const UpdateUser = ({ values, mutate }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleOpen = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title="ویرایش">
|
||||
<IconButton onClick={handleOpen}>
|
||||
<Edit />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Dialog maxWidth="sm" fullWidth={true} open={open}>
|
||||
<UpdateUserForm open={open} setOpen={setOpen} mutate={mutate} values={values} />
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default UpdateUser;
|
||||
12
src/components/dashboard/Roles/RowAcctions/index.jsx
Normal file
12
src/components/dashboard/Roles/RowAcctions/index.jsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Box } from "@mui/material";
|
||||
import Delete from "./Delete";
|
||||
import UpdateUser from "./Edit";
|
||||
const RowActions = ({ row, mutate }) => {
|
||||
return (
|
||||
<Box sx={{ display: "flex", gap: 1, alignItems: "center" }}>
|
||||
<Delete rowId={row.original.id} mutate={mutate} />
|
||||
<UpdateUser values={row.original} mutate={mutate} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
export default RowActions;
|
||||
184
src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx
Normal file
184
src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx
Normal file
@@ -0,0 +1,184 @@
|
||||
import LtrTextField from "@/core/components/LtrTextField";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
Chip,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
Divider,
|
||||
FormControlLabel, FormHelperText,
|
||||
Grid, Skeleton,
|
||||
Stack,
|
||||
} from "@mui/material";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { array, object, string } from "yup";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { CREATE_ROLE } from "@/core/utils/routes";
|
||||
import usePermissionsList from "@/lib/hooks/usePermissionsList";
|
||||
|
||||
const defaultValues = {
|
||||
name: "",
|
||||
name_fa: "",
|
||||
permissions: []
|
||||
};
|
||||
|
||||
const validationSchema = object().shape({
|
||||
name: string().required("نام فارسی نقش را وارد کنید"),
|
||||
name_fa: string().required("نام انگلیسی نقش را وارد کنید"),
|
||||
permissions: array().min(1, "حداقل یک دسترسی را انتخاب نمایید")
|
||||
});
|
||||
|
||||
const CreateRoleForm = ({ setOpen, mutate }) => {
|
||||
const requestServer = useRequest({ notificationSuccess: true });
|
||||
const { permissions, loadingPermissions } = usePermissionsList();
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { isSubmitting, errors },
|
||||
} = useForm({ defaultValues, resolver: yupResolver(validationSchema) });
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
try {
|
||||
await requestServer(CREATE_ROLE, "post", {
|
||||
data: {
|
||||
permissions: data.permissions,
|
||||
name: data.name,
|
||||
name_fa: data.name_fa,
|
||||
},
|
||||
});
|
||||
setOpen(false);
|
||||
mutate();
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DialogContent dividers>
|
||||
<Divider sx={{ mb: 3 }}>
|
||||
<Chip color="primary" variant="outlined" label="نقش جدید" />
|
||||
</Divider>
|
||||
<StyledForm
|
||||
id="createRoleForm"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
>
|
||||
<Stack spacing={2}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<LtrTextField
|
||||
{...field}
|
||||
label="نام انگلیسی نقش"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
error={!!error}
|
||||
helperText={!!error && error.message}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"name"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<LtrTextField
|
||||
{...field}
|
||||
label="نام فارسی نقش"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
error={!!error}
|
||||
helperText={!!error && error.message}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"name_fa"}
|
||||
/>
|
||||
</Grid>
|
||||
<Box sx={{width: "100%"}}>
|
||||
<Divider>
|
||||
<Chip label="سطوح دسترسی" size="medium" />
|
||||
</Divider>
|
||||
</Box>
|
||||
<Grid container spacing={1} sx={{width: "100%"}}>
|
||||
{!loadingPermissions ? (
|
||||
<Controller
|
||||
control={control}
|
||||
name="permissions"
|
||||
render={({ field, fieldState: {error} }) => (
|
||||
<>
|
||||
{permissions.map((permission) => (
|
||||
<Grid key={permission.id} size={{ xs: 12, md: 4 }}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
value={permission.id}
|
||||
checked={field.value.includes(permission.id)}
|
||||
onChange={(e) => {
|
||||
const value = parseInt(e.target.value, 10);
|
||||
if (e.target.checked) {
|
||||
field.onChange([...field.value, value]);
|
||||
} else {
|
||||
field.onChange(field.value.filter((id) => id !== value));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={permission.name_fa}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
<FormHelperText sx={{color: "error.main"}}>{!!error && error.message}</FormHelperText>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<Grid container spacing={2} width="100%">
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
<Grid size={{ xs: 12, md: 4 }}><Skeleton animation="wave" /></Grid>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Stack>
|
||||
</StyledForm>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="large"
|
||||
onClick={() => setOpen(false)}
|
||||
>
|
||||
بستن
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
form="createRoleForm"
|
||||
size="large"
|
||||
autoFocus
|
||||
variant="contained"
|
||||
>
|
||||
{isSubmitting ? "در حال ثبت نقش جدید..." : "ثبت نقش جدید"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateRoleForm;
|
||||
39
src/components/dashboard/Roles/Toolbar/Create/index.jsx
Normal file
39
src/components/dashboard/Roles/Toolbar/Create/index.jsx
Normal file
@@ -0,0 +1,39 @@
|
||||
"use client";
|
||||
import { AddCircle } from "@mui/icons-material";
|
||||
import { Button, Dialog, IconButton, useMediaQuery, useTheme } from "@mui/material";
|
||||
import CreateRoleForm from "./Form";
|
||||
import { useState } from "react";
|
||||
|
||||
const CreateRole = ({ mutate }) => {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleOpen = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{isMobile ? (
|
||||
<IconButton aria-label="نقش جدید" color="primary" onClick={handleOpen}>
|
||||
<AddCircle sx={{ fontSize: "25px" }} />
|
||||
</IconButton>
|
||||
) : (
|
||||
<Button
|
||||
size={"small"}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<AddCircle />}
|
||||
onClick={handleOpen}
|
||||
>
|
||||
نقش جدید
|
||||
</Button>
|
||||
)}
|
||||
<Dialog maxWidth="sm" fullWidth={true} open={open}>
|
||||
<CreateRoleForm open={open} setOpen={setOpen} mutate={mutate} />
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default CreateRole;
|
||||
10
src/components/dashboard/Roles/Toolbar/index.jsx
Normal file
10
src/components/dashboard/Roles/Toolbar/index.jsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import CreateRole from "./Create";
|
||||
|
||||
const Toolbar = ({ mutate }) => {
|
||||
return (
|
||||
<>
|
||||
<CreateRole mutate={mutate} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default Toolbar;
|
||||
14
src/components/dashboard/Roles/index.jsx
Normal file
14
src/components/dashboard/Roles/index.jsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import PageTitle from "@/core/components/PageTitle";
|
||||
import { Stack } from "@mui/material";
|
||||
import DataTable from "./DataTable";
|
||||
|
||||
const RolesPage = () => {
|
||||
return (
|
||||
<Stack spacing={1}>
|
||||
<PageTitle title={"نقش ها"} />
|
||||
<DataTable />
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default RolesPage;
|
||||
@@ -73,8 +73,7 @@ const DataTable = () => {
|
||||
grow: false,
|
||||
size: 130,
|
||||
ColumnSelectComponent: (props) => {
|
||||
const { provinces, errorProvinces, loadingProvinces } =
|
||||
useProvinces();
|
||||
const { provinces, errorProvinces, loadingProvinces } = useProvinces();
|
||||
const getColumnSelectOptions = useMemo(() => {
|
||||
if (loadingProvinces) {
|
||||
return [{ value: "loading", label: "در حال بارگذاری..." }];
|
||||
@@ -93,9 +92,7 @@ const DataTable = () => {
|
||||
return (
|
||||
<CustomSelectByDependency
|
||||
{...props}
|
||||
value={
|
||||
loadingProvinces ? "loading" : props.filterParameters.value
|
||||
}
|
||||
value={loadingProvinces ? "loading" : props.filterParameters.value}
|
||||
columnSelectOption={getColumnSelectOptions}
|
||||
/>
|
||||
);
|
||||
@@ -187,12 +184,10 @@ const DataTable = () => {
|
||||
enableColumnFilter: false,
|
||||
grow: false,
|
||||
size: 100,
|
||||
Cell: ({ renderedCellValue }) => (
|
||||
<>{renderedCellValue == "male" ? "آقا" : "خانم"}</>
|
||||
),
|
||||
Cell: ({ renderedCellValue }) => <>{renderedCellValue == "male" ? "آقا" : "خانم"}</>,
|
||||
},
|
||||
],
|
||||
[],
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import { DELETE_USER } from "@/core/utils/routes";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import {
|
||||
Button,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
Stack,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { Button, DialogActions, DialogContent, Stack, Typography } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
|
||||
const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => {
|
||||
@@ -30,22 +24,11 @@ const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => {
|
||||
<Typography mt={2}>آیا از حذف کاربر اطمینان دارید؟</Typography>
|
||||
</Stack>
|
||||
</DialogContent>
|
||||
<DialogActions
|
||||
sx={{ justifyContent: "center", paddingBottom: 2, width: "100%" }}
|
||||
>
|
||||
<Button
|
||||
onClick={() => setOpenDeleteDialog(false)}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
<DialogActions sx={{ justifyContent: "center", paddingBottom: 2, width: "100%" }}>
|
||||
<Button onClick={() => setOpenDeleteDialog(false)} variant="outlined" color="secondary">
|
||||
خیر !
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleClick}
|
||||
variant="contained"
|
||||
color="error"
|
||||
disabled={submitting}
|
||||
>
|
||||
<Button onClick={handleClick} variant="contained" color="error" disabled={submitting}>
|
||||
{submitting ? "درحال حذف..." : "بله اطمینان دارم"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
@@ -17,19 +17,14 @@ const Delete = ({ rowId, mutate }) => {
|
||||
onClose={() => setOpenDeleteDialog(false)}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
boxShadow:
|
||||
"rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
|
||||
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
|
||||
},
|
||||
}}
|
||||
dir="rtl"
|
||||
maxWidth={"md"}
|
||||
>
|
||||
<DialogTitle>حذف</DialogTitle>
|
||||
<DeleteContent
|
||||
rowId={rowId}
|
||||
mutate={mutate}
|
||||
setOpenDeleteDialog={setOpenDeleteDialog}
|
||||
/>
|
||||
<DeleteContent rowId={rowId} mutate={mutate} setOpenDeleteDialog={setOpenDeleteDialog} />
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -27,25 +27,20 @@ import { Controller, useForm } from "react-hook-form";
|
||||
import { object, string } from "yup";
|
||||
|
||||
const validationSchema = object().shape({
|
||||
full_name: string().required("نام و نام خانوادگی خود را وارد کنید"),
|
||||
username: string().required("نام کاربری خود را وارد کنید"),
|
||||
full_name: string().required("نام و نام خانوادگی را وارد کنید"),
|
||||
username: string().required("نام کاربری را وارد کنید"),
|
||||
phone_number: string()
|
||||
.matches(/^09\d{9}$/, "شماره همراه باید با 09 شروع شود و 11 رقم باشد.")
|
||||
.required("شماره همراه خود را وارد کنید"),
|
||||
gender: string().required("جنسیت خود را وارد کنید"),
|
||||
.required("شماره همراه را وارد کنید"),
|
||||
gender: string().required("جنسیت را وارد کنید"),
|
||||
national_id: string()
|
||||
.test(
|
||||
"max",
|
||||
"کد ملی باید شامل 10 رقم باشد",
|
||||
(value) => value.toString().length === 10,
|
||||
)
|
||||
.test("validation", "کد ملی صحیح نمی باشد", (value) =>
|
||||
validateNationalCode(value),
|
||||
)
|
||||
.required("کد ملی خود را وارد کنید"),
|
||||
position: string().required("سمت خود را وارد کنید"),
|
||||
province_id: string().required("استان خود را وارد کنید"),
|
||||
role_id: string().required("نقش خود را وارد کنید"),
|
||||
.test("max", "کد ملی باید شامل 10 رقم باشد", (value) => value.toString().length === 10)
|
||||
.test("validation", "کد ملی صحیح نمی باشد", (value) => validateNationalCode(value))
|
||||
.required("کد ملی را وارد کنید"),
|
||||
position: string().required("سمت را وارد کنید"),
|
||||
province_id: string().required("استان را وارد کنید"),
|
||||
role_id: string().required("نقش را وارد کنید"),
|
||||
telephone_id: string().required("شماره تماس داخلی را وارد کنید")
|
||||
});
|
||||
|
||||
const UpdateUserForm = ({ values, setOpen, mutate }) => {
|
||||
@@ -62,6 +57,7 @@ const UpdateUserForm = ({ values, setOpen, mutate }) => {
|
||||
phone_number: values.phone_number,
|
||||
province_id: values.province_id,
|
||||
role_id: values.roles[0].id,
|
||||
telephone_id: values.telephone_id
|
||||
};
|
||||
|
||||
const provinceSelectOptions = useMemo(() => {
|
||||
@@ -218,12 +214,12 @@ const UpdateUserForm = ({ values, setOpen, mutate }) => {
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<FormControl fullWidth error={!!error}>
|
||||
<InputLabel id={`label-phone-number`} shrink>
|
||||
<InputLabel id={`label-gender`} shrink>
|
||||
جنسیت
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId={`label-phone-number`}
|
||||
id={"phone-number"}
|
||||
labelId={`label-gender`}
|
||||
id={"gender"}
|
||||
name={`gender`}
|
||||
value={field.value}
|
||||
input={<OutlinedInput label={"جنسیت"} />}
|
||||
@@ -337,6 +333,25 @@ const UpdateUserForm = ({ values, setOpen, mutate }) => {
|
||||
name={"role_id"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<LtrTextField
|
||||
{...field}
|
||||
label="شماره تماس داخلی"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
type="tel"
|
||||
error={!!error}
|
||||
helperText={!!error && error.message}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"telephone_id"}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Stack>
|
||||
</StyledForm>
|
||||
|
||||
@@ -19,12 +19,7 @@ const UpdateUser = ({ values, mutate }) => {
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Dialog maxWidth="sm" fullWidth={true} open={open}>
|
||||
<UpdateUserForm
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
mutate={mutate}
|
||||
values={values}
|
||||
/>
|
||||
<UpdateUserForm open={open} setOpen={setOpen} mutate={mutate} values={values} />
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -6,11 +6,7 @@ const OnlineCell = ({ user_id }) => {
|
||||
const { clientsOnline } = useSocket();
|
||||
return (
|
||||
<Stack alignItems={"center"}>
|
||||
{clientsOnline.some((co) => co.user_id == user_id) ? (
|
||||
<Power color="success" />
|
||||
) : (
|
||||
<PowerOff color="error" />
|
||||
)}
|
||||
{clientsOnline.some((co) => co.user_id == user_id) ? <Power color="success" /> : <PowerOff color="error" />}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,9 +3,7 @@ import { Stack } from "@mui/material";
|
||||
|
||||
const TelephoneId = ({ user_id }) => {
|
||||
const { clientsOnline } = useSocket();
|
||||
const telephone_id = clientsOnline.find(
|
||||
(co) => co.user_id == user_id,
|
||||
)?.telephone_id;
|
||||
const telephone_id = clientsOnline.find((co) => co.user_id == user_id)?.telephone_id;
|
||||
return <Stack alignItems={"center"}>{telephone_id}</Stack>;
|
||||
};
|
||||
export default TelephoneId;
|
||||
|
||||
@@ -39,34 +39,27 @@ const defaultValues = {
|
||||
province_id: "",
|
||||
password: "",
|
||||
role_id: "",
|
||||
telephone_id: "",
|
||||
};
|
||||
|
||||
const validationSchema = object().shape({
|
||||
full_name: string().required("نام و نام خانوادگی خود را وارد کنید"),
|
||||
username: string().required("نام کاربری خود را وارد کنید"),
|
||||
full_name: string().required("نام و نام خانوادگی را وارد کنید"),
|
||||
username: string().required("نام کاربری را وارد کنید"),
|
||||
phone_number: string()
|
||||
.matches(/^09\d{9}$/, "شماره همراه باید با 09 شروع شود و 11 رقم باشد.")
|
||||
.required("شماره همراه خود را وارد کنید"),
|
||||
gender: string().required("جنسیت خود را وارد کنید"),
|
||||
.required("شماره همراه را وارد کنید"),
|
||||
gender: string().required("جنسیت را وارد کنید"),
|
||||
national_id: string()
|
||||
.test(
|
||||
"max",
|
||||
"کد ملی باید شامل 10 رقم باشد",
|
||||
(value) => value.toString().length === 10,
|
||||
)
|
||||
.test("validation", "کد ملی صحیح نمی باشد", (value) =>
|
||||
validateNationalCode(value),
|
||||
)
|
||||
.required("کد ملی خود را وارد کنید"),
|
||||
.test("max", "کد ملی باید شامل 10 رقم باشد", (value) => value.toString().length === 10)
|
||||
.test("validation", "کد ملی صحیح نمی باشد", (value) => validateNationalCode(value))
|
||||
.required("کد ملی را وارد کنید"),
|
||||
password: string()
|
||||
.required("رمز عبور خود را وارد کنید")
|
||||
.matches(
|
||||
/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/,
|
||||
"رمز عبور باید حداقل 8 کاراکتر و متشکل از عدد، حرف یا سمبل باشد",
|
||||
),
|
||||
position: string().required("سمت خود را وارد کنید"),
|
||||
province_id: string().required("استان خود را وارد کنید"),
|
||||
role_id: string().required("نقش خود را وارد کنید"),
|
||||
.required("رمز عبور را وارد کنید")
|
||||
.matches(/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/, "رمز عبور باید حداقل 8 کاراکتر و متشکل از عدد، حرف یا سمبل باشد"),
|
||||
position: string().required("سمت را وارد کنید"),
|
||||
province_id: string().required("استان را وارد کنید"),
|
||||
role_id: string().required("نقش را وارد کنید"),
|
||||
telephone_id: string().required("شماره تماس داخلی را وارد کنید"),
|
||||
});
|
||||
|
||||
const CreateUserForm = ({ setOpen, mutate }) => {
|
||||
@@ -175,11 +168,7 @@ const CreateUserForm = ({ setOpen, mutate }) => {
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<IconButton onClick={handleClickShowPassword}>
|
||||
{showPassword ? (
|
||||
<VisibilityOff />
|
||||
) : (
|
||||
<Visibility />
|
||||
)}
|
||||
{showPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
@@ -265,12 +254,12 @@ const CreateUserForm = ({ setOpen, mutate }) => {
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<FormControl fullWidth error={!!error}>
|
||||
<InputLabel id={`label-phone-number`} shrink>
|
||||
<InputLabel id={`label-gender`} shrink>
|
||||
جنسیت
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId={`label-phone-number`}
|
||||
id={"phone-number"}
|
||||
labelId={`label-gender`}
|
||||
id={"gender"}
|
||||
name={`gender`}
|
||||
value={field.value}
|
||||
input={<OutlinedInput label={"جنسیت"} />}
|
||||
@@ -384,6 +373,25 @@ const CreateUserForm = ({ setOpen, mutate }) => {
|
||||
name={"role_id"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<LtrTextField
|
||||
{...field}
|
||||
label="شماره تماس داخلی"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
type="tel"
|
||||
error={!!error}
|
||||
helperText={!!error && error.message}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"telephone_id"}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Stack>
|
||||
</StyledForm>
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
"use client";
|
||||
import { AddCircle } from "@mui/icons-material";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
IconButton,
|
||||
useMediaQuery,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { Button, Dialog, IconButton, useMediaQuery, useTheme } from "@mui/material";
|
||||
import CreateUserForm from "./Form";
|
||||
import { useState } from "react";
|
||||
|
||||
@@ -22,11 +16,7 @@ const CreateUser = ({ mutate }) => {
|
||||
return (
|
||||
<>
|
||||
{isMobile ? (
|
||||
<IconButton
|
||||
aria-label="کاربر جدید"
|
||||
color="primary"
|
||||
onClick={handleOpen}
|
||||
>
|
||||
<IconButton aria-label="کاربر جدید" color="primary" onClick={handleOpen}>
|
||||
<AddCircle sx={{ fontSize: "25px" }} />
|
||||
</IconButton>
|
||||
) : (
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Stack } from "@mui/material";
|
||||
|
||||
const OnlineUsersReport = () => {
|
||||
const { clientsOnline } = useSocket();
|
||||
return (
|
||||
<Stack>
|
||||
clientsOnline: {clientsOnline.length}
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
return <Stack>clientsOnline: {clientsOnline.length}</Stack>;
|
||||
};
|
||||
export default OnlineUsersReport;
|
||||
@@ -1,4 +1,4 @@
|
||||
"use client"
|
||||
"use client";
|
||||
import { Stack } from "@mui/material";
|
||||
import OnlineUsersReport from "./OnlineUsersReport";
|
||||
|
||||
@@ -7,6 +7,6 @@ const DashboardPage = () => {
|
||||
<Stack>
|
||||
<OnlineUsersReport />
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
export default DashboardPage;
|
||||
@@ -1,13 +1,5 @@
|
||||
import { ExpandLess, ExpandMore, Link } from "@mui/icons-material";
|
||||
import {
|
||||
Button,
|
||||
Divider,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Stack,
|
||||
} from "@mui/material";
|
||||
import { Button, Divider, ListItemIcon, ListItemText, Menu, MenuItem, Stack } from "@mui/material";
|
||||
import NextLink from "next/link";
|
||||
import { useState } from "react";
|
||||
|
||||
@@ -36,21 +28,14 @@ const HeaderMenu = ({ menu }) => {
|
||||
<Menu anchorEl={anchorEl} open={open} onClose={handleClose}>
|
||||
{menu.subMenu.flatMap((subMenu, index) => [
|
||||
...subMenu.map((sub) => (
|
||||
<MenuItem
|
||||
component={NextLink}
|
||||
href={sub.href}
|
||||
key={sub.title}
|
||||
onClick={handleClose}
|
||||
>
|
||||
<MenuItem component={NextLink} href={sub.href} key={sub.title} onClick={handleClose}>
|
||||
<ListItemIcon>
|
||||
<Link fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{sub.title}</ListItemText>
|
||||
</MenuItem>
|
||||
)),
|
||||
index < menu.subMenu.length - 1 && (
|
||||
<Divider key={`divider-${index}`} />
|
||||
),
|
||||
index < menu.subMenu.length - 1 && <Divider key={`divider-${index}`} />,
|
||||
])}
|
||||
</Menu>
|
||||
</Stack>
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
import { ExpandLess, ExpandMore } from "@mui/icons-material";
|
||||
import {
|
||||
Collapse,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Stack,
|
||||
} from "@mui/material";
|
||||
import { Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Stack } from "@mui/material";
|
||||
import Link from "next/link";
|
||||
import SidebarBadge from "./SidebarBadge";
|
||||
import SidebarSubitems from "./SidebarSubitems";
|
||||
@@ -51,21 +43,10 @@ const SidebarListItems = ({ menuItem, dispatch }) => {
|
||||
))}
|
||||
</Stack>
|
||||
)}
|
||||
{menuItem.hasSubitems ? (
|
||||
menuItem.showSubitems ? (
|
||||
<ExpandLess />
|
||||
) : (
|
||||
<ExpandMore />
|
||||
)
|
||||
) : null}
|
||||
{menuItem.hasSubitems ? menuItem.showSubitems ? <ExpandLess /> : <ExpandMore /> : null}
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
<Collapse
|
||||
in={menuItem.showSubitems}
|
||||
timeout="auto"
|
||||
mountOnEnter={true}
|
||||
unmountOnExit={true}
|
||||
>
|
||||
<Collapse in={menuItem.showSubitems} timeout="auto" mountOnEnter={true} unmountOnExit={true}>
|
||||
{menuItem.hasSubitems ? (
|
||||
<List
|
||||
disablePadding
|
||||
@@ -75,13 +56,7 @@ const SidebarListItems = ({ menuItem, dispatch }) => {
|
||||
}}
|
||||
>
|
||||
{menuItem.Subitems.map((subitem, index) => {
|
||||
return (
|
||||
<SidebarSubitems
|
||||
key={index}
|
||||
dispatch={dispatch}
|
||||
subitem={subitem}
|
||||
/>
|
||||
);
|
||||
return <SidebarSubitems key={index} dispatch={dispatch} subitem={subitem} />;
|
||||
})}
|
||||
</List>
|
||||
) : null}
|
||||
|
||||
@@ -16,15 +16,11 @@ function selectPage(item, route) {
|
||||
showSubitems: item.route === route,
|
||||
};
|
||||
} else if (item.Subitems && Array.isArray(item.Subitems)) {
|
||||
const updatedSubitems = item.Subitems.map((subitem) =>
|
||||
selectPage(subitem, route),
|
||||
);
|
||||
const updatedSubitems = item.Subitems.map((subitem) => selectPage(subitem, route));
|
||||
return {
|
||||
...item,
|
||||
Subitems: updatedSubitems,
|
||||
showSubitems: updatedSubitems.some(
|
||||
(subitem) => subitem.showSubitems || subitem.route === route,
|
||||
),
|
||||
showSubitems: updatedSubitems.some((subitem) => subitem.showSubitems || subitem.route === route),
|
||||
};
|
||||
}
|
||||
return item;
|
||||
@@ -32,9 +28,7 @@ function selectPage(item, route) {
|
||||
|
||||
function toggleSubitems(items, actionId) {
|
||||
return items.map((item) =>
|
||||
actionId === item.id
|
||||
? { ...item, showSubitems: !item.showSubitems }
|
||||
: { ...item, showSubitems: false },
|
||||
actionId === item.id ? { ...item, showSubitems: !item.showSubitems } : { ...item, showSubitems: false }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -52,9 +46,7 @@ function reducer(state, action) {
|
||||
|
||||
case "COLLAPSE_SUB_ITEMS":
|
||||
return state.map((item) =>
|
||||
item.hasSubitems
|
||||
? { ...item, Subitems: toggleSubitems(item.Subitems, action.id) }
|
||||
: item,
|
||||
item.hasSubitems ? { ...item, Subitems: toggleSubitems(item.Subitems, action.id) } : item
|
||||
);
|
||||
|
||||
case "COLLAPSE_SUB_SECOND_ITEMS":
|
||||
@@ -68,10 +60,10 @@ function reducer(state, action) {
|
||||
...subitem,
|
||||
Subitems: toggleSubitems(subitem.Subitems, action.id),
|
||||
}
|
||||
: subitem,
|
||||
: subitem
|
||||
),
|
||||
}
|
||||
: item,
|
||||
: item
|
||||
);
|
||||
|
||||
case "SELECTED":
|
||||
@@ -112,13 +104,7 @@ const SidebarMenu = () => {
|
||||
{userPermissions && (
|
||||
<List sx={{ overflow: "auto", flex: 1 }} disablePadding dense>
|
||||
{menuItems.map((menuItem) => {
|
||||
return (
|
||||
<SidebarListItems
|
||||
dispatch={dispatch}
|
||||
key={menuItem.id}
|
||||
menuItem={menuItem}
|
||||
/>
|
||||
);
|
||||
return <SidebarListItems dispatch={dispatch} key={menuItem.id} menuItem={menuItem} />;
|
||||
})}
|
||||
</List>
|
||||
)}
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
import { ExpandLess, ExpandMore } from "@mui/icons-material";
|
||||
import {
|
||||
Box,
|
||||
Collapse,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Stack,
|
||||
} from "@mui/material";
|
||||
import { Box, Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Stack } from "@mui/material";
|
||||
import Link from "next/link";
|
||||
import SidebarBadge from "./SidebarBadge";
|
||||
|
||||
@@ -64,12 +55,7 @@ const SidebarSubitems = ({ subitem, dispatch }) => {
|
||||
)}
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
<Collapse
|
||||
in={subitem.showSubitems}
|
||||
timeout="auto"
|
||||
mountOnEnter={true}
|
||||
unmountOnExit={true}
|
||||
>
|
||||
<Collapse in={subitem.showSubitems} timeout="auto" mountOnEnter={true} unmountOnExit={true}>
|
||||
{subitem.hasSubitems ? (
|
||||
<List
|
||||
disablePadding
|
||||
@@ -79,13 +65,7 @@ const SidebarSubitems = ({ subitem, dispatch }) => {
|
||||
}}
|
||||
>
|
||||
{subitem.Subitems.map((subSubitem, index) => {
|
||||
return (
|
||||
<SidebarSubitems
|
||||
key={index}
|
||||
dispatch={dispatch}
|
||||
subitem={subSubitem}
|
||||
/>
|
||||
);
|
||||
return <SidebarSubitems key={index} dispatch={dispatch} subitem={subSubitem} />;
|
||||
})}
|
||||
</List>
|
||||
) : null}
|
||||
|
||||
@@ -1,17 +1,7 @@
|
||||
"use client";
|
||||
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||
import MenuIcon from "@mui/icons-material/Menu";
|
||||
import {
|
||||
Box,
|
||||
Drawer,
|
||||
IconButton,
|
||||
Stack,
|
||||
styled,
|
||||
Toolbar,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { Box, Drawer, IconButton, Stack, styled, Toolbar, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||
import MuiAppBar from "@mui/material/AppBar";
|
||||
import { useState, useEffect } from "react";
|
||||
import HeaderMenu from "./HeaderMenu";
|
||||
@@ -21,8 +11,7 @@ import SidebarMenu from "./Sidebar/SidebarMenu";
|
||||
|
||||
const drawerWidth = 300;
|
||||
|
||||
const Main = styled(Stack, { shouldForwardProp: (prop) => prop !== "open" })(
|
||||
({ theme, open }) => ({
|
||||
const Main = styled(Stack, { shouldForwardProp: (prop) => prop !== "open" })(({ theme, open }) => ({
|
||||
flexGrow: 1,
|
||||
height: "100%",
|
||||
transition: theme.transitions.create("margin", {
|
||||
@@ -37,8 +26,7 @@ const Main = styled(Stack, { shouldForwardProp: (prop) => prop !== "open" })(
|
||||
}),
|
||||
marginLeft: 0,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
}));
|
||||
|
||||
const AppBar = styled(MuiAppBar, {
|
||||
shouldForwardProp: (prop) => prop !== "open",
|
||||
@@ -92,11 +80,7 @@ const HeaderWithSidebar = ({ children }) => {
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<AppBar
|
||||
sx={{ position: "fixed", top: "unset" }}
|
||||
elevation={0}
|
||||
open={open}
|
||||
>
|
||||
<AppBar sx={{ position: "fixed", top: "unset" }} elevation={0} open={open}>
|
||||
<Toolbar variant="dense" sx={{ minHeight: 40 }}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
@@ -158,18 +142,11 @@ const HeaderWithSidebar = ({ children }) => {
|
||||
</IconButton>
|
||||
</DrawerHeader>
|
||||
<SidebarMenu />
|
||||
<Typography
|
||||
textAlign={"center"}
|
||||
variant="caption"
|
||||
sx={{ py: 0.2, fontFamily: "sans-serif" }}
|
||||
>
|
||||
<Typography textAlign={"center"} variant="caption" sx={{ py: 0.2, fontFamily: "sans-serif" }}>
|
||||
v{process.env.NEXT_PUBLIC_VERSION}
|
||||
</Typography>
|
||||
</Drawer>
|
||||
<Main
|
||||
open={open}
|
||||
sx={{ height: "100%", width: "100%", overflow: "hidden" }}
|
||||
>
|
||||
<Main open={open} sx={{ height: "100%", width: "100%", overflow: "hidden" }}>
|
||||
<DrawerHeader />
|
||||
<Box
|
||||
sx={{
|
||||
|
||||
@@ -15,11 +15,7 @@ const ActionHeader = ({ tab }) => {
|
||||
<Typography variant="subtitle1" sx={{ marginRight: 1, color: "#fff" }}>
|
||||
.... عملیات های مربوط به تماس:
|
||||
</Typography>
|
||||
<Typography
|
||||
data-testid="phone_number"
|
||||
variant="subtitle1"
|
||||
sx={{ color: "#fff" }}
|
||||
>
|
||||
<Typography data-testid="phone_number" variant="subtitle1" sx={{ color: "#fff" }}>
|
||||
{tab.phone_number} ....
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
@@ -9,9 +9,7 @@ const CallActionCategoriesButton = ({ category, control }) => {
|
||||
<Button
|
||||
sx={{ py: 1.5 }}
|
||||
fullWidth
|
||||
variant={
|
||||
field.value === category.category_id ? "contained" : "outlined"
|
||||
}
|
||||
variant={field.value === category.category_id ? "contained" : "outlined"}
|
||||
color={"primary"}
|
||||
onClick={() => {
|
||||
field.onChange(category.category_id);
|
||||
|
||||
@@ -12,7 +12,7 @@ const CallActionSubcategoriesButton = ({ sub_category, control, onSubmit }) => {
|
||||
onSubmit();
|
||||
}, 0);
|
||||
},
|
||||
[sub_category.subcategory_id],
|
||||
[sub_category.subcategory_id]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -11,11 +11,7 @@ const CallActionsCategories = ({ control }) => {
|
||||
</Divider>
|
||||
<Stack sx={{ m: 1, p: 1 }} direction={"row"} spacing={3}>
|
||||
{categoryLists.map((category) => (
|
||||
<CallActionCategoriesButton
|
||||
key={category.category_id}
|
||||
category={category}
|
||||
control={control}
|
||||
/>
|
||||
<CallActionCategoriesButton key={category.category_id} category={category} control={control} />
|
||||
))}
|
||||
</Stack>
|
||||
</>
|
||||
|
||||
@@ -39,8 +39,7 @@ function CallActions({ tab }) {
|
||||
const onSubmit = handleSubmit(async (data) => {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
data.description != "" &&
|
||||
formData.append("description", data.description);
|
||||
data.description != "" && formData.append("description", data.description);
|
||||
formData.append("category_id", data.category_id);
|
||||
formData.append("subcategory_id", data.subcategory_id);
|
||||
await requestServer(`${CALL_ACTION}/${tab.id}`, "post", {
|
||||
@@ -71,12 +70,7 @@ function CallActions({ tab }) {
|
||||
zIndex: 9999,
|
||||
}}
|
||||
>
|
||||
<LoadingHardPage
|
||||
width={80}
|
||||
height={80}
|
||||
loading={true}
|
||||
sx={{ position: "absolute" }}
|
||||
/>
|
||||
<LoadingHardPage width={80} height={80} loading={true} sx={{ position: "absolute" }} />
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
@@ -12,9 +12,7 @@ const PreviousOperatorData = ({ historyItem }) => {
|
||||
</Box>
|
||||
<Stack>
|
||||
<Stack direction={"row"} sx={{ alignItems: "end" }}>
|
||||
<Typography sx={{ mr: 1 }}>
|
||||
{historyItem.operator_full_name}
|
||||
</Typography>
|
||||
<Typography sx={{ mr: 1 }}>{historyItem.operator_full_name}</Typography>
|
||||
<Typography variant="caption" sx={{ color: "secondary.main" }}>
|
||||
(کارشناس)
|
||||
</Typography>
|
||||
|
||||
@@ -13,9 +13,7 @@ const Topics = ({ historyItem }) => {
|
||||
>
|
||||
<Chip label={"موضوع"} size="small" variant="outlined" color="primary" />
|
||||
<Divider sx={{ flex: 1 }} />
|
||||
{historyItem.category_name && (
|
||||
<Chip label={historyItem.category_name} />
|
||||
)}
|
||||
{historyItem.category_name && <Chip label={historyItem.category_name} />}
|
||||
</Stack>
|
||||
<Stack
|
||||
sx={{
|
||||
@@ -25,16 +23,9 @@ const Topics = ({ historyItem }) => {
|
||||
spacing={1}
|
||||
direction={"row"}
|
||||
>
|
||||
<Chip
|
||||
label={"زیر موضوع"}
|
||||
size="small"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
/>
|
||||
<Chip label={"زیر موضوع"} size="small" variant="outlined" color="primary" />
|
||||
<Divider sx={{ flex: 1 }} />
|
||||
{historyItem.subcategory_name && (
|
||||
<Chip label={historyItem.subcategory_name} />
|
||||
)}
|
||||
{historyItem.subcategory_name && <Chip label={historyItem.subcategory_name} />}
|
||||
</Stack>
|
||||
<Stack
|
||||
sx={{
|
||||
@@ -44,12 +35,7 @@ const Topics = ({ historyItem }) => {
|
||||
spacing={1}
|
||||
direction={"row"}
|
||||
>
|
||||
<Chip
|
||||
label={"توضیحات تماس"}
|
||||
size="small"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
/>
|
||||
<Chip label={"توضیحات تماس"} size="small" variant="outlined" color="primary" />
|
||||
<Divider sx={{ flex: 1 }} />
|
||||
{historyItem.description && <Chip label={historyItem.description} />}
|
||||
</Stack>
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
import {
|
||||
Box,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemAvatar,
|
||||
ListItemText,
|
||||
Skeleton,
|
||||
} from "@mui/material";
|
||||
import { Box, List, ListItem, ListItemAvatar, ListItemText, Skeleton } from "@mui/material";
|
||||
|
||||
const LoadingHistory = () => {
|
||||
return (
|
||||
|
||||
@@ -9,12 +9,11 @@ import { Headphones } from "@mui/icons-material";
|
||||
|
||||
const max_size = 10;
|
||||
const CallHistory = ({ tab }) => {
|
||||
const {
|
||||
firstItemOfHistory,
|
||||
historyList,
|
||||
isLoadingHistoryList,
|
||||
errorHistoryList,
|
||||
} = useCallerHistory(tab.id, tab.phone_number, max_size);
|
||||
const { firstItemOfHistory, historyList, isLoadingHistoryList, errorHistoryList } = useCallerHistory(
|
||||
tab.id,
|
||||
tab.phone_number,
|
||||
max_size
|
||||
);
|
||||
const [showRestOfHistory, setShowRestOfHistory] = useState(false);
|
||||
|
||||
return (
|
||||
|
||||
@@ -4,12 +4,7 @@ import CallTabTime from "./CallTabTime";
|
||||
|
||||
const CallTabDetails = ({ tab }) => {
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
spacing={3}
|
||||
>
|
||||
<Stack direction="row" justifyContent="center" alignItems="center" spacing={3}>
|
||||
<Call />
|
||||
<Stack alignItems={"start"}>
|
||||
<Typography>{tab.phone_number}</Typography>
|
||||
|
||||
@@ -14,8 +14,7 @@ const CallTabLabel = ({ tab, index }) => {
|
||||
sx={{
|
||||
width: "100%",
|
||||
px: 1,
|
||||
borderRight:
|
||||
activeCall === index ? 0 : activeCall - 1 === index ? 0 : 1,
|
||||
borderRight: activeCall === index ? 0 : activeCall - 1 === index ? 0 : 1,
|
||||
borderRightColor: "divider",
|
||||
}}
|
||||
direction={"row"}
|
||||
|
||||
@@ -35,11 +35,7 @@ const CallWidgetDialog = () => {
|
||||
}, [calls.length]);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
fullScreen
|
||||
open={openCallDialog}
|
||||
slots={{ transition: DialogTransition }}
|
||||
>
|
||||
<Dialog fullScreen open={openCallDialog} slots={{ transition: DialogTransition }}>
|
||||
<CallTabs />
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -5,12 +5,7 @@ import { LocalizationProvider, MobileDatePicker } from "@mui/x-date-pickers";
|
||||
import { IconButton, InputAdornment } from "@mui/material";
|
||||
import ClearIcon from "@mui/icons-material/Clear";
|
||||
|
||||
const CustomDatePicker = ({
|
||||
dateValue,
|
||||
setDateValue,
|
||||
placeholder = "انتخاب تاریخ",
|
||||
size = "small",
|
||||
}) => {
|
||||
const CustomDatePicker = ({ dateValue, setDateValue, placeholder = "انتخاب تاریخ", size = "small" }) => {
|
||||
const handleDateChange = (newValue) => {
|
||||
setDateValue(newValue);
|
||||
};
|
||||
@@ -18,9 +13,7 @@ const CustomDatePicker = ({
|
||||
return (
|
||||
<LocalizationProvider
|
||||
dateAdapter={AdapterDateFnsJalali}
|
||||
localeText={
|
||||
faIR.components.MuiLocalizationProvider.defaultProps.localeText
|
||||
}
|
||||
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
|
||||
>
|
||||
<MobileDatePicker
|
||||
value={dateValue || null}
|
||||
|
||||
@@ -23,10 +23,7 @@ const rowSelectionReducer = (state, action) => {
|
||||
|
||||
const DataTable_Main = (props) => {
|
||||
const request = useRequest();
|
||||
const [rowSelection, dispatchRowSelection] = useReducer(
|
||||
rowSelectionReducer,
|
||||
{},
|
||||
);
|
||||
const [rowSelection, dispatchRowSelection] = useReducer(rowSelectionReducer, {});
|
||||
const { filterData, sortData, setSortData, hideData } = useDataTable();
|
||||
const {
|
||||
need_filter,
|
||||
@@ -56,20 +53,12 @@ const DataTable_Main = (props) => {
|
||||
params.set("size", pagination.pageSize);
|
||||
if (specialFilter) {
|
||||
const filteredSpecialFilterData = Object.values(specialFilter).filter(
|
||||
(filter) => !isArrayEmpty(filter.value),
|
||||
(filter) => !isArrayEmpty(filter.value)
|
||||
);
|
||||
params.set("filters", JSON.stringify(filteredSpecialFilterData || []));
|
||||
} else {
|
||||
const filteredFilterData = DataTableFilterDataStructure(
|
||||
filterData,
|
||||
isArrayEmpty,
|
||||
);
|
||||
params.set(
|
||||
"filters",
|
||||
JSON.stringify(
|
||||
filteredFilterData.length === 0 ? [] : filteredFilterData,
|
||||
),
|
||||
);
|
||||
const filteredFilterData = DataTableFilterDataStructure(filterData, isArrayEmpty);
|
||||
params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData));
|
||||
}
|
||||
params.set(
|
||||
"sorting",
|
||||
@@ -77,8 +66,8 @@ const DataTable_Main = (props) => {
|
||||
Object.values(sortData).map(({ id, ...rest }) => ({
|
||||
...rest,
|
||||
id: id.replace(/__/g, "."),
|
||||
})),
|
||||
),
|
||||
}))
|
||||
)
|
||||
);
|
||||
return `${table_url}?${params}`;
|
||||
}, [table_url, filterData, pagination, sortData, specialFilter]);
|
||||
@@ -97,16 +86,12 @@ const DataTable_Main = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const { data, isValidating, mutate } = useSWR(
|
||||
props.data ? "" : fetchUrl(),
|
||||
fetcher,
|
||||
{
|
||||
const { data, isValidating, mutate } = useSWR(props.data ? "" : fetchUrl(), fetcher, {
|
||||
revalidateIfStale: true,
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: true,
|
||||
keepPreviousData: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isValidating) return;
|
||||
@@ -118,8 +103,7 @@ const DataTable_Main = (props) => {
|
||||
columns,
|
||||
data: data ?? [],
|
||||
muiTableBodyRowProps: ({ row }) => ({
|
||||
onClick: () =>
|
||||
dispatchRowSelection({ type: "TOGGLE_ROW", payload: row.id }),
|
||||
onClick: () => dispatchRowSelection({ type: "TOGGLE_ROW", payload: row.id }),
|
||||
selected: !!rowSelection[row.id],
|
||||
}),
|
||||
initialState: {
|
||||
@@ -167,11 +151,7 @@ const DataTable_Main = (props) => {
|
||||
renderTopToolbarCustomActions: ({ table }) => (
|
||||
<>
|
||||
{TableToolbar && (
|
||||
<TableToolbar
|
||||
table={table}
|
||||
mutate={mutate}
|
||||
filterData={specialFilter || filterData}
|
||||
/>
|
||||
<TableToolbar table={table} mutate={mutate} filterData={specialFilter || filterData} />
|
||||
)}
|
||||
</>
|
||||
),
|
||||
|
||||
@@ -2,9 +2,7 @@ import { parseFromValuesOrFunc } from "@/core/utils/utils";
|
||||
import { TableBody, Typography } from "@mui/material";
|
||||
import { useMRT_RowVirtualizer, useMRT_Rows } from "material-react-table";
|
||||
import { memo, useMemo } from "react";
|
||||
import DataTable_TableBodyRow, {
|
||||
Memo_DataTable_TableBodyRow,
|
||||
} from "./TableBodyRow";
|
||||
import DataTable_TableBodyRow, { Memo_DataTable_TableBodyRow } from "./TableBodyRow";
|
||||
|
||||
const DataTable_TableBody = ({ columnVirtualizer, table, ...rest }) => {
|
||||
const {
|
||||
@@ -33,12 +31,8 @@ const DataTable_TableBody = ({ columnVirtualizer, table, ...rest }) => {
|
||||
...rest,
|
||||
};
|
||||
|
||||
const tableHeadHeight =
|
||||
((enableStickyHeader || isFullScreen) &&
|
||||
tableHeadRef.current?.clientHeight) ||
|
||||
0;
|
||||
const tableFooterHeight =
|
||||
(enableStickyFooter && tableFooterRef.current?.clientHeight) || 0;
|
||||
const tableHeadHeight = ((enableStickyHeader || isFullScreen) && tableHeadRef.current?.clientHeight) || 0;
|
||||
const tableFooterHeight = (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0;
|
||||
|
||||
const pinnedRowIds = useMemo(() => {
|
||||
if (!rowPinning.bottom?.length && !rowPinning.top?.length) return [];
|
||||
@@ -61,8 +55,7 @@ const DataTable_TableBody = ({ columnVirtualizer, table, ...rest }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{!rowPinningDisplayMode?.includes("sticky") &&
|
||||
getIsSomeRowsPinned("top") && (
|
||||
{!rowPinningDisplayMode?.includes("sticky") && getIsSomeRowsPinned("top") && (
|
||||
<TableBody
|
||||
{...tableBodyProps}
|
||||
sx={(theme) => ({
|
||||
@@ -91,9 +84,7 @@ const DataTable_TableBody = ({ columnVirtualizer, table, ...rest }) => {
|
||||
{...tableBodyProps}
|
||||
sx={(theme) => ({
|
||||
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
|
||||
height: rowVirtualizer
|
||||
? `${rowVirtualizer.getTotalSize()}px`
|
||||
: undefined,
|
||||
height: rowVirtualizer ? `${rowVirtualizer.getTotalSize()}px` : undefined,
|
||||
minHeight: !rows.length ? "100px" : undefined,
|
||||
position: "relative",
|
||||
...parseFromValuesOrFunc(tableBodyProps?.sx, theme),
|
||||
@@ -164,8 +155,7 @@ const DataTable_TableBody = ({ columnVirtualizer, table, ...rest }) => {
|
||||
</>
|
||||
))}
|
||||
</TableBody>
|
||||
{!rowPinningDisplayMode?.includes("sticky") &&
|
||||
getIsSomeRowsPinned("bottom") && (
|
||||
{!rowPinningDisplayMode?.includes("sticky") && getIsSomeRowsPinned("bottom") && (
|
||||
<TableBody
|
||||
{...tableBodyProps}
|
||||
sx={(theme) => ({
|
||||
@@ -197,5 +187,5 @@ export default DataTable_TableBody;
|
||||
|
||||
export const Memo_DataTable_TableBody = memo(
|
||||
DataTable_TableBody,
|
||||
(prev, next) => prev.table.options.data === next.table.options.data,
|
||||
(prev, next) => prev.table.options.data === next.table.options.data
|
||||
);
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
getCommonMRTCellStyles,
|
||||
parseFromValuesOrFunc,
|
||||
} from "@/core/utils/utils";
|
||||
import { getCommonMRTCellStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Skeleton, TableCell } from "@mui/material";
|
||||
import { isCellEditable, openEditingCell } from "material-react-table";
|
||||
@@ -9,15 +6,7 @@ import { memo, useEffect, useMemo, useState } from "react";
|
||||
import DataTable_CopyButton from "../buttons/CopyButton";
|
||||
import DataTable_TableBodyCellValue from "./TableBodyCellValue";
|
||||
|
||||
const DataTable_TableBodyCell = ({
|
||||
cell,
|
||||
numRows,
|
||||
rowRef,
|
||||
staticColumnIndex,
|
||||
staticRowIndex,
|
||||
table,
|
||||
...rest
|
||||
}) => {
|
||||
const DataTable_TableBodyCell = ({ cell, numRows, rowRef, staticColumnIndex, staticRowIndex, table, ...rest }) => {
|
||||
const theme = useTheme();
|
||||
const {
|
||||
getState,
|
||||
@@ -75,9 +64,7 @@ const DataTable_TableBodyCell = ({
|
||||
if ((!isLoading && !showSkeletons) || skeletonWidth !== 100) return;
|
||||
const size = column.getSize();
|
||||
setSkeletonWidth(
|
||||
columnDefType === "display"
|
||||
? size / 2
|
||||
: Math.round(Math.random() * (size - size / 3) + size / 3),
|
||||
columnDefType === "display" ? size / 2 : Math.round(Math.random() * (size - size / 3) + size / 3)
|
||||
);
|
||||
}, [isLoading, showSkeletons]);
|
||||
|
||||
@@ -90,8 +77,7 @@ const DataTable_TableBodyCell = ({
|
||||
const isLastColumn = column.getIsLastColumn();
|
||||
const isLastRow = numRows && staticRowIndex === numRows - 1;
|
||||
const isResizingColumn = columnSizingInfo.isResizingColumn === column.id;
|
||||
const showResizeBorder =
|
||||
isResizingColumn && columnResizeMode === "onChange";
|
||||
const showResizeBorder = isResizingColumn && columnResizeMode === "onChange";
|
||||
|
||||
const borderStyle = showResizeBorder
|
||||
? `2px solid ${draggingBorderColor} !important`
|
||||
@@ -102,65 +88,44 @@ const DataTable_TableBodyCell = ({
|
||||
: undefined;
|
||||
|
||||
if (showResizeBorder) {
|
||||
return columnResizeDirection === "ltr"
|
||||
? { borderRight: borderStyle }
|
||||
: { borderLeft: borderStyle };
|
||||
return columnResizeDirection === "ltr" ? { borderRight: borderStyle } : { borderLeft: borderStyle };
|
||||
}
|
||||
|
||||
return borderStyle
|
||||
? {
|
||||
borderBottom:
|
||||
isDraggingRow || isHoveredRow || (isLastRow && !isResizingColumn)
|
||||
? borderStyle
|
||||
: undefined,
|
||||
isDraggingRow || isHoveredRow || (isLastRow && !isResizingColumn) ? borderStyle : undefined,
|
||||
borderLeft:
|
||||
isDraggingColumn ||
|
||||
isHoveredColumn ||
|
||||
((isDraggingRow || isHoveredRow) && isFirstColumn)
|
||||
isDraggingColumn || isHoveredColumn || ((isDraggingRow || isHoveredRow) && isFirstColumn)
|
||||
? borderStyle
|
||||
: undefined,
|
||||
borderRight:
|
||||
isDraggingColumn ||
|
||||
isHoveredColumn ||
|
||||
((isDraggingRow || isHoveredRow) && isLastColumn)
|
||||
isDraggingColumn || isHoveredColumn || ((isDraggingRow || isHoveredRow) && isLastColumn)
|
||||
? borderStyle
|
||||
: undefined,
|
||||
borderTop: isDraggingRow || isHoveredRow ? borderStyle : undefined,
|
||||
}
|
||||
: undefined;
|
||||
}, [
|
||||
columnSizingInfo.isResizingColumn,
|
||||
draggingColumn,
|
||||
draggingRow,
|
||||
hoveredColumn,
|
||||
hoveredRow,
|
||||
staticRowIndex,
|
||||
]);
|
||||
}, [columnSizingInfo.isResizingColumn, draggingColumn, draggingRow, hoveredColumn, hoveredRow, staticRowIndex]);
|
||||
|
||||
const isColumnPinned =
|
||||
enableColumnPinning &&
|
||||
columnDef.columnDefType !== "group" &&
|
||||
column.getIsPinned();
|
||||
const isColumnPinned = enableColumnPinning && columnDef.columnDefType !== "group" && column.getIsPinned();
|
||||
|
||||
const isEditable = isCellEditable({ cell, table });
|
||||
|
||||
const isEditing =
|
||||
isEditable &&
|
||||
!["custom", "modal"].includes(editDisplayMode) &&
|
||||
(editDisplayMode === "table" ||
|
||||
editingRow?.id === row.id ||
|
||||
editingCell?.id === cell.id) &&
|
||||
(editDisplayMode === "table" || editingRow?.id === row.id || editingCell?.id === cell.id) &&
|
||||
!row.getIsGrouped();
|
||||
|
||||
const isCreating =
|
||||
isEditable && createDisplayMode === "row" && creatingRow?.id === row.id;
|
||||
const isCreating = isEditable && createDisplayMode === "row" && creatingRow?.id === row.id;
|
||||
|
||||
const showClickToCopyButton =
|
||||
(parseFromValuesOrFunc(enableClickToCopy, cell) === true ||
|
||||
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) === true) &&
|
||||
!["context-menu", false].includes(
|
||||
// @ts-ignore
|
||||
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell),
|
||||
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell)
|
||||
);
|
||||
|
||||
const isRightClickable = parseFromValuesOrFunc(enableCellActions, cell);
|
||||
@@ -181,9 +146,7 @@ const DataTable_TableBodyCell = ({
|
||||
setHoveredColumn(null);
|
||||
}
|
||||
if (enableColumnOrdering && draggingColumn) {
|
||||
setHoveredColumn(
|
||||
columnDef.enableColumnOrdering !== false ? column : null,
|
||||
);
|
||||
setHoveredColumn(columnDef.enableColumnOrdering !== false ? column : null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -227,10 +190,7 @@ const DataTable_TableBodyCell = ({
|
||||
: isEditable && editDisplayMode === "cell"
|
||||
? "pointer"
|
||||
: "inherit",
|
||||
outline:
|
||||
actionCell?.id === cell.id
|
||||
? `1px solid ${theme.palette.grey[500]}`
|
||||
: undefined,
|
||||
outline: actionCell?.id === cell.id ? `1px solid ${theme.palette.grey[500]}` : undefined,
|
||||
outlineOffset: "-1px",
|
||||
overflow: "hidden",
|
||||
p:
|
||||
@@ -247,8 +207,7 @@ const DataTable_TableBodyCell = ({
|
||||
: "1.5rem",
|
||||
|
||||
textOverflow: columnDefType !== "display" ? "ellipsis" : undefined,
|
||||
whiteSpace:
|
||||
row.getIsPinned() || density === "compact" ? "nowrap" : "normal",
|
||||
whiteSpace: row.getIsPinned() || density === "compact" ? "nowrap" : "normal",
|
||||
...getCommonMRTCellStyles({
|
||||
column,
|
||||
table,
|
||||
@@ -264,16 +223,9 @@ const DataTable_TableBodyCell = ({
|
||||
{cell.getIsPlaceholder() ? (
|
||||
(columnDef.PlaceholderCell?.({ cell, column, row, table }) ?? null)
|
||||
) : showSkeletons !== false && (isLoading || showSkeletons) ? (
|
||||
<Skeleton
|
||||
animation="wave"
|
||||
height={20}
|
||||
width={skeletonWidth}
|
||||
{...skeletonProps}
|
||||
/>
|
||||
<Skeleton animation="wave" height={20} width={skeletonWidth} {...skeletonProps} />
|
||||
) : columnDefType === "display" &&
|
||||
(["mrt-row-expand", "mrt-row-numbers", "mrt-row-select"].includes(
|
||||
column.id,
|
||||
) ||
|
||||
(["mrt-row-expand", "mrt-row-numbers", "mrt-row-select"].includes(column.id) ||
|
||||
!row.getIsGrouped()) ? (
|
||||
columnDef.Cell?.({
|
||||
cell,
|
||||
@@ -292,9 +244,7 @@ const DataTable_TableBodyCell = ({
|
||||
) : (
|
||||
<DataTable_TableBodyCellValue {...cellValueProps} />
|
||||
)}
|
||||
{cell.getIsGrouped() && !columnDef.GroupedCell && (
|
||||
<> ({row.subRows?.length})</>
|
||||
)}
|
||||
{cell.getIsGrouped() && !columnDef.GroupedCell && <> ({row.subRows?.length})</>}
|
||||
</>
|
||||
)}
|
||||
</TableCell>
|
||||
@@ -302,7 +252,4 @@ const DataTable_TableBodyCell = ({
|
||||
};
|
||||
export default DataTable_TableBodyCell;
|
||||
|
||||
export const Memo_DataTable_TableBodyCell = memo(
|
||||
DataTable_TableBodyCell,
|
||||
(prev, next) => next.cell === prev.cell,
|
||||
);
|
||||
export const Memo_DataTable_TableBodyCell = memo(DataTable_TableBodyCell, (prev, next) => next.cell === prev.cell);
|
||||
|
||||
@@ -2,13 +2,7 @@ import { Box } from "@mui/material";
|
||||
|
||||
const allowedTypes = ["string", "number"];
|
||||
|
||||
const DataTable_TableBodyCellValue = ({
|
||||
cell,
|
||||
rowRef,
|
||||
staticColumnIndex,
|
||||
staticRowIndex,
|
||||
table,
|
||||
}) => {
|
||||
const DataTable_TableBodyCellValue = ({ cell, rowRef, staticColumnIndex, staticRowIndex, table }) => {
|
||||
const {
|
||||
getState,
|
||||
options: {
|
||||
@@ -54,13 +48,10 @@ const DataTable_TableBodyCellValue = ({
|
||||
((filterValue &&
|
||||
allowedTypes.includes(typeof filterValue) &&
|
||||
["autocomplete", "text"].includes(columnDef.filterVariant)) ||
|
||||
(globalFilter &&
|
||||
allowedTypes.includes(typeof globalFilter) &&
|
||||
column.getCanGlobalFilter()))
|
||||
(globalFilter && allowedTypes.includes(typeof globalFilter) && column.getCanGlobalFilter()))
|
||||
) {
|
||||
const chunks = highlightWords?.({
|
||||
matchExactly:
|
||||
(filterValue ? columnDef._filterFn : globalFilterFn) !== "fuzzy",
|
||||
matchExactly: (filterValue ? columnDef._filterFn : globalFilterFn) !== "fuzzy",
|
||||
query: (filterValue ?? globalFilter ?? "").toString(),
|
||||
text: renderedCellValue?.toString(),
|
||||
});
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import {
|
||||
commonCellBeforeAfterStyles,
|
||||
getCommonPinnedCellStyles,
|
||||
parseFromValuesOrFunc,
|
||||
} from "@/core/utils/utils";
|
||||
import { commonCellBeforeAfterStyles, getCommonPinnedCellStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { TableRow, alpha, darken, lighten } from "@mui/material";
|
||||
import { getIsRowSelected } from "material-react-table";
|
||||
import { memo, useMemo, useRef } from "react";
|
||||
import DataTable_TableBodyCell, {
|
||||
Memo_DataTable_TableBodyCell,
|
||||
} from "./TableBodyCell";
|
||||
import DataTable_TableBodyCell, { Memo_DataTable_TableBodyCell } from "./TableBodyCell";
|
||||
import DataTable_TableDetailPanel from "./TableDetailPanel";
|
||||
|
||||
const DataTable_TableBodyRow = ({
|
||||
@@ -34,11 +28,7 @@ const DataTable_TableBodyRow = ({
|
||||
enableStickyHeader,
|
||||
layoutMode,
|
||||
memoMode,
|
||||
mrtTheme: {
|
||||
baseBackgroundColor,
|
||||
pinnedRowBackgroundColor,
|
||||
selectedRowBackgroundColor,
|
||||
},
|
||||
mrtTheme: { baseBackgroundColor, pinnedRowBackgroundColor, selectedRowBackgroundColor },
|
||||
muiTableBodyRowProps,
|
||||
renderDetailPanel,
|
||||
rowPinningDisplayMode,
|
||||
@@ -46,21 +36,12 @@ const DataTable_TableBodyRow = ({
|
||||
refs: { tableFooterRef, tableHeadRef },
|
||||
setHoveredRow,
|
||||
} = table;
|
||||
const {
|
||||
density,
|
||||
draggingColumn,
|
||||
draggingRow,
|
||||
editingCell,
|
||||
editingRow,
|
||||
hoveredRow,
|
||||
isFullScreen,
|
||||
rowPinning,
|
||||
} = getState();
|
||||
const { density, draggingColumn, draggingRow, editingCell, editingRow, hoveredRow, isFullScreen, rowPinning } =
|
||||
getState();
|
||||
|
||||
const visibleCells = row.getVisibleCells();
|
||||
|
||||
const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } =
|
||||
columnVirtualizer ?? {};
|
||||
const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } = columnVirtualizer ?? {};
|
||||
|
||||
const isRowSelected = getIsRowSelected({ row, table });
|
||||
const isRowPinned = enableRowPinning && row.getIsPinned();
|
||||
@@ -77,30 +58,17 @@ const DataTable_TableBodyRow = ({
|
||||
};
|
||||
|
||||
const [bottomPinnedIndex, topPinnedIndex] = useMemo(() => {
|
||||
if (
|
||||
!enableRowPinning ||
|
||||
!rowPinningDisplayMode?.includes("sticky") ||
|
||||
!pinnedRowIds ||
|
||||
!row.getIsPinned()
|
||||
)
|
||||
if (!enableRowPinning || !rowPinningDisplayMode?.includes("sticky") || !pinnedRowIds || !row.getIsPinned())
|
||||
return [];
|
||||
return [
|
||||
[...pinnedRowIds].reverse().indexOf(row.id),
|
||||
pinnedRowIds.indexOf(row.id),
|
||||
];
|
||||
return [[...pinnedRowIds].reverse().indexOf(row.id), pinnedRowIds.indexOf(row.id)];
|
||||
}, [pinnedRowIds, rowPinning]);
|
||||
|
||||
const tableHeadHeight =
|
||||
((enableStickyHeader || isFullScreen) &&
|
||||
tableHeadRef.current?.clientHeight) ||
|
||||
0;
|
||||
const tableFooterHeight =
|
||||
(enableStickyFooter && tableFooterRef.current?.clientHeight) || 0;
|
||||
const tableHeadHeight = ((enableStickyHeader || isFullScreen) && tableHeadRef.current?.clientHeight) || 0;
|
||||
const tableFooterHeight = (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0;
|
||||
|
||||
const sx = parseFromValuesOrFunc(tableRowProps?.sx, theme);
|
||||
|
||||
const defaultRowHeight =
|
||||
density === "compact" ? 37 : density === "comfortable" ? 53 : 69;
|
||||
const defaultRowHeight = density === "compact" ? 37 : density === "comfortable" ? 53 : 69;
|
||||
|
||||
const customRowHeight =
|
||||
// @ts-ignore
|
||||
@@ -152,9 +120,7 @@ const DataTable_TableBodyRow = ({
|
||||
selected={isRowSelected}
|
||||
{...tableRowProps}
|
||||
style={{
|
||||
transform: virtualRow
|
||||
? `translateY(${virtualRow.start}px)`
|
||||
: undefined,
|
||||
transform: virtualRow ? `translateY(${virtualRow.start}px)` : undefined,
|
||||
...tableRowProps?.style,
|
||||
}}
|
||||
sx={(theme) => ({
|
||||
@@ -195,16 +161,12 @@ const DataTable_TableBodyRow = ({
|
||||
: undefined,
|
||||
transition: virtualRow ? "none" : "all 150ms ease-in-out",
|
||||
width: "100%",
|
||||
zIndex:
|
||||
rowPinningDisplayMode?.includes("sticky") && isRowPinned ? 2 : 0,
|
||||
zIndex: rowPinningDisplayMode?.includes("sticky") && isRowPinned ? 2 : 0,
|
||||
...sx,
|
||||
})}
|
||||
>
|
||||
{virtualPaddingLeft ? (
|
||||
<td style={{ display: "flex", width: virtualPaddingLeft }} />
|
||||
) : null}
|
||||
{(virtualColumns ?? visibleCells).map(
|
||||
(cellOrVirtualCell, staticColumnIndex) => {
|
||||
{virtualPaddingLeft ? <td style={{ display: "flex", width: virtualPaddingLeft }} /> : null}
|
||||
{(virtualColumns ?? visibleCells).map((cellOrVirtualCell, staticColumnIndex) => {
|
||||
let cell = cellOrVirtualCell;
|
||||
if (columnVirtualizer) {
|
||||
staticColumnIndex = cellOrVirtualCell.index;
|
||||
@@ -230,11 +192,8 @@ const DataTable_TableBodyRow = ({
|
||||
<DataTable_TableBodyCell key={cell.id} {...props} />
|
||||
)
|
||||
) : null;
|
||||
},
|
||||
)}
|
||||
{virtualPaddingRight ? (
|
||||
<td style={{ display: "flex", width: virtualPaddingRight }} />
|
||||
) : null}
|
||||
})}
|
||||
{virtualPaddingRight ? <td style={{ display: "flex", width: virtualPaddingRight }} /> : null}
|
||||
</TableRow>
|
||||
{renderDetailPanel && !row.getIsGrouped() && (
|
||||
<DataTable_TableDetailPanel
|
||||
@@ -253,6 +212,5 @@ export default DataTable_TableBodyRow;
|
||||
|
||||
export const Memo_DataTable_TableBodyRow = memo(
|
||||
DataTable_TableBodyRow,
|
||||
(prev, next) =>
|
||||
prev.row === next.row && prev.staticRowIndex === next.staticRowIndex,
|
||||
(prev, next) => prev.row === next.row && prev.staticRowIndex === next.staticRowIndex
|
||||
);
|
||||
|
||||
@@ -53,12 +53,8 @@ const DataTable_TableDetailPanel = ({
|
||||
sx={(theme) => ({
|
||||
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
|
||||
position: virtualRow ? "absolute" : undefined,
|
||||
top: virtualRow
|
||||
? `${parentRowRef.current?.getBoundingClientRect()?.height}px`
|
||||
: undefined,
|
||||
transform: virtualRow
|
||||
? `translateY(${virtualRow?.start}px)`
|
||||
: undefined,
|
||||
top: virtualRow ? `${parentRowRef.current?.getBoundingClientRect()?.height}px` : undefined,
|
||||
transform: virtualRow ? `translateY(${virtualRow?.start}px)` : undefined,
|
||||
width: "100%",
|
||||
...parseFromValuesOrFunc(tableRowProps?.sx, theme),
|
||||
})}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
getCommonTooltipProps,
|
||||
parseFromValuesOrFunc,
|
||||
} from "@/core/utils/utils";
|
||||
import { getCommonTooltipProps, parseFromValuesOrFunc } from "@/core/utils/utils";
|
||||
import { Button, Tooltip } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
|
||||
@@ -40,10 +37,7 @@ const DataTable_CopyButton = ({ cell, table, ...rest }) => {
|
||||
return (
|
||||
<Tooltip
|
||||
{...getCommonTooltipProps("top")}
|
||||
title={
|
||||
buttonProps?.title ??
|
||||
(copied ? localization.copiedToClipboard : localization.clickToCopy)
|
||||
}
|
||||
title={buttonProps?.title ?? (copied ? localization.copiedToClipboard : localization.clickToCopy)}
|
||||
>
|
||||
<Button
|
||||
onClick={(e) => handleCopy(e, cell.getValue())}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
getCommonTooltipProps,
|
||||
parseFromValuesOrFunc,
|
||||
} from "@/core/utils/utils";
|
||||
import { getCommonTooltipProps, parseFromValuesOrFunc } from "@/core/utils/utils";
|
||||
import { IconButton, Tooltip } from "@mui/material";
|
||||
|
||||
const DataTable_GrabHandleButton = ({ location, table, ...rest }) => {
|
||||
@@ -13,10 +10,7 @@ const DataTable_GrabHandleButton = ({ location, table, ...rest }) => {
|
||||
} = table;
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
{...getCommonTooltipProps("top")}
|
||||
title={rest?.title ?? localization.move}
|
||||
>
|
||||
<Tooltip {...getCommonTooltipProps("top")} title={rest?.title ?? localization.move}>
|
||||
<IconButton
|
||||
aria-label={rest.title ?? localization.move}
|
||||
disableRipple
|
||||
|
||||
@@ -46,7 +46,7 @@ function FilterBody({ columns, drawerState, setDrawerState }) {
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, {}),
|
||||
}, {})
|
||||
);
|
||||
|
||||
setValidationSchema(schema);
|
||||
@@ -94,7 +94,7 @@ function FilterBody({ columns, drawerState, setDrawerState }) {
|
||||
reset={reset}
|
||||
/>
|
||||
)
|
||||
) : null,
|
||||
) : null
|
||||
)}
|
||||
</Box>
|
||||
<Box
|
||||
@@ -112,8 +112,7 @@ function FilterBody({ columns, drawerState, setDrawerState }) {
|
||||
disabled={!isDirty || !isValid}
|
||||
sx={{
|
||||
px: 8,
|
||||
boxShadow:
|
||||
"rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px",
|
||||
boxShadow: "rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px",
|
||||
backgroundColor: "primary2",
|
||||
":hover": {
|
||||
backgroundColor: "primary2",
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
import { Controller, useWatch } from "react-hook-form";
|
||||
import FilterBodyField from "./FilterBodyField";
|
||||
|
||||
const FilterBodyControllerWithDependency = ({
|
||||
column,
|
||||
control,
|
||||
reset,
|
||||
errors,
|
||||
}) => {
|
||||
const FilterBodyControllerWithDependency = ({ column, control, reset, errors }) => {
|
||||
const dependencyField = useWatch({ control, name: column.dependencyId });
|
||||
|
||||
return (
|
||||
|
||||
@@ -29,8 +29,7 @@ function FilterBodyField({
|
||||
}) {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const defaultFilterTranslation =
|
||||
columnFilterModeOptionFa[filterParameters.filterMode] ||
|
||||
filterParameters.filterMode;
|
||||
columnFilterModeOptionFa[filterParameters.filterMode] || filterParameters.filterMode;
|
||||
|
||||
const handleOpenFilterBox = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
|
||||
@@ -11,9 +11,7 @@ function FilterButton({ drawerState, setDrawerState }) {
|
||||
}
|
||||
return value === "" || value === null || value === undefined;
|
||||
};
|
||||
const filteredFilterData = Object.values(filterData).filter(
|
||||
(filter) => !isValueEmpty(filter.value),
|
||||
);
|
||||
const filteredFilterData = Object.values(filterData).filter((filter) => !isValueEmpty(filter.value));
|
||||
return (
|
||||
<Tooltip title="فیلتر">
|
||||
<IconButton
|
||||
|
||||
@@ -14,8 +14,7 @@ function FilterHeader({ setDrawerState }) {
|
||||
px: 2,
|
||||
py: 1,
|
||||
backgroundColor: (theme) => theme.palette.primary.main,
|
||||
boxShadow:
|
||||
"rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
|
||||
boxShadow: "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
|
||||
maxWidth: "450px",
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -29,13 +29,7 @@ function FilterOptionList({
|
||||
};
|
||||
|
||||
return (
|
||||
<Menu
|
||||
id="simple-menu"
|
||||
anchorEl={anchorEl}
|
||||
keepMounted
|
||||
open={Boolean(anchorEl)}
|
||||
onClose={handleCloseFilterBox}
|
||||
>
|
||||
<Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleCloseFilterBox}>
|
||||
{filterOption.map((option, index) => (
|
||||
<ListItem
|
||||
key={index}
|
||||
|
||||
@@ -2,12 +2,7 @@ import React from "react";
|
||||
import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
|
||||
import { Typography } from "@mui/material";
|
||||
|
||||
function CustomDatePicker({
|
||||
column,
|
||||
filterParameters,
|
||||
defaultFilterTranslation,
|
||||
handleChange,
|
||||
}) {
|
||||
function CustomDatePicker({ column, filterParameters, defaultFilterTranslation, handleChange }) {
|
||||
return (
|
||||
<MuiDatePicker
|
||||
name={`${column.id}.value`}
|
||||
@@ -17,10 +12,7 @@ function CustomDatePicker({
|
||||
}}
|
||||
placeholder={column.header}
|
||||
helperText={
|
||||
<Typography
|
||||
variant="button"
|
||||
sx={{ color: (theme) => theme.palette.primary.main }}
|
||||
>
|
||||
<Typography variant="button" sx={{ color: (theme) => theme.palette.primary.main }}>
|
||||
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
|
||||
</Typography>
|
||||
}
|
||||
|
||||
@@ -4,13 +4,7 @@ import React from "react";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
|
||||
|
||||
function CustomDatePickerRange({
|
||||
column,
|
||||
filterParameters,
|
||||
defaultFilterTranslation,
|
||||
handleChange,
|
||||
errors,
|
||||
}) {
|
||||
function CustomDatePickerRange({ column, filterParameters, defaultFilterTranslation, handleChange, errors }) {
|
||||
return (
|
||||
<Box sx={{ display: "flex", gap: 1 }}>
|
||||
<MuiDatePicker
|
||||
@@ -26,10 +20,7 @@ function CustomDatePickerRange({
|
||||
maxDate={filterParameters.value[1]}
|
||||
placeholder={`از تاریخ`}
|
||||
helperText={
|
||||
<Typography
|
||||
variant="button"
|
||||
sx={{ color: (theme) => theme.palette.primary.main }}
|
||||
>
|
||||
<Typography variant="button" sx={{ color: (theme) => theme.palette.primary.main }}>
|
||||
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
|
||||
</Typography>
|
||||
}
|
||||
@@ -46,11 +37,7 @@ function CustomDatePickerRange({
|
||||
}}
|
||||
minDate={filterParameters.value[0]}
|
||||
placeholder={`تا تاریخ`}
|
||||
helperText={
|
||||
errors?.[`${column.id}`]?.value
|
||||
? errors?.[`${column.id}`]?.value.message
|
||||
: null
|
||||
}
|
||||
helperText={errors?.[`${column.id}`]?.value ? errors?.[`${column.id}`]?.value.message : null}
|
||||
error={Boolean(errors?.[`${column.id}`]?.value)}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -6,24 +6,12 @@ import { Box, FormHelperText, IconButton, InputAdornment } from "@mui/material";
|
||||
import ClearIcon from "@mui/icons-material/Clear";
|
||||
import moment from "jalali-moment";
|
||||
|
||||
function MuiDatePicker({
|
||||
label,
|
||||
value,
|
||||
setFieldValue,
|
||||
name,
|
||||
minDate,
|
||||
maxDate,
|
||||
helperText,
|
||||
placeholder,
|
||||
error,
|
||||
}) {
|
||||
function MuiDatePicker({ label, value, setFieldValue, name, minDate, maxDate, helperText, placeholder, error }) {
|
||||
return (
|
||||
<Box sx={{ display: "flex", flexDirection: "column", my: 1 }}>
|
||||
<LocalizationProvider
|
||||
dateAdapter={AdapterDateFnsJalali}
|
||||
localeText={
|
||||
faIR.components.MuiLocalizationProvider.defaultProps.localeText
|
||||
}
|
||||
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
|
||||
>
|
||||
<MobileDatePicker
|
||||
value={value ? new Date(value) : null}
|
||||
@@ -35,9 +23,7 @@ function MuiDatePicker({
|
||||
aria-describedby="component-helper-text"
|
||||
onChange={(value) => {
|
||||
const date = new Date(value);
|
||||
const formattedDate = moment(date)
|
||||
.locale("en")
|
||||
.format("YYYY-MM-DD");
|
||||
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD");
|
||||
setFieldValue(name, formattedDate);
|
||||
}}
|
||||
minDate={minDate ? new Date(minDate) : null}
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
FormControl,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
OutlinedInput,
|
||||
Select,
|
||||
} from "@mui/material";
|
||||
import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
|
||||
function CustomSelect({ column, filterParameters, handleChange }) {
|
||||
return (
|
||||
<FormControl fullWidth sx={{ marginY: 1 }} size="small">
|
||||
@@ -20,9 +14,7 @@ function CustomSelect({ column, filterParameters, handleChange }) {
|
||||
value={filterParameters.value}
|
||||
input={<OutlinedInput label={column.header} />}
|
||||
size="small"
|
||||
onChange={(e) =>
|
||||
handleChange({ ...filterParameters, value: e.target.value })
|
||||
}
|
||||
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
|
||||
displayEmpty
|
||||
>
|
||||
{column.columnSelectOption().map((option) => (
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
OutlinedInput,
|
||||
Select,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { FormControl, FormHelperText, InputLabel, MenuItem, OutlinedInput, Select, Typography } from "@mui/material";
|
||||
import { useCallback, useEffect } from "react";
|
||||
|
||||
function CustomSelectByDependency({
|
||||
@@ -31,9 +23,7 @@ function CustomSelectByDependency({
|
||||
value={value}
|
||||
size="small"
|
||||
input={<OutlinedInput label={column.header} />}
|
||||
onChange={(e) =>
|
||||
handleChange({ ...filterParameters, value: e.target.value })
|
||||
}
|
||||
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
|
||||
displayEmpty
|
||||
>
|
||||
{columnSelectOption.map((option) => (
|
||||
|
||||
@@ -12,12 +12,7 @@ import {
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
|
||||
function CustomSelectMultiple({
|
||||
column,
|
||||
filterParameters,
|
||||
defaultFilterTranslation,
|
||||
handleChange,
|
||||
}) {
|
||||
function CustomSelectMultiple({ column, filterParameters, defaultFilterTranslation, handleChange }) {
|
||||
const columnSelectOption = column.columnSelectOption;
|
||||
|
||||
const getLabelForValue = (value) => {
|
||||
@@ -36,9 +31,7 @@ function CustomSelectMultiple({
|
||||
value={filterParameters.value}
|
||||
multiple
|
||||
size="small"
|
||||
onChange={(e) =>
|
||||
handleChange({ ...filterParameters, value: e.target.value })
|
||||
}
|
||||
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
|
||||
renderValue={(selected) => (
|
||||
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
|
||||
{selected.map((value) => (
|
||||
|
||||
@@ -15,9 +15,7 @@ function CustomTextField({
|
||||
name={column.id}
|
||||
label={column.header}
|
||||
value={filterParameters.value}
|
||||
onChange={(e) =>
|
||||
handleChange({ ...filterParameters, value: e.target.value })
|
||||
}
|
||||
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
|
||||
onBlur={handleBlur}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
@@ -25,11 +23,7 @@ function CustomTextField({
|
||||
sx={{ my: 1 }}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment
|
||||
position="end"
|
||||
sx={{ cursor: "pointer" }}
|
||||
onClick={handleOpenFilterBox}
|
||||
>
|
||||
<InputAdornment position="end" sx={{ cursor: "pointer" }} onClick={handleOpenFilterBox}>
|
||||
<FilterListIcon />
|
||||
</InputAdornment>
|
||||
),
|
||||
|
||||
@@ -25,10 +25,7 @@ function CustomTextFieldRange({
|
||||
label={<Typography>از {column.header}</Typography>}
|
||||
value={filterParameters.value[0]}
|
||||
fullWidth
|
||||
error={
|
||||
touched?.[`${column.id}`]?.value &&
|
||||
Boolean(errors?.[`${column.id}`]?.value)
|
||||
}
|
||||
error={touched?.[`${column.id}`]?.value && Boolean(errors?.[`${column.id}`]?.value)}
|
||||
helperText={
|
||||
<Typography
|
||||
variant="caption"
|
||||
@@ -55,11 +52,7 @@ function CustomTextFieldRange({
|
||||
}
|
||||
onBlur={handleBlur}
|
||||
error={Boolean(errors?.[`${column.id}`]?.value)}
|
||||
helperText={
|
||||
errors?.[`${column.id}`]?.value
|
||||
? errors?.[`${column.id}`]?.value.message
|
||||
: null
|
||||
}
|
||||
helperText={errors?.[`${column.id}`]?.value ? errors?.[`${column.id}`]?.value.message : null}
|
||||
label={<Typography>تا {column.header}</Typography>}
|
||||
value={filterParameters.value[1]}
|
||||
fullWidth
|
||||
@@ -68,11 +61,7 @@ function CustomTextFieldRange({
|
||||
sx={{ my: 1 }}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment
|
||||
position="end"
|
||||
sx={{ cursor: "pointer" }}
|
||||
onClick={handleOpenFilterBox}
|
||||
>
|
||||
<InputAdornment position="end" sx={{ cursor: "pointer" }} onClick={handleOpenFilterBox}>
|
||||
<FilterListIcon />
|
||||
</InputAdornment>
|
||||
),
|
||||
|
||||
@@ -5,12 +5,7 @@ import DataTable_TableHeadRow from "./TableHeadRow";
|
||||
const DataTable_TableHead = ({ columnVirtualizer, table, ...rest }) => {
|
||||
const {
|
||||
getState,
|
||||
options: {
|
||||
enableStickyHeader,
|
||||
layoutMode,
|
||||
muiTableHeadProps,
|
||||
positionToolbarAlertBanner,
|
||||
},
|
||||
options: { enableStickyHeader, layoutMode, muiTableHeadProps, positionToolbarAlertBanner },
|
||||
refs: { tableHeadRef },
|
||||
} = table;
|
||||
const { isFullScreen, showAlertBanner } = getState();
|
||||
|
||||
@@ -1,20 +1,10 @@
|
||||
import {
|
||||
getCommonMRTCellStyles,
|
||||
parseFromValuesOrFunc,
|
||||
} from "@/core/utils/utils";
|
||||
import { getCommonMRTCellStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, TableCell } from "@mui/material";
|
||||
import { MRT_TableHeadCellSortLabel } from "material-react-table";
|
||||
import { useMemo } from "react";
|
||||
|
||||
const DataTable_TableHeadCell = ({
|
||||
columnVirtualizer,
|
||||
header,
|
||||
staticColumnIndex,
|
||||
backgroundColor,
|
||||
table,
|
||||
...rest
|
||||
}) => {
|
||||
const DataTable_TableHeadCell = ({ columnVirtualizer, header, staticColumnIndex, backgroundColor, table, ...rest }) => {
|
||||
const theme = useTheme();
|
||||
const {
|
||||
getState,
|
||||
@@ -34,14 +24,7 @@ const DataTable_TableHeadCell = ({
|
||||
refs: { tableHeadCellRefs },
|
||||
setHoveredColumn,
|
||||
} = table;
|
||||
const {
|
||||
columnSizingInfo,
|
||||
density,
|
||||
draggingColumn,
|
||||
grouping,
|
||||
hoveredColumn,
|
||||
showColumnFilters,
|
||||
} = getState();
|
||||
const { columnSizingInfo, density, draggingColumn, grouping, hoveredColumn, showColumnFilters } = getState();
|
||||
const { column } = header;
|
||||
const { columnDef } = column;
|
||||
const { columnDefType } = columnDef;
|
||||
@@ -55,23 +38,17 @@ const DataTable_TableHeadCell = ({
|
||||
...rest,
|
||||
};
|
||||
|
||||
const isColumnPinned =
|
||||
enableColumnPinning &&
|
||||
columnDef.columnDefType !== "group" &&
|
||||
column.getIsPinned();
|
||||
const isColumnPinned = enableColumnPinning && columnDef.columnDefType !== "group" && column.getIsPinned();
|
||||
|
||||
const showColumnActions =
|
||||
(enableColumnActions || columnDef.enableColumnActions) &&
|
||||
columnDef.enableColumnActions !== false;
|
||||
(enableColumnActions || columnDef.enableColumnActions) && columnDef.enableColumnActions !== false;
|
||||
|
||||
const showDragHandle =
|
||||
enableColumnDragging !== false &&
|
||||
columnDef.enableColumnDragging !== false &&
|
||||
(enableColumnDragging ||
|
||||
(enableColumnOrdering && columnDef.enableColumnOrdering !== false) ||
|
||||
(enableGrouping &&
|
||||
columnDef.enableGrouping !== false &&
|
||||
!grouping.includes(column.id)));
|
||||
(enableGrouping && columnDef.enableGrouping !== false && !grouping.includes(column.id)));
|
||||
|
||||
const headerPL = useMemo(() => {
|
||||
let pl = 0;
|
||||
@@ -96,9 +73,7 @@ const DataTable_TableHeadCell = ({
|
||||
: undefined;
|
||||
|
||||
if (showResizeBorder) {
|
||||
return columnResizeDirection === "ltr"
|
||||
? { borderRight: borderStyle }
|
||||
: { borderLeft: borderStyle };
|
||||
return columnResizeDirection === "ltr" ? { borderRight: borderStyle } : { borderLeft: borderStyle };
|
||||
}
|
||||
const draggingBorders = borderStyle
|
||||
? {
|
||||
@@ -116,9 +91,7 @@ const DataTable_TableHeadCell = ({
|
||||
setHoveredColumn(null);
|
||||
}
|
||||
if (enableColumnOrdering && draggingColumn && columnDefType !== "group") {
|
||||
setHoveredColumn(
|
||||
columnDef.enableColumnOrdering !== false ? column : null,
|
||||
);
|
||||
setHoveredColumn(columnDef.enableColumnOrdering !== false ? column : null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -149,13 +122,7 @@ const DataTable_TableHeadCell = ({
|
||||
|
||||
return (
|
||||
<TableCell
|
||||
align={
|
||||
columnDefType === "group"
|
||||
? "center"
|
||||
: theme.direction === "rtl"
|
||||
? "right"
|
||||
: "left"
|
||||
}
|
||||
align={columnDefType === "group" ? "center" : theme.direction === "rtl" ? "right" : "left"}
|
||||
colSpan={header.colSpan}
|
||||
rowSpan={rowSpan}
|
||||
data-index={staticColumnIndex}
|
||||
@@ -190,12 +157,7 @@ const DataTable_TableHeadCell = ({
|
||||
: columnDefType === "display"
|
||||
? "1rem 1.25rem"
|
||||
: "1.5rem",
|
||||
pb:
|
||||
columnDefType === "display"
|
||||
? 0
|
||||
: showColumnFilters || density === "compact"
|
||||
? "0.4rem"
|
||||
: "0.6rem",
|
||||
pb: columnDefType === "display" ? 0 : showColumnFilters || density === "compact" ? "0.4rem" : "0.6rem",
|
||||
pt:
|
||||
columnDefType === "group" || density === "compact"
|
||||
? "0.25rem"
|
||||
@@ -221,8 +183,7 @@ const DataTable_TableHeadCell = ({
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
display: "flex",
|
||||
flexDirection:
|
||||
tableCellProps?.align === "right" ? "row-reverse" : "row",
|
||||
flexDirection: tableCellProps?.align === "right" ? "row-reverse" : "row",
|
||||
justifyContent:
|
||||
columnDefType === "group" || tableCellProps?.align === "center"
|
||||
? "center"
|
||||
@@ -238,18 +199,11 @@ const DataTable_TableHeadCell = ({
|
||||
onClick={column.getToggleSortingHandler()}
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
cursor:
|
||||
column.getCanSort() && columnDefType !== "group"
|
||||
? "pointer"
|
||||
: undefined,
|
||||
cursor: column.getCanSort() && columnDefType !== "group" ? "pointer" : undefined,
|
||||
display: "flex",
|
||||
flexDirection:
|
||||
tableCellProps?.align === "right" ? "row-reverse" : "row",
|
||||
flexDirection: tableCellProps?.align === "right" ? "row-reverse" : "row",
|
||||
overflow: columnDefType === "data" ? "hidden" : undefined,
|
||||
pl:
|
||||
tableCellProps?.align === "center"
|
||||
? `${headerPL}rem`
|
||||
: undefined,
|
||||
pl: tableCellProps?.align === "center" ? `${headerPL}rem` : undefined,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
|
||||
@@ -14,11 +14,9 @@ const DataTable_TableHeadRow = ({
|
||||
const {
|
||||
options: { enableStickyHeader, layoutMode, muiTableHeadRowProps },
|
||||
} = table;
|
||||
const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } =
|
||||
columnVirtualizer ?? {};
|
||||
const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } = columnVirtualizer ?? {};
|
||||
|
||||
const backgroundColor =
|
||||
index % 2 === 0 ? palette.primary.main : palette.secondary.main;
|
||||
const backgroundColor = index % 2 === 0 ? palette.primary.main : palette.secondary.main;
|
||||
|
||||
const tableRowProps = {
|
||||
...parseFromValuesOrFunc(muiTableHeadRowProps, {
|
||||
@@ -30,19 +28,15 @@ const DataTable_TableHeadRow = ({
|
||||
// Access theme from the sx function
|
||||
...(parseFromValuesOrFunc(muiTableHeadRowProps?.sx, theme) || {}),
|
||||
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
|
||||
position:
|
||||
enableStickyHeader && layoutMode === "semantic" ? "sticky" : "relative",
|
||||
position: enableStickyHeader && layoutMode === "semantic" ? "sticky" : "relative",
|
||||
top: 0,
|
||||
}),
|
||||
};
|
||||
|
||||
return (
|
||||
<TableRow {...tableRowProps}>
|
||||
{virtualPaddingLeft && (
|
||||
<th style={{ display: "flex", width: virtualPaddingLeft }} />
|
||||
)}
|
||||
{(virtualColumns ?? headerGroup.headers).map(
|
||||
(headerOrVirtualHeader, staticColumnIndex) => {
|
||||
{virtualPaddingLeft && <th style={{ display: "flex", width: virtualPaddingLeft }} />}
|
||||
{(virtualColumns ?? headerGroup.headers).map((headerOrVirtualHeader, staticColumnIndex) => {
|
||||
const header = columnVirtualizer
|
||||
? headerGroup.headers[headerOrVirtualHeader.index]
|
||||
: headerOrVirtualHeader;
|
||||
@@ -57,11 +51,8 @@ const DataTable_TableHeadRow = ({
|
||||
table={table}
|
||||
/>
|
||||
) : null;
|
||||
},
|
||||
)}
|
||||
{virtualPaddingRight && (
|
||||
<th style={{ display: "flex", width: virtualPaddingRight }} />
|
||||
)}
|
||||
})}
|
||||
{virtualPaddingRight && <th style={{ display: "flex", width: virtualPaddingRight }} />}
|
||||
</TableRow>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -27,12 +27,7 @@ function HideBody({ columns, drawerState, setDrawerState }) {
|
||||
<ScrollBox>
|
||||
<Box sx={{ px: 1, py: 2, display: "flex", flexDirection: "column" }}>
|
||||
{columns.map((column) => (
|
||||
<HideBodyField
|
||||
key={column.id}
|
||||
column={column}
|
||||
hideData={hideData}
|
||||
setHideData={setHideData}
|
||||
/>
|
||||
<HideBodyField key={column.id} column={column} hideData={hideData} setHideData={setHideData} />
|
||||
))}
|
||||
</Box>
|
||||
</ScrollBox>
|
||||
|
||||
@@ -44,11 +44,7 @@ function HideBodyField({ column, hideData, setHideData }) {
|
||||
if (typeof hideData[column.id] === "boolean") {
|
||||
return (
|
||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Checkbox
|
||||
checked={hideData[column.id]}
|
||||
onChange={handleCheckboxChange}
|
||||
name={column.id}
|
||||
/>
|
||||
<Checkbox checked={hideData[column.id]} onChange={handleCheckboxChange} name={column.id} />
|
||||
<Typography variant="subtitle1">{column.header}</Typography>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -7,9 +7,7 @@ import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects";
|
||||
function HideButton({ drawerState, setDrawerState }) {
|
||||
const { hideData } = useDataTable();
|
||||
const flattenHideData = flattenObjectOfObjects(hideData);
|
||||
const falseCount = Object.values(flattenHideData).filter(
|
||||
(value) => value === false,
|
||||
).length;
|
||||
const falseCount = Object.values(flattenHideData).filter((value) => value === false).length;
|
||||
|
||||
return (
|
||||
<Tooltip title="نمایش/مخفی کردن ستون ها">
|
||||
|
||||
@@ -14,8 +14,7 @@ function FilterHeader({ setDrawerState }) {
|
||||
px: 2,
|
||||
py: 1,
|
||||
backgroundColor: "#155175",
|
||||
boxShadow:
|
||||
"rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
|
||||
boxShadow: "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
|
||||
maxWidth: "450px",
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -67,8 +67,7 @@ export const FA_DATATABLE_LOCALIZATION = {
|
||||
rowsPerPage: "ردیف در هر صفحه",
|
||||
save: "ذخیره",
|
||||
search: "جستجو",
|
||||
selectedCountOfRowCountRowsSelected:
|
||||
"{selectedCount} از {rowCount} ردیف انتخاب شده",
|
||||
selectedCountOfRowCountRowsSelected: "{selectedCount} از {rowCount} ردیف انتخاب شده",
|
||||
select: "انتخاب",
|
||||
showAll: "نمایش همه",
|
||||
showAllColumns: "نمایش همه ستونها",
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import { Box, IconButton, ListItemIcon, MenuItem } from "@mui/material";
|
||||
|
||||
const DataTable_ActionMenuItem = ({
|
||||
icon,
|
||||
label,
|
||||
onOpenSubMenu,
|
||||
table,
|
||||
...rest
|
||||
}) => {
|
||||
const DataTable_ActionMenuItem = ({ icon, label, onOpenSubMenu, table, ...rest }) => {
|
||||
const {
|
||||
options: {
|
||||
icons: { ArrowRightIcon },
|
||||
@@ -34,12 +28,7 @@ const DataTable_ActionMenuItem = ({
|
||||
{label}
|
||||
</Box>
|
||||
{onOpenSubMenu && (
|
||||
<IconButton
|
||||
onClick={onOpenSubMenu}
|
||||
onMouseEnter={onOpenSubMenu}
|
||||
size="small"
|
||||
sx={{ p: 0 }}
|
||||
>
|
||||
<IconButton onClick={onOpenSubMenu} onMouseEnter={onOpenSubMenu} size="small" sx={{ p: 0 }}>
|
||||
<ArrowRightIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
|
||||
@@ -30,8 +30,7 @@ const DataTable_CellActionMenu = ({ table, ...rest }) => {
|
||||
|
||||
const internalMenuItems = [
|
||||
(parseFromValuesOrFunc(enableClickToCopy, cell) === "context-menu" ||
|
||||
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) ===
|
||||
"context-menu") && (
|
||||
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) === "context-menu") && (
|
||||
<DataTable_ActionMenuItem
|
||||
icon={<ContentCopy />}
|
||||
key={"mrt-copy"}
|
||||
@@ -68,8 +67,7 @@ const DataTable_CellActionMenu = ({ table, ...rest }) => {
|
||||
};
|
||||
|
||||
const menuItems =
|
||||
columnDef.renderCellActionMenuItems?.(renderActionProps) ??
|
||||
renderCellActionMenuItems?.(renderActionProps);
|
||||
columnDef.renderCellActionMenuItems?.(renderActionProps) ?? renderCellActionMenuItems?.(renderActionProps);
|
||||
|
||||
return (
|
||||
(!!menuItems?.length || !!internalMenuItems?.length) && (
|
||||
|
||||
@@ -93,9 +93,7 @@ const DataTable_Paper = ({
|
||||
))}
|
||||
<DataTable_TableContainer table={table} />
|
||||
{enableBottomToolbar &&
|
||||
(parseFromValuesOrFunc(renderBottomToolbar, { table }) ?? (
|
||||
<DataTable_BottomToolbar table={table} />
|
||||
))}
|
||||
(parseFromValuesOrFunc(renderBottomToolbar, { table }) ?? <DataTable_BottomToolbar table={table} />)}
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,9 +2,7 @@ import { parseCSSVarId, parseFromValuesOrFunc } from "@/core/utils/utils";
|
||||
import { Table } from "@mui/material";
|
||||
import { useMRT_ColumnVirtualizer } from "material-react-table";
|
||||
import { useMemo } from "react";
|
||||
import DataTable_TableBody, {
|
||||
Memo_DataTable_TableBody,
|
||||
} from "../body/TableBody";
|
||||
import DataTable_TableBody, { Memo_DataTable_TableBody } from "../body/TableBody";
|
||||
import DataTable_TableHead from "../head/TableHead";
|
||||
|
||||
const DataTable_Table = ({ table, ...rest }) => {
|
||||
@@ -22,8 +20,7 @@ const DataTable_Table = ({ table, ...rest }) => {
|
||||
renderCaption,
|
||||
},
|
||||
} = table;
|
||||
const { columnSizing, columnSizingInfo, columnVisibility, isFullScreen } =
|
||||
getState();
|
||||
const { columnSizing, columnSizingInfo, columnVisibility, isFullScreen } = getState();
|
||||
|
||||
const tableProps = {
|
||||
...parseFromValuesOrFunc(muiTableProps, { table }),
|
||||
|
||||
@@ -5,8 +5,7 @@ import DataTable_CellActionMenu from "../menus/CellActionMenu";
|
||||
import DataTable_Table from "./Table";
|
||||
import DataTable_TableLoadingOverlay from "./TableLoadingOverlay";
|
||||
|
||||
const useIsomorphicLayoutEffect =
|
||||
typeof window !== "undefined" ? useLayoutEffect : useEffect;
|
||||
const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
|
||||
|
||||
const DataTable_TableContainer = ({ table, ...rest }) => {
|
||||
const {
|
||||
@@ -14,11 +13,9 @@ const DataTable_TableContainer = ({ table, ...rest }) => {
|
||||
options: { enableCellActions, enableStickyHeader, muiTableContainerProps },
|
||||
refs: { bottomToolbarRef, tableContainerRef, topToolbarRef },
|
||||
} = table;
|
||||
const { actionCell, isFullScreen, isLoading, showLoadingOverlay } =
|
||||
getState();
|
||||
const { actionCell, isFullScreen, isLoading, showLoadingOverlay } = getState();
|
||||
|
||||
const loading =
|
||||
showLoadingOverlay !== false && (isLoading || showLoadingOverlay);
|
||||
const loading = showLoadingOverlay !== false && (isLoading || showLoadingOverlay);
|
||||
|
||||
const [totalToolbarHeight, setTotalToolbarHeight] = useState(0);
|
||||
|
||||
@@ -30,15 +27,10 @@ const DataTable_TableContainer = ({ table, ...rest }) => {
|
||||
};
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
const topToolbarHeight =
|
||||
typeof document !== "undefined"
|
||||
? (topToolbarRef.current?.offsetHeight ?? 0)
|
||||
: 0;
|
||||
const topToolbarHeight = typeof document !== "undefined" ? (topToolbarRef.current?.offsetHeight ?? 0) : 0;
|
||||
|
||||
const bottomToolbarHeight =
|
||||
typeof document !== "undefined"
|
||||
? (bottomToolbarRef?.current?.offsetHeight ?? 0)
|
||||
: 0;
|
||||
typeof document !== "undefined" ? (bottomToolbarRef?.current?.offsetHeight ?? 0) : 0;
|
||||
|
||||
setTotalToolbarHeight(topToolbarHeight + bottomToolbarHeight);
|
||||
});
|
||||
@@ -58,9 +50,7 @@ const DataTable_TableContainer = ({ table, ...rest }) => {
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
maxHeight: isFullScreen
|
||||
? `calc(100vh - ${totalToolbarHeight}px)`
|
||||
: undefined,
|
||||
maxHeight: isFullScreen ? `calc(100vh - ${totalToolbarHeight}px)` : undefined,
|
||||
...tableContainerProps?.style,
|
||||
}}
|
||||
sx={(theme) => ({
|
||||
@@ -75,9 +65,7 @@ const DataTable_TableContainer = ({ table, ...rest }) => {
|
||||
>
|
||||
{loading ? <DataTable_TableLoadingOverlay table={table} /> : null}
|
||||
<DataTable_Table table={table} />
|
||||
{enableCellActions && actionCell && (
|
||||
<DataTable_CellActionMenu table={table} />
|
||||
)}
|
||||
{enableCellActions && actionCell && <DataTable_CellActionMenu table={table} />}
|
||||
</TableContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
getCommonToolbarStyles,
|
||||
parseFromValuesOrFunc,
|
||||
} from "@/core/utils/utils";
|
||||
import { getCommonToolbarStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
|
||||
import { Box, alpha, useMediaQuery } from "@mui/material";
|
||||
import DataTable_LinearProgressBar from "./LinearProgressBar";
|
||||
import DataTable_TablePagination from "./TablePagination";
|
||||
@@ -9,12 +6,7 @@ import DataTable_TablePagination from "./TablePagination";
|
||||
const DataTable_BottomToolbar = ({ table, ...rest }) => {
|
||||
const {
|
||||
getState,
|
||||
options: {
|
||||
enablePagination,
|
||||
muiBottomToolbarProps,
|
||||
positionPagination,
|
||||
renderBottomToolbarCustomActions,
|
||||
},
|
||||
options: { enablePagination, muiBottomToolbarProps, positionPagination, renderBottomToolbarCustomActions },
|
||||
refs: { bottomToolbarRef },
|
||||
} = table;
|
||||
const { isFullScreen } = getState();
|
||||
@@ -59,11 +51,7 @@ const DataTable_BottomToolbar = ({ table, ...rest }) => {
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
{renderBottomToolbarCustomActions ? (
|
||||
renderBottomToolbarCustomActions({ table })
|
||||
) : (
|
||||
<span />
|
||||
)}
|
||||
{renderBottomToolbarCustomActions ? renderBottomToolbarCustomActions({ table }) : <span />}
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
@@ -73,8 +61,7 @@ const DataTable_BottomToolbar = ({ table, ...rest }) => {
|
||||
top: 0,
|
||||
}}
|
||||
>
|
||||
{enablePagination &&
|
||||
["both", "bottom"].includes(positionPagination ?? "") && (
|
||||
{enablePagination && ["both", "bottom"].includes(positionPagination ?? "") && (
|
||||
<DataTable_TablePagination position="bottom" table={table} />
|
||||
)}
|
||||
</Box>
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import {
|
||||
flipIconStyles,
|
||||
getCommonTooltipProps,
|
||||
parseFromValuesOrFunc,
|
||||
} from "@/core/utils/utils";
|
||||
import { flipIconStyles, getCommonTooltipProps, parseFromValuesOrFunc } from "@/core/utils/utils";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import {
|
||||
Box,
|
||||
@@ -81,12 +77,7 @@ const DataTable_TablePagination = ({ position = "bottom", table, ...rest }) => {
|
||||
gap: "8px",
|
||||
justifyContent: { md: "space-between", sm: "center" },
|
||||
justifySelf: "flex-end",
|
||||
mt:
|
||||
position === "top" &&
|
||||
enableToolbarInternalActions &&
|
||||
!showGlobalFilter
|
||||
? "3rem"
|
||||
: undefined,
|
||||
mt: position === "top" && enableToolbarInternalActions && !showGlobalFilter ? "3rem" : undefined,
|
||||
position: "relative",
|
||||
px: "8px",
|
||||
py: "12px",
|
||||
@@ -115,8 +106,7 @@ const DataTable_TablePagination = ({ position = "bottom", table, ...rest }) => {
|
||||
>
|
||||
{rowsPerPageOptions.map((option) => {
|
||||
const value = typeof option !== "number" ? option.value : option;
|
||||
const label =
|
||||
typeof option !== "number" ? option.label : `${option}`;
|
||||
const label = typeof option !== "number" ? option.label : `${option}`;
|
||||
return (
|
||||
SelectProps?.children ??
|
||||
(SelectProps?.native ? (
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
getCommonToolbarStyles,
|
||||
parseFromValuesOrFunc,
|
||||
} from "@/core/utils/utils";
|
||||
import { getCommonToolbarStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
|
||||
import { Box, Typography, useMediaQuery } from "@mui/material";
|
||||
import DataTable_LinearProgressBar from "./LinearProgressBar";
|
||||
import DataTable_TablePagination from "./TablePagination";
|
||||
@@ -43,10 +40,7 @@ const DataTable_TopToolbar = ({
|
||||
|
||||
const toolbarProps = parseFromValuesOrFunc(muiTopToolbarProps, { table });
|
||||
|
||||
const stackAlertBanner =
|
||||
isMobile ||
|
||||
!!renderTopToolbarCustomActions ||
|
||||
(showGlobalFilter && isTablet);
|
||||
const stackAlertBanner = isMobile || !!renderTopToolbarCustomActions || (showGlobalFilter && isTablet);
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -112,11 +106,7 @@ const DataTable_TopToolbar = ({
|
||||
>
|
||||
{!special_data && (
|
||||
<>
|
||||
<ResetStorage
|
||||
user_id={user_id}
|
||||
page_name={page_name}
|
||||
table_name={table_name}
|
||||
/>
|
||||
<ResetStorage user_id={user_id} page_name={page_name} table_name={table_name} />
|
||||
<UpdateTable mutate={mutate} />
|
||||
</>
|
||||
)}
|
||||
@@ -136,16 +126,12 @@ const DataTable_TopToolbar = ({
|
||||
/>
|
||||
)}
|
||||
{special_filter && setFilterData && (
|
||||
<FilterCustom
|
||||
filterData={special_filter}
|
||||
setFilterData={setFilterData}
|
||||
/>
|
||||
<FilterCustom filterData={special_filter} setFilterData={setFilterData} />
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
{enablePagination &&
|
||||
["both", "top"].includes(positionPagination ?? "") && (
|
||||
{enablePagination && ["both", "top"].includes(positionPagination ?? "") && (
|
||||
<DataTable_TablePagination position="top" table={table} />
|
||||
)}
|
||||
<DataTable_LinearProgressBar isTopToolbar table={table} />
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { forwardRef } from "react";
|
||||
import { Slide } from "@mui/material";
|
||||
|
||||
export const DialogTransition = forwardRef(
|
||||
function DialogTransition(props, ref) {
|
||||
export const DialogTransition = forwardRef(function DialogTransition(props, ref) {
|
||||
return <Slide direction="up" ref={ref} {...props} />;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -28,9 +28,7 @@ function FilterField({
|
||||
errors,
|
||||
}) {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const defaultFilterTranslation =
|
||||
filterModeOptionFa[filterParameters.filterMode] ||
|
||||
filterParameters.filterMode;
|
||||
const defaultFilterTranslation = filterModeOptionFa[filterParameters.filterMode] || filterParameters.filterMode;
|
||||
|
||||
const handleOpenFilterBox = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
|
||||
@@ -29,13 +29,7 @@ function FilterOptionList({
|
||||
};
|
||||
|
||||
return (
|
||||
<Menu
|
||||
id="simple-menu"
|
||||
anchorEl={anchorEl}
|
||||
keepMounted
|
||||
open={Boolean(anchorEl)}
|
||||
onClose={handleCloseFilterBox}
|
||||
>
|
||||
<Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleCloseFilterBox}>
|
||||
{filterOption.map((option, index) => (
|
||||
<ListItem
|
||||
key={index}
|
||||
|
||||
@@ -2,12 +2,7 @@ import React from "react";
|
||||
import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
|
||||
import { Typography } from "@mui/material";
|
||||
|
||||
function CustomDatePicker({
|
||||
column,
|
||||
filterParameters,
|
||||
defaultFilterTranslation,
|
||||
handleChange,
|
||||
}) {
|
||||
function CustomDatePicker({ column, filterParameters, defaultFilterTranslation, handleChange }) {
|
||||
return (
|
||||
<MuiDatePicker
|
||||
name={`${column.id}.value`}
|
||||
@@ -17,10 +12,7 @@ function CustomDatePicker({
|
||||
}}
|
||||
placeholder={column.header}
|
||||
helperText={
|
||||
<Typography
|
||||
variant="button"
|
||||
sx={{ color: (theme) => theme.palette.primary.main }}
|
||||
>
|
||||
<Typography variant="button" sx={{ color: (theme) => theme.palette.primary.main }}>
|
||||
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
|
||||
</Typography>
|
||||
}
|
||||
|
||||
@@ -4,13 +4,7 @@ import React from "react";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
|
||||
|
||||
function CustomDatePickerRange({
|
||||
item,
|
||||
filterParameters,
|
||||
defaultFilterTranslation,
|
||||
handleChange,
|
||||
errors,
|
||||
}) {
|
||||
function CustomDatePickerRange({ item, filterParameters, defaultFilterTranslation, handleChange, errors }) {
|
||||
return (
|
||||
<Box sx={{ display: "flex", gap: 1 }}>
|
||||
<MuiDatePicker
|
||||
@@ -26,10 +20,7 @@ function CustomDatePickerRange({
|
||||
maxDate={filterParameters.value[1]}
|
||||
placeholder={`از تاریخ`}
|
||||
helperText={
|
||||
<Typography
|
||||
variant="button"
|
||||
sx={{ color: (theme) => theme.palette.primary.main }}
|
||||
>
|
||||
<Typography variant="button" sx={{ color: (theme) => theme.palette.primary.main }}>
|
||||
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
|
||||
</Typography>
|
||||
}
|
||||
@@ -46,11 +37,7 @@ function CustomDatePickerRange({
|
||||
}}
|
||||
minDate={filterParameters.value[0]}
|
||||
placeholder={`تا تاریخ`}
|
||||
helperText={
|
||||
errors?.[`${item.id}`]?.value
|
||||
? errors?.[`${item.id}`]?.value.message
|
||||
: null
|
||||
}
|
||||
helperText={errors?.[`${item.id}`]?.value ? errors?.[`${item.id}`]?.value.message : null}
|
||||
error={Boolean(errors?.[`${item.id}`]?.value)}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user