diff --git a/src/app/(withAuth)/dashboard/technical-building-damage/operator/page.js b/src/app/(withAuth)/dashboard/technical-building-damage/operator/page.js new file mode 100644 index 0000000..42644d6 --- /dev/null +++ b/src/app/(withAuth)/dashboard/technical-building-damage/operator/page.js @@ -0,0 +1,13 @@ +import WithPermission from "@/core/middlewares/withPermission"; +import ActivityCodeLog from "@/core/components/ActivityCodeLog"; +import OperatorPage from "@/components/dashboard/technicalBuildingDamage/operator"; +const Page = () => { + return ( + + + {/* change permission */} + + ); +}; + +export default Page; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/CityController.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/CityController.jsx new file mode 100644 index 0000000..65dc92c --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/CityController.jsx @@ -0,0 +1,28 @@ +import SelectBox from "@/core/components/SelectBox"; +import { Controller, useWatch } from "react-hook-form"; +import useEdaratLists from "@/lib/hooks/useEdaratLists"; + +const CityController = ({ control }) => { + const provinceID = useWatch({ control, name: "province_id" }); + const { edaratList, loadingEdaratList, errorEdaratList } = useEdaratLists(provinceID); + return ( + ( + + )} + /> + ); +}; +export default CityController; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/CreateFormContent.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/CreateFormContent.jsx new file mode 100644 index 0000000..d7ae67c --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/CreateFormContent.jsx @@ -0,0 +1,232 @@ +import React, { useState } from "react"; +import { Controller, useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { array, mixed, number, object, string } from "yup"; +import { useTheme } from "@emotion/react"; +import { Box, Button, DialogActions, DialogContent, Tab, Tabs, useMediaQuery } from "@mui/material"; +import StyledForm from "@/core/components/StyledForm"; +import FileCopyIcon from "@mui/icons-material/FileCopy"; +import InfoIcon from "@mui/icons-material/Info"; +import ExitToAppIcon from "@mui/icons-material/ExitToApp"; +import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight"; +import BeenhereIcon from "@mui/icons-material/Beenhere"; +import MinorCrashIcon from "@mui/icons-material/MinorCrash"; +import DamageInfo from "./DamageInfo"; +import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft"; +import DamageReport from "./DamageReport"; +import DamageItem from "./DamageItem"; + +function TabPanel(props) { + const { children, value, index } = props; + return ( + + ); +} + +const validationSchema = object({ + accident_date: string().required("لطفا تاریخ تصادف را وارد کنید!!!"), + accident_time: string().required("لطفا زمان تصادف را وارد کنید!!!"), + accident_type: string().required("لطفا نوع تصادف را وارد کنید!!!"), + province_id: number().required("لطفا استان را وارد کنید!!!"), + city_id: number().required("لطفا شهرستان را وارد کنید!!!"), + axis_name: string().required("لطفا نام محور را وارد کنید!!!"), + driver_name: string().required("لطفا نام و نام خانوادگی را وارد کنید!!!"), + phone_number: mixed() + .test("max", "تلفن همراه باید شامل 11 رقم باشد", (value) => { + const stringValue = String(value); + return stringValue.length === 11; + }) + .required("لطفا تلفن همراه را وارد کنید!!!"), + national_code: mixed() + .test("max", "کد ملی باید شامل 10 رقم باشد", (value) => value.toString().length === 10) + .required("لطفا کد ملی را وارد کنید!!!"), + start_point: mixed() + .test("start-point-required", "لطفاً نقطه تصادف را مشخص کنید!", function (value) { + return !!value; // چک می‌کند که مقدار موجود است + }) + .required("لطفاً نقطه تصادف را مشخص کنید!"), + plate_part1: mixed() + .test("max", "2رقم", (value) => value.toString().length === 2) + .required("plate_part1 الزامیست"), + plate_part2: mixed().required("plate_part2 الزامیست"), + plate_part3: mixed() + .test("max", "3رقم", (value) => value.toString().length === 3) + .required("plate_part3الزامیست"), + plate_part4: mixed() + .test("max", "2رقم", (value) => value.toString().length === 2) + .required("plate_part4الزامیست"), + damage_picture1: mixed().nullable().required("لطفا عکس تصادف را بارگذاری کنید!"), + damage_picture2: mixed().nullable().required("لطفا عکس تصادف را بارگذاری کنید!"), + police_serial: string().when("police_file_checkbox", { + is: "police_file_checkbox", // زمانی که گزینه "police_file_checkbox" انتخاب شده باشد + then: (schema) => schema.required("شماره کروکی یا نامه پلیس راه الزامی است"), + }), + police_file_date: string().when("police_file_checkbox", { + is: "police_file_checkbox", // زمانی که گزینه "police_file_checkbox" انتخاب شده باشد + then: (schema) => schema.required("تاریخ کروکی یا نامه پلیس راه الزامی است"), + }), + police_file: string().when("police_file_checkbox", { + is: "police_file_checkbox", // زمانی که گزینه "police_file_checkbox" انتخاب شده باشد + then: (schema) => schema.required("تصویر کروکی یا نامه پلیس راه الزامی است"), + }), + items_damage: array().min(1, "حداقل یک ایتم خسارت ضروریست!!!"), +}); + +const CreateFormContent = ({ setOpen, mutate }) => { + const defaultValues = { + accident_date: "", + accident_time: "", + accident_type: "", + province_id: null, + city_id: null, + axis_name: "", + driver_name: "", + phone_number: "", + national_code: "", + plate_part1: "", + plate_part2: "الف", + plate_part3: "", + plate_part4: "", + damage_picture1: null, + damage_picture2: null, + report_base: "", + police_file_checkbox: "", + police_file: "", + police_file_date: "", + police_serial: "", + start_point: "", + items_damage: [], + }; + + const [tabState, setTabState] = useState(1); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const handleClose = () => setOpen(false); + const handleChangeTab = (event, newValue) => setTabState(newValue); + const handlePrev = () => { + if (tabState === 0) { + handleClose(); + } else { + setTabState(tabState - 1); + } + }; + const { + control, + handleSubmit, + setValue, + trigger, + formState: { errors, isSubmitting, isValid }, + } = useForm({ + defaultValues, + resolver: yupResolver(validationSchema), + mode: "all", + }); + const onSubmitBase = async (data) => { + console.log(data); + }; + const handleNext = async () => { + let fieldsToValidate = []; + if (tabState === 0) { + fieldsToValidate = [ + "phone_number", + "start_point", + "plate_part1", + "plate_part2", + "plate_part3", + "plate_part4", + "accident_date", + "accident_type", + "national_code", + "accident_time", + "province_id", + "city_id", + "axis_name", + "driver_name", + "damage_picture1", + "damage_picture2", + ]; + } else if (tabState === 1) { + fieldsToValidate = ["report_base", "police_file", "police_file_date", "police_serial"]; + } else if (tabState === 2) { + fieldsToValidate = ["items_damage"]; + } + const isValid = await trigger(fieldsToValidate); + if (isValid) { + setTabState(tabState + 1); + } + }; + return ( + + + } label="اطلاعات تصادف" /> + } label="گزارش میزان خسارت" /> + } label="ایتم خسارت" /> + + + + + + + + + + + { + return ; + }} + /> + + + + + + {tabState !== 2 ? ( + + ) : ( + + )} + + + ); +}; +export default CreateFormContent; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageAmount.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageAmount.jsx new file mode 100644 index 0000000..b2c7b90 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageAmount.jsx @@ -0,0 +1,55 @@ +import { Controller, useWatch } from "react-hook-form"; +import { Grid } from "@mui/material"; +import NumberField from "@/core/components/NumberField"; +import { useEffect } from "react"; + +const DamageAmount = ({ control, damageItemList, setValue }) => { + const itemDamage = useWatch({ control, name: "items_damge_id" }); + const itemValue = useWatch({ control, name: "items_damge_value" }); + const itemDamageId = damageItemList.find((damageItem) => damageItem.id === itemDamage); + const isDisabled = itemDamageId?.base_price ? itemDamageId?.base_price !== 0 : false; + const calculatedValue = itemValue * (itemDamageId?.base_price ? itemDamageId?.base_price : 0); + useEffect(() => { + if (isDisabled) { + setValue("items_damge_amount", calculatedValue); + } + }, [itemValue, itemDamageId, isDisabled, setValue]); + return ( + + { + return ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + if (!isDisabled) { + field.onChange(inputValue); + } + }} + label={`هزینه خسارت (ریال)`} + fullWidth + size="small" + disabled={isDisabled || itemDamage === null} + error={error} + helperText={error?.message} + /> + ); + }} + /> + + ); +}; +export default DamageAmount; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageInfo.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageInfo.jsx new file mode 100644 index 0000000..4b3457b --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageInfo.jsx @@ -0,0 +1,273 @@ +import { Controller } from "react-hook-form"; +import { Grid, Stack, TextField } from "@mui/material"; +import MuiDatePicker from "@/core/components/MuiDatePicker"; +import MuiTimePicker from "@/core/components/MuiTimePicker"; +import SelectBox from "@/core/components/SelectBox"; +import useProvinces from "@/lib/hooks/useProvince"; +import PlateNumber from "@/core/components/PlateNumber"; +import ImageUpload from "./ImageUpload"; +import MapInfoOneMarker from "@/core/components/MapInfoOneMarker"; +import CityController from "@/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/CityController"; + +const DamageInfo = ({ control, setValue, errors }) => { + const { provinces, errorProvinces, loadingProvinces } = useProvinces(); + + return ( + + + + { + return ( + field.onChange(value || [])} + helperText={error ? error.message : null} + /> + ); + }} + name={"accident_date"} + /> + + + { + return ( + field.onChange(value || null)} + helperText={error ? error.message : null} + /> + ); + }} + name={"accident_time"} + /> + + + { + return ( + + ); + }} + /> + + + + + { + return ( + + ); + }} + /> + + + + + + ( + + )} + /> + + + + + ( + + )} + /> + + + ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + field.onChange(inputValue); + }} + label="کد ملی" + placeholder={"کد ملی را وارد کنید"} + fullWidth + size="small" + error={error} + helperText={error?.message} + /> + )} + /> + + + + + ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + field.onChange(inputValue); + }} + label="شماره تماس" + placeholder={"شماره تماس را وارد کنید"} + fullWidth + size="small" + error={error} + helperText={error?.message} + /> + )} + /> + + + + + + + + ( + + )} + /> + + + ( + + )} + /> + + + + + + + ); +}; +export default DamageInfo; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageItem.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageItem.jsx new file mode 100644 index 0000000..3a5de73 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageItem.jsx @@ -0,0 +1,136 @@ +import { Autocomplete, Box, Button, Chip, Divider, Fade, Grid, Stack, TextField, Typography } from "@mui/material"; +import { Controller, useController, useForm } from "react-hook-form"; +import LinearProgress from "@mui/material/LinearProgress"; +import { useEffect, useState } from "react"; +import DamageItemInfo from "./DamageItemInfo"; +import { number, object } from "yup"; +import useDamageItemList from "@/lib/hooks/useDamageItemList"; +import DamagePrice from "./DamagePrice"; +import { yupResolver } from "@hookform/resolvers/yup"; + +const schema = object({ + items_damge_id: number().required("لطفا نوع خسارت را وارد کنید!!!"), + items_damge_value: number().required("لطفا میزان خسارت را وارد کنید!!!"), + items_damge_amount: number().required("لطفا هزینه خسارت را وارد کنید!!!"), +}); +const defaultValues = { + items_damge_id: null, + items_damge_value: null, + items_damge_amount: null, +}; +const DamageItem = ({ baseOnChange, getValues }) => { + const [selectedDamageItemList, setSelectedDamageItemList] = useState([]); + const { damageItemList, loadingDamageItemList, errorDamageItemList } = useDamageItemList(); + const { control, handleSubmit, reset, setValue } = useForm({ + defaultValues, + resolver: yupResolver(schema), + mode: "onBlur", + }); + const deleteDamageItem = (id) => { + setSelectedDamageItemList((prev) => prev.filter((DamageItem) => DamageItem.items_damge_id !== id)); + }; + useEffect(() => { + baseOnChange(selectedDamageItemList); + }, [selectedDamageItemList]); + const handleCreateDamage = (data) => { + setSelectedDamageItemList((prev) => { + const isDuplicate = prev.some((item) => item.items_damge_id === data.items_damge_id); + if (!isDuplicate) { + return [...prev, data]; + } else { + return prev; + } + }); + reset(); + }; + + return ( + <> + + {loadingDamageItemList ? ( + + + + ) : ( + <> + + ( + option.title} + isOptionEqualToValue={(option, value) => option.id === value.id} + loading={loadingDamageItemList} + renderInput={(params) => ( + + )} + onChange={(_, value) => field.onChange(value?.id)} + value={damageItemList.find((item) => item.id === field.value) || null} + /> + )} + /> + + + + + + + + + + + )} + + + + + {selectedDamageItemList.length === 0 && ( + + + ابتدا اطلاعات بالا را تکمیل نمایید + + + )} + + + {selectedDamageItemList.length !== 0 && + selectedDamageItemList.map((selectedDamageItem, index) => ( + + + + ))} + + + + ); +}; +export default DamageItem; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageItemInfo.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageItemInfo.jsx new file mode 100644 index 0000000..7af4ff4 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageItemInfo.jsx @@ -0,0 +1,43 @@ +import { Box, Card, IconButton, Stack, Typography } from "@mui/material"; +import DeleteIcon from "@mui/icons-material/Delete"; +import React from "react"; +import MinorCrashIcon from "@mui/icons-material/MinorCrash"; + +const DamageItemInfo = ({ deleteDamageItem, selectedDamageItem, damageItemList }) => { + const itemDamageId = damageItemList.find((item) => item.id == selectedDamageItem.items_damge_id); + return ( + + + + + + {itemDamageId.title} + + + میزان خسارت ({itemDamageId.unit}): {selectedDamageItem.items_damge_value} + + + هزینه خسارت (ریال): {selectedDamageItem.items_damge_amount} + + + + + deleteDamageItem(selectedDamageItem.items_damge_id)}> + + + + + ); +}; +export default DamageItemInfo; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamagePrice.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamagePrice.jsx new file mode 100644 index 0000000..02fe21a --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamagePrice.jsx @@ -0,0 +1,48 @@ +import { Controller, useWatch } from "react-hook-form"; +import { Grid, TextField } from "@mui/material"; +import DamageAmount from "./DamageAmount"; + +const DamagePrice = ({ damageItemList, control, setValue }) => { + const itemDamage = useWatch({ control, name: "items_damge_id" }); + const itemDamageId = damageItemList.find((damageItem) => damageItem.id === itemDamage); + + return ( + <> + + { + return ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + field.onChange(inputValue); + }} + label={`میزان خسارت ${itemDamageId?.unit ? `(${itemDamageId?.unit})` : ""}`} + fullWidth + size="small" + error={error} + helperText={error?.message} + /> + ); + }} + /> + + + + ); +}; +export default DamagePrice; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageReport.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageReport.jsx new file mode 100644 index 0000000..a649b14 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/DamageReport.jsx @@ -0,0 +1,53 @@ +import { FormControlLabel, RadioGroup, Stack } from "@mui/material"; +import { Controller } from "react-hook-form"; +import { useState } from "react"; +import PoliceFileReport from "./PoliceFileReport"; +import Radio from "@mui/material/Radio"; + +const DamageReport = ({ control, setValue }) => { + const [selectedOption, setSelectedOption] = useState("report_base"); + + const handleOptionChange = (e) => { + setSelectedOption(e.target.value); + if (e.target.value === "report_base") { + setValue("police_file_checkbox", ""); + setValue("report_base", "1"); + } + }; + + return ( + <> + + + } + /> + } + label="کروکی یا نامه پلیس راه (معرفی فرد به اداره)" + /> + } + /> + } + label="بازدید عوامل و کارشناسان راهداری" + /> + + + {selectedOption === "police_file_checkbox" && } + + ); +}; +export default DamageReport; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/ImageUpload.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/ImageUpload.jsx new file mode 100644 index 0000000..107d640 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/ImageUpload.jsx @@ -0,0 +1,77 @@ +import { FormControl, FormHelperText } from "@mui/material"; +import UploadSystem from "@/core/components/UploadSystem"; +import React, { useEffect, useState } from "react"; + +const ImageUpload = ({ name, value, onChange, error, beforeImage = null, title }) => { + const [beforeImg, setBeforeImg] = useState(beforeImage ? beforeImage : null); + const [beforeFileType, setBeforeFileType] = useState(beforeImage ? "image/" : null); + const [beforeFileName, setBeforeFileName] = useState(null); + const [showBeforeImage, setShowBeforeImage] = useState(!beforeImage); + + useEffect(() => { + if (value) { + setShowBeforeImage(false); + if (typeof value === "string") { + setBeforeImg(value); + setBeforeFileType("image/"); + } else if (value instanceof File) { + setBeforeImg(URL.createObjectURL(value)); + setBeforeFileType(value.type); + } + } + }, [value]); + + const handleFileChange = (event) => { + const uploadedFile = event.target?.files?.[0]; + if (uploadedFile) { + const fileType = event.target?.files?.[0].type; + const fileName = event.target?.files?.[0].name; + setBeforeImg(URL.createObjectURL(uploadedFile)); + setBeforeFileType(fileType); + setBeforeFileName(fileName); + onChange(uploadedFile); + setShowBeforeImage(false); + } + }; + + return ( + + + {title} + + + {error ? error.message : null} + + ); +}; +export default ImageUpload; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/PoliceFileReport.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/PoliceFileReport.jsx new file mode 100644 index 0000000..9a93566 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/PoliceFileReport.jsx @@ -0,0 +1,65 @@ +import { Controller } from "react-hook-form"; +import { Grid, Stack, TextField } from "@mui/material"; +import MuiDatePicker from "@/core/components/MuiDatePicker"; +import ImageUpload from "./ImageUpload"; + +const PoliceFileReport = ({ control }) => { + return ( + + + + + ( + + )} + /> + + + { + return ( + field.onChange(value || [])} + helperText={error ? error.message : null} + /> + ); + }} + name={"police_file_date"} + /> + + + + ( + + )} + /> + + ); +}; +export default PoliceFileReport; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/index.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/index.jsx new file mode 100644 index 0000000..86c05f8 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/index.jsx @@ -0,0 +1,12 @@ +"use client"; +import { Dialog } from "@mui/material"; +import CreateFormContent from "@/components/dashboard/technicalBuildingDamage/operator/Actions/create/Forms/CreateFormContent"; + +const OperatorCreateForm = ({ open, setOpen, mutate }) => { + return ( + + + + ); +}; +export default OperatorCreateForm; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/index.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/index.jsx new file mode 100644 index 0000000..5816c12 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Actions/create/index.jsx @@ -0,0 +1,38 @@ +"use client"; +import { Button, IconButton, useMediaQuery } from "@mui/material"; +import { useTheme } from "@emotion/react"; +import { useState } from "react"; +import { AddCircle } from "@mui/icons-material"; +import OperatorCreateForm from "./Forms"; + +const OperatorCreate = ({ mutate }) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [open, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + + return ( + <> + {isMobile ? ( + + + + ) : ( + + )} + + + ); +}; +export default OperatorCreate; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/OperatorList.jsx b/src/components/dashboard/technicalBuildingDamage/operator/OperatorList.jsx new file mode 100644 index 0000000..04955b3 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/OperatorList.jsx @@ -0,0 +1,356 @@ +"use client"; +import { useEffect, useMemo, useState } from "react"; +import { Box, Stack, Typography } from "@mui/material"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import Toolbar from "./Toolbar"; +import { GET_TECHNICAL_DAMAGE_OPERATOR_LIST } from "@/core/utils/routes"; +import moment from "jalali-moment"; +import RowActions from "./RowActions"; +import useProvinces from "@/lib/hooks/useProvince"; +import CustomSelectByDependency from "@/core/components/DataTable/filter/fieldsType/CustomSelectByDependency"; +import useEdaratLists from "@/lib/hooks/useEdaratLists"; +import ImageDialog from "./RowActions/ImageDialog"; +import LocationForm from "./RowActions/LocationForm"; +import ShowPlate from "./RowActions/ShowPlate"; + +const OperatorList = () => { + const statusOptions = [ + { value: 0, label: "بدون اقدام" }, + { value: 1, label: "صدور نامه بیمه و کارشناسی داغی" }, + { value: 2, label: "فیش ها ثبت شده است" }, + { value: 3, label: "فاکتور صادر شده است" }, + { value: 4, label: "فاکتور پرداخت شده است" }, + { value: 5, label: "نامه پلیس راه صادر شده است" }, + ]; + const columns = useMemo(() => { + return [ + { + accessorKey: "id", + header: "کد یکتا", // Unique Code + id: "id", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + 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_fa}, + }, + { + accessorKey: "city_id", + header: "شهرستان", // Office + id: "city_id", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + dependencyId: "province_id", + grow: false, + size: 120, + ColumnSelectComponent: (props) => { + const { edaratList, loadingEdaratList, errorEdaratList } = useEdaratLists( + props.dependencyFieldValue.value + ); + const [prevDependency, setPrevDependency] = useState(props.dependencyFieldValue.value); + + const getColumnSelectOptions = useMemo(() => { + if (props.dependencyFieldValue.value === "") { + return [{ value: "empty", label: "ابتدا استان را انتخاب کنید" }]; + } + if (loadingEdaratList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorEdaratList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "شهر" }, + ...edaratList.map((edare) => ({ + value: edare.id, + label: edare.name_fa, + })), + ]; + }, [edaratList, loadingEdaratList, errorEdaratList]); + useEffect(() => { + if (prevDependency === props.dependencyFieldValue?.value) return; + props.handleChange({ ...props.filterParameters, value: "" }); + setPrevDependency(props.dependencyFieldValue?.value); + }, [props.dependencyFieldValue?.value]); + return ( + + ); + }, + Cell: ({ row }) => <>{row.original.city_fa}, + }, + { + accessorKey: "axis_name", + header: "نام محور", + id: "axis_name", + enableColumnFilter: true, + enableSorting: true, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 120, + }, + { + accessorKey: "accident_type", + header: "نوع تصادف", // Value + id: "accident_type", + enableColumnFilter: true, + enableSorting: true, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 120, + Cell: ({ row }) => <>{row.original.accident_type_fa}, + }, + { + accessorFn: (row) => { + const formattedDate = moment(row.accident_date, "YYYY-MM-DD"); // تنظیم فرمت صحیح تاریخ + const formattedTime = row.accident_time || "00:00:00"; // در صورت خالی بودن مقدار، مقدار پیش‌فرض داده شود + return moment(`${formattedDate.format("YYYY-MM-DD")}T${formattedTime}`) + .locale("fa") + .format("HH:mm | YYYY/MM/DD"); + }, + header: "تاریخ تصادف", + id: "accident_date", + enableColumnFilter: true, + datatype: "date", + filterMode: "between", + grow: false, + size: 100, + }, + { + accessorKey: "files", + header: "تصاویر", + id: "files", + enableColumnFilter: false, + enableSorting: false, + datatype: "array", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ row }) => { + if (row.original.damage_picture1) { + const imagesList = [row.original.damage_picture1, row.original.damage_picture2]; + return ( + + + + ); + } + return ( + + بدون تصویر + + ); + }, + }, + { + accessorKey: "location", + header: "موقعیت", + 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: ({ row }) => { + return ( + + + + ); + }, + }, + { + accessorKey: "sum", + header: "مبلغ کل خسارت (ریال)", + id: "sum", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + sortDescFirst: true, + grow: false, + size: 100, + Cell: ({ row }) => ( + + {(row.original.sum / 1).toLocaleString()} + + ), + }, + { + accessorKey: "plaque", + header: "پلاک", + id: "plaque", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: true, + grow: false, + size: 100, + Cell: ({ renderedCellValue }) => , + }, + { + accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), + header: "تاریخ ثبت", + id: "created_at", + enableColumnFilter: true, + datatype: "date", + filterMode: "between", + grow: false, + size: 100, + }, + { + accessorKey: "status", + header: "اخرین وضعیت", + id: "status", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + grow: false, + size: 100, + columnSelectOption: () => { + return statusOptions.map((status) => ({ + value: status.value, + label: status.label, + })); + }, + Cell: ({ row }) => { + return {row.original.status_fa}; + }, + }, + { + header: "اطلاعات واریز", + id: "items", + enableColumnFilter: false, + enableSorting: false, + grow: false, + size: 50, + columns: [ + { + header: "مبلغ فیش (ریال)", + id: "final_amount", + enableColumnFilter: false, + grow: false, + size: 100, + Cell: ({ row }) => ( + + {(row.original.final_amount / 1).toLocaleString()} + + ), + }, + { + header: "مبلغ بیمه (ریال)", + id: "deposit_insurance_amount", + enableColumnFilter: false, + grow: false, + size: 100, + Cell: ({ row }) => ( + + {(row.original.deposit_insurance_amount / 1).toLocaleString()} + + ), + }, + { + header: "مبلغ داغی (ریال)", + id: "deposit_daghi_amount", + enableColumnFilter: false, + grow: false, + size: 100, + Cell: ({ row }) => ( + + {(row.original.deposit_daghi_amount / 1).toLocaleString()} + + ), + }, + ], + }, + ]; + }, []); + + return ( + <> + + + + + ); +}; +export default OperatorList; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/RowActions/ImageDialog/ImageFormContent.jsx b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/ImageDialog/ImageFormContent.jsx new file mode 100644 index 0000000..9aaa92e --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/ImageDialog/ImageFormContent.jsx @@ -0,0 +1,44 @@ +import { Box, DialogContent, Paper, Stack, Typography, useTheme } from "@mui/material"; +import Image from "next/image"; + +const ImageFormContent = ({ image, title }) => { + const theme = useTheme(); + return ( + + + {title} + + + Image + + + ); +}; +export default ImageFormContent; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/RowActions/ImageDialog/index.jsx b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/ImageDialog/index.jsx new file mode 100644 index 0000000..6e442ca --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/ImageDialog/index.jsx @@ -0,0 +1,44 @@ +import { Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Paper, Tooltip } from "@mui/material"; +import { useState } from "react"; +import PhotoLibraryIcon from "@mui/icons-material/PhotoLibrary"; +import ImageFormContent from "./ImageFormContent"; + +const ImageDialog = ({ images }) => { + const [openImageDialog, setOpenImageDialog] = useState(false); + + return ( + <> + + setOpenImageDialog(true)}> + + + + setOpenImageDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + maxWidth={"sm"} + scroll="paper" + > + تصاویر + + + + + + + + + + + + ); +}; +export default ImageDialog; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/RowActions/LocationForm/LocationFormContent.jsx b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/LocationForm/LocationFormContent.jsx new file mode 100644 index 0000000..14b3db3 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/LocationForm/LocationFormContent.jsx @@ -0,0 +1,35 @@ +"use client"; +import { Box, Button, DialogActions, DialogContent, Stack } from "@mui/material"; +import React from "react"; +import dynamic from "next/dynamic"; +import MapLoading from "@/core/components/MapLayer/Loading"; +import ShowLocationMarker from "@/core/components/ShowLocationMarker"; +const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { + loading: () => , + ssr: false, +}); + +const LocationFormContent = ({ setOpenLocationDialog, start_lat, start_lng, end_lat, end_lng }) => { + return ( + <> + + + + + + + + + + + + ); +}; +export default LocationFormContent; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/RowActions/LocationForm/index.jsx b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/LocationForm/index.jsx new file mode 100644 index 0000000..f578ca8 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/LocationForm/index.jsx @@ -0,0 +1,38 @@ +import React, { useState } from "react"; +import { Tooltip, IconButton, Dialog, DialogTitle } from "@mui/material"; +import ExploreIcon from "@mui/icons-material/Explore"; +import LocationFormContent from "./LocationFormContent"; +const LocationForm = ({ start_lat, start_lng, end_lat, end_lng }) => { + const [openLocationDialog, setOpenLocationDialog] = useState(false); + + return ( + <> + + setOpenLocationDialog(true)}> + + + + setOpenLocationDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + dir="rtl" + maxWidth={"md"} + > + موقعیت + + + + ); +}; +export default LocationForm; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/RowActions/ShowPlate/index.jsx b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/ShowPlate/index.jsx new file mode 100644 index 0000000..90d3ad0 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/ShowPlate/index.jsx @@ -0,0 +1,38 @@ +import { Stack } from "@mui/material"; + +const ShowPlate = ({ plate }) => { + return ( + + + {plate.split("-")[3]} + + + + {plate.split("-")[2]} + + + {plate.split("-")[1]} + + + {plate.split("-")[0]} + + + + ); +}; +export default ShowPlate; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/RowActions/index.jsx b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/index.jsx new file mode 100644 index 0000000..c9e69ef --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/RowActions/index.jsx @@ -0,0 +1,6 @@ +import { Box } from "@mui/material"; + +const RowActions = ({ row }) => { + return ; +}; +export default RowActions; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/Toolbar.jsx b/src/components/dashboard/technicalBuildingDamage/operator/Toolbar.jsx new file mode 100644 index 0000000..b774945 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/Toolbar.jsx @@ -0,0 +1,11 @@ +import { Box } from "@mui/material"; +import OperatorCreate from "./Actions/create"; + +const Toolbar = ({ table, filterData, mutate }) => { + return ( + + + + ); +}; +export default Toolbar; diff --git a/src/components/dashboard/technicalBuildingDamage/operator/index.jsx b/src/components/dashboard/technicalBuildingDamage/operator/index.jsx new file mode 100644 index 0000000..4936664 --- /dev/null +++ b/src/components/dashboard/technicalBuildingDamage/operator/index.jsx @@ -0,0 +1,14 @@ +"use client"; +import PageTitle from "@/core/components/PageTitle"; +import { Stack } from "@mui/material"; +import OperatorList from "./OperatorList"; + +const OperatorPage = () => { + return ( + + + + + ); +}; +export default OperatorPage; diff --git a/src/core/components/MapInfoOneMarker.jsx b/src/core/components/MapInfoOneMarker.jsx index b9574c1..a68d4bf 100644 --- a/src/core/components/MapInfoOneMarker.jsx +++ b/src/core/components/MapInfoOneMarker.jsx @@ -37,7 +37,7 @@ const createCustomIcon = (size, iconUrl, labelText, color) => { }; const MAX_ZOOM_FOR_MARKER = 13; -const MapInteraction = ({ setValue, startLat, startLng }) => { +const MapInteraction = ({ setValue, startLat, startLng, title }) => { const [isMarkerLocked, setIsMarkerLocked] = useState(!!(startLat && startLng)); const [enableSend, setEnableSend] = useState(false); const [startIconColor, setStartIconColor] = useState(startLat ? "#1CAC66" : "#003d4f"); @@ -109,7 +109,7 @@ const MapInteraction = ({ setValue, startLat, startLng }) => { > - برای ثبت محل فعالیت، لطفاً نقشه را بیشتر زوم کنید. + {title} @@ -131,7 +131,12 @@ const MapInteraction = ({ setValue, startLat, startLng }) => { ); }; -const MapInfoOneMarker = ({ setValue, errors, StartPoint = null }) => { +const MapInfoOneMarker = ({ + setValue, + errors, + StartPoint = null, + title = "برای ثبت محل فعالیت، لطفاً نقشه را بیشتر زوم کنید.", +}) => { return ( @@ -140,6 +145,7 @@ const MapInfoOneMarker = ({ setValue, errors, StartPoint = null }) => { setValue={setValue} startLat={StartPoint ? StartPoint.lat : null} startLng={StartPoint ? StartPoint.lng : null} + title={title} /> diff --git a/src/core/components/MuiDatePicker.jsx b/src/core/components/MuiDatePicker.jsx index 0b5d8b1..f931188 100644 --- a/src/core/components/MuiDatePicker.jsx +++ b/src/core/components/MuiDatePicker.jsx @@ -8,67 +8,69 @@ import moment from "jalali-moment"; function MuiDatePicker({ value, setFieldValue, name, minDate, maxDate, helperText, placeholder, error, label }) { 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, - size: "small", - placeholder: placeholder, - InputLabelProps: { - shrink: true, + <> + + + { + 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, + size: "small", + placeholder: placeholder, + InputLabelProps: { + shrink: true, + }, + InputProps: { + endAdornment: ( + + { + event.stopPropagation(); + setFieldValue(name, ""); + }} + sx={{ + color: "#bfbfbf", + "&:hover": { + backgroundColor: "rgba(189, 189, 189, 0.1)", + color: "#363434", + }, + }} + > + + + + ), + }, }, - InputProps: { - endAdornment: ( - - { - event.stopPropagation(); - setFieldValue(name, ""); - }} - sx={{ - color: "#bfbfbf", - "&:hover": { - backgroundColor: "rgba(189, 189, 189, 0.1)", - color: "#363434", - }, - }} - > - - - - ), - }, - }, - }} - /> - {helperText ? ( - - {helperText} - - ) : null} - - + }} + /> + + + {helperText && ( + + {helperText} + + )} + ); } diff --git a/src/core/components/MuiTimePicker.jsx b/src/core/components/MuiTimePicker.jsx index b3336d4..a8fc46c 100644 --- a/src/core/components/MuiTimePicker.jsx +++ b/src/core/components/MuiTimePicker.jsx @@ -13,66 +13,68 @@ function MuiTimePicker({ value, setFieldValue, name, minTime, maxTime, helperTex const parsedMaxTime = maxTime || null; return ( - - - { - setFieldValue(name, newValue); - }} - minTime={parsedMinTime} - maxTime={parsedMaxTime} - slotProps={{ - textField: { - placeholder: placeholder, - size: "small", - error: error, - InputLabelProps: { - shrink: true, + <> + + + { + setFieldValue(name, newValue); + }} + minTime={parsedMinTime} + maxTime={parsedMaxTime} + slotProps={{ + textField: { + placeholder: placeholder, + size: "small", + error: error, + InputLabelProps: { + shrink: true, + }, + InputProps: { + endAdornment: ( + + { + event.stopPropagation(); + setFieldValue(name, ""); + }} + sx={{ + color: "#bfbfbf", + "&:hover": { + backgroundColor: "rgba(189, 189, 189, 0.1)", + color: "#363434", + }, + }} + > + + + + ), + }, }, - InputProps: { - endAdornment: ( - - { - event.stopPropagation(); - setFieldValue(name, ""); - }} - sx={{ - color: "#bfbfbf", - "&:hover": { - backgroundColor: "rgba(189, 189, 189, 0.1)", - color: "#363434", - }, - }} - > - - - - ), - }, - }, - }} - /> - {helperText ? ( - - {helperText} - - ) : null} - - + }} + /> + + + {helperText && ( + + {helperText} + + )} + ); } diff --git a/src/core/components/PlateNumber.jsx b/src/core/components/PlateNumber.jsx new file mode 100644 index 0000000..7b396d5 --- /dev/null +++ b/src/core/components/PlateNumber.jsx @@ -0,0 +1,197 @@ +import { Box, Button, Drawer, FormHelperText, Stack, TextField } from "@mui/material"; +import AccessibleIcon from "@mui/icons-material/Accessible"; +import { Controller, useFormState, useWatch } from "react-hook-form"; +import { useEffect, useState } from "react"; + +const plate_words = [ + { id: 1, value: "الف", name: "الف" }, + { id: 2, value: "ب", name: "ب" }, + { id: 3, value: "پ", name: "پ" }, + { id: 4, value: "ت", name: "ت" }, + { id: 5, value: "ث", name: "ث" }, + { id: 6, value: "ج", name: "ج" }, + { id: 7, value: "د", name: "د" }, + { id: 8, value: "ز", name: "ز" }, + { id: 9, value: "س", name: "س" }, + { id: 10, value: "ش", name: "ش" }, + { id: 11, value: "ص", name: "ص" }, + { id: 12, value: "ط", name: "ط" }, + { id: 13, value: "ع", name: "ع" }, + { id: 14, value: "ف", name: "ف" }, + { id: 15, value: "ق", name: "ق" }, + { id: 16, value: "ک", name: "گ" }, + { id: 17, value: "ل", name: "ل" }, + { id: 18, value: "م", name: "م" }, + { id: 19, value: "ن", name: "ن" }, + { id: 20, value: "و", name: "و" }, + { id: 21, value: "ه", name: "ه" }, + { id: 22, value: "ی", name: "ی" }, + { id: 23, value: "*", name: }, +]; + +const PlateNumber = ({ control }) => { + const platePart2 = useWatch({ control, name: "plate_part2" }); + const [plateDrawer, setPlateDrawer] = useState(false); + const { errors } = useFormState({ control }); + const plateErrors = ["plate_part1", "plate_part2", "plate_part3", "plate_part4"].some((part) => errors[part]); + + return ( + <> + + ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + inputValue.length <= 2 ? field.onChange(inputValue) : null; + }} + size="small" + placeholder="xx" + sx={{ flexGrow: 2, "& fieldset": { border: "none" } }} + /> + )} + /> + ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + inputValue.length <= 3 ? field.onChange(inputValue) : null; + }} + size="small" + placeholder="xxx" + sx={{ + flexGrow: 3, + borderLeft: 1, + borderRadius: 0, + borderColor: "divider", + "& fieldset": { border: "none" }, + }} + /> + )} + /> + + + + setPlateDrawer(false)} + > + + {plate_words.map((item) => ( + ( + + )} + /> + ))} + + + ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + inputValue.length <= 2 ? field.onChange(inputValue) : null; + }} + /> + )} + /> + + + + + + + {plateErrors && ( + + پلاک نامعتبر است!!! + + )} + + ); +}; +export default PlateNumber; diff --git a/src/core/components/SelectBox.jsx b/src/core/components/SelectBox.jsx new file mode 100644 index 0000000..e6e8552 --- /dev/null +++ b/src/core/components/SelectBox.jsx @@ -0,0 +1,49 @@ +import { FormControl, FormHelperText, InputLabel, MenuItem, Select } from "@mui/material"; + +function SelectBox({ + name, + value, + onChange, + onBlur, + selectors, + label, + error, + schema, + disabled, + helperText, + isLoading, + errorEcured, + variant = "outlined", +}) { + return ( + + {label} + + {helperText || error?.message} + + ); +} +export default SelectBox; diff --git a/src/core/components/ShowPlak.jsx b/src/core/components/ShowPlak.jsx index 5d51455..6e02934 100644 --- a/src/core/components/ShowPlak.jsx +++ b/src/core/components/ShowPlak.jsx @@ -14,7 +14,6 @@ const ShowPlak = ({ plak_number }) => { }; }; const plakParts = processPlak(plak_number); - return ( value === true); + const flattenObject = (obj) => { + let result = {}; + for (const key in obj) { + if (typeof obj[key] === "object" && obj[key] !== null) { + Object.assign(result, flattenObject(obj[key])); // باز کردن اشیای تودرتو + } else { + result[key] = obj[key]; + } + } + return result; + }; + // تبدیل آبجکت به آبجکت فلت شده + const flatHideData = flattenObject(hideData); + + const CheckHideValues = Object.values(flatHideData).every((value) => value === true); hasAnyConflict = !CheckHideValues || JSON.stringify(sortData) !== JSON.stringify(initialSort) || !CheckFilterValues; diff --git a/src/lib/hooks/useDamageItemList.js b/src/lib/hooks/useDamageItemList.js new file mode 100644 index 0000000..a353627 --- /dev/null +++ b/src/lib/hooks/useDamageItemList.js @@ -0,0 +1,29 @@ +import { useEffect, useState } from "react"; +import { GET_DAMAGE_ITEM_LIST, GET_PROVINCE_LISTS } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; + +const useDamageItemList = () => { + const requestServer = useRequest(); + const [damageItemList, setDamageItemList] = useState([]); + const [loadingDamageItemList, setLoadingDamageItemList] = useState(true); + const [errorDamageItemList, setErrorDamageItemList] = useState(null); + + useEffect(() => { + const fetchCities = async () => { + try { + const response = await requestServer(`${GET_DAMAGE_ITEM_LIST}`); + setDamageItemList(response.data.data); + setLoadingDamageItemList(false); + } catch (e) { + setErrorDamageItemList(e); + setLoadingDamageItemList(false); + } + }; + + fetchCities(); + }, []); + + return { damageItemList, loadingDamageItemList, errorDamageItemList }; +}; + +export default useDamageItemList; diff --git a/src/lib/hooks/useProvince.js b/src/lib/hooks/useProvince.js index f6b98b8..a36df7d 100644 --- a/src/lib/hooks/useProvince.js +++ b/src/lib/hooks/useProvince.js @@ -15,7 +15,6 @@ const useProvinces = () => { setProvinces(response.data.data); setLoadingProvinces(false); } catch (e) { - console.error("Error fetching provinces:", e); setErrorProvinces(e); setLoadingProvinces(false); }