diff --git a/package.json b/package.json index 3e7a01c..b4ddfd0 100644 --- a/package.json +++ b/package.json @@ -22,12 +22,15 @@ "formik": "^2.4.5", "jalali-moment": "^3.3.11", "material-react-table": "^2.11.2", - "next": "14.1.0", + "next": "^14.2.3", "react": "^18", "react-dom": "^18", + "react-toastify": "^10.0.5", "sass": "^1.75.0", "stylis": "^4.3.1", - "stylis-plugin-rtl": "^2.1.1" + "stylis-plugin-rtl": "^2.1.1", + "swr": "^2.2.5", + "yup": "^1.4.0" }, "devDependencies": { "eslint": "^8", diff --git a/public/global.scss b/public/global.scss index 7802651..a383b5f 100644 --- a/public/global.scss +++ b/public/global.scss @@ -1 +1,7 @@ -@import "fontiran"; \ No newline at end of file +@import "fontiran"; + +.filter-toast { + box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, rgba(0, 0, 0, 0.3) 0px 8px 16px -8px; + background-color: #d0dfe8; + border: 1px dashed #095b8c; +} \ No newline at end of file diff --git a/src/app/(withAuth)/dashboard/layout.js b/src/app/(withAuth)/dashboard/layout.js index 877f900..213bb0a 100644 --- a/src/app/(withAuth)/dashboard/layout.js +++ b/src/app/(withAuth)/dashboard/layout.js @@ -1,6 +1,10 @@ +import 'react-toastify/dist/ReactToastify.css'; + const Layout = ({children}) => { return ( - <>{children} + <> + {children} + ) } diff --git a/src/app/(withAuth)/dashboard/template.js b/src/app/(withAuth)/dashboard/template.js index c44d626..62759c6 100644 --- a/src/app/(withAuth)/dashboard/template.js +++ b/src/app/(withAuth)/dashboard/template.js @@ -1,6 +1,7 @@ import {Box, Stack} from "@mui/material"; import HeaderWithLogo from "@/components/layouts/dashboard/headerWithLogo"; import HeaderWithSidebar from "@/components/layouts/dashboard/headerWithSidebar"; +import 'react-toastify/dist/ReactToastify.css'; const Template = ({children}) => { return ( diff --git a/src/app/template.js b/src/app/template.js index cc8a8f2..14f15b6 100644 --- a/src/app/template.js +++ b/src/app/template.js @@ -2,7 +2,9 @@ import cacheProviderRtl from "@/core/utils/cacheRtl"; import {CssBaseline, ThemeProvider} from "@mui/material"; import theme from "@/core/utils/theme"; import {AppRouterCacheProvider} from "@mui/material-nextjs/v14-appRouter"; -import "^/global.scss" +import 'react-toastify/dist/ReactToastify.css'; +import "^/global.scss"; +import {ToastContainer} from "react-toastify"; const Template = ({children}) => { return ( @@ -10,6 +12,7 @@ const Template = ({children}) => { {children} + ) diff --git a/src/components/home/Toolbar.jsx b/src/components/home/Toolbar.jsx index 437f6ee..1270b92 100644 --- a/src/components/home/Toolbar.jsx +++ b/src/components/home/Toolbar.jsx @@ -2,7 +2,9 @@ import {Button} from "@mui/material"; const Toolbar = ({columns}) => { return ( - + <> + + ) } export default Toolbar diff --git a/src/components/home/index.jsx b/src/components/home/index.jsx index 2682b64..090a572 100644 --- a/src/components/home/index.jsx +++ b/src/components/home/index.jsx @@ -17,7 +17,6 @@ function HomeComponent() { enableColumnFilter: true, datatype: "text", filterFn: "contains", - inputType: "textField", enableClickToCopy: true, columnFilterModeOptions: [ "equals", @@ -32,7 +31,6 @@ function HomeComponent() { enableColumnFilter: true, datatype: "text", filterFn: "equals", - inputType: "textField", columnFilterModeOptions: [ "equals", "notEquals", @@ -48,7 +46,6 @@ function HomeComponent() { enableColumnFilter: true, datatype: "text", filterFn: "notEquals", - inputType: "textField", columnFilterModeOptions: [ "equals", "notEquals", @@ -62,7 +59,6 @@ function HomeComponent() { enableColumnFilter: true, datatype: "text", filterFn: "equals", - inputType: "textField", columnFilterModeOptions: [ "equals", "notEquals", @@ -71,7 +67,6 @@ function HomeComponent() { "greaterThan", "fuzzy" ], - }, { accessorKey: 'state', @@ -80,7 +75,6 @@ function HomeComponent() { enableColumnFilter: true, datatype: "text", filterFn: "contains", - inputType: "textField", columnFilterModeOptions: [ "equals", "notEquals", @@ -92,9 +86,20 @@ function HomeComponent() { header: 'محدوده', id: "price", enableColumnFilter: true, - datatype: "nemeric", + datatype: "numeric", + filterFn: "equals", + columnFilterModeOptions: [ + "equals", + "notEquals", + ], + }, + { + accessorKey: 'created_at', + header: 'تاریخ ساخت', + id: "created_at", + enableColumnFilter: true, + datatype: "date", filterFn: "between", - inputType: "betweenNum", }, { accessorKey: 'updated_at', @@ -102,26 +107,33 @@ function HomeComponent() { id: "updated_at", enableColumnFilter: true, datatype: "date", - filterFn: "between", - inputType: "betweenDate", + filterFn: "equals", }, { accessorKey: 'company', header: 'نام شرکت', id: "company", enableColumnFilter: true, - datatype: "text", + datatype: "numeric", filterFn: "equals", - inputType: "select2", + columnSelectOption: [ + {value: 1, label: "وایتل"}, + {value: 2, label: "اسنپ"}, + {value: 3, label: "تپسی"} + ], }, { accessorKey: 'area', header: 'منطقه', id: "area", enableColumnFilter: true, - datatype: "text", + datatype: "array", filterFn: "equals", - inputType: "select", + columnSelectOption: [ + {value: 1, label: "وایتل"}, + {value: 2, label: "اسنپ"}, + {value: 3, label: "تپسی"} + ], }, ], [], @@ -129,7 +141,7 @@ function HomeComponent() { return ( <> - + ); diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js index d6efd7a..ec33f55 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -1,19 +1,174 @@ -import {useMaterialReactTable} from "material-react-table"; import DataTable_Paper from "./table/Paper"; +import {useMaterialReactTable} from "material-react-table"; +import {FA_DATATABLE_LOCALIZATION} from "./localization/fa/datatable"; +import useTableSetting from "@/lib/hooks/useTableSetting"; +import {flattenArrayOfObjects} from "@/core/utils/flattenArrayOfObjects"; +import Toolbar from "@/components/home/Toolbar"; +import useDataTable from "@/lib/hooks/useDataTable"; +import {useMemo, useState} from "react"; -const isTableInstanceProp = (props) => props.table !== undefined; +const data = [ + { + name: { + firstName: 'امین', + lastName: 'قاسمپور', + }, + address: 'فلان جا', + city: 'تهران', + state: 'بررسی شده', + price: '20', + updated_at: '2024/05/02', + company: 'همراه اول', + area: 'منطقه 5', + }, + { + name: { + firstName: 'امیر حسین', + lastName: 'محمودی', + }, + address: 'فلان جا', + city: 'تهران', + state: 'تکمیل شده', + price: '27', + updated_at: '2024/05/02', + company: 'وایتل', + area: 'منطقه 27', + }, + { + name: { + firstName: 'یاسمن', + lastName: 'علی اکبری', + }, + address: 'فلان جا', + city: 'شیراز', + state: 'بررسی شده', + price: '32', + updated_at: '2024/05/02', + company: 'ایرانسل', + area: 'منطقه 23', + }, + { + name: { + firstName: 'حمیدرضا', + lastName: 'رنجبرپور', + }, + address: 'فلان جا', + city: 'اصفهان', + state: 'بررسی شده', + price: '45', + updated_at: '2024/05/02', + company: 'ایرانول', + area: 'منطقه 21', + }, + { + name: { + firstName: 'محمد', + lastName: 'جلالی', + }, + address: 'فلان جا', + city: 'رشت', + state: 'درحال بررسی', + price: '8', + updated_at: '2024/05/02', + company: 'فیلیمو', + area: 'منطقه 8', + }, +]; const DataTable_Main = (props) => { - let table; + const {filterData} = useDataTable(); + const {table_url, user_id, page_name, table_name, columns, initialStateProps} = props + const flatColumns = flattenArrayOfObjects(columns, 'columns') + const {settingStore, hideAction, sortAction} = useTableSetting(); + const [pagination, setPagination] = useState({pageIndex: 0, pageSize: 10}); + const filters = Object.keys(filterData) + .map(key => { + const value = filterData[key].value; + if (value !== "" && + !(Array.isArray(value) && (value.length === 0 || (value.length === 2 && value[0] === "" && value[1] === "")))) { + return filterData[key]; + } + }) + .filter(Boolean); + const storedFilters = settingStore?.[user_id]?.[page_name]?.[table_name]?.filters; + const finalFilters = storedFilters || filters; - if (isTableInstanceProp(props)) { - table = props.table; - } else { - // eslint-disable-next-line react-hooks/rules-of-hooks - table = useMaterialReactTable(props); + const fetchUrl = useMemo(() => { + const params = new URLSearchParams(); + params.set("start", `${pagination.pageIndex * pagination.pageSize}`); + params.set("size", pagination.pageSize); + params.set("filters", JSON.stringify(finalFilters ?? [])); + params.set("sorting", JSON.stringify(settingStore?.[user_id]?.[page_name]?.[table_name]?.['sorts'] ?? [])); + return `${table_url}?${params}`; + }, [table_url, finalFilters, pagination, columns]); + + const onColumnVisibilityChange = (event) => { + const settingValue = event(); + hideAction(user_id, page_name, table_name, settingValue, flatColumns); + }; + const onSortingChange = (event) => { + const settingValue = event(settingStore?.[user_id]?.[page_name]?.[table_name]?.['sorts'] || []); + sortAction(user_id, page_name, table_name, settingValue, flatColumns); } - return ; + const table = useMaterialReactTable({ + localization: FA_DATATABLE_LOCALIZATION, + columns, + data: data, + // manualSorting: true, + renderTopToolbarCustomActions: ({table}) => (<> + + ), + initialState: { + density: 'compact', + columnVisibility: settingStore?.[user_id]?.[page_name]?.[table_name]?.['hides'], + sorting: settingStore?.[user_id]?.[page_name]?.[table_name]?.['sorts'] || [], + ...initialStateProps + }, + state: { + columnVisibility: settingStore?.[user_id]?.[page_name]?.[table_name]?.['hides'], + sorting: settingStore?.[user_id]?.[page_name]?.[table_name]?.['sorts'] || [], + pagination + }, + muiTableHeadProps: { + sx: { + borderTop: "1px solid #e1e1e1", + borderBottom: "2px solid #e1e1e1", + } + }, + muiTableHeadCellProps: { + sx: { + color: "primary.main", + borderLeft: "1px solid #e1e1e1", + "&:first-of-type": { + borderLeft: "unset" + } + }, + }, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + "&:first-of-type": { + borderLeft: "unset" + } + }, + }, + manualFiltering: true, + manualPagination: true, + onPaginationChange: setPagination, + manualSorting: true, + onColumnVisibilityChange: onColumnVisibilityChange, + onSortingChange: onSortingChange, + ...props + }) + + return ; }; export default DataTable_Main; + + + diff --git a/src/core/components/DataTable/filter/BetweenNumberFilter.jsx b/src/core/components/DataTable/filter/BetweenNumberFilter.jsx deleted file mode 100644 index 0b3512a..0000000 --- a/src/core/components/DataTable/filter/BetweenNumberFilter.jsx +++ /dev/null @@ -1,58 +0,0 @@ -import {Grid, TextField} from '@mui/material'; -import {useEffect} from "react"; - -const BetweenNumberFilter = ({formik, id , defaultValue}) => { - - useEffect(() => { - formik.setFieldValue(`${id}[0]`, defaultValue?.[0] || ''); - formik.setFieldValue(`${id}[1]`, defaultValue?.[1] || ''); - }, []); - const handleBlur = (index) => () => { - const minValue = formik.values[id][0]; - const maxValue = formik.values[id][1]; - - if (index === 0 && minValue !== '' && maxValue !== '' && parseInt(minValue) > parseInt(maxValue)) { - formik.setFieldValue(`${id}[0]`, maxValue); - } - - if (index === 1 && minValue !== '' && maxValue !== '' && parseInt(maxValue) < parseInt(minValue)) { - formik.setFieldValue(`${id}[1]`, minValue); - } - }; - return ( - - - - - - - - - ); -}; - -export default BetweenNumberFilter; diff --git a/src/core/components/DataTable/filter/DatePicker/BetweenDateFilter.jsx b/src/core/components/DataTable/filter/DatePicker/BetweenDateFilter.jsx deleted file mode 100644 index 0e4a325..0000000 --- a/src/core/components/DataTable/filter/DatePicker/BetweenDateFilter.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import {Grid} from '@mui/material'; -import MuiDatePicker from "@/core/components/DataTable/filter/DatePicker/MuiDatePicker"; -import {useEffect, useState} from "react"; - -const BetWeenDateFilter = ({formik, id, defaultValue}) => { - useEffect(() => { - formik.setFieldValue(`${id}[0]`, defaultValue?.[0] || ''); - formik.setFieldValue(`${id}[1]`, defaultValue?.[1] || ''); - }, []); - - const [dateRange, setDateRange] = useState(defaultValue); - - const handleDateChange = (index, value) => { - const newRange = [...dateRange]; - newRange[index] = value; - setDateRange(newRange); - }; - - return ( - - - handleDateChange(0, value)}/> - - - handleDateChange(1, value)}/> - - - ); -}; - -export default BetWeenDateFilter; diff --git a/src/core/components/DataTable/filter/DatePicker/MuiDatePicker.jsx b/src/core/components/DataTable/filter/DatePicker/MuiDatePicker.jsx deleted file mode 100644 index f2b0876..0000000 --- a/src/core/components/DataTable/filter/DatePicker/MuiDatePicker.jsx +++ /dev/null @@ -1,67 +0,0 @@ -import { LocalizationProvider, MobileDateTimePicker } from "@mui/x-date-pickers"; -import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali"; -import moment from "jalali-moment"; -import { faIR } from "@mui/x-date-pickers/locales"; -import { Box, IconButton, InputAdornment, TextField } from "@mui/material"; -import ClearIcon from "@mui/icons-material/Clear"; -import { useState } from "react"; - -export default function MuiDatePicker({label, name, formik, defaultValue, minDate, maxDate, onDateChange }) { - const [pickerValue, setPickerValue] = useState(defaultValue ? new Date(defaultValue) : null); - - return ( - - - { - const date = new Date(newValue); - const formattedDate = moment(date) - .locale("en") - .format("YYYY-MM-DD HH:mm"); - formik.setFieldValue(name, formattedDate); - onDateChange(formattedDate); - setPickerValue(newValue); - }} - slotProps={{ - textField: { - placeholder: "تاریخ خود را وارد کنید", - helperText: label, - InputProps: { - endAdornment: ( - - { - event.stopPropagation(); - formik.setFieldValue(name, ""); - setPickerValue(null); - }} - sx={{ - color: "#bfbfbf", - '&:hover': { - backgroundColor: 'rgba(189, 189, 189, 0.1)', - }, - }} - > - - - - ), - }, - }, - }} - value={pickerValue} - minDate={minDate ? new Date(minDate) : null} - maxDate={maxDate ? new Date(maxDate) : null} - /> - - - ); -} diff --git a/src/core/components/DataTable/filter/FilterBody.jsx b/src/core/components/DataTable/filter/FilterBody.jsx new file mode 100644 index 0000000..385981b --- /dev/null +++ b/src/core/components/DataTable/filter/FilterBody.jsx @@ -0,0 +1,207 @@ +'use client' + +import {Box, Button, Drawer, styled} from "@mui/material"; +import {Form, Formik} from "formik"; +import useTableSetting from "@/lib/hooks/useTableSetting"; +import {useEffect, useRef, useState} from "react"; +import FilterHeader from "@/core/components/DataTable/filter/FilterHeader"; +import * as Yup from "yup"; +import FilterBodyField from "@/core/components/DataTable/filter/FilterBodyField"; +import {toast} from "react-toastify"; +import AskForKeep from "@/core/components/NotificationDesign/AskForKeep"; +import useDataTable from "@/lib/hooks/useDataTable"; + +const ScrollBox = styled(Box)({ + flexGrow: 1, + overflowY: 'scroll', + maxWidth: "450px", + '::-webkit-scrollbar': { + width: '5px', + }, + '::-webkit-scrollbar-track': { + boxShadow: 'inset 0 0 5px #fff', + borderRadius: '5px', + }, + '::-webkit-scrollbar-thumb': { + background: '#155175', + borderRadius: '0px', + } +}); + +function FilterBody({columns, drawerState, setDrawerState, user_id, page_name, table_name}) { + const {settingStore, filterAction} = useTableSetting(); + const [initialValues, setInitialValues] = useState({}); + const [validationSchema, setValidationSchema] = useState({}); + const {filterData, setFilterData} = useDataTable(); + const filterDataRef = useRef(filterData); + useEffect(() => { + filterDataRef.current = filterData; + }, [filterData]); + + useEffect(() => { + const values = columns.reduce((acc, column) => { + if (!column.enableColumnFilter) return acc; + const filter = settingStore?.[user_id]?.[page_name]?.[table_name]?.['filters']?.find((filter) => filter.id === column.id); + if (column.datatype === 'array') { + acc[column.id] = { + id: column.id, + value: filter?.value || [], + filterFn: filter?.fn || column._filterFn, + datatype: column.datatype + }; + } else if (column._filterFn === "between") { + acc[column.id] = { + id: column.id, + value: filter?.value || ["", ""], + filterFn: filter?.fn || column._filterFn, + datatype: column.datatype + }; + } else { + acc[column.id] = { + id: column.id, + value: filter?.value || '', + filterFn: filter?.fn || column._filterFn, + datatype: column.datatype + }; + } + return acc; + }, {}); + setInitialValues(Object.keys(filterData).length !== 0 ? filterData : values); + }, [columns, settingStore, user_id, page_name, table_name, filterData]); + + + useEffect(() => { + const generatedSchema = Yup.object().shape( + Object.keys(initialValues).reduce((acc, key) => { + const initialValue = initialValues[key]; + if (initialValue.filterFn === "between") { + acc[key] = Yup.object().shape({ + value: Yup.array() + .of(Yup.string().nullable()) + .test({ + test(value, ctx) { + const [start, end] = value || ["", ""]; + if (initialValue.datatype === "numeric" && parseInt(end, 10) <= parseInt(start, 10)) { + return ctx.createError({ + message: `مقدار وارده باید بیشتر از (${start}) باشد`, + }); + } else if ((start && !end) || (!start && end)) { + return ctx.createError({ + message: "این بخش را تکمیل نمایید", + }); + } + return true; + }, + }), + }); + } + return acc; + }, {}) + ); + + setValidationSchema(generatedSchema); + }, [initialValues]); + + + const handleSubmit = (values, {setSubmitting}) => { + toast.dismiss({containerId: "filtering"}); + setDrawerState(false); + setFilterData(values); + toast(, { + containerId: "filtering", + className: "filter-toast", + position: "bottom-left", + draggable: true, + autoClose: false, + }); + setSubmitting(false); + }; + + const onSaveFilter = () => { + const currentFilterData = filterDataRef.current; + const arrayOfObjects = Object.keys(currentFilterData).map(key => { + const value = currentFilterData[key].value; + if (value !== "" && + !(Array.isArray(value) && (value.length === 0 || (value.length === 2 && value[0] === "" && value[1] === "")))) { + return currentFilterData[key]; + } + }).filter(Boolean); + filterAction(user_id, page_name, table_name, arrayOfObjects, columns) + toast.dismiss({containerId: "filtering"}); + }; + + return ( + setDrawerState(false)} + sx={{overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%"}}> + + {Object.keys(initialValues).length > 0 && ( + + + { + ({ + values, + handleChange, + handleBlur, + setFieldValue, + errors, + touched, + isSubmitting, + isValid, + dirty, + resetForm + }) => ( +
+ + { + columns.map((column) => ( + column.enableColumnFilter && ( + + ) + )) + } + + + + +
+ )} +
+
+ )} +
+ ); +} + +export default FilterBody; \ No newline at end of file diff --git a/src/core/components/DataTable/filter/FilterBodyField.jsx b/src/core/components/DataTable/filter/FilterBodyField.jsx new file mode 100644 index 0000000..b12e770 --- /dev/null +++ b/src/core/components/DataTable/filter/FilterBodyField.jsx @@ -0,0 +1,111 @@ +import {useState} from "react"; +import FilterOptionList from "@/core/components/DataTable/filter/FilterOptionList"; +import CustomSelect from "@/core/components/DataTable/filter/fieldsType/CustomSelect"; +import CustomTextField from "@/core/components/DataTable/filter/fieldsType/CustomTextField"; +import CustomTextFieldRange from "@/core/components/DataTable/filter/fieldsType/CustomTextFieldRange"; +import CustomDatePickerRange from "@/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePickerRange"; +import CustomDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePicker"; +import CustomSelectMultiple from "@/core/components/DataTable/filter/fieldsType/CustomSelectMultiple"; + +const columnFilterModeOptionFa = { + equals: "برابر", + notEquals: "نابرابر", + contains: "شامل", + lessThan: "کوچکتر", + greaterThan: "بزرگتر", + fuzzy: "فازی", + between: "مابین" +}; + +function FilterBodyField({ + column, + filterParameters, + handleChange, + handleBlur, + setFieldValue, + errors, + touched, + resetForm + }) { + const [anchorEl, setAnchorEl] = useState(null); + const defaultFilterTranslation = columnFilterModeOptionFa[filterParameters.filterFn] || filterParameters.filterFn; + + const handleOpenFilterBox = (event) => { + setAnchorEl(event.currentTarget); + }; + + return ( + <> + {filterParameters.datatype === "numeric" && filterParameters.filterFn === "between" ? ( + + ) : filterParameters.datatype === "numeric" && filterParameters.filterFn === "equals" && Array.isArray(column.columnSelectOption) ? ( + + ) : filterParameters.datatype === "date" && filterParameters.filterFn === "equals" ? ( + + ) : filterParameters.datatype === "date" && filterParameters.filterFn === "between" ? ( + + ) : filterParameters.datatype === "array" && filterParameters.filterFn === "equals" ? ( + + ) : ( + setFieldValue(`${column.id}.value`, e.target.value)} + /> + )} + {Array.isArray(column.columnFilterModeOptions) && ( + + )} + + ); +} + +export default FilterBodyField; \ No newline at end of file diff --git a/src/core/components/DataTable/filter/FilterButton.jsx b/src/core/components/DataTable/filter/FilterButton.jsx new file mode 100644 index 0000000..ec444bb --- /dev/null +++ b/src/core/components/DataTable/filter/FilterButton.jsx @@ -0,0 +1,17 @@ +'use client' +import FilterAltIcon from '@mui/icons-material/FilterAlt'; +import {IconButton, Tooltip} from "@mui/material"; + +function FilterButton({drawerState, setDrawerState}) { + return ( + + { + setDrawerState(!drawerState) + }} aria-label="filter table"> + + + + ); +} + +export default FilterButton; diff --git a/src/core/components/DataTable/filter/FilterColumn.jsx b/src/core/components/DataTable/filter/FilterColumn.jsx deleted file mode 100644 index 3c0a16c..0000000 --- a/src/core/components/DataTable/filter/FilterColumn.jsx +++ /dev/null @@ -1,201 +0,0 @@ -"use client" -import {Box, Button, Divider, Drawer, FormControl, IconButton, styled, Tooltip, Typography} from '@mui/material'; -import {useFormik} from 'formik'; -import {useEffect, useState} from "react"; -import useTableSetting from "@/lib/hooks/useTableSetting"; -import BetweenNumberFilter from "@/core/components/DataTable/filter/BetweenNumberFilter"; -import BetWeenDateFilter from "@/core/components/DataTable/filter/DatePicker/BetweenDateFilter"; -import SelectBoxMultiple from "@/core/components/DataTable/filter/SelectBoxMultiple"; -import SelectBox from "@/core/components/DataTable/filter/SelectBox"; -import FilterAltIcon from '@mui/icons-material/FilterAlt'; -import CloseIcon from '@mui/icons-material/Close'; -import TextFieldWithFnBox from "@/core/components/DataTable/filter/TextFieldWithFnBox/TextFieldWithFnBox"; - -function FilterColumn({columns}) { - const [open, setOpen] = useState(false); - const [selectedFilters, setSelectedFilters] = useState([]); - const [userId, setUserId] = useState(0); - const [pageName, setPageName] = useState('testPage'); - const [tableName, setTableName] = useState('testTable'); - const {settingStore, hideAction, filterAction, sortAction,} = useTableSetting(); - - const DrawerHeader = styled('div')(({theme}) => ({ - display: 'flex', - alignItems: 'center', - padding: theme.spacing(0, 1), - justifyContent: 'space-between', - })); - const toggleDrawer = (newOpen) => () => { - setOpen(newOpen); - }; - const handleDrawerClose = () => { - setOpen(false); - }; - useEffect(() => { - const settingValue = settingStore?.[userId]?.[pageName]?.[tableName]?.['filters'] || []; - setSelectedFilters(settingValue.length > 0 ? settingValue : []); - if (!settingValue.length > 0) { - formik.resetForm(); - } - }, [settingStore]); - - const handleSelectFilter = (fieldName, filterFn) => { - const filterIndex = selectedFilters.findIndex(filter => filter.id === fieldName); - if (filterIndex !== -1) { - const updatedFilters = [...selectedFilters]; - updatedFilters[filterIndex].fn = filterFn; - setSelectedFilters(updatedFilters); - } else { - const newFilter = {id: fieldName, fn: filterFn}; - const updatedFilters = [...selectedFilters, newFilter]; - setSelectedFilters(updatedFilters); - } - }; - - const initialValues = columns.reduce((acc, column) => { - if (column.enableColumnFilter) { - const filter = settingStore?.[userId]?.[pageName]?.[tableName]?.['filters']?.find((filter) => filter.id === column.id); - if (column.filterFn === 'betweenNum' || column.filterFn === 'betweenDate') { - acc[column.id] = filter?.value || ["", ""]; - } else if (column.type === 'select2') { - acc[column.id] = filter?.value || []; - } else { - acc[column.id] = filter?.value || ''; - } - } - return acc; - }, {}); - - const formik = useFormik({ - initialValues, - onSubmit: (values) => { - const updatedFilters = selectedFilters.map(filter => { - const value = values[filter.id]; - if (value !== undefined) { - return {...filter, value}; - } - return filter; - }); - Object.entries(values).forEach(([fieldName, value]) => { - const filterIndex = updatedFilters.findIndex(filter => filter.id === fieldName); - if (filterIndex === -1 && value !== '' && value !== null && value !== undefined) { - const column = columns.find(col => col.id === fieldName); - updatedFilters.push({id: fieldName, value, fn: column.filterFn, datatype: column.datatype}); - } - }); - - const newArrayFilter = updatedFilters.filter((filter) => { - const value = values[filter.id]; - - return ( - value !== '' && - value !== null && - value !== undefined && - !(Array.isArray(value) && (value.length === 0 || (value.length === 2 && value.every((v) => v === '')))) - ); - }); - - setSelectedFilters(newArrayFilter); - filterAction(userId, pageName, tableName, newArrayFilter, columns); - } - - }); - console.log(settingStore?.[userId]?.[pageName]?.[tableName]?.['filters']) - return ( - <> - - - - - - - - فیلتر - - - - - - - {columns.map((column, index) => ( - column.enableColumnFilter && - (column.inputType === 'betweenDate' ? - filter.id === column.id)?.value || ''} - /> - : column.inputType === 'betweenNum' ? - filter.id === column.id)?.value || ["", ""]} - /> - : column.inputType === 'select2' ? - filter.id === column.id)?.value || []} - /> - : column.inputType === 'select' ? - filter.id === column.id)?.value || ''} - /> - : - filter.id === column.id)?.fn || column._filterFn} - columnFilterModeOptions={column.columnFilterModeOptions} - onSelectFilter={(filterFn) => handleSelectFilter(column.id, filterFn)} - defaultValue={formik.values[column.id] || (settingStore?.[userId]?.[pageName]?.[tableName]?.['filters'] || []).find(filter => filter.id === column.id)?.value || ''} - /> - ) - ))} - - - - - - - - - - - ); -} - -export default FilterColumn; - - diff --git a/src/core/components/DataTable/filter/FilterHeader.jsx b/src/core/components/DataTable/filter/FilterHeader.jsx new file mode 100644 index 0000000..2acd0b7 --- /dev/null +++ b/src/core/components/DataTable/filter/FilterHeader.jsx @@ -0,0 +1,32 @@ +'use client' + +import {Box, IconButton, Typography} from "@mui/material"; +import CancelIcon from '@mui/icons-material/Cancel'; +import FilterAltIcon from '@mui/icons-material/FilterAlt'; + +function FilterHeader({setDrawerState}) { + return ( + + + + فیلتر + + setDrawerState(false)}> + + + + ); +} + +export default FilterHeader; \ No newline at end of file diff --git a/src/core/components/DataTable/filter/FilterOptionList.jsx b/src/core/components/DataTable/filter/FilterOptionList.jsx new file mode 100644 index 0000000..ce02c23 --- /dev/null +++ b/src/core/components/DataTable/filter/FilterOptionList.jsx @@ -0,0 +1,48 @@ +'use client' + +import {ListItem, Menu} from "@mui/material"; +import {useState} from "react"; + +function FilterOptionList({ + column, + filterType, + filterOption, + anchorEl, + columnFilterModeOptionFa, + setAnchorEl, + setFieldValue + }) { + const [selectedFilter, setSelectedFilter] = useState(filterType); + + const handleChangeItem = (event, index) => { + setFieldValue(`${column.id}.value`, filterOption[index] === "between" ? ["", ""] : ""); + setFieldValue(`${column.id}.filterFn`, filterOption[index]); + setSelectedFilter(filterOption[index]); + setAnchorEl(null); + } + + const handleCloseFilterBox = () => { + setAnchorEl(null); + }; + + return ( + + {filterOption.map((option, index) => ( + handleChangeItem(event, index)} + selected={option === selectedFilter} + sx={{cursor: 'pointer', width: "100px", display: "flex", justifyContent: "center"}}> + {columnFilterModeOptionFa[option]} + + ))} + + ); +} + +export default FilterOptionList; \ No newline at end of file diff --git a/src/core/components/DataTable/filter/SelectBox.jsx b/src/core/components/DataTable/filter/SelectBox.jsx deleted file mode 100644 index 88cce6e..0000000 --- a/src/core/components/DataTable/filter/SelectBox.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import InputLabel from '@mui/material/InputLabel'; -import MenuItem from '@mui/material/MenuItem'; -import FormControl from '@mui/material/FormControl'; -import Select from '@mui/material/Select'; -import {useEffect, useState} from "react"; -const names = [ - 'Oliver Hansen', - 'Van Henry', - 'April Tucker', - 'Ralph Hubbard', - 'Omar Alexander', - 'Carlos Abbott', - 'Miriam Wagner', - 'Bradley Wilkerson', - 'Virginia Andrews', - 'Kelly Snyder', -]; -const SelectBox = ({ formik, id, defaultValue }) => { - - useEffect(() => { - formik.setFieldValue(id, defaultValue || ''); - }, []); - - const [selectedValue, setSelectedValue] = useState(defaultValue || ''); - - const handleChange = (event) => { - const { value } = event.target; - setSelectedValue(value); - formik.setFieldValue(id, value); - }; - - return ( - <> - - انتخاب - - - - ); -}; - -export default SelectBox; diff --git a/src/core/components/DataTable/filter/SelectBoxMultiple.jsx b/src/core/components/DataTable/filter/SelectBoxMultiple.jsx deleted file mode 100644 index 4355c72..0000000 --- a/src/core/components/DataTable/filter/SelectBoxMultiple.jsx +++ /dev/null @@ -1,116 +0,0 @@ -import {useTheme} from '@mui/material/styles'; -import Box from '@mui/material/Box'; -import OutlinedInput from '@mui/material/OutlinedInput'; -import InputLabel from '@mui/material/InputLabel'; -import MenuItem from '@mui/material/MenuItem'; -import FormControl from '@mui/material/FormControl'; -import Select from '@mui/material/Select'; -import Chip from '@mui/material/Chip'; -import {useEffect, useState} from "react"; - -const ITEM_HEIGHT = 48; -const ITEM_PADDING_TOP = 8; -const MenuProps = { - PaperProps: { - style: { - maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, - width: 250, - }, - }, -}; - -const names = [ - 'Oliver Hansen', - 'Van Henry', - 'April Tucker', - 'Ralph Hubbard', - 'Omar Alexander', - 'Carlos Abbott', - 'Miriam Wagner', - 'Bradley Wilkerson', - 'Virginia Andrews', - 'Kelly Snyder', -]; - -function getStyles(name, personName, theme) { - return { - fontWeight: - personName.indexOf(name) === -1 - ? theme.typography.fontWeightRegular - : theme.typography.fontWeightMedium, - }; -} - -const SelectBoxMultiple = ({formik, id, defaultValue}) => { - const theme = useTheme(); - const [personName, setPersonName] = useState(defaultValue || []); - - useEffect(() => { - defaultValue.forEach((value, index) => { - formik.setFieldValue(`${id}[${index}]`, value || ''); - }); - - }, []); - - const handleChange = (event) => { - const { - target: {value}, - } = event; - - const selectedValues = typeof value === 'string' ? value.split(',').filter(item => item.trim() !== '') : value; - - formik.setFieldValue(id, []); - - if (selectedValues.length === 0) { - setPersonName([]); - formik.setFieldValue(id, []); - } else { - setPersonName(selectedValues); - selectedValues.forEach((selectedValue, index) => { - formik.setFieldValue(`${id}[${index}]`, selectedValue); - }); - } - }; - - return ( - <> - - انتخاب - - - - ); -}; - -export default SelectBoxMultiple; diff --git a/src/core/components/DataTable/filter/TextFieldWithFnBox/FilterBox.jsx b/src/core/components/DataTable/filter/TextFieldWithFnBox/FilterBox.jsx deleted file mode 100644 index 3bba610..0000000 --- a/src/core/components/DataTable/filter/TextFieldWithFnBox/FilterBox.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import {ClickAwayListener, List, ListItem, ListItemText, Paper, Popper} from '@mui/material'; -import {useState} from "react"; - -const columnFilterModeOptionFa = { - equals: "برابر", - notEquals: "نابرابر", - contains: "شامل", - lessThan: "کوچکتر", - greaterThan: "بزرگتر", - fuzzy: "فازی", -} - -function FilterBox({ - anchorEl, open = false, handleClose = () => { - }, columnFilterModeOptions, onSelectFilter, defaultFilter - }) { - const [selectedFilter, setSelectedFilter] = useState(defaultFilter); - - const id = open ? 'simple-popper' : undefined; - const handleSelectFilter = (filterFn) => { - setSelectedFilter(filterFn); - onSelectFilter(filterFn); - handleClose(); - }; - - return ( -
- - - - - {columnFilterModeOptions.map((option, index) => ( - handleSelectFilter(option)} - selected={option === selectedFilter} sx={{cursor: 'pointer'}}> - - - ))} - - - - -
- ); -} - -export default FilterBox; diff --git a/src/core/components/DataTable/filter/TextFieldWithFnBox/TextFieldWithFnBox.jsx b/src/core/components/DataTable/filter/TextFieldWithFnBox/TextFieldWithFnBox.jsx deleted file mode 100644 index 18600dc..0000000 --- a/src/core/components/DataTable/filter/TextFieldWithFnBox/TextFieldWithFnBox.jsx +++ /dev/null @@ -1,61 +0,0 @@ -import {IconButton, TextField} from '@mui/material'; -import ArtTrackIcon from '@mui/icons-material/ArtTrack'; -import {useEffect, useState} from "react"; -import FilterBox from "@/core/components/DataTable/filter/TextFieldWithFnBox/FilterBox"; - -const TextFieldWithFnBox = ({ - formik, - id, - header, - defaultValue, - defaultFilter, - columnFilterModeOptions, - onSelectFilter - }) => { - - const [anchorEl, setAnchorEl] = useState(null); - const [open, setOpen] = useState(false); - - useEffect(() => { - formik.setFieldValue(id, defaultValue || ''); - }, []); - - const handleClick = (event) => { - setOpen((prevOpen) => !prevOpen); - setAnchorEl(anchorEl ? null : event.currentTarget); - }; - - const handleClose = () => { - setOpen(false); - setAnchorEl(null); - }; - - return ( - <> - - - - ) - }} - sx={{ - position: 'relative' - }} - /> - - - ); -}; - -export default TextFieldWithFnBox; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePicker.jsx b/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePicker.jsx new file mode 100644 index 0000000..e92a426 --- /dev/null +++ b/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePicker.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker"; +import {Typography} from "@mui/material"; + +function CustomDatePicker({column, filterParameters, defaultFilterTranslation, setFieldValue}) { + return ( + + نوع فیلتر: {defaultFilterTranslation} (تاریخ) + + } + /> + ); +} + +export default CustomDatePicker; \ No newline at end of file diff --git a/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePickerRange.jsx b/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePickerRange.jsx new file mode 100644 index 0000000..b870061 --- /dev/null +++ b/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePickerRange.jsx @@ -0,0 +1,35 @@ +'use client' + +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, setFieldValue, errors, touched}) { + return ( + + + نوع فیلتر: {defaultFilterTranslation} (تاریخ) + + } + /> + + + ); +} + +export default CustomDatePickerRange; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx b/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx new file mode 100644 index 0000000..5031372 --- /dev/null +++ b/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx @@ -0,0 +1,72 @@ +import React from 'react'; +import {LocalizationProvider, MobileDatePicker} from "@mui/x-date-pickers"; +import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali"; +import {faIR} from "@mui/x-date-pickers/locales"; +import {Box, FormHelperText, IconButton, InputAdornment} from "@mui/material"; +import ClearIcon from "@mui/icons-material/Clear"; +import moment from "jalali-moment"; + +function MuiDatePicker({value, setFieldValue, name, minDate, maxDate, helperText, placeholder, error}) { + + // console.log("error", error); + // + // console.log("helperText", helperText) + + return ( + + + { + const date = new Date(value); + const formattedDate = moment(date) + .locale("en") + .format("YYYY-MM-DD"); + setFieldValue(name, formattedDate); + }} + minDate={minDate ? new Date(minDate) : null} + maxDate={maxDate ? new Date(maxDate) : null} + slotProps={{ + textField: { + error: error, + placeholder: placeholder, + InputProps: { + endAdornment: ( + + { + event.stopPropagation(); + setFieldValue(name, ""); + }} + sx={{ + color: "#bfbfbf", + '&:hover': { + backgroundColor: 'rgba(189, 189, 189, 0.1)', + color: "#363434" + }, + }} + > + + + + ), + }, + }, + }} + /> + + {helperText ? helperText : ""} + + + + ); +} + +export default MuiDatePicker; \ No newline at end of file diff --git a/src/core/components/DataTable/filter/fieldsType/CustomSelect.jsx b/src/core/components/DataTable/filter/fieldsType/CustomSelect.jsx new file mode 100644 index 0000000..44f0599 --- /dev/null +++ b/src/core/components/DataTable/filter/fieldsType/CustomSelect.jsx @@ -0,0 +1,40 @@ +'use client' + +import {FormControl, FormHelperText, InputLabel, MenuItem, OutlinedInput, Select, Typography} from "@mui/material"; + +function CustomSelect({column, filterParameters, defaultFilterTranslation, setFieldValue}) { + const columnSelectOption = column.columnSelectOption; + + return ( + + {column.header} + + + + نوع فیلتر: {defaultFilterTranslation} + + + + ); +} + +export default CustomSelect; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomSelectMultiple.jsx b/src/core/components/DataTable/filter/fieldsType/CustomSelectMultiple.jsx new file mode 100644 index 0000000..ae027fe --- /dev/null +++ b/src/core/components/DataTable/filter/fieldsType/CustomSelectMultiple.jsx @@ -0,0 +1,62 @@ +'use client' + +import { + Box, + Chip, + FormControl, + FormHelperText, + InputLabel, + MenuItem, + OutlinedInput, + Select, + Typography +} from "@mui/material"; + +function CustomSelectMultiple({column, filterParameters, defaultFilterTranslation, setFieldValue}) { + const columnSelectOption = column.columnSelectOption; + + const getLabelForValue = (value) => { + const option = columnSelectOption.find(opt => opt.value === value); + return option ? option.label : value; + }; + + return ( + + {column.header} + + + + نوع فیلتر: {defaultFilterTranslation} + + + + ); +} + +export default CustomSelectMultiple; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomTextField.jsx b/src/core/components/DataTable/filter/fieldsType/CustomTextField.jsx new file mode 100644 index 0000000..eacd820 --- /dev/null +++ b/src/core/components/DataTable/filter/fieldsType/CustomTextField.jsx @@ -0,0 +1,39 @@ +import {InputAdornment, TextField, Typography} from "@mui/material"; +import FilterListIcon from '@mui/icons-material/FilterList'; + +function CustomTextField({ + column, + filterParameters, + defaultFilterTranslation, + handleOpenFilterBox, + handleChange, + handleBlur + }) { + + return ( + + نوع فیلتر: {defaultFilterTranslation} + } + variant="outlined" + size="normal" + sx={{marginY: 1}} + InputProps={{ + endAdornment: ( + + + + ), + }} + /> + ); +} + +export default CustomTextField; \ No newline at end of file diff --git a/src/core/components/DataTable/filter/fieldsType/CustomTextFieldRange.jsx b/src/core/components/DataTable/filter/fieldsType/CustomTextFieldRange.jsx new file mode 100644 index 0000000..35c9358 --- /dev/null +++ b/src/core/components/DataTable/filter/fieldsType/CustomTextFieldRange.jsx @@ -0,0 +1,56 @@ +import {Box, InputAdornment, TextField, Typography} from "@mui/material"; +import FilterListIcon from '@mui/icons-material/FilterList'; + +function CustomTextFieldRange({ + column, + filterParameters, + defaultFilterTranslation, + handleOpenFilterBox, + handleChange, + handleBlur, + errors, + touched + }) { + return ( + + از {column.header}} + value={filterParameters.value[0]} + fullWidth + error={touched?.[`${column.id}`]?.value && Boolean(errors?.[`${column.id}`]?.value)} + helperText={نوع + فیلتر: {defaultFilterTranslation}} + variant="outlined" + size="normal" + sx={{marginY: 1, marginRight: 1}} + /> + تا {column.header}} + value={filterParameters.value[1]} + fullWidth + variant="outlined" + size="normal" + sx={{marginY: 1}} + InputProps={{ + endAdornment: ( + + + + ), + }} + /> + + ); +} + +export default CustomTextFieldRange; \ No newline at end of file diff --git a/src/core/components/DataTable/filter/index.jsx b/src/core/components/DataTable/filter/index.jsx new file mode 100644 index 0000000..65a93d2 --- /dev/null +++ b/src/core/components/DataTable/filter/index.jsx @@ -0,0 +1,19 @@ +'use client' + +import {useState} from "react"; +import FilterButton from "@/core/components/DataTable/filter/FilterButton"; +import FilterBody from "@/core/components/DataTable/filter/FilterBody"; + +function FilterColumn({columns, user_id, page_name, table_name}) { + const [open, setOpen] = useState(false); + + return ( + <> + + + + ); +} + +export default FilterColumn; diff --git a/src/core/components/DataTable/index.js b/src/core/components/DataTable/index.js index aba1d1c..e440895 100644 --- a/src/core/components/DataTable/index.js +++ b/src/core/components/DataTable/index.js @@ -1,142 +1,12 @@ -import {useMaterialReactTable} from "material-react-table"; import DataTable_Main from "./Main"; -import {FA_DATATABLE_LOCALIZATION} from "./localization/fa/datatable"; -import useTableSetting from "@/lib/hooks/useTableSetting"; -import {flattenArrayOfObjects} from "@/core/utils/flattenArrayOfObjects"; -import Toolbar from "@/components/home/Toolbar"; - -const data = [ - { - name: { - firstName: 'امین', - lastName: 'قاسمپور', - }, - address: 'فلان جا', - city: 'تهران', - state: 'بررسی شده', - price: '20', - updated_at: '2024/05/02', - company: 'همراه اول', - area: 'منطقه 5', - }, - { - name: { - firstName: 'امیر حسین', - lastName: 'محمودی', - }, - address: 'فلان جا', - city: 'تهران', - state: 'تکمیل شده', - price: '27', - updated_at: '2024/05/02', - company: 'وایتل', - area: 'منطقه 27', - }, - { - name: { - firstName: 'یاسمن', - lastName: 'علی اکبری', - }, - address: 'فلان جا', - city: 'شیراز', - state: 'بررسی شده', - price: '32', - updated_at: '2024/05/02', - company: 'ایرانسل', - area: 'منطقه 23', - }, - { - name: { - firstName: 'حمیدرضا', - lastName: 'رنجبرپور', - }, - address: 'فلان جا', - city: 'اصفهان', - state: 'بررسی شده', - price: '45', - updated_at: '2024/05/02', - company: 'ایرانول', - area: 'منطقه 21', - }, - { - name: { - firstName: 'محمد', - lastName: 'جلالی', - }, - address: 'فلان جا', - city: 'رشت', - state: 'درحال بررسی', - price: '8', - updated_at: '2024/05/02', - company: 'فیلیمو', - area: 'منطقه 8', - }, -]; +import DataTableProvider from "@/lib/contexts/DataTable"; const DataTable = (props) => { - const {userId, pageName, tableName, columns, initialStateProps} = props - const {settingStore, hideAction, sortAction} = useTableSetting(); - const flatColumns = flattenArrayOfObjects(columns, 'columns') - - const onColumnVisibilityChange = (event) => { - const settingValue = event(); - hideAction(userId, pageName, tableName, settingValue, flatColumns); - }; - const onSortingChange = (event) => { - const settingValue = event(settingStore?.[userId]?.[pageName]?.[tableName]?.['sorts'] || []); - sortAction(userId, pageName, tableName, settingValue, flatColumns); - } - - - const table = useMaterialReactTable({ - localization: FA_DATATABLE_LOCALIZATION, - columns, - data: data, - // manualSorting: true, - renderTopToolbarCustomActions: ({table}) => (<> - - ), - initialState: { - density: 'compact', - columnVisibility: settingStore?.[userId]?.[pageName]?.[tableName]?.['hides'], - sorting: settingStore?.[userId]?.[pageName]?.[tableName]?.['sorts'] || [], - ...initialStateProps - }, - state: { - columnVisibility: settingStore?.[userId]?.[pageName]?.[tableName]?.['hides'], - sorting: settingStore?.[userId]?.[pageName]?.[tableName]?.['sorts'] || [] - }, - muiTableHeadProps: { - sx: { - borderTop: "1px solid #e1e1e1", - borderBottom: "2px solid #e1e1e1", - } - }, - muiTableHeadCellProps: { - sx: { - color: "primary.main", - borderLeft: "1px solid #e1e1e1", - "&:first-of-type": { - borderLeft: "unset" - } - }, - }, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - "&:first-of-type": { - borderLeft: "unset" - } - }, - }, - onColumnVisibilityChange: onColumnVisibilityChange, - onSortingChange: onSortingChange, - ...props - }) - - return ; + return ( + + + + ); }; -export default DataTable; +export default DataTable; \ No newline at end of file diff --git a/src/core/components/DataTable/refactor/RefactorTable.jsx b/src/core/components/DataTable/refactor/RefactorTable.jsx index 06f75c1..71e302c 100644 --- a/src/core/components/DataTable/refactor/RefactorTable.jsx +++ b/src/core/components/DataTable/refactor/RefactorTable.jsx @@ -6,9 +6,9 @@ import {useState} from "react"; function RefactorTable() { const {refactorAction} = useTableSetting(); - const [userId, setUserId] = useState(2); - const [pageName, setPageName] = useState('loan'); - const [tableName, setTableName] = useState('loan_table'); + const [userId, setUserId] = useState(0); + const [pageName, setPageName] = useState('testPage'); + const [tableName, setTableName] = useState('testTable'); const refactor = () => { refactorAction(userId, pageName, tableName); diff --git a/src/core/components/DataTable/table/Paper.js b/src/core/components/DataTable/table/Paper.js index ede47c1..9a3be31 100644 --- a/src/core/components/DataTable/table/Paper.js +++ b/src/core/components/DataTable/table/Paper.js @@ -65,7 +65,10 @@ const DataTable_Paper = ({table, ...rest}) => { > {enableTopToolbar && (parseFromValuesOrFunc(renderTopToolbar, {table}) ?? ( - + ))} {enableBottomToolbar && diff --git a/src/core/components/DataTable/toolbar/TopToolbar.js b/src/core/components/DataTable/toolbar/TopToolbar.js index 2b9641c..7a321e2 100644 --- a/src/core/components/DataTable/toolbar/TopToolbar.js +++ b/src/core/components/DataTable/toolbar/TopToolbar.js @@ -3,10 +3,10 @@ import {Box, useMediaQuery} from "@mui/material"; import DataTable_LinearProgressBar from "./LinearProgressBar"; import DataTable_TablePagination from "./TablePagination"; import DataTable_ToolbarInternalButtons from "./ToolbarInternalButtons"; -import FilterColumn from "@/core/components/DataTable/filter/FilterColumn"; +import FilterColumn from "@/core/components/DataTable/filter"; import RefactorTable from "@/core/components/DataTable/refactor/RefactorTable"; -const DataTable_TopToolbar = ({table, columns}) => { +const DataTable_TopToolbar = ({table, columns, table_url, user_id, page_name, table_name}) => { const { getState, options: { @@ -73,7 +73,8 @@ const DataTable_TopToolbar = ({table, columns}) => { }} > - + )} diff --git a/src/core/components/NotificationDesign/AskForKeep.jsx b/src/core/components/NotificationDesign/AskForKeep.jsx new file mode 100644 index 0000000..7a68d2f --- /dev/null +++ b/src/core/components/NotificationDesign/AskForKeep.jsx @@ -0,0 +1,47 @@ +'use client' + +import SaveIcon from '@mui/icons-material/Save'; +import {Box, Button, Typography} from "@mui/material"; +import DownloadIcon from '@mui/icons-material/Download'; +import {toast} from "react-toastify"; + +function AskForKeep({onSaveFilter}) { + + const handleDismiss = () => { + toast.dismiss({containerId: "filtering"}); + }; + + return ( + + + + ذخیره سازی اطلاعات + + + + + + آیا مایل به ذخیره فیلتر های اعمال شده برای دفعات بعد هستید؟ + + + + + + + + ); +} + +export default AskForKeep; \ No newline at end of file diff --git a/src/core/utils/theme.js b/src/core/utils/theme.js index 3abbb52..d96fc53 100644 --- a/src/core/utils/theme.js +++ b/src/core/utils/theme.js @@ -1,5 +1,5 @@ 'use client' -import { createTheme } from "@mui/material"; +import {createTheme} from "@mui/material"; const theme = createTheme({ direction: 'rtl', diff --git a/src/lib/contexts/DataTable.jsx b/src/lib/contexts/DataTable.jsx new file mode 100644 index 0000000..975b859 --- /dev/null +++ b/src/lib/contexts/DataTable.jsx @@ -0,0 +1,15 @@ +import {createContext, useState} from "react"; + +export const DataTableContext = createContext(); + +const DataTableProvider = ({children}) => { + const [filterData, setFilterData] = useState({}); + + return ( + + {children} + + ); +}; + +export default DataTableProvider; \ No newline at end of file diff --git a/src/lib/hooks/useDataTable.jsx b/src/lib/hooks/useDataTable.jsx new file mode 100644 index 0000000..ba7acb5 --- /dev/null +++ b/src/lib/hooks/useDataTable.jsx @@ -0,0 +1,9 @@ +import {useContext} from "react"; +import {DataTableContext} from "@/lib/contexts/DataTable"; + +const useTableSetting = () => { + const {filterData, setFilterData} = useContext(DataTableContext); + return {filterData, setFilterData}; +}; + +export default useTableSetting;