Merge branch 'feature/examination_page' into 'develop'
complete design of adding new test and bundling and saving map data next step... See merge request witel-front-end/rms!28
This commit is contained in:
7
src/app/(withAuth)/dashboard/test/page.js
Normal file
7
src/app/(withAuth)/dashboard/test/page.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import TestPage from "@/components/dashboard/test";
|
||||
|
||||
const Page = () => {
|
||||
return <TestPage/>;
|
||||
};
|
||||
|
||||
export default Page;
|
||||
18
src/app/api/fake-tests-type/route.js
Normal file
18
src/app/api/fake-tests-type/route.js
Normal 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});
|
||||
}
|
||||
71
src/app/api/fake-tests/route.js
Normal file
71
src/app/api/fake-tests/route.js
Normal 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});
|
||||
}
|
||||
BIN
src/assets/images/examine_marker.png
Normal file
BIN
src/assets/images/examine_marker.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/images/examine_marker_active.png
Normal file
BIN
src/assets/images/examine_marker_active.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -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;
|
||||
}
|
||||
@@ -25,4 +25,3 @@
|
||||
font-size: 12px;
|
||||
color: #ffeb3b;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
33
src/components/dashboard/test/Actions/create/index.jsx
Normal file
33
src/components/dashboard/test/Actions/create/index.jsx
Normal 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;
|
||||
@@ -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;
|
||||
50
src/components/dashboard/test/ShowLocation/index.jsx
Normal file
50
src/components/dashboard/test/ShowLocation/index.jsx
Normal 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;
|
||||
135
src/components/dashboard/test/TestList.jsx
Normal file
135
src/components/dashboard/test/TestList.jsx
Normal 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;
|
||||
10
src/components/dashboard/test/Toolbar.jsx
Normal file
10
src/components/dashboard/test/Toolbar.jsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import TestCreate from "./Actions/Create";
|
||||
|
||||
const Toolbar = ({mutate}) => {
|
||||
return (
|
||||
<>
|
||||
<TestCreate mutate={mutate}/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default Toolbar;
|
||||
15
src/components/dashboard/test/index.jsx
Normal file
15
src/components/dashboard/test/index.jsx
Normal 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;
|
||||
@@ -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"],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
30
src/lib/hooks/useTest.js
Normal 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;
|
||||
Reference in New Issue
Block a user