diff --git a/.env.local.example b/.env.local.example index c93a078..856ddc0 100644 --- a/.env.local.example +++ b/.env.local.example @@ -1,2 +1,3 @@ -NEXT_PUBLIC_VERSION="0.2.0" -NEXT_PUBLIC_API_URL="https://rms.witel.ir" \ No newline at end of file +NEXT_PUBLIC_VERSION="0.3.1" +NEXT_PUBLIC_API_URL="https://rms.witel.ir" +NEXT_PUBLIC_MAPTILE_ENDPOINT="https://rmsmap.rmto.ir/141map" \ No newline at end of file diff --git a/package.json b/package.json index 4a1bf6b..36ec3d1 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,8 @@ "next": "^14.2.3", "react": "^18", "react-dom": "^18", + "react-hook-form": "^7.52.1", + "react-leaflet": "^4.2.1", "react-toastify": "^10.0.5", "sass": "^1.75.0", "stylis": "^4.3.1", @@ -41,4 +43,4 @@ "eslint-config-prettier": "^9.1.0", "prettier": "^3.3.2" } -} \ No newline at end of file +} diff --git a/public/global.scss b/public/global.scss index 1af3ae3..7b73e7e 100644 --- a/public/global.scss +++ b/public/global.scss @@ -1,9 +1,10 @@ @import "fontiran"; +@import "leaflet/dist/leaflet.css"; @import "react-toastify/dist/ReactToastify.css"; .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; + 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; } diff --git a/public/images/locationMarker.png b/public/images/locationMarker.png new file mode 100644 index 0000000..5e19b95 Binary files /dev/null and b/public/images/locationMarker.png differ diff --git a/src/app/(withAuth)/dashboard/inquiry_privacy/fencing/page.js b/src/app/(withAuth)/dashboard/inquiry_privacy/fencing/page.js new file mode 100644 index 0000000..b7aecdd --- /dev/null +++ b/src/app/(withAuth)/dashboard/inquiry_privacy/fencing/page.js @@ -0,0 +1,7 @@ +import InquiryPrivacyFencingPage from "@/components/dashboard/inquiryPrivacyFencing"; + +const Page = () => { + return ; +}; + +export default Page; diff --git a/src/app/(withAuth)/dashboard/layout.js b/src/app/(withAuth)/dashboard/layout.js new file mode 100644 index 0000000..5a85c25 --- /dev/null +++ b/src/app/(withAuth)/dashboard/layout.js @@ -0,0 +1,13 @@ +import HeaderWithLogo from "@/components/layouts/dashboard/headerWithLogo"; +import HeaderWithSidebar from "@/components/layouts/dashboard/headerWithSidebar"; +import { Stack } from "@mui/material"; + +const Layout = ({ children }) => { + return ( + + + {children} + + ); +}; +export default Layout; diff --git a/src/app/(withAuth)/dashboard/page.js b/src/app/(withAuth)/dashboard/page.js index a7efa2a..46d4a05 100644 --- a/src/app/(withAuth)/dashboard/page.js +++ b/src/app/(withAuth)/dashboard/page.js @@ -1,11 +1,5 @@ -"use client"; - const Page = () => { - - return ( - <> - - ); + return <>; }; export default Page; diff --git a/src/app/(withAuth)/dashboard/template.js b/src/app/(withAuth)/dashboard/template.js deleted file mode 100644 index 28b4ea0..0000000 --- a/src/app/(withAuth)/dashboard/template.js +++ /dev/null @@ -1,17 +0,0 @@ -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 ( - - - - {children} - - - ); -}; - -export default Template; diff --git a/src/app/layout.js b/src/app/layout.js index 64aea89..1f5a2c5 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -7,7 +7,7 @@ export const metadata = { export default function RootLayout({ children }) { return ( - + {children} diff --git a/src/app/page.js b/src/app/page.js index 2997c35..a98fa16 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -1,7 +1,8 @@ import { redirect } from "next/navigation"; +const prefix = process.env.NODE_ENV === "production" ? "/v3" : ""; function Page() { - redirect("/dashboard", "replace"); + redirect(prefix + "/dashboard", "replace"); return null; } diff --git a/src/app/template.js b/src/app/template.js index 3ffc656..3e14053 100644 --- a/src/app/template.js +++ b/src/app/template.js @@ -1,5 +1,5 @@ import cacheProviderRtl from "@/core/utils/cacheRtl"; -import { CssBaseline, ThemeProvider } from "@mui/material"; +import { CssBaseline, GlobalStyles, ThemeProvider } from "@mui/material"; import theme from "@/core/utils/theme"; import { AppRouterCacheProvider } from "@mui/material-nextjs/v14-appRouter"; import "^/global.scss"; @@ -9,6 +9,25 @@ const Template = ({ children }) => { return ( + {children} diff --git a/src/components/dashboard/inquiryPrivacyFencing/Create/Form/LocationOnMap/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/Create/Form/LocationOnMap/index.jsx new file mode 100644 index 0000000..be24704 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacyFencing/Create/Form/LocationOnMap/index.jsx @@ -0,0 +1,23 @@ +import MapLoading from "@/core/components/MapLayer/Loading"; +import MarkerLocation from "@/core/components/MapLayer/MarkerLocation"; +import { Paper, Stack } from "@mui/material"; +import { useFormikContext } from "formik"; +import dynamic from "next/dynamic"; + +const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { + loading: () => , + ssr: false, +}); + +const LocationOnMap = ({ setValue }) => { + return ( + + + + + + + + ) +} +export default LocationOnMap \ No newline at end of file diff --git a/src/components/dashboard/inquiryPrivacyFencing/Create/Form/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/Create/Form/index.jsx new file mode 100644 index 0000000..9fff4da --- /dev/null +++ b/src/components/dashboard/inquiryPrivacyFencing/Create/Form/index.jsx @@ -0,0 +1,570 @@ +import LtrTextField from "@/core/components/LtrTextField"; +import StyledForm from "@/core/components/StyledForm"; +import { SET_INQUIRE_PRIVACY_FENCING } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; +import { Autocomplete, Box, Button, Chip, DialogActions, DialogContent, Fade, Grid, InputAdornment, Stack, TextField, Typography } from "@mui/material"; +import { DatePicker, LocalizationProvider, faIR } from "@mui/x-date-pickers"; +import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali"; +import moment from "jalali-moment"; +import { Controller, useForm } from "react-hook-form"; +import LocationOnMap from "./LocationOnMap"; + +const CreateForm = ({ handleClose, mutate }) => { + const { control, watch, register, handleSubmit, setValue } = useForm({ + defaultValues: { + dabirkhaneh_number: '', + nameh_date: moment(), + nameh_date_fa: '', + marjae_pasokh: '', + motaghazi_is_legal_id: null, + motaghazi_is_legal: '', + motaghazi_type_id: '', + motaghazi_type: null, + motaghazi_firstname: '', + motaghazi_lastname: '', + national_id: '', + shenase_melli: '', + tel_number: '', + mobile_number: '', + address: '', + edare_kol_id: null, + edare_kol: '', + edare_shahri_id: null, + edare_shahri: '', + rah_type_id: null, + rah_type: '', + name_mehvar_id: '', + name_mehvar_fa: null, + mizan_harim: null, + arze_navar: null, + samt_id: null, + samt: '', + kilometr: '', + lat: '', + lon: '', + zone: null, + karbari_type_id: null, + karbari_type: '', + tarh_title: '', + masahat_zirbana: '', + ehdasat_type_id: [], + ehdasat_type: '', + divarkeshi_distance: '', + mostahadesat_distance: '', + mahale_ejra_id: null, + mahale_ejra: '', + traffic_id: null, + traffic: '', + vaziat_eghtesadi_id: null, + vaziat_eghtesadi: '', + has_access_id: null, + has_access: '', + shomare_estelam_harim: '', + max_month: '', + max_day: '', + shomare_tahaodname: '', + shomare_daftarkhaneh: '', + description: '', + ronevesht: '', + } + }); + const request = useRequest() + + const onSubmit = async (data) => { + const formData = new FormData() + formData.append('dabirkhaneh_number', data.dabirkhaneh_number) + formData.append('nameh_date', data.nameh_date.format('YYYY-MM-DD')) + formData.append('nameh_date_fa', data.nameh_date) + formData.append('marjae_pasokh', data.marjae_pasokh) + formData.append('motaghazi_is_legal_id', data.motaghazi_is_legal_id) + formData.append('motaghazi_is_legal', data.motaghazi_is_legal_id) + formData.append('motaghazi_type_id', 1) + formData.append('motaghazi_type', data.motaghazi_type) + formData.append('motaghazi_firstname', data.motaghazi_firstname) + formData.append('motaghazi_lastname', data.motaghazi_lastname) + formData.append('national_id', data.national_id) + formData.append('shenase_melli', data.national_id) + formData.append('tel_number', data.tel_number) + formData.append('mobile_number', data.mobile_number) + formData.append('address', data.address) + formData.append('edare_kol_id', data.edare_kol_id) + formData.append('edare_kol', data.edare_kol_id) + formData.append('edare_shahri_id', data.edare_shahri_id) + formData.append('edare_shahri', data.edare_shahri_id) + formData.append('rah_type_id', data.rah_type_id) + formData.append('rah_type', data.rah_type_id) + formData.append('name_mehvar_id', 1) + formData.append('name_mehvar_fa', data.name_mehvar_id) + formData.append('mizan_harim', data.mizan_harim) + formData.append('arze_navar', data.arze_navar) + formData.append('samt_id', data.samt_id) + formData.append('samt', data.samt_id) + formData.append('kilometr', data.kilometr) + formData.append('lat', data.lat) + formData.append('lon', data.lon) + formData.append('zone', data.zone) + formData.append('karbari_type_id', data.karbari_type_id) + formData.append('karbari_type', data.karbari_type_id) + formData.append('tarh_title', data.tarh_title) + formData.append('masahat_zirbana', data.masahat_zirbana) + formData.append('ehdasat_type_id', data.ehdasat_type_id.join("|")) + formData.append('ehdasat_type', data.ehdasat_type_id.join("|")) + formData.append('divarkeshi_distance', data.divarkeshi_distance) + formData.append('mostahadesat_distance', data.mostahadesat_distance) + formData.append('mahale_ejra_id', data.mahale_ejra_id) + formData.append('mahale_ejra', data.mahale_ejra) + formData.append('traffic_id', data.traffic_id) + formData.append('traffic', data.traffic_id) + formData.append('vaziat_eghtesadi_id', data.vaziat_eghtesadi_id) + formData.append('vaziat_eghtesadi', data.vaziat_eghtesadi) + formData.append('has_access_id', data.has_access_id) + formData.append('has_access', data.has_access_id) + formData.append('shomare_estelam_harim', data.shomare_estelam_harim) + formData.append('max_month', data.max_month) + formData.append('max_day', data.max_day) + formData.append('shomare_tahaodname', data.shomare_tahaodname) + formData.append('shomare_daftarkhaneh', data.shomare_daftarkhaneh) + formData.append('description', data.description) + formData.append('ronevesht', data.ronevesht) + + try { + await request(SET_INQUIRE_PRIVACY_FENCING, 'post', { data: formData }) + handleClose() + mutate() + } catch (error) { + + } + }; + + return ( + + + + + + + + + ( + onChange(moment(newValue))} + label="تاریخ نامه درخواست *" + slotProps={{ + textField: { fullWidth: true, size: "small", autoComplete: 'off' }, + }} + /> + )} + /> + + + + + + ( + { + onChange(newValue) + }} + options={["حقوقی", "حقیقی"]} + renderInput={(params) => } + /> + )} + /> + + + + + ( + { + onChange(newValue) + }} + options={["دولتی", "خصوصی"]} + renderInput={(params) => } + /> + )} + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + { + onChange(newValue) + }} + options={["تهران"]} + renderInput={(params) => ( + + )} + /> + )} + /> + + + ( + { + onChange(newValue) + }} + options={["تهران"]} + renderInput={(params) => } + /> + )} + /> + + + ( + { + onChange(newValue) + }} + options={["آزاد راه", "بزرگراه", 'راه فرعی درجه 3']} + renderInput={(params) => } + /> + )} + /> + + + ( + { + onChange(newValue) + }} + options={["سایر"]} + renderInput={(params) => } + /> + )} + /> + + + + + + + + ( + { + onChange(newValue) + }} + options={["چپ", "راست"]} + renderInput={(params) => } + /> + )} + /> + + + ( + { + onChange(newValue) + }} + options={["12.5", "17.5"]} + renderInput={(params) => } + /> + )} + /> + + + + + ( + { + onChange(newValue) + }} + options={["15", "30"]} + renderInput={(params) => } + /> + )} + /> + + + + + + + + + + + + + + ( + { + onChange(newValue) + }} + options={["38", "39"]} + renderInput={(params) => } + /> + )} + /> + + + + ( + { + onChange(newValue) + }} + options={["اتاقک نگهبانی", "دولتی"]} + renderInput={(params) => } + /> + )} + /> + + + + + + + مترمربع, + }} /> + + + ( + { + onChange(newValue) + }} + renderTags={(value, getTagProps) => + value.map((option, index) => { + const { key, ...tagProps } = getTagProps({ index }); + return ( + + ); + }) + } + options={["تعمیرات", "احداث بنا"]} + renderInput={(params) => } + /> + )} + /> + + + متر, + }} /> + + + متر, + }} /> + + + ( + { + onChange(newValue) + }} + options={["داخل حریم"]} + renderInput={(params) => } + /> + )} + /> + + + ( + { + onChange(newValue) + }} + options={["سبک (ضریب ۱)"]} + renderInput={(params) => } + /> + )} + /> + + + ( + { + onChange(newValue) + }} + options={["تست"]} + renderInput={(params) => } + /> + )} + /> + + + ( + { + onChange(newValue) + }} + options={["بله", "خیر"]} + renderInput={(params) => } + /> + )} + /> + + + + + + + حداکثر مدت زمان شروع عملیات: * + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; +export default CreateForm; diff --git a/src/components/dashboard/inquiryPrivacyFencing/Create/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/Create/index.jsx new file mode 100644 index 0000000..9010277 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacyFencing/Create/index.jsx @@ -0,0 +1,32 @@ +"use client"; +import DialogTransition from "@/core/components/DialogTransition"; +import { Close } from "@mui/icons-material"; +import { Dialog, DialogTitle, IconButton } from "@mui/material"; +import CreateForm from "./Form"; + +const InquiryPrivacyFencingCreate = ({ open, handleClose, mutate }) => { + + return ( + <> + + + ایجاد پاسخ به استعلام + + theme.palette.grey[500], + }} + > + + + + + + ); +}; +export default InquiryPrivacyFencingCreate; diff --git a/src/components/dashboard/inquiryPrivacyFencing/Toolbar.jsx b/src/components/dashboard/inquiryPrivacyFencing/Toolbar.jsx new file mode 100644 index 0000000..9646db4 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacyFencing/Toolbar.jsx @@ -0,0 +1,26 @@ +import { Button } from "@mui/material"; +import AddCircleIcon from "@mui/icons-material/AddCircle"; +import { useState } from "react"; +import InquiryPrivacyFencingCreate from "@/components/dashboard/inquiryPrivacyFencing/Create"; + +const Toolbar = ({ mutate }) => { + const [open, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + + const handleClose = () => { + setOpen(false); + }; + + return ( + <> + + + + ); +}; +export default Toolbar; diff --git a/src/components/dashboard/inquiryPrivacyFencing/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/index.jsx new file mode 100644 index 0000000..832cd3b --- /dev/null +++ b/src/components/dashboard/inquiryPrivacyFencing/index.jsx @@ -0,0 +1,352 @@ +"use client"; + +import { useMemo } from "react"; +import Toolbar from "@/components/dashboard/inquiryPrivacyFencing/Toolbar"; +import DataTable from "@/core/components/DataTable"; +import { Box } from "@mui/material"; +import { GET_INQUIRY_PRIVACY_FENCING_ROUTE } from "@/core/utils/routes"; + +const InquiryPrivacyFencingPage = () => { + const columns = useMemo( + () => [ + { + accessorKey: "dabirkhaneh_number", + header: "شماره دبیرخانه درخواست", + id: "dabirkhaneh_number", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "marjae_pasokh", + header: "مرجع درخواست کننده پاسخ به استعلام", + id: "marjae_pasokh", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "fuzzy"], + }, + { + accessorKey: "motaghazi_is_legal", + header: "متقاضی", + id: "motaghazi_is_legal", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "nameh_date", + header: "تاریخ نامه درخواست", + id: "nameh_date", + enableColumnFilter: false, + datatype: "date", + filterFn: "equals", + }, + { + accessorKey: "motaghazi_type", + header: "نوع متقاضی", + id: "motaghazi_type", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "motaghazi_firstname", + header: "نام متقاضی", + id: "motaghazi_firstname", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "motaghazi_lastname", + header: "نام خانوادگی متقاضی", + id: "motaghazi_lastname", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "national_id", + header: "کد ملی/شناسه ملی", + id: "national_id", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "tel_number", + header: "تلفن", + id: "tel_number", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "mobile_number", + header: "تلفن همراه", + id: "mobile_number", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "address", + header: "آدرس", + id: "address", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "edare_kol", + header: "اداره كل راهداری", + id: "edare_kol", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "edare_shahri", + header: "اداره شهرستان", + id: "edare_shahri", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "rah_type", + header: "نوع راه", + id: "rah_type", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "name_mehvar_fa", + header: "نام محور", + id: "name_mehvar_fa", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "mizan_harim", + header: "میزان حریم", + id: "mizan_harim", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "arze_navar", + header: "عرض نوار تاسیساتی زیربنایی", + id: "arze_navar", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "samt", + header: "سمت", + id: "samt", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "kilometr", + header: "كيلومتر", + id: "kilometr", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "zone", + header: "zone", + id: "zone", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "karbari_type", + header: "نوع کاربری", + id: "karbari_type", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "tarh_title", + header: "عنوان طرح", + id: "tarh_title", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "masahat_zirbana", + header: "مساحت زیربنا", + id: "masahat_zirbana", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "ehdasat_type", + header: "نوع احداثات", + id: "ehdasat_type", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "divarkeshi_distance", + header: "فاصله دیوارکشی از آکس محور", + id: "divarkeshi_distance", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "mahale_ejra", + header: "محل اجرا", + id: "mahale_ejra", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "traffic", + header: "میزان ترافیک", + id: "traffic", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "vaziat_eghtesadi", + header: "وضعیت اقتصادی", + id: "vaziat_eghtesadi", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "has_access", + header: "آیا راه دسترسی از قبل وجود دارد؟", + id: "has_access", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "shomare_estelam_harim", + header: "شماره استعلام دفتر ایمنی و حریم", + id: "shomare_estelam_harim", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "max_month", + header: "ماه", + id: "max_month", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "max_day", + header: "روز", + id: "max_day", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "shomare_tahaodname", + header: "شماره تعهدنامه", + id: "shomare_tahaodname", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "shomare_daftarkhaneh", + header: "شماره دفترخانه", + id: "shomare_daftarkhaneh", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "description", + header: "توضیحات", + id: "description", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + { + accessorKey: "ronevesht", + header: "رونوشت", + id: "ronevesht", + enableColumnFilter: false, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["equals", "notEquals", "contains"], + }, + ], + [] + ); + + return ( + + ); +}; +export default InquiryPrivacyFencingPage; + diff --git a/src/components/home/Toolbar.jsx b/src/components/home/Toolbar.jsx deleted file mode 100644 index 82f2646..0000000 --- a/src/components/home/Toolbar.jsx +++ /dev/null @@ -1,10 +0,0 @@ -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 deleted file mode 100644 index 7344232..0000000 --- a/src/components/home/index.jsx +++ /dev/null @@ -1,129 +0,0 @@ -"use client"; -import DataTable from "@/core/components/DataTable"; -import { useMemo } from "react"; - -function HomeComponent() { - const columns = useMemo( - () => [ - { - accessorKey: "fullname", - header: "نام کامل", - id: "fullname", - columns: [ - { - accessorKey: "name.firstName", - header: "نام", - id: "firstName", - enableColumnFilter: true, - datatype: "text", - filterFn: "contains", - enableClickToCopy: true, - columnFilterModeOptions: ["equals", "notEquals", "contains"], - }, - { - accessorKey: "name.lastName", - header: "نام خانوادگی", - id: "lastName", - enableColumnFilter: true, - datatype: "text", - filterFn: "equals", - columnFilterModeOptions: ["equals", "notEquals", "contains"], - }, - ], - }, - { - accessorKey: "address", - header: "آدرس", - id: "address", - enableColumnFilter: true, - datatype: "text", - filterFn: "notEquals", - columnFilterModeOptions: ["equals", "notEquals", "contains"], - }, - { - accessorKey: "city", - header: "شهر", - id: "city", - enableColumnFilter: true, - datatype: "text", - filterFn: "equals", - columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "fuzzy"], - }, - { - accessorKey: "state", - header: "وضعیت", - id: "state", - enableColumnFilter: true, - datatype: "text", - filterFn: "contains", - columnFilterModeOptions: ["equals", "notEquals", "contains"], - }, - { - accessorKey: "price", - header: "محدوده", - id: "price", - enableColumnFilter: true, - datatype: "numeric", - filterFn: "equals", - columnFilterModeOptions: ["equals", "notEquals"], - }, - { - accessorKey: "created_at", - header: "تاریخ ساخت", - id: "created_at", - enableColumnFilter: true, - datatype: "date", - filterFn: "between", - }, - { - accessorKey: "updated_at", - header: "تاریخ بروزرسانی", - id: "updated_at", - enableColumnFilter: true, - datatype: "date", - filterFn: "equals", - }, - { - accessorKey: "company", - header: "نام شرکت", - id: "company", - enableColumnFilter: true, - datatype: "numeric", - filterFn: "equals", - columnSelectOption: [ - { value: 1, label: "وایتل" }, - { value: 2, label: "اسنپ" }, - { value: 3, label: "تپسی" }, - ], - }, - { - accessorKey: "area", - header: "منطقه", - id: "area", - enableColumnFilter: true, - datatype: "array", - filterFn: "equals", - columnSelectOption: [ - { value: 1, label: "وایتل" }, - { value: 2, label: "اسنپ" }, - { value: 3, label: "تپسی" }, - ], - }, - ], - [] - ); - - return ( - <> - - - ); -} - -export default HomeComponent; diff --git a/src/components/layouts/dashboard/headerWithLogo/index.jsx b/src/components/layouts/dashboard/headerWithLogo/index.jsx index 16ef4b2..2d0b7bc 100644 --- a/src/components/layouts/dashboard/headerWithLogo/index.jsx +++ b/src/components/layouts/dashboard/headerWithLogo/index.jsx @@ -4,7 +4,7 @@ import HeaderBottom from "./HaederBottom"; const HeaderWithLogo = () => { return ( - + diff --git a/src/components/layouts/dashboard/headerWithSidebar/index.jsx b/src/components/layouts/dashboard/headerWithSidebar/index.jsx index c8febb6..afa0456 100644 --- a/src/components/layouts/dashboard/headerWithSidebar/index.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/index.jsx @@ -2,15 +2,16 @@ import SidebarMenu from "@/core/components/SidebarMenu"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; import MenuIcon from "@mui/icons-material/Menu"; -import { Box, Drawer, IconButton, Paper, styled, Toolbar } from "@mui/material"; +import { Box, Drawer, IconButton, Paper, Stack, styled, Toolbar } from "@mui/material"; import MuiAppBar from "@mui/material/AppBar"; import { useState } from "react"; import HeaderMenu from "./HeaderMenu"; const drawerWidth = 300; -const Main = styled(Paper, { 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", { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.leavingScreen, @@ -47,6 +48,7 @@ const DrawerHeader = styled("div")(({ theme }) => ({ alignItems: "center", padding: theme.spacing(0, 1), ...theme.mixins.toolbar, + minHeight: '48px !important', justifyContent: "flex-end", })); @@ -60,7 +62,7 @@ const HeaderWithSidebar = ({ children }) => { setOpen(false); }; return ( - + { { -
+
- {children} + + {children} +
); }; -export default HeaderWithSidebar; +export default HeaderWithSidebar; \ No newline at end of file diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js index db8aebd..cc726b5 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -3,138 +3,68 @@ 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 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 useRequest from "@/lib/hooks/useRequest"; +import useSWR from "swr"; const DataTable_Main = (props) => { - const { filterData } = useDataTable(); - const { table_url, user_id, page_name, table_name, columns, initialStateProps } = props; + const request = useRequest(); + const isEmptyObject = (obj) => obj && Object.keys(obj).length === 0 && obj.constructor === Object; + const { filterData, sortData, setSortData } = useDataTable(); + const { need_filter, table_url, user_id, page_name, table_name, columns, initialStateProps, TableToolbar } = props; const flatColumns = flattenArrayOfObjects(columns, "columns"); - const { settingStore, hideAction, sortAction } = useTableSetting(); + const { settingStore, hideAction } = 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; - - 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); + setSortData(event); }; + const fetchUrl = useMemo(() => { + const params = new URLSearchParams(); + params.set("start", `${pagination.pageIndex * pagination.pageSize}`); + params.set("size", pagination.pageSize); + params.set("filters", JSON.stringify(isEmptyObject(filterData) ? [] : [filterData])); + params.set("sorting", JSON.stringify(sortData)); + return `${table_url}?${params}`; + }, [table_url, filterData, pagination, columns, sortData]); + + const fetcher = async (url) => { + try { + const response = await request(url); + return response.data; + } catch (error) { + throw error; + } + }; + + const { data, isValidating, mutate } = useSWR(fetchUrl, fetcher, { + revalidateIfStale: true, + revalidateOnFocus: false, + revalidateOnReconnect: true, + keepPreviousData: true, + }); + const table = useMaterialReactTable({ localization: FA_DATATABLE_LOCALIZATION, columns, - data: data, - // manualSorting: true, - renderTopToolbarCustomActions: ({ table }) => ( - <> - - - ), + data: data?.data ?? [], initialState: { density: "compact", columnVisibility: settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"], - sorting: settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || [], + sorting: sortData, ...initialStateProps, }, state: { + showProgressBars: isValidating, columnVisibility: settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"], - sorting: settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || [], + sorting: sortData, pagination, }, muiTableHeadProps: { @@ -162,16 +92,24 @@ const DataTable_Main = (props) => { }, manualFiltering: true, manualPagination: true, - onPaginationChange: setPagination, manualSorting: true, + onPaginationChange: setPagination, onColumnVisibilityChange: onColumnVisibilityChange, onSortingChange: onSortingChange, + renderTopToolbarCustomActions: ({ table }) => ( + <> + + + ), ...props, }); return ( { - 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); + setInitialValues(filterData); }, [columns, settingStore, user_id, page_name, table_name, filterData]); useEffect(() => { @@ -107,49 +72,16 @@ function FilterBody({ columns, drawerState, setDrawerState, user_id, page_name, }, [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%", - }} + sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%" }} > {Object.keys(initialValues).length > 0 && ( @@ -203,9 +135,9 @@ function FilterBody({ columns, drawerState, setDrawerState, user_id, page_name, px: 8, boxShadow: "rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px", - backgroundColor: "#155175", + backgroundColor: "primary2", ":hover": { - backgroundColor: "#155175", + backgroundColor: "primary2", }, }} > diff --git a/src/core/components/DataTable/filter/FilterOptionList.jsx b/src/core/components/DataTable/filter/FilterOptionList.jsx index e088832..86a4745 100644 --- a/src/core/components/DataTable/filter/FilterOptionList.jsx +++ b/src/core/components/DataTable/filter/FilterOptionList.jsx @@ -32,12 +32,7 @@ function FilterOptionList({ key={index} onClick={(event) => handleChangeItem(event, index)} selected={option === selectedFilter} - sx={{ - cursor: "pointer", - width: "100px", - display: "flex", - justifyContent: "center", - }} + sx={{ cursor: "pointer", width: "100px", display: "flex", justifyContent: "center" }} > {columnFilterModeOptionFa[option]} diff --git a/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx b/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx index b4da7f5..22eb5f9 100644 --- a/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx +++ b/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx @@ -7,7 +7,6 @@ import ClearIcon from "@mui/icons-material/Clear"; import moment from "jalali-moment"; function MuiDatePicker({ value, setFieldValue, name, minDate, maxDate, helperText, placeholder, error }) { - return ( diff --git a/src/core/components/DataTable/index.js b/src/core/components/DataTable/index.js index f387d06..f5bbdfd 100644 --- a/src/core/components/DataTable/index.js +++ b/src/core/components/DataTable/index.js @@ -3,7 +3,12 @@ import DataTableProvider from "@/lib/contexts/DataTable"; const DataTable = (props) => { return ( - + ); diff --git a/src/core/components/DataTable/refactor/RefactorTable.jsx b/src/core/components/DataTable/refactor/RefactorTable.jsx index 49217a0..e9ed9ff 100644 --- a/src/core/components/DataTable/refactor/RefactorTable.jsx +++ b/src/core/components/DataTable/refactor/RefactorTable.jsx @@ -1,17 +1,10 @@ "use client"; import { IconButton, Tooltip } from "@mui/material"; import RestartAltIcon from "@mui/icons-material/RestartAlt"; -import useTableSetting from "@/lib/hooks/useTableSetting"; -import { useState } from "react"; - -function RefactorTable() { - const { refactorAction } = useTableSetting(); - const [userId, setUserId] = useState(0); - const [pageName, setPageName] = useState("testPage"); - const [tableName, setTableName] = useState("testTable"); +function RefactorTable({ mutate }) { const refactor = () => { - refactorAction(userId, pageName, tableName); + mutate(); }; return ( diff --git a/src/core/components/DataTable/table/Paper.js b/src/core/components/DataTable/table/Paper.js index ede80b3..289cabd 100644 --- a/src/core/components/DataTable/table/Paper.js +++ b/src/core/components/DataTable/table/Paper.js @@ -4,7 +4,17 @@ import DataTable_BottomToolbar from "../toolbar/BottomToolbar"; import DataTable_TopToolbar from "../toolbar/TopToolbar"; import DataTable_TableContainer from "./TableContainer"; -const DataTable_Paper = ({ table, ...rest }) => { +const DataTable_Paper = ({ + table, + table_name, + columns, + user_id, + page_name, + mutate, + need_filter, + table_url, + ...rest +}) => { const { getState, options: { @@ -66,12 +76,14 @@ const DataTable_Paper = ({ table, ...rest }) => { {enableTopToolbar && (parseFromValuesOrFunc(renderTopToolbar, { table }) ?? ( ))} diff --git a/src/core/components/DataTable/toolbar/TopToolbar.js b/src/core/components/DataTable/toolbar/TopToolbar.js index b0e5297..81bc84a 100644 --- a/src/core/components/DataTable/toolbar/TopToolbar.js +++ b/src/core/components/DataTable/toolbar/TopToolbar.js @@ -6,7 +6,7 @@ import DataTable_ToolbarInternalButtons from "./ToolbarInternalButtons"; import FilterColumn from "@/core/components/DataTable/filter"; import RefactorTable from "@/core/components/DataTable/refactor/RefactorTable"; -const DataTable_TopToolbar = ({ table, columns, table_url, user_id, page_name, table_name }) => { +const DataTable_TopToolbar = ({ mutate, need_filter, table, columns, table_url, user_id, page_name, table_name }) => { const { getState, options: { @@ -69,14 +69,16 @@ const DataTable_TopToolbar = ({ table, columns, table_url, user_id, page_name, t justifyContent: "flex-end", }} > - - + + {need_filter && ( + + )} )} diff --git a/src/core/components/DialogTransition.jsx b/src/core/components/DialogTransition.jsx new file mode 100644 index 0000000..f289140 --- /dev/null +++ b/src/core/components/DialogTransition.jsx @@ -0,0 +1,8 @@ +import { Slide } from "@mui/material"; +import React from "react"; + +const DialogTransition = React.forwardRef(function Transition(props, ref) { + return ; +}); + +export default DialogTransition \ No newline at end of file diff --git a/src/core/components/LtrTextField.jsx b/src/core/components/LtrTextField.jsx new file mode 100644 index 0000000..f31527c --- /dev/null +++ b/src/core/components/LtrTextField.jsx @@ -0,0 +1,10 @@ +import { TextField, styled } from "@mui/material"; + +const LtrTextField = styled(TextField)` + .MuiInputBase-input { + /* @noflip */ + direction: ltr; + } +`; + +export default LtrTextField; diff --git a/src/core/components/MapLayer/Loading/index.jsx b/src/core/components/MapLayer/Loading/index.jsx new file mode 100644 index 0000000..5d42012 --- /dev/null +++ b/src/core/components/MapLayer/Loading/index.jsx @@ -0,0 +1,17 @@ +import { Box, LinearProgress, Stack } from "@mui/material"; + +function MapLoading() { + return ( + + + + + + ); +} + +export default MapLoading; \ No newline at end of file diff --git a/src/core/components/MapLayer/MarkerLocation/index.jsx b/src/core/components/MapLayer/MarkerLocation/index.jsx new file mode 100644 index 0000000..a75d191 --- /dev/null +++ b/src/core/components/MapLayer/MarkerLocation/index.jsx @@ -0,0 +1,32 @@ +import { useRef } from "react"; +import { Marker, useMapEvents } from "react-leaflet"; + +const prefix = process.env.NODE_ENV === "production" ? "/v3" : ""; + +const locationMarker = L.icon({ + iconUrl: prefix + "/images/locationMarker.png", + iconSize: [50, 50], + iconAnchor: [25, 50], +}); + +const MarkerLocation = ({ setValue }) => { + const location = useRef(); + const map = useMapEvents({ + move: (e) => { + const latlon = e.target.getCenter() + location.current?.setLatLng(latlon); + setValue('lat', latlon.lat) + setValue('lon', latlon.lng) + }, + zoom: (e) => { + const latlon = e.target.getCenter() + location.current?.setLatLng(latlon); + setValue('lat', latlon.lat) + setValue('lon', latlon.lng) + }, + }); + return ( + + ) +} +export default MarkerLocation \ No newline at end of file diff --git a/src/core/components/MapLayer/index.jsx b/src/core/components/MapLayer/index.jsx new file mode 100644 index 0000000..52209da --- /dev/null +++ b/src/core/components/MapLayer/index.jsx @@ -0,0 +1,43 @@ +"use client"; +import { MapContainer, TileLayer, useMap } from "react-leaflet"; + +export const IRAN_CENTER = L.latLng(32.4279, 53.6880); + +const MapOptions = ({ options }) => { + const map = useMap(); + if (!options) return; + + if (options.mapDrag) { + map.dragging.enable(); + map.scrollWheelZoom.enable(); + map.touchZoom.enable(); + map.doubleClickZoom.enable(); + } else { + map.dragging.disable(); + map.scrollWheelZoom.disable(); + map.touchZoom.disable(); + map.doubleClickZoom.disable(); + } +}; + +function MapLayer({ children, style, otherLayers, options }) { + return ( + <> + + + + {children} + + {otherLayers} + + ); +} + +export default MapLayer; \ No newline at end of file diff --git a/src/core/components/NotificationDesign/AskForKeep.jsx b/src/core/components/NotificationDesign/AskForKeepData.jsx similarity index 57% rename from src/core/components/NotificationDesign/AskForKeep.jsx rename to src/core/components/NotificationDesign/AskForKeepData.jsx index d4721bb..8918a4c 100644 --- a/src/core/components/NotificationDesign/AskForKeep.jsx +++ b/src/core/components/NotificationDesign/AskForKeepData.jsx @@ -4,29 +4,46 @@ 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"; +import useTableSetting from "@/lib/hooks/useTableSetting"; + +function AskForKeepData({ filterData, sortData, user_id, page_name, table_name, columns }) { + const { filterAction, sortAction } = useTableSetting(); + + const onSaveFilter = () => { + const filteredItems = 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); + filterAction(user_id, page_name, table_name, filteredItems, columns); + + sortAction(user_id, page_name, table_name, sortData, columns); + toast.dismiss({ containerId: "datatable" }); + }; -function AskForKeep({ onSaveFilter }) { const handleDismiss = () => { - toast.dismiss({ containerId: "filtering" }); + toast.dismiss({ containerId: "datatable" }); }; return ( - + - ذخیره سازی اطلاعات + ذخیره سازی تغییرات - آیا مایل به ذخیره فیلتر های اعمال شده برای دفعات بعد هستید؟ + آیا مایل به ذخیره تغییر های اعمال شده برای دفعات بعد هستید؟ ); } -export default AskForKeep; +export default AskForKeepData; diff --git a/src/core/components/SidebarMenu.jsx b/src/core/components/SidebarMenu.jsx index 326dd11..74291a3 100644 --- a/src/core/components/SidebarMenu.jsx +++ b/src/core/components/SidebarMenu.jsx @@ -7,95 +7,80 @@ import { useEffect, useReducer, useState } from "react"; import { filterMenuItems } from "../utils/filterMenuItems"; import { pageMenu } from "../utils/pageMenu"; +function selectPage(item, route) { + if (item.type === "page") { + return { + ...item, + selected: item.route === route, + showSubitems: item.route === route, + }; + } else if (item.Subitems && Array.isArray(item.Subitems)) { + const updatedSubitems = item.Subitems.map((subitem) => selectPage(subitem, route)); + return { + ...item, + Subitems: updatedSubitems, + showSubitems: updatedSubitems.some((subitem) => subitem.showSubitems || subitem.route === route), + }; + } + return item; +} + function reducer(state, action) { switch (action.type) { case "UPDATE_MENU": - const _permissions = action.permissions || [] - const filteredPageMenu = filterMenuItems(pageMenu, ['all', ..._permissions]) - return filteredPageMenu + const _permissions = action.permissions || []; + const filteredPageMenu = filterMenuItems(state, ["all", ..._permissions]); + return filteredPageMenu; case "COLLAPSE_MENU": return state.map((item) => action.id == item.id ? { - ...item, - showSubitems: !item.showSubitems, - } + ...item, + showSubitems: !item.showSubitems, + } : item ); case "COLLAPSE_SUB_ITEMS": return state.map((item) => { return item.hasSubitems ? { - ...item, - Subitems: item.Subitems.map((subitem) => - action.id === subitem.id - ? { - ...subitem, - showSubitems: !subitem.showSubitems, - } - : subitem - ), - } + ...item, + Subitems: item.Subitems.map((subitem) => + action.id === subitem.id + ? { + ...subitem, + showSubitems: !subitem.showSubitems, + } + : subitem + ), + } : item; }); case "COLLAPSE_SUB_SECOND_ITEMS": return state.map((item) => { return item.hasSubitems ? { - ...item, - Subitems: item.Subitems.map((subitem) => { - return subitem.hasSubitems - ? { - ...subitem, - Subitems: subitem.Subitems.map((secondSubitem) => - action.id === secondSubitem.id - ? { - ...secondSubitem, - showSubitems: !secondSubitem.showSubitems, - } - : secondSubitem - ), - } - : subitem; - }), - } + ...item, + Subitems: item.Subitems.map((subitem) => { + return subitem.hasSubitems + ? { + ...subitem, + Subitems: subitem.Subitems.map((secondSubitem) => + action.id === secondSubitem.id + ? { + ...secondSubitem, + showSubitems: !secondSubitem.showSubitems, + } + : secondSubitem + ), + } + : subitem; + }), + } : item; }); case "SELECTED": - return state.map((item) => { - return item.type === "page" - ? { - ...item, - selected: action.route === item.route, - showSubitems: item.route === action.route, - } - : item.Subitems && Array.isArray(item.Subitems) - ? { - ...item, - Subitems: item.Subitems.map((subitem) => { - return subitem.type === "page" - ? { - ...subitem, - selected: action.route === subitem.route, - showSubitems: subitem.route === action.route, - } - : subitem.Subitems && Array.isArray(subitem.Subitems) - ? { - ...subitem, - Subitems: subitem.Subitems.map((secondSubItem) => ({ - ...secondSubItem, - selected: secondSubItem.route === action.route, - })), - showSubitems: subitem.Subitems.some( - (secondSubItem) => secondSubItem.route === action.route - ), - } - : subitem; - }), - showSubitems: item.Subitems.some((subitem) => subitem.showSubitems), - } - : item; - }); + return state.map((item) => selectPage(item, action.route)); default: throw new Error(); @@ -103,19 +88,20 @@ function reducer(state, action) { } const SidebarMenu = () => { - const { data: userPermissions } = usePermissions() + const { data: userPermissions } = usePermissions(); const [menuItems, dispatch] = useReducer(reducer, pageMenu); const pathname = usePathname(); const [selectedKey, setSelectedKey] = useState(null); - useEffect(() => { - dispatch({ type: 'UPDATE_MENU', permissions: userPermissions }); - }, [userPermissions]) - useEffect(() => { dispatch({ type: "SELECTED", route: pathname }); setSelectedKey(pathname); - }, [pathname]); + }, [userPermissions, pathname]); + + useEffect(() => { + if (!userPermissions) return; + dispatch({ type: "UPDATE_MENU", permissions: userPermissions }); + }, [userPermissions]); useEffect(() => { selectedKey && @@ -126,11 +112,13 @@ const SidebarMenu = () => { }, [selectedKey]); return ( - - {menuItems.map((menuItem) => { - return ; - })} - + userPermissions && ( + + {menuItems.map((menuItem) => { + return ; + })} + + ) ); }; export default SidebarMenu; diff --git a/src/core/components/StyledForm.jsx b/src/core/components/StyledForm.jsx new file mode 100644 index 0000000..4513129 --- /dev/null +++ b/src/core/components/StyledForm.jsx @@ -0,0 +1,5 @@ +import { styled } from "@mui/material"; + +const StyledForm = styled('form')``; + +export default StyledForm; diff --git a/src/core/utils/filterMenuItems.js b/src/core/utils/filterMenuItems.js index 7bceeb5..bd35a95 100644 --- a/src/core/utils/filterMenuItems.js +++ b/src/core/utils/filterMenuItems.js @@ -1,7 +1,7 @@ export function filterMenuItems(items, _permissions = []) { return items.reduce((acc, item) => { if (item.permissions) { - if (item.permissions.some(permission => _permissions.includes(permission))) { + if (item.permissions.some((permission) => _permissions.includes(permission))) { acc.push(item); } } else if (item.hasSubitems) { @@ -14,4 +14,4 @@ export function filterMenuItems(items, _permissions = []) { } return acc; }, []); -} \ No newline at end of file +} diff --git a/src/core/utils/pageMenu.js b/src/core/utils/pageMenu.js index 524468f..d47d020 100644 --- a/src/core/utils/pageMenu.js +++ b/src/core/utils/pageMenu.js @@ -1,5 +1,5 @@ import { Security } from "@mui/icons-material"; -const prefix = process.env.NODE_ENV === 'production' ? '/v3' : '' +const prefix = process.env.NODE_ENV === "production" ? "/v3" : ""; export const pageMenu = [ { @@ -8,7 +8,7 @@ export const pageMenu = [ type: "page", route: prefix + "/dashboard", icon: , - permissions: ["all"] + permissions: ["all"], }, { id: "userManagement", @@ -16,7 +16,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/user_management", icon: , - permissions: ['full-user-management', 'limited-user-management'] + permissions: ["full-user-management", "limited-user-management"], }, { id: "projectsManagment", @@ -31,7 +31,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/finance", icon: , - permissions: ['show-contract', 'show-contract-province'], + permissions: ["show-contract", "show-contract-province"], }, { id: "projectsManagmentList", @@ -39,7 +39,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/projects_list", icon: , - permissions: ["all"] + permissions: ["all"], }, { id: "projectsManagmentProposal", @@ -47,7 +47,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/proposal", icon: , - permissions: ['show-proposal', 'show-proposal-province'] + permissions: ["show-proposal", "show-proposal-province"], }, { id: "projectsManagmentLawmaker", @@ -55,7 +55,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/lawmakers", icon: , - permissions: ['show-lawmaker', 'show-lawmaker-province'] + permissions: ["show-lawmaker", "show-lawmaker-province"], }, { id: "projectsManagmentMap", @@ -63,7 +63,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=rahdari_projects", icon: , - permissions: ["all"] + permissions: ["all"], }, ], }, @@ -86,7 +86,10 @@ export const pageMenu = [ label: "کارتابل", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_items/supervisor/cartable", - permissions: ['show-road-item-supervise-cartable', 'show-road-item-supervise-cartable-province'] + permissions: [ + "show-road-item-supervise-cartable", + "show-road-item-supervise-cartable-province", + ], }, ], }, @@ -102,14 +105,14 @@ export const pageMenu = [ label: "ثبت فعالیت", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_items/operator/create", - permissions: ['create-road-item'] + permissions: ["create-road-item"], }, { id: "roadItemManagmentOparationCartable", label: "کارتابل", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_items/operator/cartable", - permissions: ['create-road-item'] + permissions: ["create-road-item"], }, ], }, @@ -119,7 +122,11 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=road_items", icon: , - permissions: ['show-road-item-supervise-cartable', 'show-road-item-supervise-cartable-province', 'create-road-item'] + permissions: [ + "show-road-item-supervise-cartable", + "show-road-item-supervise-cartable-province", + "create-road-item", + ], }, { id: "roadItemManagmentReport", @@ -127,7 +134,11 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_items/report", icon: , - permissions: ['show-road-item-supervise-cartable', 'show-road-item-supervise-cartable-province', 'create-road-item'] + permissions: [ + "show-road-item-supervise-cartable", + "show-road-item-supervise-cartable-province", + "create-road-item", + ], }, ], }, @@ -150,7 +161,10 @@ export const pageMenu = [ label: "کارتابل", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/road_patrols/supervisor/cartable", - permissions: ['show-road-patrol-supervise-cartable', 'show-road-patrol-supervise-cartable-province'] + permissions: [ + "show-road-patrol-supervise-cartable", + "show-road-patrol-supervise-cartable-province", + ], }, ], }, @@ -166,14 +180,14 @@ export const pageMenu = [ label: "ثبت اقدام", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_patrols/operator/create", - permissions: ['add-road-patrol'] + permissions: ["add-road-patrol"], }, { id: "roadPatrolManagmentOparationCartable", label: "کارتابل", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_patrols/operator/cartable", - permissions: ['add-road-patrol'] + permissions: ["add-road-patrol"], }, ], }, @@ -183,7 +197,11 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=road_patrols", icon: , - permissions: ['add-road-patrol', 'show-road-patrol-supervise-cartable', 'show-road-patrol-supervise-cartable-province'] + permissions: [ + "add-road-patrol", + "show-road-patrol-supervise-cartable", + "show-road-patrol-supervise-cartable-province", + ], }, { id: "roadPatrolManagmentReport", @@ -191,7 +209,41 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_patrols/report", icon: , - permissions: ['add-road-patrol', 'show-road-patrol-supervise-cartable', 'show-road-patrol-supervise-cartable-province'] + permissions: [ + "add-road-patrol", + "show-road-patrol-supervise-cartable", + "show-road-patrol-supervise-cartable-province", + ], + }, + ], + }, + { + id: "inquiryPrivacyManagment", + label: "استعلام حریم راه", + type: "menu", + icon: , + hasSubitems: true, + Subitems: [ + { + id: "inquiryPrivacyManagmentFencing", + label: "احداث و بهره برداری دیوارکشی و مستحدثات", + type: "page", + route: prefix + "/dashboard/inquiry_privacy/fencing", + permissions: ["all"], + }, + { + id: "inquiryPrivacyManagmentRoad", + label: "احداث راه دسترسی اختصاصی", + type: "page", + route: prefix + "/dashboard/inquiry_privacy/road", + permissions: ["all"], + }, + { + id: "inquiryPrivacyManagmentInfrastructure", + label: "احداث و بهره برداری تاسیسات زیربنایی", + type: "page", + route: prefix + "/dashboard/inquiry_privacy/infrastructure", + permissions: ["all"], }, ], }, @@ -214,14 +266,18 @@ export const pageMenu = [ label: "ثبت فعالیت", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/safety_and_privacy/operator/first_step", - permissions: ['add-safety-and-privacy'] + permissions: ["add-safety-and-privacy"], }, { id: "safetyAndPrivacyManagmentOparationCartable", label: "کارتابل", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/safety_and_privacy/operator/cartable", - permissions: ['show-safety-and-privacy-operator-cartable', 'show-safety-and-privacy-operator-cartable-province', 'show-safety-and-privacy-operator-cartable-edarate-shahri'] + permissions: [ + "show-safety-and-privacy-operator-cartable", + "show-safety-and-privacy-operator-cartable-province", + "show-safety-and-privacy-operator-cartable-edarate-shahri", + ], }, ], }, @@ -231,8 +287,12 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=safety_and_privacy", icon: , - permissions: ['show-safety-and-privacy-operator-cartable', 'show-safety-and-privacy-operator-cartable-province', - 'show-safety-and-privacy-operator-cartable-edarate-shahri', 'add-safety-and-privacy'] + permissions: [ + "show-safety-and-privacy-operator-cartable", + "show-safety-and-privacy-operator-cartable-province", + "show-safety-and-privacy-operator-cartable-edarate-shahri", + "add-safety-and-privacy", + ], }, { id: "safetyAndPrivacyManagmentReport", @@ -240,8 +300,12 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/safety_and_privacy/report", icon: , - permissions: ['show-safety-and-privacy-operator-cartable', 'show-safety-and-privacy-operator-cartable-province', - 'show-safety-and-privacy-operator-cartable-edarate-shahri', 'add-safety-and-privacy'] + permissions: [ + "show-safety-and-privacy-operator-cartable", + "show-safety-and-privacy-operator-cartable-province", + "show-safety-and-privacy-operator-cartable-edarate-shahri", + "add-safety-and-privacy", + ], }, ], }, @@ -264,7 +328,7 @@ export const pageMenu = [ label: "کارتابل", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_observations/supervisor/cartable", - permissions: ['supervise-fast-react', 'supervise-fast-react-province'] + permissions: ["supervise-fast-react", "supervise-fast-react-province"], }, ], }, @@ -274,7 +338,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_observations", icon: , - permissions: ['show-fast-react', 'show-fast-react-province', 'show-fast-react-edarate-shahri'] + permissions: ["show-fast-react", "show-fast-react-province", "show-fast-react-edarate-shahri"], }, { id: "roadObservationsManagmentOparation", @@ -288,7 +352,7 @@ export const pageMenu = [ label: "کارتابل", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_observations/operator/cartable", - permissions: ['show-fast-react', 'show-fast-react-province', 'show-fast-react-edarate-shahri'] + permissions: ["show-fast-react", "show-fast-react-province", "show-fast-react-edarate-shahri"], }, ], }, @@ -298,7 +362,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=road_observations", icon: , - permissions: ["all"] + permissions: ["all"], }, { id: "roadObservationsManagmentReport", @@ -306,7 +370,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_observations/report/index", icon: , - permissions: ["all"] + permissions: ["all"], }, ], }, @@ -323,7 +387,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/winter_camp", icon: , - permissions: ['show-camp', 'show-camp-province'] + permissions: ["show-camp", "show-camp-province"], }, { id: "winterCampManagmentFirstRing", @@ -331,7 +395,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=camp", icon: , - permissions: ['show-camp', 'show-camp-province'] + permissions: ["show-camp", "show-camp-province"], }, { id: "winterCampManagmentReport", @@ -339,7 +403,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=campNew", icon: , - permissions: ['show-camp', 'show-camp-province'] + permissions: ["show-camp", "show-camp-province"], }, ], }, @@ -362,7 +426,7 @@ export const pageMenu = [ label: "کارتابل", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/receipt", - permissions: ["all"] + permissions: ["all"], }, ], }, @@ -372,7 +436,7 @@ export const pageMenu = [ type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/receipt/report", icon: , - permissions: ["all"] + permissions: ["all"], }, ], }, diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js index 81ac016..7c0f4dc 100644 --- a/src/core/utils/routes.js +++ b/src/core/utils/routes.js @@ -1,6 +1,10 @@ const api = process.env.NEXT_PUBLIC_API_URL; +export const GET_CSRF = api + "/csrf"; + export const GET_USER_ROUTE = api + "/webapi/user/get-permission"; export const GET_LOGIN_ROUTE = api + "/login_dev"; +export const GET_INQUIRY_PRIVACY_FENCING_ROUTE = api + "/api/v3/harim/divarkeshi"; +export const GET_PERMISSIONS_ROUTE = api + "/webapi/user/get-permission"; -export const GET_PERMISSIONS_ROUTE = api + "/webapi/user/get-permission"; \ No newline at end of file +export const SET_INQUIRE_PRIVACY_FENCING = api + "/api/v3/harim/divarkeshi/store"; diff --git a/src/lib/contexts/DataTable.js b/src/lib/contexts/DataTable.js index fb03fd7..42fa4b9 100644 --- a/src/lib/contexts/DataTable.js +++ b/src/lib/contexts/DataTable.js @@ -1,11 +1,110 @@ -import { createContext, useState } from "react"; +import { createContext, useEffect, useState } from "react"; +import { toast } from "react-toastify"; +import useTableSetting from "@/lib/hooks/useTableSetting"; +import { flattenArrayOfObjects } from "@/core/utils/flattenArrayOfObjects"; +import AskForKeepData from "@/core/components/NotificationDesign/AskForKeepData"; export const DataTableContext = createContext(); -const DataTableProvider = ({ children }) => { +const DataTableProvider = ({ children, user_id, page_name, table_name, columns }) => { + const { settingStore } = useTableSetting(); + const [isInitStates, setInitStates] = useState(false); + const flatColumns = flattenArrayOfObjects(columns, "columns"); + const [initFilter, setInitFilter] = useState({}); + const [initSort, setInitSort] = useState([]); const [filterData, setFilterData] = useState({}); + const [sortData, setSortData] = useState([]); - return {children}; + useEffect(() => { + if (!settingStore) return; + const values = flatColumns.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?.filterFn || column._filterFn, + datatype: column.datatype, + }; + } else if (column._filterFn === "between") { + acc[column.id] = { + id: column.id, + value: filter?.value || ["", ""], + filterFn: filter?.filterFn || column._filterFn, + datatype: column.datatype, + }; + } else { + acc[column.id] = { + id: column.id, + value: filter?.value || "", + filterFn: filter?.filterFn || column._filterFn, + datatype: column.datatype, + }; + } + return acc; + }, {}); + setFilterData(values); + setSortData(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || []); + setInitFilter(values); + setInitSort(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || []); + setInitStates(true); + }, [settingStore, isInitStates]); + + useEffect(() => { + if ( + JSON.stringify(initFilter) !== JSON.stringify(filterData) || + JSON.stringify(initSort) !== JSON.stringify(sortData) + ) { + if (!toast.isActive("keep_data", "filtering")) { + toast( + , + { + containerId: "filtering", + toastId: "keep_data", + className: "filter-toast", + position: "bottom-left", + draggable: true, + autoClose: false, + } + ); + } else { + toast.update("keep_data", { + containerId: "filtering", + toastId: "keep_data", + render: ( + + ), + }); + } + } else { + toast.dismiss({ containerId: "datatable" }); + } + }, [filterData, sortData]); + + if (!isInitStates) return null; + + return ( + + {children} + + ); }; export default DataTableProvider; diff --git a/src/lib/contexts/tableSetting.js b/src/lib/contexts/tableSetting.js index 3611df9..b5b63d9 100644 --- a/src/lib/contexts/tableSetting.js +++ b/src/lib/contexts/tableSetting.js @@ -55,23 +55,7 @@ export const TableSettingProvider = ({ children }) => { localStorage.setItem("_setting-app", JSON.stringify(updatedLocalStorage)); setSettingStore(updatedLocalStorage); }; - const refactorAction = (user_id, page_name, table_name) => { - const prevLocalStorage = JSON.parse(localStorage.getItem("_setting-app")) || {}; - const userSettings = prevLocalStorage[user_id] || {}; - const pageSettings = userSettings[page_name] || {}; - const refactorData = { - ...prevLocalStorage, - [user_id]: { - ...userSettings, - [page_name]: { - ...pageSettings, - [table_name]: {}, - }, - }, - }; - localStorage.setItem("_setting-app", JSON.stringify(refactorData)); - setSettingStore(refactorData); - }; + const SummaryTextMessage = (values, columns) => { let SummaryText = ""; let HideText = ""; @@ -96,10 +80,7 @@ export const TableSettingProvider = ({ children }) => { } if (values.hides) { - const hidesArray = Object.entries(values.hides).map((e) => ({ - id: e[0], - value: e[1], - })); + const hidesArray = Object.entries(values.hides).map((e) => ({ id: e[0], value: e[1] })); if (hidesArray.length > 0) { const _list = []; for (const hide of hidesArray) { @@ -136,15 +117,7 @@ export const TableSettingProvider = ({ children }) => { }; return ( - + {children} ); diff --git a/src/lib/hooks/useDataTable.js b/src/lib/hooks/useDataTable.js index e396908..e2feecb 100644 --- a/src/lib/hooks/useDataTable.js +++ b/src/lib/hooks/useDataTable.js @@ -2,8 +2,8 @@ import { useContext } from "react"; import { DataTableContext } from "@/lib/contexts/DataTable"; const useTableSetting = () => { - const { filterData, setFilterData } = useContext(DataTableContext); - return { filterData, setFilterData }; + const { filterData, setFilterData, sortData, setSortData } = useContext(DataTableContext); + return { filterData, setFilterData, sortData, setSortData }; }; export default useTableSetting; diff --git a/src/lib/hooks/usePermissions.js b/src/lib/hooks/usePermissions.js index 4f54b41..004ff6d 100644 --- a/src/lib/hooks/usePermissions.js +++ b/src/lib/hooks/usePermissions.js @@ -3,16 +3,16 @@ import useSWR from "swr"; import useRequest from "./useRequest"; export const usePermissions = () => { - const request = useRequest() + const request = useRequest(); const fetcher = async (url) => { try { - const response = await request(url) - return response.data.data + const response = await request(url); + return response.data.data; } catch (error) { throw new Error(); } }; return useSWR(GET_PERMISSIONS_ROUTE, fetcher, { keepPreviousData: true }); -} \ No newline at end of file +}; diff --git a/src/lib/hooks/useRequest.js b/src/lib/hooks/useRequest.js index 2e35512..8805a56 100644 --- a/src/lib/hooks/useRequest.js +++ b/src/lib/hooks/useRequest.js @@ -1,7 +1,18 @@ import { errorResponse } from "@/core/utils/errorResponse"; +import { GET_CSRF } from "@/core/utils/routes"; import { successRequest } from "@/core/utils/successRequest"; import axios from "axios"; +const getCsrfToken = async () => { + try { + const response = await axios.get(GET_CSRF); + return response.data.data; + } catch (error) { + console.error("Error fetching CSRF token:", error); + throw error; + } +}; + const defaultOptions = { data: {}, requestOptions: { @@ -15,13 +26,27 @@ const defaultOptions = { }; const useRequest = (initOptions) => { + const instance = axios.create(); + instance.interceptors.request.use( + async function (config) { + if (config.method !== 'get') { + const csrfToken = await getCsrfToken(); + config.headers['X-CSRF-TOKEN'] = csrfToken; + } + return config; + }, + function (error) { + return Promise.reject(error); + } + ); + const _options = Object.assign({}, defaultOptions, initOptions); return async (url = "", method = "get", options) => { const mergedOptions = Object.assign({}, _options, options); try { - const response = await axios({ + const response = await instance({ url, method, data: method === "get" ? null : mergedOptions.data, diff --git a/src/lib/hooks/useTableSetting.js b/src/lib/hooks/useTableSetting.js index 6588446..e9e6cef 100644 --- a/src/lib/hooks/useTableSetting.js +++ b/src/lib/hooks/useTableSetting.js @@ -2,8 +2,8 @@ import { useContext } from "react"; import { TableSettingContext } from "../contexts/tableSetting"; const useTableSetting = () => { - const { settingStore, hideAction, sortAction, filterAction, refactorAction } = useContext(TableSettingContext); - return { settingStore, hideAction, sortAction, filterAction, refactorAction }; + const { settingStore, hideAction, sortAction, filterAction } = useContext(TableSettingContext); + return { settingStore, hideAction, sortAction, filterAction }; }; export default useTableSetting;