complete design of adding new test and bundling and saving map data next step...

This commit is contained in:
2024-10-26 05:31:11 +00:00
committed by AmirHossein Mahmoodi
parent 3058fc8c7b
commit 45d1665155
22 changed files with 1363 additions and 46 deletions

View File

@@ -0,0 +1,7 @@
import TestPage from "@/components/dashboard/test";
const Page = () => {
return <TestPage/>;
};
export default Page;

View File

@@ -0,0 +1,18 @@
const data = [
{
id: 1,
name: "تست نوع 1",
},
{
id: 2,
name: "تست نوع 2",
},
{
id: 3,
name: "تست نوع 3",
},
];
export async function GET() {
return Response.json({data});
}

View File

@@ -0,0 +1,71 @@
const data = [
{
id: 1,
test_type_name: 1,
project_name: "نوع پروژه",
employer: "کارفرما",
consultant: "مشاور",
contractor: "پیمانکار",
applicant: "متقاضی",
work_number: "شماره کار",
request_number: "شماره درخواست",
request_date: "تاریخ درخواست",
report_date: "تاریخ گزارش"
},
{
id: 2,
test_type_name: 5,
project_name: "نوع پروژه",
employer: "کارفرما",
consultant: "مشاور",
contractor: "پیمانکار",
applicant: "متقاضی",
work_number: "شماره کار",
request_number: "شماره درخواست",
request_date: "تاریخ درخواست",
report_date: "تاریخ گزارش"
},
{
id: 3,
test_type_name: 2,
project_name: "نوع پروژه",
employer: "کارفرما",
consultant: "مشاور",
contractor: "پیمانکار",
applicant: "متقاضی",
work_number: "شماره کار",
request_number: "شماره درخواست",
request_date: "تاریخ درخواست",
report_date: "تاریخ گزارش"
},
{
id: 4,
test_type_name: 4,
project_name: "نوع پروژه",
employer: "کارفرما",
consultant: "مشاور",
contractor: "پیمانکار",
applicant: "متقاضی",
work_number: "شماره کار",
request_number: "شماره درخواست",
request_date: "تاریخ درخواست",
report_date: "تاریخ گزارش"
},
{
id: 5,
test_type_name: 3,
project_name: "نوع پروژه",
employer: "کارفرما",
consultant: "مشاور",
contractor: "پیمانکار",
applicant: "متقاضی",
work_number: "شماره کار",
request_number: "شماره درخواست",
request_date: "تاریخ درخواست",
report_date: "تاریخ گزارش"
},
];
export async function GET() {
return Response.json({data});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -3,8 +3,7 @@
@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;
}
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;
}

View File

@@ -25,4 +25,3 @@
font-size: 12px;
color: #ffeb3b;
}

View File

@@ -0,0 +1,162 @@
"use client";
import {Marker, useMapEvents} from "react-leaflet";
import {useEffect, useRef} from "react";
import L from "leaflet";
import TestIcon from "@/assets/images/examine_marker.png";
import TestActiveIcon from "@/assets/images/examine_marker_active.png";
import {
Box,
Button,
FormControl,
InputAdornment,
InputLabel,
OutlinedInput,
Stack,
Tooltip,
useMediaQuery
} from "@mui/material";
import NewReleasesIcon from '@mui/icons-material/NewReleases';
import VerifiedIcon from '@mui/icons-material/Verified';
import EditIcon from '@mui/icons-material/Edit';
import {useTheme} from "@emotion/react";
const ChooseLocation = ({mapBoxData, setMapBoxData}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const mapTestMarker = useRef();
const defaultIconSize = [35, 35];
const createCustomIcon = (size, iconUrl) => {
return L.icon({
iconUrl: iconUrl,
iconSize: size,
iconAnchor: [size[0] / 2, size[1]],
popupAnchor: [0, -size[1]]
});
};
const map = useMapEvents({
move(e) {
if (!mapBoxData) {
mapTestMarker.current.setLatLng(e.target.getCenter());
}
},
movestart() {
if (!mapBoxData) {
mapTestMarker.current.setIcon(createCustomIcon([45, 45], TestIcon.src));
}
},
moveend() {
if (!mapBoxData) {
mapTestMarker.current.setIcon(createCustomIcon(defaultIconSize, TestIcon.src));
}
}
});
useEffect(() => {
if (mapTestMarker.current) {
const newIcon = mapBoxData
? createCustomIcon([45, 45], TestActiveIcon.src)
: createCustomIcon(defaultIconSize, TestIcon.src);
mapTestMarker.current.setIcon(newIcon);
}
if (mapBoxData) {
mapTestMarker.current.setLatLng(mapBoxData);
map.flyTo(mapBoxData, 14);
}
}, [mapBoxData]);
const handleMarkerClick = () => {
if (!mapBoxData) {
setMapBoxData({lat: mapTestMarker.current.getLatLng().lat, lng: mapTestMarker.current.getLatLng().lng});
}
};
const handleEditLocation = () => {
setMapBoxData(null);
}
return (
<>
<Marker
position={map.getCenter()}
ref={mapTestMarker}
eventHandlers={{click: handleMarkerClick}}
icon={createCustomIcon(defaultIconSize, TestIcon.src)}
/>
<Box sx={{
zIndex: "400",
position: "absolute",
background: "#ffffff94",
p: 2,
borderRadius: "10px",
boxShadow: "rgba(0, 0, 0, 0.24) 0px 3px 8px",
bottom: "5px",
left: "10px",
right: isMobile ? "10px" : "",
}}>
<Stack sx={{gap: 2}}>
<Tooltip title="با کلیک بر روی مارکر، محل آزمایش را انتخاب کنید" arrow>
<FormControl size="small" variant="outlined">
<InputLabel sx={{color: mapBoxData ? "success.main" : ""}} htmlFor="lat">
طول جغرافیایی
</InputLabel>
<OutlinedInput
id="lat"
type="text"
size="small"
readOnly
sx={{
'& .MuiOutlinedInput-notchedOutline': {
borderColor: mapBoxData ? "success.main" : "",
},
color: mapBoxData ? "success.main" : ""
}}
value={mapBoxData ? `${mapBoxData.lat}` : ""}
endAdornment={
<InputAdornment position="end">
{mapBoxData ? <VerifiedIcon color="success"/> :
<NewReleasesIcon color="error"/>}
</InputAdornment>
}
label="طول جغرافیایی"
/>
</FormControl>
</Tooltip>
<Tooltip title="با کلیک بر روی مارکر، محل آزمایش را انتخاب کنید" arrow>
<FormControl size="small" variant="outlined">
<InputLabel sx={{color: mapBoxData ? "success.main" : ""}} htmlFor="lng">
عرض جغرافیایی
</InputLabel>
<OutlinedInput
id="lng"
type="text"
size="small"
readOnly
sx={{
'& .MuiOutlinedInput-notchedOutline': {
borderColor: mapBoxData ? "success.main" : "",
},
color: mapBoxData ? "success.main" : ""
}}
value={mapBoxData ? `${mapBoxData.lng}` : ""}
endAdornment={
<InputAdornment position="end">
{mapBoxData ? <VerifiedIcon color="success"/> :
<NewReleasesIcon color="error"/>}
</InputAdornment>
}
label="عرض جغرافیایی"
/>
</FormControl>
</Tooltip>
<Button variant="contained" color="primary" disabled={!mapBoxData} startIcon={<EditIcon/>}
onClick={handleEditLocation}>ویرایش مختصات</Button>
</Stack>
</Box>
</>
);
};
export default ChooseLocation;

View File

@@ -0,0 +1,59 @@
"use client";
import {Box, Typography} from "@mui/material";
import TextSnippetIcon from '@mui/icons-material/TextSnippet';
import TravelExploreIcon from '@mui/icons-material/TravelExplore';
import {
Timeline,
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
timelineItemClasses,
TimelineSeparator
} from "@mui/lab";
const CreateTimeLine = ({tabState}) => {
return (
<Box sx={{display: "flex", alignItems: "center"}}>
<Timeline position="right" sx={{
[`& .${timelineItemClasses.root}:before`]: {flex: 0, padding: 0}
}}>
<TimelineItem>
<TimelineSeparator>
<TimelineConnector/>
<TimelineDot sx={{backgroundColor: "#fff"}}>
<TravelExploreIcon color={tabState === 0 ? "primary" : "error"}
sx={{width: "1.5rem", height: "1.5rem"}}/>
</TimelineDot>
<TimelineConnector/>
</TimelineSeparator>
<TimelineContent sx={{py: '12px', px: 2}}>
<Typography variant="h6">
نقشه
</Typography>
<Typography variant="caption" sx={{color: "#606060"}}>ثبت مختصات محل
آزمایش</Typography>
</TimelineContent>
</TimelineItem>
<TimelineItem>
<TimelineSeparator>
<TimelineConnector/>
<TimelineDot sx={{backgroundColor: "#fff"}}>
<TextSnippetIcon color={tabState === 1 ? "primary" : "error"}
sx={{width: "1.5rem", height: "1.5rem"}}/>
</TimelineDot>
<TimelineConnector/>
</TimelineSeparator>
<TimelineContent sx={{py: '12px', px: 2}}>
<Typography variant="h6">
مشخصات آزمایش
</Typography>
<Typography variant="caption" sx={{color: "#606060"}}>ثبت مشخصات اولیه</Typography>
</TimelineContent>
</TimelineItem>
</Timeline>
</Box>
);
};
export default CreateTimeLine;

View File

@@ -0,0 +1,39 @@
"use client";
import {Box, Stack} from "@mui/material";
import dynamic from "next/dynamic";
import MapLoading from "@/core/components/MapLayer/Loading";
import ChooseLocation from "./ChooseLocation";
const MapLayer = dynamic(() => import("@/core/components/MapLayer"), {
loading: () => <MapLoading/>,
ssr: false,
});
const MapBox = ({mapBoxData, setMapBoxData}) => {
return (
<Stack spacing={1} sx={{height: "500px"}}>
<Box sx={{
p: 1,
border: "1px dashed",
borderColor: "divider",
borderRadius: 1,
height: "100%"
}}>
<Box
sx={{
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<MapLayer>
<ChooseLocation mapBoxData={mapBoxData} setMapBoxData={setMapBoxData}/>
</MapLayer>
</Box>
</Box>
</Stack>
);
};
export default MapBox;

View File

@@ -0,0 +1,387 @@
"use client";
import {Controller} from "react-hook-form";
import {
Autocomplete,
CircularProgress,
FormControl,
FormHelperText,
Grid,
IconButton,
InputAdornment,
InputLabel,
OutlinedInput,
TextField,
Typography
} from "@mui/material";
import useTest from "@/lib/hooks/useTest";
import useProvinces from "@/lib/hooks/useProvince";
import {LocalizationProvider, MobileDatePicker} from "@mui/x-date-pickers";
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
import {faIR} from "@mui/x-date-pickers/locales";
import ClearIcon from "@mui/icons-material/Clear";
import React from "react";
const TestGeneralInfo = ({control, register, setValue, errors}) => {
const {tests, errorTests, loadingTests} = useTest();
const {provinces, errorProvinces, loadingProvinces} = useProvinces();
return (
<Grid container spacing={2}>
<Grid item xs={12} md={6}
sx={{display: "flex", alignItems: "center", justifyContent: "center"}}>
<Controller
name="azmayesh_type_id"
control={control}
render={({field: {onChange, value}, fieldState: {error}}) => (
<FormControl error={!!errors.azmayesh_type_id} size="small" fullWidth
variant="outlined">
<InputLabel htmlFor="azmayesh_type_id"/>
{errorTests ? (
<Typography color={"red"}
sx={{display: "flex", alignItems: "center", gap: 2}}>
خطایی در دریافت لیست آزمایش ها رخ داده است!
</Typography>
) : loadingTests ? (
<Typography sx={{display: "flex", alignItems: "center", gap: 2}}>
<CircularProgress size={20}/>
درحال دریافت لیست آزمایش ها
</Typography>
) : (
<Autocomplete
id="azmayesh_type_id"
size="small"
value={tests.find((test) => test.id === value) || null}
disablePortal
options={tests}
getOptionLabel={(test) => test.name}
isOptionEqualToValue={(option, value) => option.id === value?.id}
onChange={(event, newValue) => {
onChange(newValue ? newValue.id : "");
setValue("azmayesh_type_name", newValue ? newValue.name : "");
}}
renderInput={(params) => (
<TextField
{...params}
autoComplete="off"
error={!!errors.azmayesh_type_id}
fullWidth
label="نوع آزمایش"
/>
)}
/>
)}
<FormHelperText id="azmayesh_type_id">
{errors.azmayesh_type_id ? errors.azmayesh_type_id.message : null}
</FormHelperText>
</FormControl>
)}
/>
</Grid>
<Grid item xs={12} md={6}
sx={{display: "flex", alignItems: "center", justifyContent: "center"}}>
<Controller
name="province_id"
control={control}
render={({field: {onChange, value}, fieldState: {error}}) => (
<FormControl error={!!errors.province_id} size="small" fullWidth
variant="outlined">
<InputLabel htmlFor="province_id"/>
{errorProvinces ? (
<Typography color={"red"}
sx={{display: "flex", alignItems: "center", gap: 2}}>
خطایی در دریافت لیست استان ها رخ داده است!
</Typography>
) : loadingProvinces ? (
<Typography sx={{display: "flex", alignItems: "center", gap: 2}}>
<CircularProgress size={20}/>
درحال دریافت لیست استان ها
</Typography>
) : (
<Autocomplete
id="province_id"
size="small"
value={provinces.find((province) => province.id === value) || null}
disablePortal
options={provinces}
getOptionLabel={(province) => province.name}
isOptionEqualToValue={(option, value) => option.id === value?.id}
onChange={(event, newValue) => {
onChange(newValue ? newValue.id : "");
setValue("province_name", newValue ? newValue.name : "");
}}
renderInput={(params) => (
<TextField
{...params}
autoComplete="off"
error={!!errors.province_id}
fullWidth
label="استان"
/>
)}
/>
)}
<FormHelperText id="province_id">
{errors.province_id ? errors.province_id.message : null}
</FormHelperText>
</FormControl>
)}
/>
</Grid>
<Grid item xs={12} md={6}>
<FormControl error={!!errors.project_name} size="small" fullWidth
variant="outlined">
<InputLabel htmlFor="project_name">
پروژه
</InputLabel>
<OutlinedInput
id="project_name"
label={"پروژه"}
autoComplete="off"
{...register("project_name")}
size="small"
fullWidth
type="text"
/>
<FormHelperText id="project_name">
{errors.project_name ? errors.project_name.message : null}
</FormHelperText>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl error={!!errors.employer} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="employer">
کارفرما
</InputLabel>
<OutlinedInput
id="employer"
label={"کارفرما"}
autoComplete="off"
{...register("employer")}
size="small"
fullWidth
type="text"
/>
<FormHelperText id="employer">
{errors.employer ? errors.employer.message : null}
</FormHelperText>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl error={!!errors.consultant} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="consultant">
مشاور
</InputLabel>
<OutlinedInput
id="consultant"
label={"مشاور"}
autoComplete="off"
{...register("consultant")}
size="small"
fullWidth
type="text"
/>
<FormHelperText id="consultant">
{errors.consultant ? errors.consultant.message : null}
</FormHelperText>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl error={!!errors.contractor} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="contractor">
پیمانکار
</InputLabel>
<OutlinedInput
id="contractor"
label={"پیمانکار"}
autoComplete="off"
{...register("contractor")}
size="small"
fullWidth
type="text"
/>
<FormHelperText id="contractor">
{errors.contractor ? errors.contractor.message : null}
</FormHelperText>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl error={!!errors.applicant} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="applicant">
متقاضی
</InputLabel>
<OutlinedInput
id="applicant"
label={"متقاضی"}
autoComplete="off"
{...register("applicant")}
size="small"
fullWidth
type="text"
/>
<FormHelperText id="applicant">
{errors.applicant ? errors.applicant.message : null}
</FormHelperText>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl error={!!errors.work_number} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="work_number">
شماره کار
</InputLabel>
<OutlinedInput
id="work_number"
label={"شماره کار"}
autoComplete="off"
{...register("work_number")}
size="small"
fullWidth
type="text"
/>
<FormHelperText id="work_number">
{errors.work_number ? errors.work_number.message : null}
</FormHelperText>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl error={!!errors.request_number} size="small" fullWidth
variant="outlined">
<InputLabel htmlFor="request_number">
شماره درخواست
</InputLabel>
<OutlinedInput
id="request_number"
label={"شماره درخواست"}
autoComplete="off"
{...register("request_number")}
size="small"
fullWidth
type="text"
/>
<FormHelperText id="request_number">
{errors.request_number ? errors.request_number.message : null}
</FormHelperText>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<Controller
name="request_date"
control={control}
defaultValue={new Date()}
render={({field: {onChange, value}, fieldState: {error}}) => (
<FormControl
error={!!errors.request_date}
fullWidth
size="small"
variant="outlined"
>
<LocalizationProvider
dateAdapter={AdapterDateFnsJalali}
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
>
<MobileDatePicker
value={value || null}
onChange={(newValue) => {
onChange(newValue);
}}
slotProps={{
textField: {
size: "small",
error: !!errors.request_date,
placeholder: "تاریخ درخواست",
InputProps: {
endAdornment: (
<InputAdornment position="end">
<IconButton
size="small"
onClick={(event) => {
event.stopPropagation();
setValue("request_date", "");
}}
sx={{
color: "#bfbfbf",
"&:hover": {
backgroundColor: "rgba(189, 189, 189, 0.1)",
color: "#363434",
},
}}
>
<ClearIcon/>
</IconButton>
</InputAdornment>
),
},
},
}}
/>
</LocalizationProvider>
<FormHelperText id="request_date">
{errors.request_date ? errors.request_date.message : null}
</FormHelperText>
</FormControl>
)}
/>
</Grid>
<Grid item xs={12} md={6}>
<Controller
name="report_date"
control={control}
defaultValue={new Date()}
render={({field: {onChange, value}, fieldState: {error}}) => (
<FormControl
error={!!errors.report_date}
fullWidth
size="small"
variant="outlined"
>
<LocalizationProvider
dateAdapter={AdapterDateFnsJalali}
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
>
<MobileDatePicker
value={value || null}
onChange={(newValue) => {
onChange(newValue);
}}
slotProps={{
textField: {
size: "small",
error: !!errors.report_date,
placeholder: "تاریخ گزارش",
InputProps: {
endAdornment: (
<InputAdornment position="end">
<IconButton
size="small"
onClick={(event) => {
event.stopPropagation();
setValue("report_date", "");
}}
sx={{
color: "#bfbfbf",
"&:hover": {
backgroundColor: "rgba(189, 189, 189, 0.1)",
color: "#363434",
},
}}
>
<ClearIcon/>
</IconButton>
</InputAdornment>
),
},
},
}}
/>
</LocalizationProvider>
<FormHelperText id="report_date">
{errors.report_date ? errors.report_date.message : null}
</FormHelperText>
</FormControl>
)}
/>
</Grid>
</Grid>
);
};
export default TestGeneralInfo;

View File

@@ -0,0 +1,187 @@
"use client";
import {Box, Button, Dialog, DialogActions, DialogContent, Tab, Tabs, useMediaQuery} from "@mui/material";
import {useTheme} from "@emotion/react";
import React, {useState} from "react";
import MapBox from "./MapBox";
import TravelExploreIcon from '@mui/icons-material/TravelExplore';
import TextSnippetIcon from '@mui/icons-material/TextSnippet';
import KeyboardDoubleArrowRightIcon from '@mui/icons-material/KeyboardDoubleArrowRight';
import KeyboardDoubleArrowLeftIcon from '@mui/icons-material/KeyboardDoubleArrowLeft';
import ExitToAppIcon from '@mui/icons-material/ExitToApp';
import BeenhereIcon from '@mui/icons-material/Beenhere';
import CreateTimeLine from "./CreateTimeLine";
import {useForm} from "react-hook-form";
import StyledForm from "@/core/components/StyledForm";
import {object, string} from "yup";
import useRequest from "@/lib/hooks/useRequest";
import {yupResolver} from "@hookform/resolvers/yup";
import moment from "jalali-moment";
import {POST_TEST} from "@/core/utils/routes";
import TestGeneralInfo from "@/components/dashboard/test/Actions/create/CreateDialog/TestGeneralInfo";
function TabPanel(props) {
const {children, value, index} = props;
return (
<div
role="tabpanel"
hidden={value !== index}
>
{value === index && (
<Box>
{children}
</Box>
)}
</div>
);
}
const CreateDialog = ({open, setOpen}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const [tabState, setTabState] = useState(0);
const [mapBoxData, setMapBoxData] = useState(null);
const handleClose = () => {
setOpen(false);
};
const handleChangeTab = (event, newValue) => {
setTabState(newValue);
};
const handlePrev = () => {
if (tabState === 0) {
handleClose();
} else {
setTabState(tabState - 1)
}
};
const validationSchema = object({
azmayesh_type_id: string().required("نوع آزمایش را مشخص کنید!"),
province_id: string().required("استان را وارد کنید!"),
project_name: string().required("عنوان پروژه را وارد کنید!"),
employer: string().required("کارفرما را وارد کنید!"),
consultant: string().required("مشاور را وارد کنید!"),
contractor: string().required("پیمانکار را وارد کنید!"),
applicant: string().required("متقاضی را وارد کنید!"),
work_number: string().required("شماره کار را وارد کنید!"),
request_number: string().required("شماره درخواست را وارد کنید!"),
request_date: string().required("تاریخ درخواست را وارد کنید!"),
report_date: string().required("تاریخ گزارش را وارد کنید!"),
});
const requestServer = useRequest({auth: true});
const defaultValues = {
azmayesh_type_id: "",
azmayesh_type_name: "",
province_id: "",
province_name: "",
project_name: "",
employer: "",
consultant: "",
contractor: "",
applicant: "",
work_number: "",
request_number: "",
request_date: "",
report_date: "",
};
const {
control,
register,
handleSubmit,
setValue,
formState: {isSubmitting, errors, touchedFields},
} = useForm({defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur"});
const onSubmit = async (data) => {
console.log("data", data);
const formData = new FormData();
formData.append("lat", mapBoxData.lat);
formData.append("lng", mapBoxData.lng);
formData.append("azmayesh_type_id", data.azmayesh_type_id);
formData.append("azmayesh_type_name", data.azmayesh_type_name);
formData.append("province_id", data.province_id);
formData.append("province_name", data.province_name);
formData.append("project_name", data.project_name);
formData.append("employer", data.employer);
formData.append("consultant", data.consultant);
formData.append("contractor", data.contractor);
formData.append("applicant", data.applicant);
formData.append("work_number", data.work_number);
formData.append("request_number", data.request_number);
formData.append("request_date", moment(data.request_date).format("YYYY-MM-DD"));
formData.append("report_date", moment(data.report_date).format("YYYY-MM-DD"));
for (var pair of formData.entries()) {
console.log(pair[0] + ', ' + pair[1]);
}
requestServer(POST_TEST, "post", {
data: formData,
})
.then(() => {
handleClose();
})
.catch(() => {
});
};
return (
<Dialog open={open} fullWidth={true} maxWidth={"lg"}>
<StyledForm onSubmit={handleSubmit(onSubmit)}>
<Tabs allowScrollButtonsMobile value={tabState} onChange={handleChangeTab}
variant={`${isMobile ? "scrollable" : "fullWidth"}`}
sx={{
display: "flex",
justifyContent: "space-around",
width: "100%",
backgroundColor: "#efefef"
}}>
<Tab icon={<TravelExploreIcon/>} label="انتخاب محل آزمایش"></Tab>
<Tab disabled={!mapBoxData} icon={<TextSnippetIcon/>} label="مشخصات آزمایش"></Tab>
</Tabs>
<DialogContent dividers sx={{display: "flex"}}>
<Box sx={{flex: 1}}>
<TabPanel value={tabState} index={0}>
<MapBox mapBoxData={mapBoxData} setMapBoxData={setMapBoxData}/>
</TabPanel>
<TabPanel value={tabState} index={1}>
<TestGeneralInfo control={control} register={register} setValue={setValue} errors={errors}/>
</TabPanel>
</Box>
{!isMobile && (
<Box sx={{display: "flex", alignItems: "center"}}>
<CreateTimeLine tabState={tabState}/>
</Box>
)}
</DialogContent>
<DialogActions sx={{alignItems: "center", justifyContent: "center"}}>
<Button onClick={handlePrev} variant="outlined" color="error" size="large"
startIcon={tabState === 0 ? <ExitToAppIcon/> : <KeyboardDoubleArrowRightIcon/>}>
{tabState === 0 ? "بستن" : "مرحله قبل"}
</Button>
{
tabState === 0 ? <Button onClick={() => setTabState(tabState + 1)} variant="contained"
size="large"
disabled={!mapBoxData}
endIcon={<KeyboardDoubleArrowLeftIcon/>}>
مرحله بعد
</Button> : <Button variant="contained"
size="large"
disabled={isSubmitting}
type={"submit"}
endIcon={<BeenhereIcon/>}>
{isSubmitting ? "در حال ثبت آزمایش" : "ثبت آزمایش"}
</Button>
}
</DialogActions>
</StyledForm>
</Dialog>
);
};
export default CreateDialog;

View File

@@ -0,0 +1,33 @@
"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 CreateDialog from "./CreateDialog";
const TestCreate = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const [open, setOpen] = useState(false);
const handleOpen = () => {
setOpen(true);
};
return (
<>
{isMobile ? (
<IconButton aria-label="ایجاد آزمایش جدید" color="primary" onClick={handleOpen}>
<AddCircle sx={{fontSize: "25px"}}/>
</IconButton>
) : (
<Button variant="contained" color="primary" startIcon={<AddCircle/>} onClick={handleOpen}>
ثبت آزمایش
</Button>
)}
{open && <CreateDialog open={open} setOpen={setOpen}/>}
</>
);
};
export default TestCreate;

View File

@@ -0,0 +1,105 @@
"use client";
import {Marker, useMap} from "react-leaflet";
import {useEffect, useRef} from "react";
import L from "leaflet";
import TestActiveIcon from "@/assets/images/examine_marker_active.png";
import {Box, FormControl, InputAdornment, InputLabel, OutlinedInput, Stack, useMediaQuery} from "@mui/material";
import VerifiedIcon from '@mui/icons-material/Verified';
import {useTheme} from "@emotion/react";
const ShowLocationMarker = ({lat, lng}) => {
const map = useMap();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const mapTestMarker = useRef();
const defaultIconSize = [35, 35];
const createCustomIcon = (size, iconUrl) => {
return L.icon({
iconUrl: iconUrl,
iconSize: size,
iconAnchor: [size[0] / 2, size[1]],
popupAnchor: [0, -size[1]]
});
};
useEffect(() => {
map.flyTo({lat: lat, lng: lng}, 14);
}, []);
return (
<>
<Marker
position={{lat: lat, lng: lng}}
ref={mapTestMarker}
icon={createCustomIcon(defaultIconSize, TestActiveIcon.src)}
/>
<Box sx={{
zIndex: "400",
position: "absolute",
background: "#ffffff94",
p: 2,
borderRadius: "10px",
boxShadow: "rgba(0, 0, 0, 0.24) 0px 3px 8px",
bottom: "5px",
left: "10px",
right: isMobile ? "10px" : "",
}}>
<Stack sx={{gap: 2}}>
<FormControl size="small" variant="outlined">
<InputLabel sx={{color: "success.main"}} htmlFor="lat">
طول جغرافیایی
</InputLabel>
<OutlinedInput
id="lat"
type="text"
size="small"
readOnly
sx={{
'& .MuiOutlinedInput-notchedOutline': {
borderColor: "success.main",
},
color: "success.main"
}}
value={lat}
endAdornment={
<InputAdornment position="end">
<VerifiedIcon color="success"/>
</InputAdornment>
}
label="طول جغرافیایی"
/>
</FormControl>
<FormControl size="small" variant="outlined">
<InputLabel sx={{color: "success.main"}} htmlFor="lng">
عرض جغرافیایی
</InputLabel>
<OutlinedInput
id="lng"
type="text"
size="small"
readOnly
sx={{
'& .MuiOutlinedInput-notchedOutline': {
borderColor: "success.main",
},
color: "success.main"
}}
value={lng}
endAdornment={
<InputAdornment position="end">
<VerifiedIcon color="success"/>
</InputAdornment>
}
label="عرض جغرافیایی"
/>
</FormControl>
</Stack>
</Box>
</>
);
};
export default ShowLocationMarker;

View File

@@ -0,0 +1,50 @@
"use client";
import ExploreIcon from "@mui/icons-material/Explore";
import {Box, Button, Dialog, DialogActions, DialogContent, IconButton} from "@mui/material";
import {useState} from "react";
import dynamic from "next/dynamic";
import MapLoading from "@/core/components/MapLayer/Loading";
import ShowLocationMarker from "./ShowLocationMarker";
const MapLayer = dynamic(() => import("@/core/components/MapLayer"), {
loading: () => <MapLoading/>,
ssr: false,
});
const ShowLocation = ({lat, lng}) => {
const [openShowLocationModal, setOpenShowLocationModal] = useState(false);
const handleOpenShowLocationModal = () => {
setOpenShowLocationModal(true);
};
const handleCloseShowLocationModal = () => {
setOpenShowLocationModal(false);
};
return (
<Box sx={{display: "flex", justifyContent: "center"}}>
<IconButton onClick={handleOpenShowLocationModal} size="small" color="primary"><ExploreIcon/></IconButton>
<Dialog
open={openShowLocationModal}
onClose={handleCloseShowLocationModal}
aria-labelledby="responsive-dialog-title"
>
<DialogContent>
<Box sx={{width: "400px", height: "400px"}}>
<MapLayer>
<ShowLocationMarker lat={lat} lng={lng}/>
</MapLayer>
</Box>
</DialogContent>
<DialogActions>
<Button color="error" variant="outlined" onClick={handleCloseShowLocationModal}>
بستن
</Button>
</DialogActions>
</Dialog>
</Box>
);
};
export default ShowLocation;

View File

@@ -0,0 +1,135 @@
"use client";
import {useMemo} from "react";
import {Box, Typography} from "@mui/material";
import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import Toolbar from "./Toolbar";
import {GET_AZMAYESH_LIST} from "@/core/utils/routes";
import moment from "jalali-moment";
import ShowLocation from "./ShowLocation";
const TestList = () => {
const columns = useMemo(
() => [
{
accessorKey: "id",
header: "کد یکتا",
id: "id",
enableColumnFilter: false,
datatype: "text",
filterFn: "notEquals",
},
{
accessorKey: "azmayesh_type_name",
header: "نوع آزمایش",
id: "azmayesh_type_name",
enableColumnFilter: false,
datatype: "text",
filterFn: "notEquals",
},
{
accessorKey: "project_name",
header: "پروژه",
id: "project_name",
enableColumnFilter: false,
datatype: "text",
filterFn: "equals",
},
{
accessorKey: "lat",
header: "نمایش مختصات",
id: "lat",
enableColumnFilter: false,
datatype: "text",
filterFn: "equals",
Cell: ({row}) => (<ShowLocation lat={row.original.lat} lng={row.original.lng}/>),
},
{
accessorKey: "employer",
header: "کارفرما",
id: "employer",
enableColumnFilter: false,
datatype: "text",
filterFn: "equals",
},
{
accessorKey: "consultant",
header: "مشاور",
id: "consultant",
enableColumnFilter: false,
datatype: "text",
filterFn: "equals",
},
{
accessorKey: "contractor",
header: "پیمانکار",
id: "contractor",
enableColumnFilter: false,
datatype: "text",
filterFn: "equals",
},
{
accessorKey: "applicant",
header: "متقاضی",
id: "applicant",
enableColumnFilter: false,
datatype: "text",
filterFn: "equals",
},
{
accessorKey: "work_number",
header: "شماره کار",
id: "work_number",
enableColumnFilter: false,
datatype: "text",
filterFn: "equals",
},
{
accessorKey: "request_number",
header: "شماره درخواست",
id: "request_number",
enableColumnFilter: false,
datatype: "text",
filterFn: "equals",
},
{
accessorKey: "request_date",
header: "تاریخ درخواست",
id: "request_date",
enableColumnFilter: false,
datatype: "date",
filterFn: "equals",
Cell: ({renderedCellValue}) => (<Typography
variant="body2">{moment(renderedCellValue).locale("fa").format("YYYY/MM/DD")}</Typography>),
},
{
accessorKey: "report_date",
header: "تاریخ گزارش",
id: "report_date",
enableColumnFilter: false,
datatype: "date",
filterFn: "equals",
Cell: ({renderedCellValue}) => (<Typography
variant="body2">{moment(renderedCellValue).locale("fa").format("YYYY/MM/DD")}</Typography>),
},
],
[]
);
return (
<>
<Box sx={{p: 1, border: 1, borderColor: "divider", borderRadius: 1}}>
<DataTableWithAuth
table_title={"لیست آزمایش ها"}
need_filter={false}
columns={columns}
table_url={GET_AZMAYESH_LIST}
page_name={"azmayesh"}
table_name={"azmayeshList"}
TableToolbar={Toolbar}
/>
</Box>
</>
);
};
export default TestList;

View File

@@ -0,0 +1,10 @@
import TestCreate from "./Actions/Create";
const Toolbar = ({mutate}) => {
return (
<>
<TestCreate mutate={mutate}/>
</>
);
};
export default Toolbar;

View File

@@ -0,0 +1,15 @@
"use client";
import PageTitle from "@/core/components/PageTitle";
import {Stack} from "@mui/material";
import TestList from "./TestList";
const TestPage = () => {
return (
<Stack spacing={1}>
<PageTitle title={"آزمایشات"}/>
<TestList/>
</Stack>
);
};
export default TestPage;

View File

@@ -18,6 +18,7 @@ import EngineeringIcon from "@mui/icons-material/Engineering";
import ReportIcon from "@mui/icons-material/Report";
import AssignmentLateIcon from "@mui/icons-material/AssignmentLate";
import LineAxisIcon from "@mui/icons-material/LineAxis";
import ScienceIcon from '@mui/icons-material/Science';
export const pageMenu = [
{
@@ -25,7 +26,7 @@ export const pageMenu = [
label: "پیشخوان",
type: "page",
route: "/dashboard",
icon: <SpaceDashboardIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <SpaceDashboardIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["all"],
},
{
@@ -33,14 +34,14 @@ export const pageMenu = [
label: "مدیریت کاربران",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/user_management",
icon: <GroupsIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <GroupsIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["full-user-management", "limited-user-management"],
},
{
id: "projectsManagment",
label: "پروژه های راهداری",
type: "menu",
icon: <AccountTreeIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <AccountTreeIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
Subitems: [
{
@@ -48,7 +49,7 @@ export const pageMenu = [
label: "ثبت قرارداد و پروژه",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/finance",
icon: <GavelIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <GavelIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["show-contract", "show-contract-province"],
},
{
@@ -56,7 +57,7 @@ export const pageMenu = [
label: "لیست پروژه ها",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/projects_list",
icon: <BallotIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <BallotIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["all"],
},
{
@@ -64,7 +65,7 @@ export const pageMenu = [
label: "پروژه های پیشنهادی",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/proposal",
icon: <AssistantIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <AssistantIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["show-proposal", "show-proposal-province"],
},
{
@@ -72,7 +73,7 @@ export const pageMenu = [
label: "درخواست نمایندگان",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/lawmakers",
icon: <AdminPanelSettingsIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <AdminPanelSettingsIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["show-lawmaker", "show-lawmaker-province"],
},
{
@@ -80,7 +81,7 @@ export const pageMenu = [
label: "پراکندگی بر روی نقشه",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=rahdari_projects",
icon: <MapIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <MapIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["all"],
},
],
@@ -89,7 +90,7 @@ export const pageMenu = [
id: "roadItemManagment",
label: "فعالیت های روزانه",
type: "menu",
icon: <FactCheckIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <FactCheckIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
badges: ["road_items.total"],
Subitems: [
@@ -97,7 +98,7 @@ export const pageMenu = [
id: "roadItemManagmentSupervisor",
label: "ارزیابی",
type: "menu",
icon: <SpeedIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <SpeedIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
badges: ["road_items.supervise_cnt"],
Subitems: [
@@ -117,7 +118,7 @@ export const pageMenu = [
id: "roadItemManagmentOparation",
label: "عملیات",
type: "menu",
icon: <EngineeringIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <EngineeringIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
badges: ["road_items.operation_cnt"],
Subitems: [
@@ -142,7 +143,7 @@ export const pageMenu = [
label: "پراکندگی بر روی نقشه",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=road_items",
icon: <MapIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <MapIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: [
"show-road-item-supervise-cartable",
"show-road-item-supervise-cartable-province",
@@ -154,7 +155,7 @@ export const pageMenu = [
label: "گزارش ها",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_items/report",
icon: <ReportIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <ReportIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: [
"show-road-item-supervise-cartable",
"show-road-item-supervise-cartable-province",
@@ -167,7 +168,7 @@ export const pageMenu = [
id: "roadPatrolManagment",
label: "گشت راهداری و ترابری",
type: "menu",
icon: <FireTruckIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <FireTruckIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
badges: ["road_patrols.total"],
Subitems: [
@@ -175,7 +176,7 @@ export const pageMenu = [
id: "roadPatrolManagmentSupervisor",
label: "ارزیابی",
type: "menu",
icon: <SpeedIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <SpeedIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
badges: ["road_patrols.supervise_cnt"],
Subitems: [
@@ -195,7 +196,7 @@ export const pageMenu = [
id: "roadPatrolManagmentOparation",
label: "عملیات",
type: "menu",
icon: <EngineeringIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <EngineeringIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
badges: ["road_patrols.operation_cnt"],
Subitems: [
@@ -220,7 +221,7 @@ export const pageMenu = [
label: "پراکندگی بر روی نقشه",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=road_patrols",
icon: <MapIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <MapIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: [
"add-road-patrol",
"show-road-patrol-supervise-cartable",
@@ -232,7 +233,7 @@ export const pageMenu = [
label: "گزارش ها",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_patrols/report",
icon: <ReportIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <ReportIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: [
"add-road-patrol",
"show-road-patrol-supervise-cartable",
@@ -245,7 +246,7 @@ export const pageMenu = [
id: "inquiryPrivacyManagment",
label: "استعلام حریم راه",
type: "menu",
icon: <DoorbellIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <DoorbellIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
Subitems: [
{
@@ -282,7 +283,7 @@ export const pageMenu = [
id: "safetyAndPrivacyManagment",
label: "نگهداری حریم راه",
type: "menu",
icon: <RouteIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <RouteIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
badges: ["safety_and_privacy.step_one", "safety_and_privacy.step_two"],
Subitems: [
@@ -290,7 +291,7 @@ export const pageMenu = [
id: "safetyAndPrivacyManagmentOparation",
label: "عملیات",
type: "menu",
icon: <EngineeringIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <EngineeringIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
Subitems: [
{
@@ -318,7 +319,7 @@ export const pageMenu = [
label: "پراکندگی بر روی نقشه",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=safety_and_privacy",
icon: <MapIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <MapIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: [
"show-safety-and-privacy-operator-cartable",
"show-safety-and-privacy-operator-cartable-province",
@@ -331,7 +332,7 @@ export const pageMenu = [
label: "گزارش ها",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/safety_and_privacy/report",
icon: <ReportIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <ReportIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: [
"show-safety-and-privacy-operator-cartable",
"show-safety-and-privacy-operator-cartable-province",
@@ -345,7 +346,7 @@ export const pageMenu = [
id: "roadObservationsManagment",
label: "واکنش سریع",
type: "menu",
icon: <ElectricBoltIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <ElectricBoltIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
badges: ["road_observations.total"],
Subitems: [
@@ -353,7 +354,7 @@ export const pageMenu = [
id: "roadObservationsManagmentSupervisor",
label: "ارزیابی",
type: "menu",
icon: <SpeedIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <SpeedIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
badges: ["road_observations.supervise_cnt"],
Subitems: [
@@ -371,14 +372,14 @@ export const pageMenu = [
label: "رسیدگی به شکایات",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_observations",
icon: <AssignmentLateIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <AssignmentLateIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["show-fast-react", "show-fast-react-province", "show-fast-react-edarate-shahri"],
},
{
id: "roadObservationsManagmentOparation",
label: "عملیات",
type: "menu",
icon: <EngineeringIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <EngineeringIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
badges: ["road_observations.operation_cnt"],
Subitems: [
@@ -396,7 +397,7 @@ export const pageMenu = [
label: "پراکندگی بر روی نقشه",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=road_observations",
icon: <MapIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <MapIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["all"],
},
{
@@ -404,7 +405,7 @@ export const pageMenu = [
label: "گزارش ها",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_observations/report/index",
icon: <ReportIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <ReportIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["all"],
},
],
@@ -413,7 +414,7 @@ export const pageMenu = [
id: "winterCampManagment",
label: "قرارگاه زمستانی",
type: "menu",
icon: <CottageIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <CottageIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
Subitems: [
{
@@ -421,7 +422,7 @@ export const pageMenu = [
label: "محور های انسدادی",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/winter_camp",
icon: <LineAxisIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <LineAxisIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["show-camp", "show-camp-province"],
},
{
@@ -429,7 +430,7 @@ export const pageMenu = [
label: "محور های حلقه اول",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=camp",
icon: <LineAxisIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <LineAxisIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["show-camp", "show-camp-province"],
},
{
@@ -437,7 +438,7 @@ export const pageMenu = [
label: "گزارش ها",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=campNew",
icon: <ReportIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <ReportIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["show-camp", "show-camp-province"],
},
],
@@ -446,14 +447,14 @@ export const pageMenu = [
id: "receiptManagment",
label: "خسارات وارده بر ابنیه فنی و تاسیسات راه",
type: "menu",
icon: <GppMaybeIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <GppMaybeIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
Subitems: [
{
id: "receiptManagmentOparation",
label: "عملیات",
type: "menu",
icon: <EngineeringIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <EngineeringIcon sx={{width: "inherit", height: "inherit"}}/>,
hasSubitems: true,
Subitems: [
{
@@ -470,9 +471,17 @@ export const pageMenu = [
label: "گزارش ها",
type: "page",
route: process.env.NEXT_PUBLIC_API_URL + "/v2/receipt/report",
icon: <ReportIcon sx={{ width: "inherit", height: "inherit" }} />,
icon: <ReportIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["all"],
},
],
},
{
id: "test",
label: "آزمایشات",
type: "page",
route: "/dashboard/test",
icon: <ScienceIcon sx={{width: "inherit", height: "inherit"}}/>,
permissions: ["all"],
},
];

View File

@@ -12,3 +12,6 @@ export const GET_CITY_LISTS = "/v3/api/fake-cities";
export const GET_PROVINCE_LISTS = "/v3/api/fake-provinces";
export const GET_PREV_STATE_OPINION = "/v3/api/fake-prev-state-opinion";
export const SUBMIT_ROAD_SAFETY_FORM = "/v3/api/fake-submit";
export const POST_TEST = api + "/api/v3/azmayeshes/store";
export const GET_TESTS_LIST = api + "/api/v3/azmayesh_types";
export const GET_AZMAYESH_LIST = api + "/api/v3/azmayeshes";

View File

@@ -1,6 +1,5 @@
import { useState, useEffect } from "react";
import axios from "axios";
import { GET_PROVINCE_LISTS } from "@/core/utils/routes";
import {useEffect, useState} from "react";
import {GET_PROVINCE_LISTS} from "@/core/utils/routes";
import useRequest from "@/lib/hooks/useRequest";
const useProvinces = () => {
@@ -25,7 +24,7 @@ const useProvinces = () => {
fetchCities(); // Call the fetch function
}, []); // Empty dependency array to ensure it only runs once
return { provinces, loadingProvinces, errorProvinces };
return {provinces, loadingProvinces, errorProvinces};
};
export default useProvinces;

30
src/lib/hooks/useTest.js Normal file
View File

@@ -0,0 +1,30 @@
import {useEffect, useState} from "react";
import {GET_TESTS_LIST} from "@/core/utils/routes";
import useRequest from "@/lib/hooks/useRequest";
const useTest = () => {
const requestServer = useRequest();
const [tests, setTests] = useState([]);
const [loadingTests, setLoadingTests] = useState(true);
const [errorTests, setErrorTests] = useState(null);
useEffect(() => {
const fetchTests = async () => {
try {
const response = await requestServer(`${GET_TESTS_LIST}`);
setTests(response.data.data);
setLoadingTests(false);
} catch (e) {
console.error("Error fetching tests types:", e);
setErrorTests(e);
setLoadingTests(false);
}
};
fetchTests();
}, []);
return {tests, loadingTests, errorTests};
};
export default useTest;