Merge branch 'release/v0.7.1'

This commit is contained in:
Amirhossein Mahmoodi
2024-10-26 13:49:28 +03:30
31 changed files with 589 additions and 570 deletions

View File

@@ -1,3 +1,3 @@
NEXT_PUBLIC_VERSION="0.7.0" NEXT_PUBLIC_VERSION="0.7.1"
NEXT_PUBLIC_API_URL="https://rms.witel.ir" NEXT_PUBLIC_API_URL="https://rms.witel.ir"
NEXT_PUBLIC_MAPTILE_ENDPOINT="https://rmsmap.rmto.ir/141map" NEXT_PUBLIC_MAPTILE_ENDPOINT="https://rmsmap.rmto.ir/141map"

View File

@@ -15,10 +15,10 @@
"@emotion/react": "^11.11.3", "@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@hookform/resolvers": "^3.9.0", "@hookform/resolvers": "^3.9.0",
"@mui/icons-material": "^5.15.6", "@mui/icons-material": "^5.16.7",
"@mui/lab": "^5.0.0-alpha.173", "@mui/lab": "^5.0.0-alpha.173",
"@mui/material": "^5.15.6", "@mui/material": "^5.16.7",
"@mui/material-nextjs": "^5.15.6", "@mui/material-nextjs": "^5.16.6",
"@mui/x-date-pickers": "^6.19.5", "@mui/x-date-pickers": "^6.19.5",
"@mui/x-tree-view": "^7.11.0", "@mui/x-tree-view": "^7.11.0",
"axios": "^1.7.2", "axios": "^1.7.2",

View File

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

View File

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

View File

@@ -14,5 +14,5 @@ const data = [
]; ];
export async function GET() { export async function GET() {
return Response.json({data}); return Response.json({ data });
} }

View File

@@ -10,7 +10,7 @@ const data = [
work_number: "شماره کار", work_number: "شماره کار",
request_number: "شماره درخواست", request_number: "شماره درخواست",
request_date: "تاریخ درخواست", request_date: "تاریخ درخواست",
report_date: "تاریخ گزارش" report_date: "تاریخ گزارش",
}, },
{ {
id: 2, id: 2,
@@ -23,7 +23,7 @@ const data = [
work_number: "شماره کار", work_number: "شماره کار",
request_number: "شماره درخواست", request_number: "شماره درخواست",
request_date: "تاریخ درخواست", request_date: "تاریخ درخواست",
report_date: "تاریخ گزارش" report_date: "تاریخ گزارش",
}, },
{ {
id: 3, id: 3,
@@ -36,7 +36,7 @@ const data = [
work_number: "شماره کار", work_number: "شماره کار",
request_number: "شماره درخواست", request_number: "شماره درخواست",
request_date: "تاریخ درخواست", request_date: "تاریخ درخواست",
report_date: "تاریخ گزارش" report_date: "تاریخ گزارش",
}, },
{ {
id: 4, id: 4,
@@ -49,7 +49,7 @@ const data = [
work_number: "شماره کار", work_number: "شماره کار",
request_number: "شماره درخواست", request_number: "شماره درخواست",
request_date: "تاریخ درخواست", request_date: "تاریخ درخواست",
report_date: "تاریخ گزارش" report_date: "تاریخ گزارش",
}, },
{ {
id: 5, id: 5,
@@ -62,10 +62,10 @@ const data = [
work_number: "شماره کار", work_number: "شماره کار",
request_number: "شماره درخواست", request_number: "شماره درخواست",
request_date: "تاریخ درخواست", request_date: "تاریخ درخواست",
report_date: "تاریخ گزارش" report_date: "تاریخ گزارش",
}, },
]; ];
export async function GET() { export async function GET() {
return Response.json({data}); return Response.json({ data });
} }

View File

@@ -3,7 +3,8 @@
@import "react-toastify/dist/ReactToastify.css"; @import "react-toastify/dist/ReactToastify.css";
.filter-toast { .filter-toast {
box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, box-shadow:
rgba(0, 0, 0, 0.3) 0px 8px 16px -8px; rgba(50, 50, 93, 0.25) 0px 13px 27px -5px,
background-color: #d0dfe8; rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
background-color: #d0dfe8;
} }

View File

@@ -1,27 +1,27 @@
.leaflet-draw-tooltip { .leaflet-draw-tooltip {
background-color: #4f4f4f; background-color: #4f4f4f;
font-family: IRANSans; font-family: IRANSans;
color: #fff; color: #fff;
font-size: 10px; font-size: 10px;
padding: 2px 8px; padding: 2px 8px;
margin-right: 15px; margin-right: 15px;
border-radius: 4px; border-radius: 4px;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
} }
.leaflet-draw-tooltip:before { .leaflet-draw-tooltip:before {
content: ""; content: "";
position: absolute; position: absolute;
bottom: 100%; bottom: 100%;
left: 103%; left: 103%;
transform: rotate(90deg); transform: rotate(90deg);
margin-left: -6px; margin-left: -6px;
border-width: 6px; border-width: 6px;
border-style: solid; border-style: solid;
border-color: transparent transparent #333 transparent; border-color: transparent transparent #333 transparent;
} }
.leaflet-draw-tooltip-subtext { .leaflet-draw-tooltip-subtext {
font-size: 12px; font-size: 12px;
color: #ffeb3b; color: #ffeb3b;
} }

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import {Controller} from "react-hook-form"; import { Controller } from "react-hook-form";
import { import {
Autocomplete, Autocomplete,
CircularProgress, CircularProgress,
@@ -12,49 +12,46 @@ import {
InputLabel, InputLabel,
OutlinedInput, OutlinedInput,
TextField, TextField,
Typography Typography,
} from "@mui/material"; } from "@mui/material";
import useTest from "@/lib/hooks/useTest"; import useAzmayesh from "@/lib/hooks/useAzmayesh";
import useProvinces from "@/lib/hooks/useProvince"; import useProvinces from "@/lib/hooks/useProvince";
import {LocalizationProvider, MobileDatePicker} from "@mui/x-date-pickers"; import { LocalizationProvider, MobileDatePicker } from "@mui/x-date-pickers";
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali"; import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali";
import {faIR} from "@mui/x-date-pickers/locales"; import { faIR } from "@mui/x-date-pickers/locales";
import ClearIcon from "@mui/icons-material/Clear"; import ClearIcon from "@mui/icons-material/Clear";
import React from "react"; import React from "react";
const TestGeneralInfo = ({control, register, setValue, errors}) => { const AzmayeshGeneralInfo = ({ control, register, setValue, errors }) => {
const {tests, errorTests, loadingTests} = useTest(); const { azmayeshes, errorAzmayeshes, loadingAzmayeshes } = useAzmayesh();
const {provinces, errorProvinces, loadingProvinces} = useProvinces(); const { provinces, errorProvinces, loadingProvinces } = useProvinces();
return ( return (
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} md={6} <Grid item xs={12} md={6} sx={{ display: "flex", alignItems: "center", justifyContent: "center" }}>
sx={{display: "flex", alignItems: "center", justifyContent: "center"}}>
<Controller <Controller
name="azmayesh_type_id" name="azmayesh_type_id"
control={control} control={control}
render={({field: {onChange, value}, fieldState: {error}}) => ( render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl error={!!errors.azmayesh_type_id} size="small" fullWidth <FormControl error={!!errors.azmayesh_type_id} size="small" fullWidth variant="outlined">
variant="outlined"> <InputLabel htmlFor="azmayesh_type_id" />
<InputLabel htmlFor="azmayesh_type_id"/> {errorAzmayeshes ? (
{errorTests ? ( <Typography color={"red"} sx={{ display: "flex", alignItems: "center", gap: 2 }}>
<Typography color={"red"}
sx={{display: "flex", alignItems: "center", gap: 2}}>
خطایی در دریافت لیست آزمایش ها رخ داده است! خطایی در دریافت لیست آزمایش ها رخ داده است!
</Typography> </Typography>
) : loadingTests ? ( ) : loadingAzmayeshes ? (
<Typography sx={{display: "flex", alignItems: "center", gap: 2}}> <Typography sx={{ display: "flex", alignItems: "center", gap: 2 }}>
<CircularProgress size={20}/> <CircularProgress size={20} />
درحال دریافت لیست آزمایش ها درحال دریافت لیست آزمایش ها
</Typography> </Typography>
) : ( ) : (
<Autocomplete <Autocomplete
id="azmayesh_type_id" id="azmayesh_type_id"
size="small" size="small"
value={tests.find((test) => test.id === value) || null} value={azmayeshes.find((azmayesh) => azmayesh.id === value) || null}
disablePortal disablePortal
options={tests} options={azmayeshes}
getOptionLabel={(test) => test.name} getOptionLabel={(azmayesh) => azmayesh.name}
isOptionEqualToValue={(option, value) => option.id === value?.id} isOptionEqualToValue={(option, value) => option.id === value?.id}
onChange={(event, newValue) => { onChange={(event, newValue) => {
onChange(newValue ? newValue.id : ""); onChange(newValue ? newValue.id : "");
@@ -78,23 +75,20 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
)} )}
/> />
</Grid> </Grid>
<Grid item xs={12} md={6} <Grid item xs={12} md={6} sx={{ display: "flex", alignItems: "center", justifyContent: "center" }}>
sx={{display: "flex", alignItems: "center", justifyContent: "center"}}>
<Controller <Controller
name="province_id" name="province_id"
control={control} control={control}
render={({field: {onChange, value}, fieldState: {error}}) => ( render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl error={!!errors.province_id} size="small" fullWidth <FormControl error={!!errors.province_id} size="small" fullWidth variant="outlined">
variant="outlined"> <InputLabel htmlFor="province_id" />
<InputLabel htmlFor="province_id"/>
{errorProvinces ? ( {errorProvinces ? (
<Typography color={"red"} <Typography color={"red"} sx={{ display: "flex", alignItems: "center", gap: 2 }}>
sx={{display: "flex", alignItems: "center", gap: 2}}>
خطایی در دریافت لیست استان ها رخ داده است! خطایی در دریافت لیست استان ها رخ داده است!
</Typography> </Typography>
) : loadingProvinces ? ( ) : loadingProvinces ? (
<Typography sx={{display: "flex", alignItems: "center", gap: 2}}> <Typography sx={{ display: "flex", alignItems: "center", gap: 2 }}>
<CircularProgress size={20}/> <CircularProgress size={20} />
درحال دریافت لیست استان ها درحال دریافت لیست استان ها
</Typography> </Typography>
) : ( ) : (
@@ -129,11 +123,8 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
/> />
</Grid> </Grid>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<FormControl error={!!errors.project_name} size="small" fullWidth <FormControl error={!!errors.project_name} size="small" fullWidth variant="outlined">
variant="outlined"> <InputLabel htmlFor="project_name">پروژه</InputLabel>
<InputLabel htmlFor="project_name">
پروژه
</InputLabel>
<OutlinedInput <OutlinedInput
id="project_name" id="project_name"
label={"پروژه"} label={"پروژه"}
@@ -150,9 +141,7 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
</Grid> </Grid>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<FormControl error={!!errors.employer} size="small" fullWidth variant="outlined"> <FormControl error={!!errors.employer} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="employer"> <InputLabel htmlFor="employer">کارفرما</InputLabel>
کارفرما
</InputLabel>
<OutlinedInput <OutlinedInput
id="employer" id="employer"
label={"کارفرما"} label={"کارفرما"}
@@ -162,16 +151,12 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
fullWidth fullWidth
type="text" type="text"
/> />
<FormHelperText id="employer"> <FormHelperText id="employer">{errors.employer ? errors.employer.message : null}</FormHelperText>
{errors.employer ? errors.employer.message : null}
</FormHelperText>
</FormControl> </FormControl>
</Grid> </Grid>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<FormControl error={!!errors.consultant} size="small" fullWidth variant="outlined"> <FormControl error={!!errors.consultant} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="consultant"> <InputLabel htmlFor="consultant">مشاور</InputLabel>
مشاور
</InputLabel>
<OutlinedInput <OutlinedInput
id="consultant" id="consultant"
label={"مشاور"} label={"مشاور"}
@@ -188,9 +173,7 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
</Grid> </Grid>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<FormControl error={!!errors.contractor} size="small" fullWidth variant="outlined"> <FormControl error={!!errors.contractor} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="contractor"> <InputLabel htmlFor="contractor">پیمانکار</InputLabel>
پیمانکار
</InputLabel>
<OutlinedInput <OutlinedInput
id="contractor" id="contractor"
label={"پیمانکار"} label={"پیمانکار"}
@@ -207,9 +190,7 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
</Grid> </Grid>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<FormControl error={!!errors.applicant} size="small" fullWidth variant="outlined"> <FormControl error={!!errors.applicant} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="applicant"> <InputLabel htmlFor="applicant">متقاضی</InputLabel>
متقاضی
</InputLabel>
<OutlinedInput <OutlinedInput
id="applicant" id="applicant"
label={"متقاضی"} label={"متقاضی"}
@@ -219,16 +200,12 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
fullWidth fullWidth
type="text" type="text"
/> />
<FormHelperText id="applicant"> <FormHelperText id="applicant">{errors.applicant ? errors.applicant.message : null}</FormHelperText>
{errors.applicant ? errors.applicant.message : null}
</FormHelperText>
</FormControl> </FormControl>
</Grid> </Grid>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<FormControl error={!!errors.work_number} size="small" fullWidth variant="outlined"> <FormControl error={!!errors.work_number} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="work_number"> <InputLabel htmlFor="work_number">شماره کار</InputLabel>
شماره کار
</InputLabel>
<OutlinedInput <OutlinedInput
id="work_number" id="work_number"
label={"شماره کار"} label={"شماره کار"}
@@ -244,11 +221,8 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
</FormControl> </FormControl>
</Grid> </Grid>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<FormControl error={!!errors.request_number} size="small" fullWidth <FormControl error={!!errors.request_number} size="small" fullWidth variant="outlined">
variant="outlined"> <InputLabel htmlFor="request_number">شماره درخواست</InputLabel>
<InputLabel htmlFor="request_number">
شماره درخواست
</InputLabel>
<OutlinedInput <OutlinedInput
id="request_number" id="request_number"
label={"شماره درخواست"} label={"شماره درخواست"}
@@ -268,13 +242,8 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
name="request_date" name="request_date"
control={control} control={control}
defaultValue={new Date()} defaultValue={new Date()}
render={({field: {onChange, value}, fieldState: {error}}) => ( render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl <FormControl error={!!errors.request_date} fullWidth size="small" variant="outlined">
error={!!errors.request_date}
fullWidth
size="small"
variant="outlined"
>
<LocalizationProvider <LocalizationProvider
dateAdapter={AdapterDateFnsJalali} dateAdapter={AdapterDateFnsJalali}
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText} localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
@@ -306,7 +275,7 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
}, },
}} }}
> >
<ClearIcon/> <ClearIcon />
</IconButton> </IconButton>
</InputAdornment> </InputAdornment>
), ),
@@ -327,13 +296,8 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
name="report_date" name="report_date"
control={control} control={control}
defaultValue={new Date()} defaultValue={new Date()}
render={({field: {onChange, value}, fieldState: {error}}) => ( render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl <FormControl error={!!errors.report_date} fullWidth size="small" variant="outlined">
error={!!errors.report_date}
fullWidth
size="small"
variant="outlined"
>
<LocalizationProvider <LocalizationProvider
dateAdapter={AdapterDateFnsJalali} dateAdapter={AdapterDateFnsJalali}
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText} localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
@@ -365,7 +329,7 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
}, },
}} }}
> >
<ClearIcon/> <ClearIcon />
</IconButton> </IconButton>
</InputAdornment> </InputAdornment>
), ),
@@ -384,4 +348,4 @@ const TestGeneralInfo = ({control, register, setValue, errors}) => {
</Grid> </Grid>
); );
}; };
export default TestGeneralInfo; export default AzmayeshGeneralInfo;

View File

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

View File

@@ -0,0 +1,65 @@
"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

@@ -1,25 +1,27 @@
"use client"; "use client";
import {Box, Stack} from "@mui/material"; import { Box, Stack } from "@mui/material";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import MapLoading from "@/core/components/MapLayer/Loading"; import MapLoading from "@/core/components/MapLayer/Loading";
import ChooseLocation from "./ChooseLocation"; import ChooseLocation from "./ChooseLocation";
const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { const MapLayer = dynamic(() => import("@/core/components/MapLayer"), {
loading: () => <MapLoading/>, loading: () => <MapLoading />,
ssr: false, ssr: false,
}); });
const MapBox = ({mapBoxData, setMapBoxData}) => { const MapBox = ({ mapBoxData, setMapBoxData }) => {
return ( return (
<Stack spacing={1} sx={{height: "500px"}}> <Stack spacing={1} sx={{ height: "500px" }}>
<Box sx={{ <Box
p: 1, sx={{
border: "1px dashed", p: 1,
borderColor: "divider", border: "1px dashed",
borderRadius: 1, borderColor: "divider",
height: "100%" borderRadius: 1,
}}> height: "100%",
}}
>
<Box <Box
sx={{ sx={{
height: "100%", height: "100%",
@@ -29,7 +31,7 @@ const MapBox = ({mapBoxData, setMapBoxData}) => {
}} }}
> >
<MapLayer> <MapLayer>
<ChooseLocation mapBoxData={mapBoxData} setMapBoxData={setMapBoxData}/> <ChooseLocation mapBoxData={mapBoxData} setMapBoxData={setMapBoxData} />
</MapLayer> </MapLayer>
</Box> </Box>
</Box> </Box>

View File

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

View File

@@ -1,12 +1,12 @@
"use client"; "use client";
import {Button, IconButton, useMediaQuery} from "@mui/material"; import { Button, IconButton, useMediaQuery } from "@mui/material";
import {useTheme} from "@emotion/react"; import { useTheme } from "@emotion/react";
import {useState} from "react"; import { useState } from "react";
import {AddCircle} from "@mui/icons-material"; import { AddCircle } from "@mui/icons-material";
import CreateDialog from "./CreateDialog"; import CreateDialog from "./CreateDialog";
const TestCreate = () => { const AzmayeshCreate = ({ mutate }) => {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm")); const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@@ -19,15 +19,15 @@ const TestCreate = () => {
<> <>
{isMobile ? ( {isMobile ? (
<IconButton aria-label="ایجاد آزمایش جدید" color="primary" onClick={handleOpen}> <IconButton aria-label="ایجاد آزمایش جدید" color="primary" onClick={handleOpen}>
<AddCircle sx={{fontSize: "25px"}}/> <AddCircle sx={{ fontSize: "25px" }} />
</IconButton> </IconButton>
) : ( ) : (
<Button variant="contained" color="primary" startIcon={<AddCircle/>} onClick={handleOpen}> <Button variant="contained" color="primary" startIcon={<AddCircle />} onClick={handleOpen}>
ثبت آزمایش ثبت آزمایش
</Button> </Button>
)} )}
{open && <CreateDialog open={open} setOpen={setOpen}/>} {open && <CreateDialog open={open} setOpen={setOpen} mutate={mutate} />}
</> </>
); );
}; };
export default TestCreate; export default AzmayeshCreate;

View File

@@ -1,14 +1,14 @@
"use client"; "use client";
import {useMemo} from "react"; import { useMemo } from "react";
import {Box, Typography} from "@mui/material"; import { Box, Typography } from "@mui/material";
import DataTableWithAuth from "@/core/components/DataTableWithAuth"; import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import Toolbar from "./Toolbar"; import Toolbar from "./Toolbar";
import {GET_AZMAYESH_LIST} from "@/core/utils/routes"; import { GET_AZMAYESH_LIST } from "@/core/utils/routes";
import moment from "jalali-moment"; import moment from "jalali-moment";
import ShowLocation from "./ShowLocation"; import ShowLocation from "./ShowLocation";
const TestList = () => { const AzmayeshList = () => {
const columns = useMemo( const columns = useMemo(
() => [ () => [
{ {
@@ -42,7 +42,7 @@ const TestList = () => {
enableColumnFilter: false, enableColumnFilter: false,
datatype: "text", datatype: "text",
filterFn: "equals", filterFn: "equals",
Cell: ({row}) => (<ShowLocation lat={row.original.lat} lng={row.original.lng}/>), Cell: ({ row }) => <ShowLocation lat={row.original.lat} lng={row.original.lng} />,
}, },
{ {
accessorKey: "employer", accessorKey: "employer",
@@ -99,8 +99,11 @@ const TestList = () => {
enableColumnFilter: false, enableColumnFilter: false,
datatype: "date", datatype: "date",
filterFn: "equals", filterFn: "equals",
Cell: ({renderedCellValue}) => (<Typography Cell: ({ renderedCellValue }) => (
variant="body2">{moment(renderedCellValue).locale("fa").format("YYYY/MM/DD")}</Typography>), <Typography variant="body2">
{moment(renderedCellValue).locale("fa").format("YYYY/MM/DD")}
</Typography>
),
}, },
{ {
accessorKey: "report_date", accessorKey: "report_date",
@@ -109,8 +112,11 @@ const TestList = () => {
enableColumnFilter: false, enableColumnFilter: false,
datatype: "date", datatype: "date",
filterFn: "equals", filterFn: "equals",
Cell: ({renderedCellValue}) => (<Typography Cell: ({ renderedCellValue }) => (
variant="body2">{moment(renderedCellValue).locale("fa").format("YYYY/MM/DD")}</Typography>), <Typography variant="body2">
{moment(renderedCellValue).locale("fa").format("YYYY/MM/DD")}
</Typography>
),
}, },
], ],
[] []
@@ -118,7 +124,7 @@ const TestList = () => {
return ( return (
<> <>
<Box sx={{p: 1, border: 1, borderColor: "divider", borderRadius: 1}}> <Box sx={{ p: 1, border: 1, borderColor: "divider", borderRadius: 1 }}>
<DataTableWithAuth <DataTableWithAuth
table_title={"لیست آزمایش ها"} table_title={"لیست آزمایش ها"}
need_filter={false} need_filter={false}
@@ -132,4 +138,4 @@ const TestList = () => {
</> </>
); );
}; };
export default TestList; export default AzmayeshList;

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import {Box, Button, ButtonGroup} from "@mui/material"; import { Box, Button, ButtonGroup } from "@mui/material";
import AutoModeIcon from "@mui/icons-material/AutoMode"; import AutoModeIcon from "@mui/icons-material/AutoMode";
import DeleteIcon from "@mui/icons-material/Delete"; import DeleteIcon from "@mui/icons-material/Delete";
import EditLocationAltIcon from "@mui/icons-material/EditLocationAlt"; import EditLocationAltIcon from "@mui/icons-material/EditLocationAlt";
@@ -6,31 +6,33 @@ import SaveIcon from "@mui/icons-material/Save";
import CancelIcon from "@mui/icons-material/Cancel"; import CancelIcon from "@mui/icons-material/Cancel";
const MapActionButtons = ({ const MapActionButtons = ({
disableToCreate, disableToCreate,
disableToEditAndDelete, disableToEditAndDelete,
disableToSaveAndCancel, disableToSaveAndCancel,
onDraw, onDraw,
onEdit, onEdit,
onRemove, onRemove,
onSave, onSave,
onCancel, onCancel,
}) => ( }) => (
<> <>
<Box sx={{ <Box
background: "#ffffff", sx={{
position: "absolute", background: "#ffffff",
zIndex: "1999", position: "absolute",
bottom: 0, zIndex: "1999",
left: 0, bottom: 0,
p: 2, left: 0,
pl: 0.5, p: 2,
pb: 0.5, pl: 0.5,
borderTopRightRadius: 8, pb: 0.5,
}}> borderTopRightRadius: 8,
}}
>
<ButtonGroup variant="contained" orientation="vertical" aria-label="map action group button"> <ButtonGroup variant="contained" orientation="vertical" aria-label="map action group button">
<Button <Button
sx={{justifyContent: "space-between"}} sx={{ justifyContent: "space-between" }}
startIcon={<AutoModeIcon/>} startIcon={<AutoModeIcon />}
color="primary" color="primary"
disabled={disableToCreate} disabled={disableToCreate}
onClick={onDraw} onClick={onDraw}
@@ -38,8 +40,8 @@ const MapActionButtons = ({
اصلاح اصلاح
</Button> </Button>
<Button <Button
sx={{justifyContent: "space-between"}} sx={{ justifyContent: "space-between" }}
startIcon={<EditLocationAltIcon/>} startIcon={<EditLocationAltIcon />}
color="warning" color="warning"
disabled={disableToEditAndDelete} disabled={disableToEditAndDelete}
onClick={onEdit} onClick={onEdit}
@@ -47,8 +49,8 @@ const MapActionButtons = ({
ویرایش ویرایش
</Button> </Button>
<Button <Button
sx={{justifyContent: "space-between"}} sx={{ justifyContent: "space-between" }}
startIcon={<DeleteIcon/>} startIcon={<DeleteIcon />}
color="error" color="error"
disabled={disableToEditAndDelete} disabled={disableToEditAndDelete}
onClick={onRemove} onClick={onRemove}
@@ -58,18 +60,20 @@ const MapActionButtons = ({
</ButtonGroup> </ButtonGroup>
</Box> </Box>
<Box sx={{ <Box
position: "absolute", sx={{
zIndex: "1999", position: "absolute",
right: 10, zIndex: "1999",
top: 10, right: 10,
background: "#fff", top: 10,
borderRadius: 1, background: "#fff",
padding: 0.5, borderRadius: 1,
}}> padding: 0.5,
}}
>
<Button <Button
sx={{justifyContent: "space-between", mr: 1}} sx={{ justifyContent: "space-between", mr: 1 }}
startIcon={<SaveIcon/>} startIcon={<SaveIcon />}
variant="outlined" variant="outlined"
size="small" size="small"
color="success" color="success"
@@ -79,8 +83,8 @@ const MapActionButtons = ({
ذخیره ذخیره
</Button> </Button>
<Button <Button
sx={{justifyContent: "space-between"}} sx={{ justifyContent: "space-between" }}
startIcon={<CancelIcon/>} startIcon={<CancelIcon />}
variant="outlined" variant="outlined"
size="small" size="small"
color="error" color="error"

View File

@@ -22,67 +22,72 @@ import GppMaybeIcon from "@mui/icons-material/GppMaybe";
import PolygonForDesign from "./PolygonForDesign"; import PolygonForDesign from "./PolygonForDesign";
const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { const MapLayer = dynamic(() => import("@/core/components/MapLayer"), {
loading: () => <MapLoading/>, loading: () => <MapLoading />,
ssr: false, ssr: false,
}); });
const MapModifyDialog = ({mapModifyModal, setMapModifyModal}) => { const MapModifyDialog = ({ mapModifyModal, setMapModifyModal }) => {
const handleClose = () => { const handleClose = () => {
setMapModifyModal(false); setMapModifyModal(false);
}; };
return ( return (
<Dialog open={mapModifyModal} onClose={handleClose} maxWidth="lg" fullWidth> <Dialog open={mapModifyModal} onClose={handleClose} maxWidth="lg" fullWidth>
<DialogContent sx={{p: 2}} dividers> <DialogContent sx={{ p: 2 }} dividers>
<Divider sx={{my: 3}}> <Divider sx={{ my: 3 }}>
<Chip color="primary" sx={{mx: 1, fontSize: "13px", fontWeight: 500}} <Chip
label="بررسی پلیگان طرح متقاضی"/> color="primary"
sx={{ mx: 1, fontSize: "13px", fontWeight: 500 }}
label="بررسی پلیگان طرح متقاضی"
/>
</Divider> </Divider>
<Box sx={{ <Box
width: "100%", sx={{
height: "400px", width: "100%",
borderRadius: 3, height: "400px",
borderBottomLeftRadius: 0, borderRadius: 3,
overflow: "hidden", borderBottomLeftRadius: 0,
}}> overflow: "hidden",
}}
>
<MapLayer> <MapLayer>
<PolygonForDesign/> <PolygonForDesign />
</MapLayer> </MapLayer>
</Box> </Box>
<Box sx={{display: "flex", my: 2, alignItems: "center"}}> <Box sx={{ display: "flex", my: 2, alignItems: "center" }}>
<GppMaybeIcon color="warning"/> <GppMaybeIcon color="warning" />
<Typography variant="button" sx={{color: "warning.main", ml: 1}}> <Typography variant="button" sx={{ color: "warning.main", ml: 1 }}>
نکته: اصلاح ننمودن طرح به منزله تایید طرح میباشد. نکته: اصلاح ننمودن طرح به منزله تایید طرح میباشد.
</Typography> </Typography>
</Box> </Box>
<Box sx={{ <Box
display: "flex", sx={{
alignItems: "center", display: "flex",
justifyContent: "center", alignItems: "center",
border: "1px solid #e1e1e1", justifyContent: "center",
p: 2, border: "1px solid #e1e1e1",
borderRadius: 1, p: 2,
}}> borderRadius: 1,
<FormControl sx={{flexDirection: "row", alignItems: "center", gap: 2}}> }}
<FormLabel id="way-status" sx={{fontWeight: 500, fontSize: "16px", color: "warning.main"}}>آیا >
طرح نیاز به ایجاد راه <FormControl sx={{ flexDirection: "row", alignItems: "center", gap: 2 }}>
دسترسی <FormLabel id="way-status" sx={{ fontWeight: 500, fontSize: "16px", color: "warning.main" }}>
دارد؟</FormLabel> آیا طرح نیاز به ایجاد راه دسترسی دارد؟
<RadioGroup </FormLabel>
row <RadioGroup row aria-labelledby="way-status" defaultValue={0} name="radio-buttons-group">
aria-labelledby="way-status" <FormControlLabel value={1} control={<Radio color="warning" />} label="بله" />
defaultValue={0} <FormControlLabel value={0} control={<Radio color="warning" />} label="خیر" />
name="radio-buttons-group"
>
<FormControlLabel value={1} control={<Radio color="warning"/>} label="بله"/>
<FormControlLabel value={0} control={<Radio color="warning"/>} label="خیر"/>
</RadioGroup> </RadioGroup>
</FormControl> </FormControl>
</Box> </Box>
</DialogContent> </DialogContent>
<DialogActions sx={{justifyContent: "center", py: 2}}> <DialogActions sx={{ justifyContent: "center", py: 2 }}>
<Button size="large" variant="outlined">بستن</Button> <Button size="large" variant="outlined">
<Button size="large" variant="contained">ثبت</Button> بستن
</Button>
<Button size="large" variant="contained">
ثبت
</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
); );

View File

@@ -1,13 +1,12 @@
"use client"; "use client";
import "leaflet-draw/dist/leaflet.draw.css"; import "leaflet-draw/dist/leaflet.draw.css";
import "@/assets/scss/map-styles.scss" import "@/assets/scss/map-styles.scss";
import {FeatureGroup, useMap} from "react-leaflet"; import { FeatureGroup, useMap } from "react-leaflet";
import {EditControl} from "react-leaflet-draw"; import { EditControl } from "react-leaflet-draw";
import {useEffect, useRef, useState} from "react"; import { useEffect, useRef, useState } from "react";
import MapActionButtons from "./MapActionButtons"; import MapActionButtons from "./MapActionButtons";
const PolygonForDesign = () => { const PolygonForDesign = () => {
const map = useMap(); const map = useMap();
const editableFG = useRef(null); const editableFG = useRef(null);
@@ -18,7 +17,7 @@ const PolygonForDesign = () => {
const [editToolbar, setEditToolbar] = useState(null); const [editToolbar, setEditToolbar] = useState(null);
useEffect(() => { useEffect(() => {
const {L} = window; const { L } = window;
L.drawLocal.draw.handlers.polygon.tooltip = { L.drawLocal.draw.handlers.polygon.tooltip = {
start: "برای شروع کشیدن پلیگان، کلیک کنید.", start: "برای شروع کشیدن پلیگان، کلیک کنید.",
cont: "گوشه های دیگر پلیگان را نیز انتخاب کنید.", cont: "گوشه های دیگر پلیگان را نیز انتخاب کنید.",
@@ -31,14 +30,14 @@ const PolygonForDesign = () => {
}, []); }, []);
const handleDrawPolygon = () => { const handleDrawPolygon = () => {
const {L} = window; const { L } = window;
const drawControl = new L.Draw.Polygon(map); const drawControl = new L.Draw.Polygon(map);
drawControl.enable(); drawControl.enable();
setDisableToCreate(true); setDisableToCreate(true);
}; };
const handleEditPolygon = () => { const handleEditPolygon = () => {
const {L} = window; const { L } = window;
if (editableFG.current && polygonLayer) { if (editableFG.current && polygonLayer) {
const editControlInstance = new L.EditToolbar.Edit(map, { const editControlInstance = new L.EditToolbar.Edit(map, {
featureGroup: editableFG.current, featureGroup: editableFG.current,
@@ -98,7 +97,7 @@ const PolygonForDesign = () => {
rectangle: false, rectangle: false,
polyline: false, polyline: false,
}} }}
edit={{edit: false, remove: false}} edit={{ edit: false, remove: false }}
/> />
</FeatureGroup> </FeatureGroup>
<MapActionButtons <MapActionButtons

View File

@@ -1,9 +1,9 @@
import {IconButton, Tooltip} from "@mui/material"; import { IconButton, Tooltip } from "@mui/material";
import MapIcon from "@mui/icons-material/Map"; import MapIcon from "@mui/icons-material/Map";
import {useState} from "react"; import { useState } from "react";
import MapModifyDialog from "./MapModifyDialog"; import MapModifyDialog from "./MapModifyDialog";
const MapModify = ({rowId, mutate}) => { const MapModify = ({ rowId, mutate }) => {
const [mapModifyModal, setMapModifyModal] = useState(false); const [mapModifyModal, setMapModifyModal] = useState(false);
const openMapModifyDialog = () => { const openMapModifyDialog = () => {
@@ -14,11 +14,15 @@ const MapModify = ({rowId, mutate}) => {
<> <>
<Tooltip title="بررسی پلیگان طرح" arrow placement="right"> <Tooltip title="بررسی پلیگان طرح" arrow placement="right">
<IconButton color="primary" onClick={openMapModifyDialog}> <IconButton color="primary" onClick={openMapModifyDialog}>
<MapIcon/> <MapIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<MapModifyDialog mapModifyModal={mapModifyModal} setMapModifyModal={setMapModifyModal} rowId={rowId} <MapModifyDialog
mutate={mutate}/> mapModifyModal={mapModifyModal}
setMapModifyModal={setMapModifyModal}
rowId={rowId}
mutate={mutate}
/>
</> </>
); );
}; };

View File

@@ -1,16 +1,16 @@
import ReferForm from "./Refer"; import ReferForm from "./Refer";
import TaskDetail from "./TaskDetail"; import TaskDetail from "./TaskDetail";
import {Box} from "@mui/material"; import { Box } from "@mui/material";
import RoadSafetyForm from "./RoadSafetyForm"; import RoadSafetyForm from "./RoadSafetyForm";
import MapModify from "./MapModify"; import MapModify from "./MapModify";
const RowActions = ({row, mutate}) => { const RowActions = ({ row, mutate }) => {
return ( return (
<Box sx={{display: "flex", gap: 1}}> <Box sx={{ display: "flex", gap: 1 }}>
<MapModify mutate={mutate} rowId={row.getValue("id")}/> <MapModify mutate={mutate} rowId={row.getValue("id")} />
<ReferForm mutate={mutate} rowId={row.getValue("id")}/> <ReferForm mutate={mutate} rowId={row.getValue("id")} />
<TaskDetail mutate={mutate} rowId={row.getValue("id")}/> <TaskDetail mutate={mutate} rowId={row.getValue("id")} />
<RoadSafetyForm rowId={row.getValue("id")} mutate={mutate}/> <RoadSafetyForm rowId={row.getValue("id")} mutate={mutate} />
</Box> </Box>
); );
}; };

View File

@@ -1,59 +0,0 @@
"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

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

View File

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

View File

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

View File

@@ -0,0 +1,30 @@
import { useEffect, useState } from "react";
import { GET_AZMAYESH_TYPE_LIST } from "@/core/utils/routes";
import useRequest from "@/lib/hooks/useRequest";
const useAzmayesh = () => {
const requestServer = useRequest();
const [azmayeshes, setAzmayeshes] = useState([]);
const [loadingAzmayeshes, setLoadingAzmayeshes] = useState(true);
const [errorAzmayeshes, setErrorAzmayeshes] = useState(null);
useEffect(() => {
const fetchTests = async () => {
try {
const response = await requestServer(`${GET_AZMAYESH_TYPE_LIST}`);
setAzmayeshes(response.data.data);
setLoadingAzmayeshes(false);
} catch (e) {
console.error("Error fetching tests types:", e);
setErrorAzmayeshes(e);
setLoadingAzmayeshes(false);
}
};
fetchTests();
}, []);
return { azmayeshes, loadingAzmayeshes, errorAzmayeshes };
};
export default useAzmayesh;

View File

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

View File

@@ -1,30 +0,0 @@
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;