From bc74c65622851697bd09be10610a37bd6b2d39c9 Mon Sep 17 00:00:00 2001 From: Amirhossein Mahmoodi Date: Sun, 7 Sep 2025 10:11:43 +0330 Subject: [PATCH] Feature/amirris add area tollhouse (#2) * add area * formatting * change text * add province permission --- .../CreateTollHouseContent.jsx | 41 ++++- .../Form/CreateTollHouse/MachineInfo.jsx | 12 +- .../Form/CreateTollHouse/TollHouseArea.jsx | 80 ++++++++++ .../Form/CreateTollHouse/TollHouseInfo.jsx | 6 +- .../tollHouse/Form/CreateTollHouse/index.jsx | 12 ++ .../tollHouse/Form/Edit/EditController.jsx | 11 ++ .../tollHouse/TollHouseList.jsx | 144 +++++++++--------- 7 files changed, 222 insertions(+), 84 deletions(-) create mode 100644 src/components/infrastructure/tollHouse/Form/CreateTollHouse/TollHouseArea.jsx diff --git a/src/components/infrastructure/tollHouse/Form/CreateTollHouse/CreateTollHouseContent.jsx b/src/components/infrastructure/tollHouse/Form/CreateTollHouse/CreateTollHouseContent.jsx index bb3cb1b..a19dfa5 100644 --- a/src/components/infrastructure/tollHouse/Form/CreateTollHouse/CreateTollHouseContent.jsx +++ b/src/components/infrastructure/tollHouse/Form/CreateTollHouse/CreateTollHouseContent.jsx @@ -7,13 +7,15 @@ import OtherHousesIcon from "@mui/icons-material/OtherHouses"; import LocalShippingIcon from "@mui/icons-material/LocalShipping"; import EditLocationAltIcon from "@mui/icons-material/EditLocationAlt"; import React, { useState } from "react"; -import { useForm } from "react-hook-form"; +import { Controller, useForm } from "react-hook-form"; import { yupResolver } from "@hookform/resolvers/yup"; -import { mixed, number, object, string } from "yup"; +import { array, mixed, number, object, string } from "yup"; import TollHouseInfo from "./TollHouseInfo"; import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft"; import MachineInfo from "@/components/infrastructure/tollHouse/Form/CreateTollHouse/MachineInfo"; import TollHouseLocation from "@/components/infrastructure/tollHouse/Form/CreateTollHouse/TollHouseLocation"; +import { Route } from "@mui/icons-material"; +import TollHouseArea from "./TollHouseArea"; function TabPanel(props) { const { children, value, index } = props; @@ -54,6 +56,23 @@ const validationSchema = object({ return !!value; }) .required("لطفاً محل پروژه را مشخص کنید!"), + area: array() + .of( + object().shape({ + lat: number() + .typeError("عرض جغرافیایی باید یک عدد معتبر باشد") + .required("عرض جغرافیایی الزامی است") + .min(25, "عرض جغرافیایی نمی‌تواند کمتر از 25 باشد") + .max(40, "عرض جغرافیایی نمی‌تواند بیشتر از 40 باشد"), + lon: number("وارد کردن طول جغرافیایی الزامیست") + .typeError("طول جغرافیایی باید یک عدد معتبر باشد") + .required("طول جغرافیایی الزامی است") + .min(44, "طول جغرافیایی نمی‌تواند کمتر از 44 باشد") + .max(64, "طول جغرافیایی نمی‌تواند بیشتر از 64 باشد"), + }) + ) + .min(4, "حداقل باید ۴ نقطه وجود داشته باشد") + .required("محدوده الزامی است"), }); const CreateTollHouseContent = ({ setOpen, SubmitCreateTollHouse, defaultValues }) => { const [tabState, setTabState] = useState(0); @@ -137,8 +156,9 @@ const CreateTollHouseContent = ({ setOpen, SubmitCreateTollHouse, defaultValues }} > } label="اطلاعات راهدارخانه" /> - } label="ماشین آلات" /> - } label="موقعیت" /> + } label="ماشین آلات" /> + } label="موقعیت" /> + } label="محدوده" /> @@ -151,6 +171,15 @@ const CreateTollHouseContent = ({ setOpen, SubmitCreateTollHouse, defaultValues + + ( + + )} + /> + @@ -163,7 +192,7 @@ const CreateTollHouseContent = ({ setOpen, SubmitCreateTollHouse, defaultValues > {tabState === 0 ? "بستن" : "مرحله قبل"} - {tabState !== 2 && ( + {tabState !== 3 && ( + + + + + ); +}; +export default TollHouseArea; diff --git a/src/components/infrastructure/tollHouse/Form/CreateTollHouse/TollHouseInfo.jsx b/src/components/infrastructure/tollHouse/Form/CreateTollHouse/TollHouseInfo.jsx index 22e3fdc..dc56843 100644 --- a/src/components/infrastructure/tollHouse/Form/CreateTollHouse/TollHouseInfo.jsx +++ b/src/components/infrastructure/tollHouse/Form/CreateTollHouse/TollHouseInfo.jsx @@ -106,9 +106,9 @@ const TollHouseInfo = ({ control }) => { value={field.value} label="نوع" selectors={[ - { id: 0, name: "داعمی" }, - { id: 1, name: "موقت" }, - { id: 2, name: "فصلی" }, + { id: 1, name: "دائمی" }, + { id: 2, name: "موقت" }, + { id: 3, name: "فصلی" }, ]} schema={{ name: "name", value: "id" }} error={error} diff --git a/src/components/infrastructure/tollHouse/Form/CreateTollHouse/index.jsx b/src/components/infrastructure/tollHouse/Form/CreateTollHouse/index.jsx index 7dbe3d5..a9cb7cf 100644 --- a/src/components/infrastructure/tollHouse/Form/CreateTollHouse/index.jsx +++ b/src/components/infrastructure/tollHouse/Form/CreateTollHouse/index.jsx @@ -51,6 +51,12 @@ const CreateTollHouse = ({ mutate }) => { }); formData.append("lat", result.start_point.lat); formData.append("lng", result.start_point.lng); + formData.append("area[type]", "polygon"); + result.area.map((point, pointIndex) => { + formData.append(`area[coordinates][${pointIndex}][0]`, point.lat); + formData.append(`area[coordinates][${pointIndex}][1]`, point.lon); + }); + await requestServer(`${CREATE_TOLL_HOUSE}`, "post", { data: formData, }) @@ -83,6 +89,12 @@ const CreateTollHouse = ({ mutate }) => { overview_files_4: null, overview_files_5: null, start_point: "", + area: [ + { lat: "", lon: "" }, + { lat: "", lon: "" }, + { lat: "", lon: "" }, + { lat: "", lon: "" }, + ], }; return ( <> diff --git a/src/components/infrastructure/tollHouse/Form/Edit/EditController.jsx b/src/components/infrastructure/tollHouse/Form/Edit/EditController.jsx index a9d4281..58b108b 100644 --- a/src/components/infrastructure/tollHouse/Form/Edit/EditController.jsx +++ b/src/components/infrastructure/tollHouse/Form/Edit/EditController.jsx @@ -47,6 +47,12 @@ const EditController = ({ rowId, mutate, setOpenEditDialog }) => { overview_files_3: tollHouseItemDetails?.files[2]?.path || null, overview_files_4: tollHouseItemDetails?.files[3]?.path || null, overview_files_5: tollHouseItemDetails?.files[4]?.path || null, + area: tollHouseItemDetails?.area?.coordinates.map(([lat, lon]) => ({ lat, lon })) || [ + { lat: "", lon: "" }, + { lat: "", lon: "" }, + { lat: "", lon: "" }, + { lat: "", lon: "" }, + ], }; const HandleSubmit = async (result) => { const fields = [ @@ -79,6 +85,11 @@ const EditController = ({ rowId, mutate, setOpenEditDialog }) => { } formData.append("lat", result.start_point.lat); formData.append("lng", result.start_point.lng); + formData.append("area[type]", "polygon"); + result.area.map((point, pointIndex) => { + formData.append(`area[coordinates][${pointIndex}][0]`, point.lat); + formData.append(`area[coordinates][${pointIndex}][1]`, point.lon); + }); await requestServer(`${UPDATE_TOLL_HOUSE_ITEM}/${rowId}`, "post", { data: formData, diff --git a/src/components/infrastructure/tollHouse/TollHouseList.jsx b/src/components/infrastructure/tollHouse/TollHouseList.jsx index 113dcbc..4ef1674 100644 --- a/src/components/infrastructure/tollHouse/TollHouseList.jsx +++ b/src/components/infrastructure/tollHouse/TollHouseList.jsx @@ -12,6 +12,7 @@ import useEdaratLists from "@/lib/hooks/useEdaratLists"; import { usePermissions } from "@/lib/hooks/usePermissions"; import LocationForm from "./RowActions/LocationForm"; import ImageDialog from "./RowActions/ImageForm"; +import { useAuth } from "@/lib/contexts/auth"; const statusOptions = [ { value: "", label: "همه وضعیت ها" }, @@ -21,14 +22,51 @@ const statusOptions = [ const typeOptions = [ { value: "", label: "همه نوع ها" }, { value: 0, label: "فصلی" }, - { value: 1, label: "داعمی" }, + { value: 1, label: "دائمی" }, { value: 2, label: "موقت" }, ]; const TollHouseList = () => { const { data: userPermissions } = usePermissions(); - const hasProvincePermission = userPermissions.some((item) => ["add-tollhouse"].includes(item)); + const hasCountryPermission = userPermissions?.includes("show-tollhouse"); + const { user } = useAuth(); const columns = useMemo(() => { + const provinceColumn = { + accessorKey: "province_id", + header: "استان", + id: "province_id", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + grow: false, + size: 130, + ColumnSelectComponent: (props) => { + const { provinces, errorProvinces, loadingProvinces } = useProvinces(); + const getColumnSelectOptions = useMemo(() => { + if (loadingProvinces) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorProvinces) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "کل کشور" }, + ...provinces.map((province) => ({ + value: province.id, + label: province.name_fa, + })), + ]; + }, [provinces, errorProvinces, loadingProvinces]); + return ( + + ); + }, + Cell: ({ row }) => <>{row.original.province_name}, + }; return [ { accessorKey: "id", @@ -64,42 +102,7 @@ const TollHouseList = () => { grow: false, size: 100, }, - { - accessorKey: "province_id", - header: "استان", - id: "province_id", - enableColumnFilter: true, - datatype: "numeric", - filterMode: "equals", - grow: false, - size: 130, - ColumnSelectComponent: (props) => { - const { provinces, errorProvinces, loadingProvinces } = useProvinces(); - const getColumnSelectOptions = useMemo(() => { - if (loadingProvinces) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorProvinces) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "کل کشور" }, - ...provinces.map((province) => ({ - value: province.id, - label: province.name_fa, - })), - ]; - }, [provinces, errorProvinces, loadingProvinces]); - return ( - - ); - }, - Cell: ({ row }) => <>{row.original.province_name}, - }, + ...(hasCountryPermission ? [provinceColumn] : []), { accessorKey: "city_id", header: "شهرستان", // Office @@ -107,17 +110,19 @@ const TollHouseList = () => { enableColumnFilter: true, datatype: "numeric", filterMode: "equals", - dependencyId: "province_id", + dependencyId: hasCountryPermission ? "province_id" : null, grow: false, size: 120, ColumnSelectComponent: (props) => { const { edaratList, loadingEdaratList, errorEdaratList } = useEdaratLists( - props.dependencyFieldValue.value + hasCountryPermission ? props.dependencyFieldValue.value : user.province_id + ); + const [prevDependency, setPrevDependency] = useState( + hasCountryPermission ? props.dependencyFieldValue.value : user.province_id ); - const [prevDependency, setPrevDependency] = useState(props.dependencyFieldValue.value); const getColumnSelectOptions = useMemo(() => { - if (props.dependencyFieldValue.value === "") { + if (hasCountryPermission && props.dependencyFieldValue.value === "") { return [{ value: "empty", label: "ابتدا استان را انتخاب کنید" }]; } if (loadingEdaratList) { @@ -135,10 +140,11 @@ const TollHouseList = () => { ]; }, [edaratList, loadingEdaratList, errorEdaratList]); useEffect(() => { + if (hasCountryPermission) return; if (prevDependency === props.dependencyFieldValue?.value) return; props.handleChange({ ...props.filterParameters, value: "" }); setPrevDependency(props.dependencyFieldValue?.value); - }, [props.dependencyFieldValue?.value]); + }, [props.dependencyFieldValue?.value, hasCountryPermission]); return ( { return {row.original.type_fa}; }, }, + { + header: "موقعیت", // Location + id: "location", + enableColumnFilter: false, + enableSorting: false, + datatype: "array", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue, row }) => { + return ( + + + + ); + }, + }, { accessorKey: "phone", header: "تلفن راهدارخانه", @@ -352,31 +383,6 @@ const TollHouseList = () => { }, ], }, - { - header: "موقعیت", // Location - id: "location", - enableColumnFilter: false, - enableSorting: false, - datatype: "array", - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", - }, - }, - }, - Cell: ({ renderedCellValue, row }) => { - return ( - - - - ); - }, - }, { accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), header: "تاریخ ثبت", @@ -402,7 +408,7 @@ const TollHouseList = () => { sorting={[{ id: "id", desc: true }]} TableToolbar={Toolbar} enableRowActions - positionActionsColumn={"last"} + positionActionsColumn={"first"} RowActions={RowActions} />