push rasad front on new repo

This commit is contained in:
2026-01-18 14:32:49 +03:30
commit 4fe6e70525
2139 changed files with 303150 additions and 0 deletions

View File

@@ -0,0 +1,408 @@
import { Button, TextField, Typography } from "@mui/material";
import { useContext, useEffect, useState } from "react";
import PlagiarismIcon from "@mui/icons-material/Plagiarism";
// import { ROUTE_CITY_FILE } from "../../../../routes/routes";
// import { avicultureGetRequests } from "../../../aviculture/services/aviculture-requests";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { AppContext } from "../../../../contexts/AppContext";
import { PageTable } from "../../../../components/page-table/PageTable";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import axios from "axios";
import { DatePicker } from "@mui/x-date-pickers";
import moment from "moment/moment";
import { formatJustDate } from "../../../../utils/formatTime";
import { IconButton } from "@mui/material";
import { ROUTE_CITY_FILE } from "../../../../routes/routes";
import { useNavigate } from "react-router-dom";
import { RiSearchLine } from "react-icons/ri";
export const CityActiveRequests = () => {
const navigate = useNavigate();
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
useContext(AppContext);
useEffect(() => {
const currentDate = moment(new Date()).format("YYYY-MM-DD");
setSelectedDate1(currentDate);
setSelectedDate2(currentDate);
}, []);
// page table
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [textValue, setTextValue] = useState("");
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const fetchApiData = async (page, textValue) => {
setLoading(true);
let response = await axios.get(
`Poultry_Request/?state=accepted&date1=${selectedDate1}&date2=${selectedDate2}&search=filter&value=${
textValue ? textValue : ""
}&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}`
);
setData(response.data.results);
setTotalRows(response.data.count);
setLoading(false);
};
const handlePageChange = (page) => {
fetchApiData(page, textValue);
};
const handlePerRowsChange = async (newPerPage, page) => {
setLoading(true);
let response = await axios.get(
`Poultry_Request/?state=accepted&date1=${selectedDate1}&date2=${selectedDate2}&search=filter&value=${
textValue ? textValue : ""
}&page=${page}&page_size=${newPerPage}`
);
setData(response.data.results);
setTotalRows(response.data.count);
setPerPage(newPerPage);
setLoading(false);
};
useEffect(() => {
fetchApiData(1);
}, [selectedDate1, selectedDate2, perPage]);
const handleSubmit = async (event) => {
event.preventDefault();
setLoading(true);
try {
const response = await axios.get(
`Poultry_Request/?state=accepted&date1=${selectedDate1}&date2=${selectedDate2}&role=${getRoleFromUrl()}&search=filter&value=${
textValue ? textValue : ""
}`
);
setData(response.data.results);
setTotalRows(response.data.count);
} catch (error) {
console.error("Error fetching data:", error);
} finally {
setLoading(false);
}
};
const columns = [
{
name: "ردیف",
selector: (item, i) => {
return i + 1;
},
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "40px",
},
{
name: "وضعیت",
selector: (item) => (
<Typography
variant="body2"
color={item.provinceState === "rejected" ? "error" : "promary"}
>
{item.provinceState === "pending"
? "درانتظار تایید استان"
: item.provinceState === "accepted"
? "تایید شده توسط استان"
: "رد شده"}
</Typography>
),
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "کدسفارش",
selector: (item) => item.orderCode,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "تاریخ ثبت درخواست",
selector: (item) => formatJustDate(item.createDate),
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "نوع کشتار",
selector: (item) => {
return item?.freezing ? "انجماد" : item?.export ? "صادرات" : "عادی";
},
sortable: true,
wrap: true,
allowOverflow: true,
center: true,
width: "80px",
},
{
name: "تاریخ کشتار",
selector: (item) => formatJustDate(item.sendDate),
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "مرغداری",
selector: (item) =>
`${item?.poultry?.unitName} (${item?.poultry?.user?.mobile})`,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "شهر",
selector: (item) => item?.poultry?.address?.city?.name,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "استان",
selector: (item) => item?.poultry?.address?.province?.name,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "تاریخ جوجه ریزی",
selector: (item) => formatJustDate(item.hatching.hatchingDate),
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "سن",
selector: (item) => item.hatching.age,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "تعداد (قطعه)",
selector: (item) => item?.quantity,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "مشاهده",
selector: (item) => {
return (
<IconButton
aria-label="delete"
color="primary"
onClick={() => navigate(ROUTE_CITY_FILE + item?.id)}
>
<PlagiarismIcon />
</IconButton>
);
},
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
];
// useEffect(() => {
// dispatch(LOADING_START());
// dispatch(avicultureGetRequests({ selectedDate1, selectedDate2 })).then(
// (r) => {
// dispatch(LOADING_END());
// }
// );
// }, [selectedDate1, selectedDate2]);
// useEffect(() => {
// const filteredData = avicultureRequests?.filter(
// (item, i) => item.stateProcess === "pending"
// );
// const d = filteredData?.map((item, i) => {
// return [
// i + 1,
// item.orderCode,
// item.poultry.userprofile.baseOrder,
// formatJustDate(item.createDate),
// formatJustDate(item.sendDate),
// item?.process?.poultry?.poultryName,
// item?.process?.poultry?.poultryMobile,
// item?.process?.poultry?.poultryCity,
// item?.process?.poultry?.poultryProvince,
// formatJustDate(item.hatching.date),
// item?.process?.poultry?.age,
// item?.process?.poultry?.poultryQuantity,
// <IconButton
// key={i}
// color="primary"
// onClick={() =>
// dispatch(
// DRAWER({
// right: !(window.innerWidth <= 600),
// bottom: window.innerWidth <= 600,
// content: (
// <CityFileOperations id={item.id} file={item?.process} />
// ),
// title: "انجام عملیات شهرستان",
// })
// )
// }
// >
// <CreateIcon />
// </IconButton>,
// <IconButton
// key={i}
// aria-label="delete"
// color="primary"
// onClick={() =>
// navigate(ROUTE_CITY_FILE + item?.process?.poultry?.poultryRequestId)
// }
// >
// <PlagiarismIcon />
// </IconButton>,
// ];
// });
// setDataTable(d);
// }, [avicultureRequests]);
return (
<>
{/* <AdvancedTable
name={
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Grid container gap={SPACING.TINY}>
<Typography>درخواست های جدید فروش اتحادیه</Typography>
</Grid>
<Grid container gap={SPACING.SMALL}>
<Grid>
<DatePicker
label="از تاریخ"
id="date"
renderInput={(params) => (
<TextField style={{ width: "160px" }} {...params} />
)}
value={selectedDate1}
onChange={(e) => {
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<DatePicker
label="تا تاریخ"
id="date"
renderInput={(params) => (
<TextField style={{ width: "160px" }} {...params} />
)}
value={selectedDate2}
onChange={(e) => {
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
</Grid>
</Grid>
}
columns={columnsName}
data={dataTable}
/> */}
<Grid alignItems="center" justifyContent="center" mt={4}>
<PageTable
title={
<Grid
container
alignItems="center"
justifyContent="space-between"
gap={2}
paddingTop={2}
mb={1}
>
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Typography>درخواست های فعال</Typography>
<Grid container gap={SPACING.SMALL}>
<Grid>
<DatePicker
label="از تاریخ"
id="date"
renderInput={(params) => (
<TextField style={{ width: "160px" }} {...params} />
)}
value={selectedDate1}
onChange={(e) => {
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<DatePicker
label="تا تاریخ"
id="date"
renderInput={(params) => (
<TextField style={{ width: "160px" }} {...params} />
)}
value={selectedDate2}
onChange={(e) => {
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
</Grid>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button
// disabled={!textValue}
type="submit"
onClick={handleSubmit}
endIcon={<RiSearchLine />}
>
جستجو
</Button>
</form>
</Grid>
</Grid>
}
columns={columns}
data={data}
progressPending={loading}
pagination
paginationServer
paginationTotalRows={totalRows}
onChangeRowsPerPage={handlePerRowsChange}
onChangePage={handlePageChange}
/>
</Grid>
</>
);
};

View File

@@ -0,0 +1,87 @@
import React, { useContext } from "react";
import { useFormik } from "formik";
import { Button, TextField } from "@mui/material";
import { useDispatch } from "react-redux";
import { AppContext } from "../../../../contexts/AppContext";
import { archiveHatchingService } from "../../services/archive-hatching";
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
import * as Yup from "yup";
// import { cityGetHatchingsByAge } from "../../services/city-get-hatchings-by-age";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { cityGetHatchingsByAge } from "../../services/city-get-hatchings-by-age";
const validationSchema = Yup.object({
name: Yup.string(),
});
export const CityArchiveHatchingDrawer = ({
item,
selectedAge1,
selectedAge2,
updateTable,
}) => {
const [openNotif] = useContext(AppContext);
const dispatch = useDispatch();
const formik = useFormik({
initialValues: {
name: "",
},
validationSchema,
onSubmit: (values) => {
dispatch(
archiveHatchingService({
key: item.key,
archive_state: "",
message: values.name,
role: getRoleFromUrl(),
})
).then((r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
dispatch(DRAWER({ right: false, bottom: false, content: null }));
if (selectedAge1) {
dispatch(cityGetHatchingsByAge({ selectedAge1, selectedAge2 }));
}
updateTable();
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
},
});
return (
<form onSubmit={formik.handleSubmit}>
<TextField
id="name"
name="name"
label="توضیحات"
variant="outlined"
multiline
rows={4}
fullWidth
margin="normal"
value={formik.values.name}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={formik.touched.name && formik.errors.name}
error={formik.touched.name && Boolean(formik.errors.name)}
/>
<Button type="submit" variant="contained" color="primary" fullWidth>
ثبت
</Button>
</form>
);
};

View File

@@ -0,0 +1,91 @@
import {
Button,
FormControl,
FormHelperText,
TextField,
Typography,
} from "@mui/material";
import { useFormik } from "formik";
import { useContext } from "react";
import { useDispatch } from "react-redux";
import { Grid } from "../../../../components/grid/Grid";
import { AppContext } from "../../../../contexts/AppContext";
import { SPACING } from "../../../../data/spacing";
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
import { Yup } from "../../../../lib/yup/yup";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { archiveOldHatchingsService } from "../../services/archive-old-hatchings";
export const CityArchiveOldHatchings = () => {
const dispatch = useDispatch();
const [openNotif] = useContext(AppContext);
const validationSchema = Yup.object().shape({
numberField: Yup.number().typeError("عدد وارد کنید").required("اجباری است"),
});
const initialValues = {
numberField: "",
};
const onSubmit = (values) => {
dispatch(
archiveOldHatchingsService({
age: values.numberField,
role: getRoleFromUrl(),
})
).then((r) => {
dispatch(CLOSE_MODAL());
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.data.msg,
severity: "success",
});
}
});
};
const formik = useFormik({
initialValues,
onSubmit,
validationSchema,
});
return (
<form onSubmit={formik.handleSubmit}>
<Grid container gap={SPACING.TINY}>
<Typography variant="caption" color="error">
توجه : تمام جوجه ریزی های فعالی که بیشتر از سن وارده شده در کادر زیر
باشند به بایگانی منتقل میشوند.
</Typography>
<FormControl
fullWidth
error={formik.touched.numberField && formik.errors.numberField}
>
<TextField
name="numberField"
label="بایگانی کردن جوجه ریزی ها از سن"
type="number"
value={formik.values.numberField}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.numberField && formik.errors.numberField && (
<FormHelperText>{formik.errors.numberField}</FormHelperText>
)}
</FormControl>
<Button type="submit" variant="contained" color="primary" fullWidth>
ثبت
</Button>
</Grid>
</form>
);
};

View File

@@ -0,0 +1,554 @@
import {
Autocomplete,
Button,
Chip,
Divider,
FormControl,
InputLabel,
MenuItem,
Select,
TextField,
} from "@mui/material";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import React, { useEffect } from "react";
import { Yup } from "../../../../lib/yup/yup";
import { useFormik } from "formik";
import { useDispatch } from "react-redux";
import { cityGetProvinces } from "../../services/CityGetProvinces";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { useState } from "react";
import { cityGetCity } from "../../services/city-get-city";
import { cityEditAvicultureInfo } from "../../services/city-edit-avculture.info";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { PropTypes } from "prop-types";
import { cityGetPoultryFarm } from "../../services/city-get-poultry-farms";
export const CityEditAvicultureInfoForm = ({ item }) => {
const dispatch = useDispatch();
const [openNotif] = useContext(AppContext);
const [provinceData, setProvinceData] = useState();
const [cityData, setCityData] = useState();
const [provinceKey, setProvinceKey] = useState();
const [cityKey, setCityKey] = useState();
const [isExistProvince, setIsExistProvince] = useState(true);
const formik = useFormik({
initialValues: {
avicultureName: item?.unitName ? item?.unitName : "",
postal: item?.address.postalCode ? item?.address.postalCode : "",
address: item?.address.address ? item?.address.address : "",
bankUser: item?.userBankInfo?.nameOfBankUser
? item?.userBankInfo?.nameOfBankUser
: "",
card: item?.userBankInfo?.card ? item?.userBankInfo.card : "",
account: item?.userBankInfo?.account ? item?.userBankInfo.account : "",
bankName: "",
shaba: item?.userBankInfo?.shaba ? item?.userBankInfo.shaba : "",
hall: item?.numberOfHalls ? item?.numberOfHalls : "",
breedingUniqueId: item?.breedingUniqueId ? item?.breedingUniqueId : "",
systemCode: item?.systemCode ? item?.systemCode : "",
epidemiologicalCode: item?.epidemiologicalCode
? item?.epidemiologicalCode
: "",
totalCapacity: item?.totalCapacity ? item?.totalCapacity : "",
healthCertificateNumber: item?.healthCertificateNumber
? item?.healthCertificateNumber
: "",
},
validationSchema: Yup.object({
avicultureName: Yup.string().typeError(
"لطفا فیلد را به درستی وارد کنید!"
),
address: Yup.string().typeError("لطفا فیلد را به درستی وارد کنید!"),
card: Yup.number().typeError("لطفا فیلد را به درستی وارد کنید!"),
bankUser: Yup.string().typeError("لطفا فیلد را به درستی وارد کنید!"),
postal: Yup.number().typeError("لطفا فیلد را به درستی وارد کنید!"),
account: Yup.number().typeError("لطفا فیلد را به درستی وارد کنید!"),
bankName: Yup.string().typeError("لطفا فیلد را به درستی وارد کنید!"),
shaba: Yup.string().typeError("لطفا فیلد را به درستی وارد کنید!"),
hall: Yup.number().typeError("لطفا فیلد را به درستی وارد کنید!"),
breedingUniqueId: Yup.number().typeError(
"لطفا فیلد را به درستی وارد کنید!"
),
systemCode: Yup.number().typeError("لطفا فیلد را به درستی وارد کنید!"),
epidemiologicalCode: Yup.number().typeError(
"لطفا فیلد را به درستی وارد کنید!"
),
totalCapacity: Yup.number().typeError("لطفا فیلد را به درستی وارد کنید!"),
healthCertificateNumber: Yup.number().typeError(
"لطفا فیلد را به درستی وارد کنید!"
),
}),
});
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
dispatch(LOADING_START());
dispatch(cityGetProvinces())?.then((r) => {
dispatch(LOADING_END());
setProvinceData(r.payload.data);
});
}, []);
useEffect(() => {
if (provinceKey) {
dispatch(LOADING_START());
dispatch(cityGetCity(provinceKey)).then((r) => {
setCityData(r.payload.data);
setIsExistProvince(false);
dispatch(LOADING_END());
});
}
}, [provinceKey]);
return (
<Grid
container
gap={SPACING.SMALL}
direction="column"
flex="1"
height="100%"
justifyContent="space-between"
display="block"
>
<Grid container direction="column" gap={SPACING.SMALL}>
<Grid>
<TextField
id="breedingUniqueId"
label="شناسه یکتا"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.breedingUniqueId}
error={
formik.touched.breedingUniqueId
? Boolean(formik.errors.breedingUniqueId)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.breedingUniqueId &&
Boolean(formik.errors.breedingUniqueId)
? formik.errors.breedingUniqueId
: null
}
/>
</Grid>
<Grid>
<TextField
id="systemCode"
label="کد سیستمی"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.systemCode}
error={
formik.touched.systemCode
? Boolean(formik.errors.systemCode)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.systemCode && Boolean(formik.errors.systemCode)
? formik.errors.systemCode
: null
}
/>
</Grid>
<Grid>
<TextField
id="epidemiologicalCode"
label="کد اپیدمیولوژیک"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.epidemiologicalCode}
error={
formik.touched.epidemiologicalCode
? Boolean(formik.errors.epidemiologicalCode)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.epidemiologicalCode &&
Boolean(formik.errors.epidemiologicalCode)
? formik.errors.epidemiologicalCode
: null
}
/>
</Grid>
<Grid>
<TextField
id="avicultureName"
label="نام مرغداری"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.avicultureName}
error={
formik.touched.avicultureName
? Boolean(formik.errors.avicultureName)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.avicultureName &&
Boolean(formik.errors.avicultureName)
? formik.errors.avicultureName
: null
}
/>
</Grid>
<Grid>
<Autocomplete
disablePortal
id="province"
options={
provinceData
? provinceData?.map((i) => ({ id: i.key, label: i.name }))
: []
}
onChange={(event, value) => {
setProvinceKey(value.id);
}}
renderInput={(params) => (
<TextField {...params} label="استان را انتخاب کنید" />
)}
/>
</Grid>
<Grid>
<Autocomplete
disabled={isExistProvince}
disablePortal
id="city"
options={
cityData
? cityData.map((i) => ({ id: i.key, label: i.name }))
: []
}
onChange={(event, value) => {
setCityKey(value.id);
}}
renderInput={(params) => (
<TextField {...params} label="شهر را انتخاب کنید" />
)}
/>
</Grid>
<Grid>
<TextField
id="address"
label="آدرس"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.address}
error={
formik.touched.address ? Boolean(formik.errors.address) : null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.address && Boolean(formik.errors.address)
? formik.errors.address
: null
}
/>
</Grid>
<Grid>
<TextField
id="postal"
label="کد پستی"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.postal}
error={formik.touched.postal ? Boolean(formik.errors.postal) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.postal && Boolean(formik.errors.postal)
? formik.errors.postal
: null
}
/>
</Grid>
<Grid>
<TextField
id="hall"
label="تعداد سالن"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.hall}
error={formik.touched.postal ? Boolean(formik.errors.hall) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.hall && Boolean(formik.errors.hall)
? formik.errors.hall
: null
}
/>
</Grid>
<Grid>
<TextField
id="totalCapacity"
label="ظرفیت کل"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.totalCapacity}
error={
formik.touched.totalCapacity
? Boolean(formik.errors.totalCapacity)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.totalCapacity &&
Boolean(formik.errors.totalCapacity)
? formik.errors.totalCapacity
: null
}
/>
</Grid>
<Grid>
<TextField
id="healthCertificateNumber"
label="شماره گواهی بهداشتی"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.healthCertificateNumber}
error={
formik.touched.healthCertificateNumber
? Boolean(formik.errors.healthCertificateNumber)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.healthCertificateNumber &&
Boolean(formik.errors.healthCertificateNumber)
? formik.errors.healthCertificateNumber
: null
}
/>
</Grid>
<Divider>
<Chip label="اطلاعات بانکی" />
</Divider>
<Grid>
<TextField
id="bankUser"
label="نام صاحب حساب"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.bankUser}
error={
formik.touched.bankUser ? Boolean(formik.errors.bankUser) : null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.bankUser && Boolean(formik.errors.bankUser)
? formik.errors.bankUser
: null
}
/>
</Grid>
<Grid>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">بانک</InputLabel>
<Select
id="bankName"
label="نام بانک"
value={formik.values.bankName}
error={
formik.touched.bankName ? Boolean(formik.errors.bankName) : null
}
onChange={(e) => {
formik.setFieldValue("bankName", e.target.value);
}}
onBlur={formik.handleBlur}
>
<MenuItem value={"موسسه افضل توس"}>موسسه افضل توس</MenuItem>
<MenuItem value={"انصار"}>انصار</MenuItem>
<MenuItem value={"سپه"}>سپه</MenuItem>
<MenuItem value={"دی"}>دی</MenuItem>
<MenuItem value={"کاب"}>اقتصاد نوین</MenuItem>
<MenuItem value={"گردشگری"}>گردشگری</MenuItem>
<MenuItem value={"حکمت ایرانیان"}>حکمت ایرانیان</MenuItem>
<MenuItem value={"ایران زمین"}>ایران زمین</MenuItem>
<MenuItem value={"کشاورزی"}>کشاورزی</MenuItem>
<MenuItem value={"مسکن"}>مسکن</MenuItem>
<MenuItem value={"مهر ایران"}>مهر ایران</MenuItem>
<MenuItem value={"مهر اقتصاد"}>مهر اقتصاد</MenuItem>
<MenuItem value={"ملت"}>ملت</MenuItem>
<MenuItem value={"ملی"}>ملی</MenuItem>
<MenuItem value={"پارسیان"}>پارسیان</MenuItem>
<MenuItem value={"پاسارگاد"}>پاسارگاد</MenuItem>
<MenuItem value={"پست بانک ایران"}>پست بانک ایران</MenuItem>
<MenuItem value={"صادرات"}>صادرات</MenuItem>
<MenuItem value={"سامان"}>سامان</MenuItem>
<MenuItem value={"صنعت و معدن"}>صنعت و معدن</MenuItem>
<MenuItem value={"سرمایه"}>سرمایه</MenuItem>
<MenuItem value={"شهر"}>شهر</MenuItem>
<MenuItem value={"سینا"}>سینا</MenuItem>
<MenuItem value={"تجارت"}>تجارت</MenuItem>
<MenuItem value={"موسسه اعتباری توسعه"}>
موسسه اعتباری توسعه
</MenuItem>
<MenuItem value={"خاورمیانه"}>خاورمیانه</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid>
<TextField
id="card"
label="شماره کارت"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.card}
error={formik.touched.card ? Boolean(formik.errors.card) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.card && Boolean(formik.errors.card)
? formik.errors.card
: null
}
/>
</Grid>
<Grid>
<TextField
id="account"
label="شماره حساب"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.account}
error={
formik.touched.account ? Boolean(formik.errors.account) : null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.account && Boolean(formik.errors.account)
? formik.errors.account
: null
}
/>
</Grid>
<Grid>
<TextField
id="shaba"
label="شماره شبا"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.shaba}
error={formik.touched.shaba ? Boolean(formik.errors.shaba) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.shaba && Boolean(formik.errors.shaba)
? formik.errors.shaba
: null
}
/>
</Grid>
<Grid mb={SPACING.SMALL}>
<Button
fullWidth
variant="contained"
disabled={!formik.validateForm}
onClick={() => {
dispatch(
cityEditAvicultureInfo({
poultry_key: item.key,
breedingUniqueId: formik.values.breedingUniqueId
? formik.values.breedingUniqueId
: null,
systemCode: formik.values.systemCode
? formik.values.systemCode
: null,
epidemiologicalCode: formik.values.epidemiologicalCode
? formik.values.epidemiologicalCode
: null,
totalCapacity: formik.values.totalCapacity
? formik.values.totalCapacity
: null,
healthCertificateNumber: formik.values.healthCertificateNumber
? formik.values.healthCertificateNumber
: null,
address: {
province: provinceKey ? provinceKey : null,
city: cityKey ? cityKey : null,
address: formik.values.address
? formik.values.address
: null,
postal_code: formik.values.postal
? formik.values.postal
: null,
},
user_bank_info: {
name_of_bank_user: formik.values.bankUser
? formik.values.bankUser
: null,
bank_name: formik.values.bankName
? formik.values.bankName
: null,
card: formik.values.card ? formik.values.card : null,
shaba: formik.values.shaba ? formik.values.shaba : null,
account: formik.values.account
? formik.values.account
: null,
},
unit_name: formik.values.avicultureName
? formik.values.avicultureName
: null,
hall: formik.values.hall ? formik.values.hall : null,
})
).then((r) => {
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است.",
severity: "error",
});
dispatch(LOADING_END());
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
dispatch(cityGetPoultryFarm());
dispatch(
DRAWER({ right: false, bottom: false, content: null })
);
});
}}
>
ثبت اطلاعات
</Button>
</Grid>
</Grid>
</Grid>
);
};
CityEditAvicultureInfoForm.propTypes = {
item: PropTypes.any,
};

View File

@@ -0,0 +1,110 @@
import { Button, IconButton, TextField, Tooltip } from "@mui/material";
import EditIcon from "@mui/icons-material/Edit";
import { useDispatch } from "react-redux";
import { CLOSE_MODAL, OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
import { useContext, useState } from "react";
import { cityEditHatchingQuantityService } from "../../services/city-edit-hatching-quantity";
import { AppContext } from "../../../../contexts/AppContext";
// import { cityGetHatchings } from "../../services/city-get-hatchings";
// import { cityGetHatchingsByAge } from "../../services/city-get-hatchings-by-age";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
export const CityEditHatchingQuantity = ({
quantity,
hatchingKey,
selectedAge1,
selectedAge2,
updateTable,
}) => {
const dispatch = useDispatch();
return (
<Tooltip title={"ویرایش تعداد جوجه ریزی"} placement="left-start">
<IconButton
size="small"
color="primary"
onClick={() => {
dispatch(
OPEN_MODAL({
title: "ویرایش تعداد جوجه ریزی",
content: (
<ModalContent
selectedAge1={selectedAge1}
selectedAge2={selectedAge2}
quantity={quantity}
hatchingKey={hatchingKey}
updateTable={updateTable}
/>
),
})
);
}}
>
<EditIcon fontSize="10" />
</IconButton>
</Tooltip>
);
};
const ModalContent = ({
quantity,
hatchingKey,
selectedAge1,
selectedAge2,
updateTable,
}) => {
const dispatch = useDispatch();
const [openNotif] = useContext(AppContext);
const [value, setValue] = useState(quantity);
const handleChange = (event) => {
setValue(event.target.value);
};
return (
<>
<TextField
label="تعداد"
type="number"
variant="outlined"
value={value}
onChange={handleChange}
/>
<Button
disabled={!value}
fullWidth
variant="contained"
onClick={() => {
dispatch(
cityEditHatchingQuantityService({
key: hatchingKey,
quantity: Number(value),
role: getRoleFromUrl(),
})
).then((r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
// dispatch(cityGetHatchingsByAge({ selectedAge1, selectedAge2 }));
// dispatch(cityGetHatchings({ selectedDate1, selectedDate2 }));
updateTable();
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
dispatch(CLOSE_MODAL());
}
});
}}
>
ثبت
</Button>
</>
);
};

View File

@@ -0,0 +1,291 @@
import React, { useContext, useEffect } from "react";
import {
Button,
TextField,
Tooltip,
Typography,
Box,
Divider,
Chip,
} from "@mui/material";
import { DatePicker } from "@mui/x-date-pickers";
import moment from "moment";
import { useDispatch, useSelector } from "react-redux";
import { cityGetHatchingInfo } from "../../services/city-get-hatching-info";
import { cityGetHatchingInfoFull } from "../../services/city-get-hatching-info-full";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import { AppContext } from "../../../../contexts/AppContext";
import { RiFileExcel2Fill } from "react-icons/ri";
import { useFormik } from "formik";
import axios from "axios";
import { Grid } from "../../../../components/grid/Grid";
export const CityHatchingInfo = () => {
const { hatchingInfoWithDate, hatchingInfoFull } = useSelector(
(state) => state.citySlice
);
const dispatch = useDispatch();
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
useContext(AppContext);
useEffect(() => {
const currentDate = moment(new Date()).format("YYYY-MM-DD");
setSelectedDate1(currentDate);
setSelectedDate2(currentDate);
}, []);
useEffect(() => {
dispatch(cityGetHatchingInfoFull());
}, []);
useEffect(() => {
dispatch(cityGetHatchingInfo({ selectedDate1, selectedDate2 }));
}, [selectedDate1, selectedDate2]);
const formik = useFormik({
initialValues: {
minAge: "",
maxAge: "",
},
});
return (
<Box bgcolor="#f9f9f9" borderRadius={2} boxShadow={3}>
<Divider style={{ width: "100%" }}>
<Chip
label={
<Typography
variant="body1"
gutterBottom
color="primary"
fontWeight="bold"
>
اطلاعات جوجه ریزی
</Typography>
}
/>
</Divider>
<Grid container spacing={3} m={0} pb={2}>
{/* Full Summary Table */}
<Grid item xs={12}>
<ResponsiveTable
noPagination
title="آمار جوجه ریزی"
columns={[
"تعداد فارم",
"تعداد کل جوجه ریزی",
"تعداد باقی مانده در سالن",
"تعداد کشتار شده",
"وزن کشتار شده",
"مانده سالن (20 تا 30 روزه)",
"مانده سالن (30 تا 40 روزه)",
"مانده سالن (40 تا 50 روزه)",
"مانده سالن (50 تا 60 روزه)",
"بیشتر از 60 روزه",
]}
data={[
[
hatchingInfoFull?.poultries?.toLocaleString(),
hatchingInfoFull?.totalHatchingQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingLeftOverQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingKilledQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingKilledWeight?.toLocaleString(),
hatchingInfoFull?.age2030?.toLocaleString(),
hatchingInfoFull?.age3040?.toLocaleString(),
hatchingInfoFull?.age4050?.toLocaleString(),
hatchingInfoFull?.age5060?.toLocaleString(),
hatchingInfoFull?.ageMoreThan60?.toLocaleString(),
],
]}
/>
</Grid>
<Divider style={{ width: "100%", marginTop: 8 }}>
<Chip
label={
<Typography
variant="body1"
color="primary"
gutterBottom
fontWeight="medium"
>
بر اساس بازه
</Typography>
}
/>
</Divider>
<Grid item xs={12} mt={2}>
<Grid container alignItems="center" spacing={2}>
<Grid item>
<DatePicker
label="از تاریخ"
renderInput={(params) => (
<TextField {...params} size="small" fullWidth />
)}
value={selectedDate1}
onChange={(e) =>
setSelectedDate1(moment(e).format("YYYY-MM-DD"))
}
/>
</Grid>
<Grid item>
<DatePicker
label="تا تاریخ"
renderInput={(params) => (
<TextField {...params} size="small" fullWidth />
)}
value={selectedDate2}
onChange={(e) =>
setSelectedDate2(moment(e).format("YYYY-MM-DD"))
}
/>
</Grid>
<Grid item>
<Tooltip title="خروجی اکسل">
<a
href={`${axios.defaults.baseURL}hatching_date_range_excel/?date1=${selectedDate1}&date2=${selectedDate2}`}
rel="noreferrer"
>
<Button variant="contained" color="success">
<RiFileExcel2Fill size={24} />
</Button>
</a>
</Tooltip>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<ResponsiveTable
noPagination
title="خلاصه آمار"
columns={[
"تعداد فارم های فعال",
"تعداد کل جوجه ریزی",
"تعداد باقی مانده در سالن",
"تعداد کشتار شده",
"وزن کشتار شده",
]}
data={[
[
hatchingInfoWithDate?.poultries?.toLocaleString(),
hatchingInfoWithDate?.totalHatchingQuantity?.toLocaleString(),
hatchingInfoWithDate?.totalHatchingLeftOverQuantity?.toLocaleString(),
hatchingInfoWithDate?.totalHatchingKilledQuantity?.toLocaleString(),
hatchingInfoWithDate?.totalHatchingKilledWeight?.toLocaleString(),
],
]}
/>
</Grid>
<Divider
style={{
width: "100%",
marginTop: 8,
}}
sx={{
display: { xs: "none", sm: "block" },
}}
>
<Chip
label={
<Typography
variant="body1"
color="primary"
gutterBottom
fontWeight="medium"
mx="auto"
>
گزارش مانده سالن فارم های بیشتر از 10 درصد
</Typography>
}
/>
</Divider>
<Typography
variant="body1"
backgroundColor="rgba(0, 0, 0, 0.08)"
color="primary"
gutterBottom
fontWeight="medium"
mt={4}
mx="auto"
sx={{
display: { xs: "block", sm: "none" },
borderRadius: 2,
}}
width={{
xs: "80%",
sm: "auto",
}}
>
گزارش مانده سالن فارم های بیشتر از 10 درصد
</Typography>
<Grid
item
xs={12}
container
justifyContent="center"
gap={2}
alignItems="center"
mt={4}
px={1}
>
<Grid
container
sx={{
gap: 2,
}}
alignItems="center"
>
<Grid
item
sx={{
maxWidth: { xs: "46%", sm: "100px" },
}}
>
<TextField
id="minAge"
label="از سن"
variant="outlined"
size="small"
value={formik.values.minAge}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
</Grid>
<Grid
item
sx={{
maxWidth: { xs: "46%", sm: "100px" },
}}
>
<TextField
id="maxAge"
label="تا سن"
variant="outlined"
size="small"
value={formik.values.maxAge}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
</Grid>
<Grid item>
<Tooltip title="خروجی اکسل">
<a
href={`${axios.defaults.baseURL}hatching_by_age_range/?min_age=${formik.values.minAge}&max_age=${formik.values.maxAge}`}
rel="noreferrer"
>
<Button variant="contained" color="success">
<RiFileExcel2Fill size={24} />
</Button>
</a>
</Tooltip>
</Grid>
</Grid>
</Grid>
</Grid>
</Box>
);
};

View File

@@ -0,0 +1,39 @@
import { useLocation } from "react-router-dom";
import { Button } from "@mui/material";
import { NavLink } from "../../../../components/nav-link/NavLink";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import {
ROUTE_CITY_HATCHING,
ROUTE_CITY_NEW_REQUEST,
} from "../../../../routes/routes";
export const CityHatchingOperations = () => {
const { pathname } = useLocation();
return (
<Grid
container
gap={SPACING.SMALL}
p={SPACING.SMALL}
direction={{ xs: "column", md: "row" }}
>
<NavLink
to={ROUTE_CITY_HATCHING}
active={pathname === ROUTE_CITY_HATCHING ? "true" : null}
>
<Button variant="text" color="inherit">
ثبت اطلاعات جوجه ریزی
</Button>
</NavLink>
<NavLink
to={ROUTE_CITY_NEW_REQUEST}
active={pathname === ROUTE_CITY_NEW_REQUEST ? "true" : null}
>
<Button variant="text" color="inherit">
ثبت درخواست کشتار
</Button>
</NavLink>
</Grid>
);
};

View File

@@ -0,0 +1,691 @@
import {
Button,
IconButton,
TextField,
Tooltip,
Typography,
} from "@mui/material";
import axios from "axios";
import { useContext, useEffect, useState } from "react";
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { formatTime, formatJustDate } from "../../../../utils/formatTime";
import { getFaUserRole } from "../../../../utils/getFaUserRole";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { CityManageHatchingsArchiveActions } from "../city-manage-hatchings-operations/CityManageHatchingsOperations";
import { useDispatch, useSelector } from "react-redux";
import { AppContext } from "../../../../contexts/AppContext";
import { cityGetHatchingInfoFull } from "../../services/city-get-hatching-info-full";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import {
// DRAWER,
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../../../../lib/redux/slices/appSlice";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import ShowImage from "../../../../components/show-image/ShowImage";
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
import ArticleIcon from "@mui/icons-material/Article";
import {
ROUTE_ADMINXـHATCHINGS,
ROUTE_CITY_JIHADـHATCHINGS,
ROUTE_CITY_POULTRYـHATCHINGS,
ROUTE_PROVINCE_SUPERVISORـHATCHINGS,
ROUTE_PROVINCEـHATCHINGS,
ROUTE_SUPER_ADMINـHATCHINGS,
ROUTE_SUPPORTERـHATCHINGS,
} from "../../../../routes/routes";
import { useNavigate } from "react-router-dom";
// import { CityHatchingShowTableDetail } from "../city-hatching-show-table-detail/CityHatchingShowTableDetail";
export const CityHatchingUnassigned = ({ readOnly }) => {
const dispatch = useDispatch();
const isReadOnly = readOnly || false;
const [selectedAge1, setSelectedAge1] = useState(0);
const [selectedAge2, setSelectedAge2] = useState(0);
const [data, setData] = useState([]);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [textValue, setTextValue] = useState("");
const [page, setPage] = useState(1);
const [tableData, setTableData] = useState([]);
const userKey = useSelector((state) => state.userSlice.userProfile.key);
const navigate = useNavigate();
const [openNotif] = useContext(AppContext);
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const hatchingAdded = useSelector((state) => state.citySlice.hatchingAdded);
useEffect(() => {
fetchApiData();
}, [hatchingAdded]);
const fetchApiData = async (pageParam = page, perPageParam = perPage) => {
dispatch(LOADING_START());
const response = await axios.get("poultry_hatching/", {
params: {
unknown: true,
search: "filter",
value: textValue,
role: getRoleFromUrl(),
page: pageParam,
page_size: perPageParam,
age1: selectedAge1 || 0,
age2: selectedAge2 || 0,
},
});
dispatch(LOADING_END());
setData(response.data.results);
setTotalRows(response.data.count);
};
const handlePageChange = (page) => {
setPage(page);
fetchApiData(page, perPage);
};
const handlePerRowsChange = (perRows) => {
setPerPage(perRows);
setPage(1);
};
useEffect(() => {
fetchApiData();
}, [perPage]);
const updateTable = () => {
fetchApiData();
};
// const killedNumber = (item) => {
// let killedNumber = "";
// killedNumber = item.quantity - item.losses - item.leftOver;
// return killedNumber;
// };
useEffect(() => {
const d = data?.map((item, i) => {
return [
<CityManageHatchingsArchiveActions
selectedAge1={null}
selectedAge2={null}
updateTable={updateTable}
item={item}
key={"archive-actions"}
readOnly={isReadOnly}
/>,
<Tooltip placement="left" title="جزئیات جوجه ریزی" key={item?.key}>
<IconButton
color="primary"
onClick={() => {
navigate(
getRoleFromUrl() === "AdminX"
? `${ROUTE_ADMINXـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "Supporter"
? `${ROUTE_SUPPORTERـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "SuperAdmin"
? `${ROUTE_SUPER_ADMINـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "CityPoultry"
? `${ROUTE_CITY_POULTRYـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "ProvinceSupervisor"
? `${ROUTE_PROVINCE_SUPERVISORـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "ProvinceOperator"
? `${ROUTE_PROVINCEـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "CityJahad"
? `${ROUTE_CITY_JIHADـHATCHINGS}/${item.key}`
: ""
);
}}
>
<RemoveRedEyeIcon />
</IconButton>
</Tooltip>,
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
<Tooltip
disableHoverListener={
!(item?.killingInfo?.violationMessage && item?.violation)
}
key={item?.key}
title={
item?.violation
? `متن گزارش تخلف: ${item?.killingInfo?.violationMessage}`
: null
}
sx={{
"&:hover": {
cursor: item?.violation ? "pointer" : "default",
},
}}
placement="top"
>
<Typography
variant="body2"
color={item?.violation ? "error" : "primary"}
>
{item?.violation ? "پیگیری" : "عادی"}
</Typography>
</Tooltip>,
item?.licenceNumber,
item?.poultry?.breedingUniqueId,
item?.CertId,
// item?.commitmentType === "free" ? "آزاد" : "دولتی",
item?.poultry?.unitName || "-",
`${item?.poultry?.userprofile?.fullName ?? "-"} (${
item?.poultry?.userprofile?.mobile ?? "-"
}) ${item?.violationReport ? "✉️" : ""}`,
item?.InteractTypeName ? (
<Typography
variant="body2"
color={item?.hasTenant ? "success.main" : ""}
fontWeight={item?.hasTenant ? "bold" : "normal"}
>
{item?.InteractTypeName}
</Typography>
) : (
"-"
),
item?.PersonTypeName,
item?.UnionTypeName,
`${item?.poultry?.address?.city?.name ?? "-"}/${
item?.poultry?.cityOperator
? item?.poultry?.cityOperator
: "بدون تعاونی"
}`,
item?.vetFarm?.vetFarmMobile
? `${item?.vetFarm?.vetFarmFullName} (${item?.vetFarm?.vetFarmMobile})`
: "-",
item.hall,
item.period,
formatTime(item?.createDate),
formatTime(item?.date),
item?.poultry?.killingAveAge?.toLocaleString(),
item?.predicateDate ? formatJustDate(item?.predicateDate) : "-",
item.chickenBreed,
item.age,
item?.quantity?.toLocaleString(),
item?.increaseQuantity?.toLocaleString(),
`${item.losses} (%${((item.losses * 100) / item.quantity).toFixed(0)})`,
<Tooltip
key={item?.key}
placement="top"
title="جهت مشاهده ثبت کننده تلفات کلیک کنید"
>
<Button
// variant="outlined"
style={{ color: "rgba(0,0,0,0.87)" }}
onClick={() => {
dispatch(
OPEN_MODAL({
title: "ویرایش تعداد جوجه ریزی",
content: (
<Grid container xs={12}>
{!item?.directLossesInputer &&
!item?.directLossesInputer ? (
<Typography variant="body1">
برای این جوجه ریزی تلفاتی ثبت نشده است.
</Typography>
) : (
<Grid xs={12}>
<Typography variant="body1">
ثبت کننده تلفات اتحادیه:{" "}
{item?.directLossesInputer
? `${
item?.directLossesInputer
} در تاریخ ${formatJustDate(
item?.directLossesDate
)}`
: " - "}
</Typography>
<Typography variant="body1">
ویرایش کننده تلفات اتحادیه:
{item?.directLossesEditor
? `${
item?.directLossesEditor
} در تاریخ ${formatJustDate(
item?.directLossesLastEditDate
)}`
: " - "}
</Typography>
</Grid>
)}
</Grid>
),
})
);
}}
>
{`${item?.directLosses?.toLocaleString()} (%${(
(item.directLosses * 100) /
item.quantity
).toFixed(0)})`}
</Button>
</Tooltip>,
`${item?.totalLosses?.toLocaleString()} (%${(
(item.totalLosses * 100) /
item.quantity
).toFixed(0)})`,
`${item?.totalCommitmentQuantity?.toLocaleString()}`,
`${item?.totalFreeCommitmentQuantity?.toLocaleString()}`,
`${item?.governmentalQuantity?.toLocaleString()}`,
`${item?.governmentalKilledQuantity?.toLocaleString()}`,
`${item?.freeQuantity?.toLocaleString()}`,
`${item?.freeKilledQuantity?.toLocaleString()}`,
`${item?.outProvinceKilledQuantity?.toLocaleString()}`,
`${item?.outProvinceKilledWeight?.toLocaleString()}`,
`${item?.barDifferenceRequestQuantity?.toLocaleString()}`,
`${item?.barDifferenceRequestWeight?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequests?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequestsQuantity?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequestsWeight?.toLocaleString()}`,
item?.killedQuantity?.toLocaleString() +
` (%${((item?.killedQuantity * 100) / item.quantity).toFixed(0)})`,
item?.leftOver?.toLocaleString(),
`%${((item?.leftOver * 100) / item?.quantity).toFixed(0)}`,
// item?.totalCommitment?.toLocaleString(),
`%${((item.totalLosses * 100) / item.quantity).toFixed(0)}`,
`%${((item?.killedQuantity * 100) / item.quantity).toFixed(0)}`,
`%${((item?.leftOver * 100) / item?.quantity).toFixed(0)}`,
`%${(
((item?.killedQuantity + item?.totalLosses) * 100) /
item?.quantity
).toFixed(0)}`,
item?.samasatDischargePercentage
? `%${item?.samasatDischargePercentage}`
: "-",
item?.totalCommitment?.toLocaleString(),
item?.governmentalKilledQuantity?.toLocaleString(),
item?.freeKilledQuantity?.toLocaleString(),
item?.totalAverageKilledWeight?.toLocaleString(),
item?.totalKilledWeight?.toLocaleString(),
item?.activeKill?.activeKill ? "دارد" : "ندارد",
item?.activeKill?.countOfRequest ? item.activeKill.countOfRequest : "-",
item?.killingInfo?.killHouseRequests?.toLocaleString(),
item?.killingInfo?.killHouseRequestsFirstQuantity?.toLocaleString(),
item?.killingInfo?.killHouseRequestsFirstWeight?.toLocaleString(),
item?.killingInfo?.barCompleteWithKillHouse?.toLocaleString(),
item?.killingInfo?.acceptedRealWightFinal?.toLocaleString(),
item?.chainKilledQuantity?.toLocaleString(),
item?.chainKilledWeight?.toLocaleString(),
item?.exportKilledQuantity?.toLocaleString(),
item?.exportKilledWeight?.toLocaleString(),
item?.killingInfo?.wareHouseBars?.toLocaleString(),
item?.killingInfo?.wareHouseBarsQuantity?.toLocaleString(),
item?.killingInfo?.wareHouseBarsWeight?.toLocaleString(),
item?.killingInfo?.wareHouseBarsWeightLose?.toFixed(2),
item.lastChange
? `${item.lastChange.fullName} (${getFaUserRole(
item.lastChange.role
)}) در تاریخ ${formatTime(item.lastChange.date)}`
: "-",
item.latestHatchingChange
? `${item.latestHatchingChange.fullName} (${getFaUserRole(
item.latestHatchingChange.role
)}) در تاریخ ${formatTime(item.latestHatchingChange.date)}`
: "-",
item?.violationReport ? (
<Tooltip title="مشاهده گزارش" placement="top" key={item?.key}>
<IconButton
color="primary"
onClick={() => {
dispatch(
OPEN_MODAL({
title: "گزارش ",
content: (
<SimpleTable
columns={[
"ثبت کننده",
"تاریخ ثبت",
"تخلف",
"متن گزارش",
"سند",
]}
data={[
[
item?.violationReporter,
formatJustDate(item?.violationReportDate),
item?.violation ? "دارد" : "ندارد",
item?.violationReport,
<Grid
key={item?.key}
container
xs={12}
justifyContent="center"
gap={1}
>
{item?.violationImage?.map((option, index) => (
<ShowImage
key={`${option}-${index}`}
src={option}
/>
))}
</Grid>,
],
]}
/>
),
})
);
}}
>
<ArticleIcon />
</IconButton>
</Tooltip>
) : (
"-"
),
];
});
setTableData(d);
}, [data]);
const handleSubmit = async (event) => {
event.preventDefault();
dispatch(LOADING_START());
dispatch(
cityGetHatchingInfoFull({
age1: selectedAge1,
age2: selectedAge2,
tab: "unknown",
textValue: textValue,
})
);
try {
const response = await axios.get(
`poultry_hatching/?role=${getRoleFromUrl()}&age1=${
selectedAge1 ? selectedAge1 : 0
}&age2=${
selectedAge2 ? selectedAge2 : 0
}&search=filter&value=${textValue}&page=${1}&page_size=${perPage}&unknown=true`
);
setData(response.data.results);
setTotalRows(response.data.count);
dispatch(LOADING_END());
} catch (error) {
console.error("Error fetching data:", error);
}
};
const handleRemoveFilter = async (event) => {
event.preventDefault();
setSelectedAge1(0);
setSelectedAge2(0);
dispatch(LOADING_START());
setTextValue("");
dispatch(
cityGetHatchingInfoFull({
age1: 0,
age2: 0,
tab: "unknown",
textValue: textValue,
})
);
try {
const response = await axios.get(
`poultry_hatching?role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&search=filter&value=${textValue}&unknown=true`
);
setData(response.data.results);
setTotalRows(response.data.count);
} catch (error) {
console.error("Error fetching data:", error);
} finally {
dispatch(LOADING_END());
}
};
const [lastUpdateData, setLastUpdateData] = useState();
useEffect(() => {
async function fetchData() {
try {
const response = await axios.get(`last_update/?type=poultry_hatching`);
setLastUpdateData(response.data);
} catch (error) {
console.error("Error fetching data:", error);
}
}
fetchData();
}, []);
const tableTitle = (
<Grid
container
alignItems="center"
justifyContent="space-between"
gap={2}
paddingTop={2}
mb={1}
xs={12}
mt={2}
>
<form onSubmit={handleSubmit} style={{ flex: 1 }}>
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Grid sx={{ width: { xs: "72px", sm: "80px" } }}>
<TextField
size="small"
label="از سن"
id="outlined-controlled"
value={selectedAge1}
onChange={(event) => {
setSelectedAge1(event.target.value);
}}
/>
</Grid>
<Grid sx={{ width: { xs: "72px", sm: "80px" } }}>
<TextField
size="small"
label="تا سن"
id="outlined-controlled"
value={selectedAge2}
onChange={(event) => {
setSelectedAge2(event.target.value);
}}
/>
</Grid>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
sx={{ maxWidth: { xs: "100%", sm: 250 } }}
value={textValue}
onChange={handleTextChange}
onKeyDown={(e) => {
if (e.key === "Enter") {
handleSubmit(e);
}
}}
/>
<Button type="submit" endIcon={<RiSearchLine />}>
جستجو
</Button>
<Tooltip title="خروجی اکسل" px={0}>
<Button
color="success"
onClick={() => {
openNotif({
vertical: "top",
horizontal: "center",
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
severity: "success",
});
const link = `${
axios.defaults.baseURL
}0/hatching_excel/?unknown=true&role=${getRoleFromUrl()}&key=${userKey}&age1=${
selectedAge1 ? selectedAge1 : 0
}&age2=${
selectedAge2 ? selectedAge2 : 0
}&search=filter&value=${textValue}`;
window.location.href = link;
}}
>
<RiFileExcel2Fill size={32} />
</Button>
</Tooltip>
</Grid>
</form>
<Button onClick={handleRemoveFilter} color="error">
حذف فیلتر
</Button>
</Grid>
);
const { hatchingInfoFull } = useSelector((state) => state.citySlice);
useEffect(() => {
dispatch(
cityGetHatchingInfoFull({
age1: selectedAge1,
age2: selectedAge2,
tab: "unknown",
textValue: textValue,
})
);
}, []);
return (
<Grid alignItems="center" justifyContent="center" mt={2} xs={12}>
<Grid alignItems="center" justifyContent="center" isDashboard xs={12}>
<ResponsiveTable
noPagination
isDashboard
title={
lastUpdateData &&
`آخرین بروزرسانی : ${formatTime(lastUpdateData)} ${" "}`
}
columns={[
"تعداد فارم",
"تعداد جوجه ریزی",
"حجم کل جوجه ریزی",
"حجم باقی مانده در سالن",
"حجم کشتار شده",
"وزن کشتار شده",
"حجم کل تلفات",
"حجم تلفات اتحادیه",
"حجم تلفات دامپزشک",
"مانده سالن ( 20 تا 30 روزه)",
"مانده سالن ( 30 تا 40 روزه)",
"مانده سالن ( 40 تا 50 روزه)",
"مانده سالن ( 50 تا 60 روزه)",
"بیشتر از 60 روزه",
]}
data={[
[
hatchingInfoFull?.poultries?.toLocaleString(),
hatchingInfoFull?.hatchings?.toLocaleString(),
hatchingInfoFull?.totalHatchingQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingLeftOverQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingKilledQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingKilledWeight?.toLocaleString(),
hatchingInfoFull?.totalHatchingAllLosses?.toLocaleString(),
hatchingInfoFull?.totalHatchingUnionLosses?.toLocaleString(),
hatchingInfoFull?.totalHatchingVetLosses?.toLocaleString(),
hatchingInfoFull?.age2030?.toLocaleString(),
hatchingInfoFull?.age3040?.toLocaleString(),
hatchingInfoFull?.age4050?.toLocaleString(),
hatchingInfoFull?.age5060?.toLocaleString(),
hatchingInfoFull?.ageMoreThan60?.toLocaleString(),
],
]}
/>
</Grid>
{tableTitle}
<ResponsiveTable
data={tableData}
columns={[
"عملیات",
"جزئیات",
"ردیف",
"وضعیت",
"شماره مجوز جوجه ریزی",
"شناسه یکتا",
"مجوز بهداشتی جوجه ریزی",
// "نوع تعهد",
"نام فارم",
"مرغدار",
"بهره برداری",
"مالکیت",
"ارتباط",
"شهر/تعاونی",
"دامپزشک فارم",
"سالن",
"دوره جوجه ریزی",
"تاریخ ثبت جوجه ریزی",
"تاریخ جوجه ریزی",
"میانگین سن کشتار",
"پیش بینی تاریخ کشتار",
"نژاد",
"سن",
"حجم جوجه ریزی",
"حجم افزایشی",
"تلفات دامپزشک",
"تلفات اتحادیه",
"تلفات کل",
"حجم تعهد دولتی",
"حجم تعهد آزاد",
"حجم کشتار دولتی",
"وزن کشتار دولتی",
"حجم کشتار آزاد",
"وزن کشتار شده آزاد",
"حجم فروش به خارج استان",
"وزن فروش به خارج استان",
"حجم اختلاف کشتار",
"وزن اختلاف کشتار",
"تخصیصات بدون بار",
"حجم تخصیصات بدون بار",
"وزن تخصیصات بدون بار",
"حجم کشتار شده",
"حجم مانده در سالن",
" درصد مانده در سالن",
" تلفات",
" کشتار شده",
" باقی مانده در سالن",
"تایید تخلیه رصدیار",
" تایید تخلیه در سماصط",
"وزن تعهد دولتی",
"وزن کشتار دولتی",
"وزن کشتار آزاد",
"میانگین وزن کشتار",
"وزن کل کشتار شده",
"تعداد کشتار فعال",
"تعداد درخواست کشتار",
"تعداد بارها",
"حجم بارها",
"وزن بارها",
"حجم بارهای تحویلی",
"وزن بارهای تحویلی",
"حجم زنجیره",
"وزن زنجیره",
"حجم صادرات",
"وزن صادرات",
"بارهای ورودی به انبار",
"حجم لاشه های انبار",
"وزن لاشه های انبار",
"درصد افت بارها",
"آخرین تغییر",
"سازنده جوجه ریزی",
"گزارش",
]}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
title="تعیین تکلیف نشده‌ها"
/>
</Grid>
);
};

View File

@@ -0,0 +1,251 @@
import {
IconButton,
Popover,
List,
ListItemButton,
ListItemIcon,
ListItemText,
Typography,
} from "@mui/material";
import { useContext, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import TuneIcon from "@mui/icons-material/Tune";
import { useDispatch, useSelector } from "react-redux";
import { hatchingUndoArchiveService } from "../../services/hatching-undo-archive";
import { AppContext } from "../../../../contexts/AppContext";
import axios from "axios";
import { RiFileExcel2Fill } from "react-icons/ri";
import { OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
import { CitySubmitHatchingReport } from "../city-submit-hatching-report/CitySubmitHatchingReport";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import InsertPageBreakIcon from "@mui/icons-material/InsertPageBreak";
import { VetFarmSubmitFarmInfoLosses } from "../../../vet-farm/components/vet-farm-submit-farm-info-losses/VetFarmSubmitFarmInfoLosses";
import AddIcon from "@mui/icons-material/Add";
import KeyboardReturnIcon from "@mui/icons-material/KeyboardReturn";
import SmsIcon from "@mui/icons-material/Sms";
import { cityGetTicketDiffrentClearanceCode } from "../../services/city-get-ticket-different-clearance-code";
export const CityHatchingsArchiveOperations = ({
item,
updateArchive,
readOnly,
}) => {
const { userProfile } = useSelector((state) => state.userSlice);
const dispatch = useDispatch();
const [popoverOpen, setPopoverOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);
const [openNotif] = useContext(AppContext);
const role = getRoleFromUrl();
const openPopover = (event) => {
setPopoverOpen(true);
setAnchorEl(event.currentTarget);
};
const closePopover = () => {
setPopoverOpen(false);
setAnchorEl(null);
};
const handleUndoArchive = () => {
closePopover();
dispatch(
hatchingUndoArchiveService({
key: item.key,
type: "return_archive",
})
).then((r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
updateArchive(1);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
};
const handleOpenReportModal = () => {
closePopover();
dispatch(
OPEN_MODAL({
title: "ثبت گزارش",
content: (
<CitySubmitHatchingReport
updateTable={updateArchive}
item={item}
isArchive
/>
),
})
);
};
const handleOpenLossesModal = () => {
closePopover();
dispatch(
OPEN_MODAL({
title: "ثبت تلفات پایان دوره",
content: (
<VetFarmSubmitFarmInfoLosses
item={item}
updateTable={updateArchive}
/>
),
})
);
};
const handleExcelExport = () => {
closePopover();
const url = `${axios.defaults.baseURL}process-for-each-hatching/?key=${item.key}`;
window.open(url, "_blank");
};
const handleCreateTicket = () => {
closePopover();
dispatch(
cityGetTicketDiffrentClearanceCode({
licence_number: item?.licenceNumber,
mobile: userProfile?.mobile,
})
).then((r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
updateArchive(1);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
};
const provinceAndAdminRoles = [
"ProvinceOperator",
"CityOperator",
"AdminX",
"SuperAdmin",
];
const vetRoles = ["VetFarm", "CityVet", "VetSupervisor"];
const options = [
!readOnly && {
key: "undo",
label: "بازگشت جوجه ریزی",
color: "primary.main",
icon: <KeyboardReturnIcon sx={{ fontSize: { xs: 20, md: 18 } }} />,
action: handleUndoArchive,
},
provinceAndAdminRoles.includes(role) && {
key: "report",
label: "ثبت گزارش",
color: "secondary.main",
icon: <AddIcon sx={{ fontSize: { xs: 20, md: 18 } }} />,
action: handleOpenReportModal,
},
vetRoles.includes(role) && {
key: "losses",
label: "ثبت تلفات پایان دوره",
color: "error.main",
icon: <InsertPageBreakIcon sx={{ fontSize: { xs: 20, md: 18 } }} />,
action: handleOpenLossesModal,
},
{
key: "excel",
label: "خروجی اکسل",
color: "success.main",
icon: <RiFileExcel2Fill size={18} style={{ color: "inherit" }} />,
action: handleExcelExport,
},
{
key: "ticket",
label: "تیکت گزارش کشتار جوجه ریزی",
color: "error.main",
icon: <SmsIcon sx={{ fontSize: { xs: 20, md: 18 } }} />,
action: handleCreateTicket,
},
].filter(Boolean);
return (
<Grid>
<IconButton variant="contained" color="primary" onClick={openPopover}>
<TuneIcon />
</IconButton>
<Popover
open={popoverOpen}
anchorEl={anchorEl}
onClose={closePopover}
anchorOrigin={{
vertical: "bottom",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<List sx={{ width: 200, p: 1 }}>
{options.map((option) => (
<ListItemButton
key={option.key}
onClick={() => {
if (option.disabled) {
return;
}
option.action();
}}
disabled={Boolean(option.disabled)}
sx={{
borderRadius: 1,
mb: 0.5,
color: option.disabled ? "text.disabled" : option.color,
"&:last-of-type": {
mb: 0,
},
}}
>
<ListItemIcon
sx={{
color: option.disabled ? "text.disabled" : option.color,
minWidth: 36,
}}
>
{option.icon}
</ListItemIcon>
<ListItemText
primary={
<Typography
sx={{
color: option.disabled ? "text.disabled" : option.color,
fontWeight: 600,
fontSize: { xs: "13px", md: "14px" },
}}
>
{option.label}
</Typography>
}
/>
</ListItemButton>
))}
</List>
</Popover>
</Grid>
);
};

View File

@@ -0,0 +1,585 @@
import React, { useContext, useEffect, useState } from "react";
import {
Button,
Checkbox,
IconButton,
TextField,
Tooltip,
Typography,
} from "@mui/material";
import { DatePicker } from "@mui/x-date-pickers";
import moment from "moment";
import { useDispatch, useSelector } from "react-redux";
import axios from "axios";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import { Grid } from "../../../../components/grid/Grid";
import {
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../../../../lib/redux/slices/appSlice";
import { getFaUserRole } from "../../../../utils/getFaUserRole";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { CityHatchingsArchiveOperations } from "../city-hatchings-archive-operations/CityHatchingsArchiveOperations";
import { cityGetHatchingInfoFull } from "../../services/city-get-hatching-info-full";
import { AppContext } from "../../../../contexts/AppContext";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import ShowImage from "../../../../components/show-image/ShowImage";
import { formatJustDate, formatTime } from "../../../../utils/formatTime";
import { RiFileExcel2Fill } from "react-icons/ri";
import { RiSearchLine } from "react-icons/ri";
import ToggleOffOutlinedIcon from "@mui/icons-material/ToggleOffOutlined";
import ToggleOnIcon from "@mui/icons-material/ToggleOn";
import { useNavigate } from "react-router-dom";
import {
ROUTE_ADMINXـHATCHINGS,
ROUTE_CITY_POULTRYـHATCHINGS,
ROUTE_CITY_VISOR_STATICSـHATCHINGS_DETAILS,
ROUTE_PROVINCE_SUPERVISORـHATCHINGS,
ROUTE_PROVINCEـHATCHINGS,
ROUTE_SUPER_ADMINـHATCHINGS,
ROUTE_SUPPORTERـHATCHINGS,
} from "../../../../routes/routes";
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
export const CityHatchingsArchive = ({ readOnly }) => {
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
useContext(AppContext);
const userKey = useSelector((state) => state.userSlice.userProfile.key);
const { hatchingInfoFull } = useSelector((state) => state.citySlice);
const navigate = useNavigate();
const dispatch = useDispatch();
useEffect(() => {
const currentDate = moment(new Date()).format("YYYY-MM-DD");
setSelectedDate1(currentDate);
setSelectedDate2(currentDate);
}, []);
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const [data, setData] = useState([]);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [textValue, setTextValue] = useState("");
const [page, setPage] = useState(1);
const [tableData, setTableData] = useState([]);
const [withDate, setWithDate] = useState(false);
const fetchApiData = async (page) => {
dispatch(LOADING_START());
const response = await axios.get(
`poultry_hatching/?archive=true&search=filter&value=${textValue}&role=${getRoleFromUrl()}
&key=${userKey}&page=${page}&page_size=${perPage}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}`
);
dispatch(LOADING_END());
setData(response.data.results);
setTotalRows(response.data.count);
};
const handlePageChange = (page) => {
fetchApiData(page);
setPage(page);
};
const handlePerRowsChange = (perRows) => {
setPerPage(perRows);
setPage(1);
};
const updateTable = () => {
fetchApiData(page !== 0 ? page : 1);
};
useEffect(() => {
const d = data?.map((item, i) => {
return [
<CityHatchingsArchiveOperations
key={i}
item={item}
updateArchive={updateTable}
readOnly={readOnly}
/>,
<Tooltip placement="left" title=" جزئیات" key={i}>
<IconButton
color="primary"
onClick={() => {
navigate(
getRoleFromUrl() === "AdminX"
? `${ROUTE_ADMINXـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "Supporter"
? `${ROUTE_SUPPORTERـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "SuperAdmin"
? `${ROUTE_SUPER_ADMINـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "CityPoultry"
? `${ROUTE_CITY_POULTRYـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "ProvinceSupervisor"
? `${ROUTE_PROVINCE_SUPERVISORـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "province"
? `${ROUTE_PROVINCEـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "CityJahad"
? `${ROUTE_CITY_VISOR_STATICSـHATCHINGS_DETAILS}/${item.key}`
: ""
);
}}
>
<RemoveRedEyeIcon />
</IconButton>
</Tooltip>,
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
<Tooltip
disableHoverListener={
!(item?.killingInfo?.violationMessage && item?.violation)
}
key={i}
title={
item?.violation
? `متن گزارش تخلف: ${item?.killingInfo?.violationMessage}`
: null
}
sx={{
"&:hover": {
cursor: item?.violation ? "pointer" : "default",
},
}}
placement="top"
>
<Typography
variant="body2"
color={item?.violation ? "error" : "primary"}
>
{item?.violation ? "متخلف" : "عادی"}
</Typography>
</Tooltip>,
item?.licenceNumber,
item?.poultry?.breedingUniqueId,
item?.CertId || "-",
item?.poultry?.unitName || "-",
`${item?.poultry?.userprofile?.fullName ?? "-"} (${
item?.poultry?.userprofile?.mobile ?? "-"
})`,
item?.InteractTypeName,
item?.PersonTypeName,
item?.UnionTypeName,
`${item?.poultry?.address?.city?.name ?? "-"}/${
item?.poultry?.cityOperator
? item?.poultry?.cityOperator
: "بدون تعاونی"
}`,
item?.vetFarm?.vetFarmMobile
? `${item?.vetFarm?.vetFarmFullName} (${item?.vetFarm?.vetFarmMobile})`
: "-",
item?.hall || "-",
item?.period || "-",
formatTime(item?.createDate),
formatTime(item?.date),
item?.poultry?.killingAveAge?.toLocaleString(),
item?.predicateDate ? formatJustDate(item?.predicateDate) : "-",
item.chickenBreed || "-",
item?.age || "-",
item?.archiveDate ? formatTime(item?.archiveDate) : "-",
item.nowAge || "-",
item?.quantity?.toLocaleString(),
item?.increaseQuantity?.toLocaleString() || "-",
`${item.losses} (%${((item.losses * 100) / item.quantity).toFixed(0)})`,
`${item?.directLosses?.toLocaleString()} (%${(
(item.directLosses * 100) /
item.quantity
).toFixed(0)})`,
`${item?.totalLosses?.toLocaleString()} (%${(
(item.totalLosses * 100) /
item.quantity
).toFixed(0)})`,
`${item?.totalCommitmentQuantity?.toLocaleString()}`,
`${item?.totalFreeCommitmentQuantity?.toLocaleString()}`,
`${item?.governmentalQuantity?.toLocaleString()}`,
`${item?.governmentalKilledQuantity?.toLocaleString()}`,
`${item?.freeQuantity?.toLocaleString()}`,
`${item?.freeKilledQuantity?.toLocaleString()}`,
`${item?.outProvinceKilledQuantity?.toLocaleString()}`,
`${item?.outProvinceKilledWeight?.toLocaleString()}`,
`${item?.barDifferenceRequestQuantity?.toLocaleString()}`,
`${item?.barDifferenceRequestWeight?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequests?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequestsQuantity?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequestsWeight?.toLocaleString()}`,
item?.killedQuantity?.toLocaleString() +
` (%${((item?.killedQuantity * 100) / item.quantity).toFixed(0)})`,
`${item?.leftOver?.toLocaleString()} (%${(
(item.leftOver * 100) /
item.quantity
).toFixed(0)})`,
`${item?.quantity?.toLocaleString()}`,
// item?.totalCommitment?.toLocaleString(),
`%${((item.totalLosses * 100) / item.quantity).toFixed(0)}`,
`%${((item?.killedQuantity * 100) / item.quantity).toFixed(0)}`,
`%${(
((item?.killedQuantity + item?.totalLosses) * 100) /
item?.quantity
).toFixed(0)}`,
item?.samasatDischargePercentage
? `%${item?.samasatDischargePercentage}`
: "-",
item?.totalCommitment?.toLocaleString(),
item?.governmentalKilledQuantity?.toLocaleString(),
item?.freeKilledQuantity?.toLocaleString(),
item?.totalAverageKilledWeight?.toLocaleString(),
item?.totalKilledWeight?.toLocaleString(),
item?.activeKill?.activeKill ? "دارد" : "ندارد",
item?.activeKill?.countOfRequest ? item.activeKill.countOfRequest : "-",
item?.killingInfo?.killHouseRequests?.toLocaleString(),
item?.killingInfo?.killHouseRequestsFirstQuantity?.toLocaleString(),
item?.killingInfo?.killHouseRequestsFirstWeight?.toLocaleString(),
item?.killingInfo?.barCompleteWithKillHouse?.toLocaleString(),
item?.killingInfo?.acceptedRealWightFinal?.toLocaleString(),
item?.chainKilledQuantity?.toLocaleString(),
item?.chainKilledWeight?.toLocaleString(),
item?.exportKilledQuantity?.toLocaleString(),
item?.exportKilledWeight?.toLocaleString(),
item?.killingInfo?.wareHouseBars?.toLocaleString(),
item?.killingInfo?.wareHouseBarsQuantity?.toLocaleString(),
item?.killingInfo?.wareHouseBarsWeight?.toLocaleString(),
item?.killingInfo?.wareHouseBarsWeightLose?.toFixed(2),
item.lastChange
? `${item.lastChange.fullName} (${getFaUserRole(
item.lastChange.role
)}) در تاریخ ${formatTime(item.lastChange.date)}`
: "-",
item.latestHatchingChange
? `${item.latestHatchingChange.fullName} (${getFaUserRole(
item.latestHatchingChange.role
)}) در تاریخ ${formatTime(item.latestHatchingChange.date)}`
: "-",
item?.violationReport ? (
<Button
key={i}
onClick={() => {
dispatch(
OPEN_MODAL({
title: "گزارش ",
content: (
<SimpleTable
columns={[
"ثبت کننده",
"تاریخ ثبت",
"تخلف",
"متن گزارش",
"سند",
]}
data={[
[
item?.violationReporter,
formatJustDate(item?.violationReportDate),
item?.violation ? "دارد" : "ندارد",
item?.violationReport,
<ShowImage key={i} src={item?.violationImage} />,
],
]}
/>
),
})
);
}}
>
نمایش
</Button>
) : (
"بدون گزارش"
),
];
});
setTableData(d);
}, [data]);
useEffect(() => {
fetchApiData(1);
}, [selectedDate1, selectedDate2, perPage, withDate]);
useEffect(() => {
dispatch(
cityGetHatchingInfoFull(
withDate
? {
tab: "archive",
date1: selectedDate1,
date2: selectedDate2,
textValue: textValue,
}
: { tab: "archive", textValue: textValue }
)
);
}, [dispatch, withDate, selectedDate1, selectedDate2]);
const handleSubmit = async (event) => {
event.preventDefault();
dispatch(LOADING_START());
try {
const response = await axios.get(
`poultry_hatching/?archive=true&search=filter&value=${textValue}&role=${getRoleFromUrl()}&key=${userKey}&page=${1}&page_size=${perPage}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}`
);
dispatch(
cityGetHatchingInfoFull(
withDate
? {
tab: "archive",
date1: selectedDate1,
date2: selectedDate2,
textValue: textValue,
}
: { tab: "archive", textValue: textValue }
)
);
setData(response.data.results);
setTotalRows(response.data.count);
dispatch(LOADING_END());
} catch (error) {
console.error("Error fetching data:", error);
}
};
return (
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
<Grid alignItems="center" justifyContent="center" isDashboard xs={12}>
<ResponsiveTable
noPagination
isDashboard
title={null}
columns={[
"تعداد فارم",
"تعداد جوجه ریزی",
"حجم کل جوجه ریزی",
"حجم باقی مانده در سالن",
"حجم کشتار شده",
"وزن کشتار شده",
"حجم کل تلفات",
"حجم تلفات اتحادیه",
"حجم تلفات دامپزشک",
"مانده سالن ( 20 تا 30 روزه)",
"مانده سالن ( 30 تا 40 روزه)",
"مانده سالن ( 40 تا 50 روزه)",
"مانده سالن ( 50 تا 60 روزه)",
"بیشتر از 60 روزه",
]}
data={[
[
hatchingInfoFull?.poultries?.toLocaleString(),
hatchingInfoFull?.hatchings?.toLocaleString(),
hatchingInfoFull?.totalHatchingQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingLeftOverQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingKilledQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingKilledWeight?.toLocaleString(),
hatchingInfoFull?.totalHatchingAllLosses?.toLocaleString(),
hatchingInfoFull?.totalHatchingUnionLosses?.toLocaleString(),
hatchingInfoFull?.totalHatchingVetLosses?.toLocaleString(),
hatchingInfoFull?.age2030?.toLocaleString(),
hatchingInfoFull?.age3040?.toLocaleString(),
hatchingInfoFull?.age4050?.toLocaleString(),
hatchingInfoFull?.age5060?.toLocaleString(),
hatchingInfoFull?.ageMoreThan60?.toLocaleString(),
],
]}
/>
</Grid>
<Grid
container
xs={12}
justifyContent="start"
alignItems="center"
gap={2}
>
<Grid
container
gap={1}
style={{
borderStyle: "solid",
borderWidth: "1px",
padding: "5px",
borderRadius: "15px",
borderColor: "gray",
justifyContent: "left",
}}
alignItems="center"
>
<Checkbox
icon={<ToggleOffOutlinedIcon />}
checkedIcon={<ToggleOnIcon />}
checked={withDate}
onChange={() => setWithDate(!withDate)}
color="primary"
size="large"
/>
<Grid>
<DatePicker
disabled={!withDate}
label="از تاریخ"
id="date"
renderInput={(params) => (
<TextField
size="small"
style={{ width: "160px" }}
{...params}
/>
)}
value={selectedDate1}
onChange={(e) => {
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<DatePicker
disabled={!withDate}
label="تا تاریخ"
id="date"
renderInput={(params) => (
<TextField
size="small"
style={{ width: "160px" }}
{...params}
/>
)}
value={selectedDate2}
onChange={(e) => {
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
</Grid>
<Grid>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button
// disabled={!textValue}
type="submit"
onClick={handleSubmit}
endIcon={<RiSearchLine />}
>
جستجو
</Button>
</form>
</Grid>
<Tooltip title="خروجی اکسل">
<a
href={`${
axios.defaults.baseURL
}archive_hatching_excel/?search=filter&value=${textValue}&role=${getRoleFromUrl()}&key=${userKey}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}`}
rel="noreferrer"
>
<Button color="success">
<RiFileExcel2Fill size={32} />
</Button>
</a>
</Tooltip>
</Grid>
<ResponsiveTable
data={tableData}
columns={[
"عملیات",
"جزئیات",
"ردیف",
"وضعیت",
"شماره مجوز جوجه ریزی",
"شناسه یکتا",
"مجوز بهداشتی جوجه ریزی",
"نام فارم",
"مرغدار",
"بهره برداری",
"مالکیت",
"ارتباط",
"شهر/تعاونی",
"دامپزشک فارم",
"سالن",
"دوره جوجه ریزی",
"تاریخ ثبت جوجه ریزی",
"تاریخ جوجه ریزی",
"میانگین سن کشتار",
"پیش بینی تاریخ کشتار",
"نژاد",
"سن ورود به بایگانی",
"تاریخ ورود به بایگانی",
"سن فعلی",
"حجم جوجه ریزی",
"حجم افزایشی",
"تلفات دامپزشک",
"تلفات اتحادیه",
"تلفات کل",
"حجم تعهد دولتی",
"حجم تعهد آزاد",
"حجم کشتار دولتی",
"وزن کشتار دولتی",
"حجم کشتار آزاد",
"وزن کشتار شده آزاد",
"حجم فروش به خارج استان",
"وزن فروش به خارج استان",
"حجم اختلاف کشتار",
"وزن اختلاف کشتار",
"تخصیصات بدون بار",
"حجم تخصیصات بدون بار",
"وزن تخصیصات بدون بار",
"حجم کشتار شده",
" حجم مانده در سالن",
" درصد مانده در سالن",
" تلفات",
" کشتار شده",
"تایید تخلیه رصدیار",
" تایید تخلیه در سماصط",
"وزن تعهد دولتی",
"وزن کشتار دولتی",
"وزن کشتار آزاد",
"میانگین وزن کشتار",
"وزن کل کشتار شده",
"تعداد کشتار فعال",
"تعداد درخواست کشتار",
"تعداد بارها",
"حجم بارها",
"وزن بارها",
"حجم بارهای تحویلی",
"وزن بارهای تحویلی",
"حجم زنجیره",
"وزن زنجیره",
"حجم صادرات",
"وزن صادرات",
"بارهای ورودی به انبار",
"حجم لاشه های انبار",
"وزن لاشه های انبار",
"درصد افت بارها",
"آخرین تغییر",
"سازنده جوجه ریزی",
"گزارش",
]}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
title="بایگانی جوجه ریزی"
/>
</Grid>
);
};

View File

@@ -0,0 +1,672 @@
import {
Button,
IconButton,
TextField,
Tooltip,
Typography,
} from "@mui/material";
import axios from "axios";
import { useContext, useEffect, useState } from "react";
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { formatTime, formatJustDate } from "../../../../utils/formatTime";
import { getFaUserRole } from "../../../../utils/getFaUserRole";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { CityManageHatchingsOperations } from "../city-manage-hatchings-operations/CityManageHatchingsOperations";
import { useDispatch, useSelector } from "react-redux";
import { AppContext } from "../../../../contexts/AppContext";
import { cityGetHatchingInfoFull } from "../../services/city-get-hatching-info-full";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import {
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../../../../lib/redux/slices/appSlice";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import ShowImage from "../../../../components/show-image/ShowImage";
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
import ArticleIcon from "@mui/icons-material/Article";
import {
ROUTE_ADMINXـHATCHINGS,
ROUTE_CITY_JIHADـHATCHINGS,
ROUTE_CITY_POULTRYـHATCHINGS,
ROUTE_PROVINCE_SUPERVISORـHATCHINGS,
ROUTE_PROVINCEـHATCHINGS,
ROUTE_SUPER_ADMINـHATCHINGS,
ROUTE_SUPPORTERـHATCHINGS,
} from "../../../../routes/routes";
import { useNavigate } from "react-router-dom";
export const CityHatchingsTotal = ({ readOnly }) => {
const dispatch = useDispatch();
const isReadOnly = readOnly || false;
const [selectedAge1, setSelectedAge1] = useState(0);
const [selectedAge2, setSelectedAge2] = useState(0);
const [data, setData] = useState([]);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [textValue, setTextValue] = useState("");
const [page, setPage] = useState(1);
const [tableData, setTableData] = useState([]);
const userKey = useSelector((state) => state.userSlice.userProfile.key);
const navigate = useNavigate();
const [openNotif] = useContext(AppContext);
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const hatchingAdded = useSelector((state) => state.citySlice.hatchingAdded);
useEffect(() => {
fetchApiData(1);
}, [hatchingAdded]);
const fetchApiData = async (page) => {
dispatch(LOADING_START());
const response = await axios.get(
`poultry_hatching?search=filter&value=${textValue}&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&age1=${
selectedAge1 ? selectedAge1 : 0
}&age2=${selectedAge2 ? selectedAge2 : 0}&all_active_and_archive`
);
dispatch(LOADING_END());
setData(response.data.results);
setTotalRows(response.data.count);
};
const handlePageChange = (page) => {
fetchApiData(page);
setPage(page);
};
const handlePerRowsChange = (perRows) => {
setPerPage(perRows);
setPage(1);
};
useEffect(() => {
fetchApiData(1);
}, [dispatch, perPage]);
const updateTable = () => {
fetchApiData(page !== 0 ? page : 1);
};
useEffect(() => {
const d = data?.map((item, i) => {
return [
<CityManageHatchingsOperations
selectedAge1={null}
selectedAge2={null}
updateTable={updateTable}
item={item}
key={"4"}
readOnly={isReadOnly}
/>,
<Tooltip placement="left" title="جزئیات جوجه ریزی" key={i}>
<IconButton
color="primary"
onClick={() => {
navigate(
getRoleFromUrl() === "AdminX"
? `${ROUTE_ADMINXـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "Supporter"
? `${ROUTE_SUPPORTERـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "SuperAdmin"
? `${ROUTE_SUPER_ADMINـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "CityPoultry"
? `${ROUTE_CITY_POULTRYـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "ProvinceSupervisor"
? `${ROUTE_PROVINCE_SUPERVISORـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "ProvinceOperator"
? `${ROUTE_PROVINCEـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "CityJahad"
? `${ROUTE_CITY_JIHADـHATCHINGS}/${item.key}`
: ""
);
}}
>
<RemoveRedEyeIcon />
</IconButton>
</Tooltip>,
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
<Tooltip
disableHoverListener={
!(item?.killingInfo?.violationMessage && item?.violation)
}
key={i}
title={
item?.violation
? `متن گزارش تخلف: ${item?.killingInfo?.violationMessage}`
: null
}
sx={{
"&:hover": {
cursor: item?.violation ? "pointer" : "default",
},
}}
placement="top"
>
<Typography
variant="body2"
color={item?.violation ? "error" : "primary"}
>
{item?.violation ? "پیگیری" : "عادی"}
</Typography>
</Tooltip>,
item?.licenceNumber,
item?.poultry?.breedingUniqueId,
item?.CertId,
item?.poultry?.unitName || "-",
`${item?.poultry?.userprofile?.fullName ?? "-"} (${
item?.poultry?.userprofile?.mobile ?? "-"
}) ${item?.violationReport ? "✉️" : ""}`,
item?.InteractTypeName ? (
<Typography
variant="body2"
color={item?.hasTenant ? "success.main" : ""}
fontWeight={item?.hasTenant ? "bold" : "normal"}
>
{item?.InteractTypeName}
</Typography>
) : (
"-"
),
item?.PersonTypeName,
item?.UnionTypeName,
`${item?.poultry?.address?.city?.name ?? "-"}/${
item?.poultry?.cityOperator
? item?.poultry?.cityOperator
: "بدون تعاونی"
}`,
item?.vetFarm?.vetFarmMobile
? `${item?.vetFarm?.vetFarmFullName} (${item?.vetFarm?.vetFarmMobile})`
: "-",
item.hall,
item.period,
formatTime(item?.createDate),
formatTime(item?.date),
item?.poultry?.killingAveAge?.toLocaleString(),
item?.predicateDate ? formatJustDate(item?.predicateDate) : "-",
item.chickenBreed,
item.age,
item?.quantity?.toLocaleString(),
item?.increaseQuantity?.toLocaleString(),
`${item.losses} (%${((item.losses * 100) / item.quantity).toFixed(0)})`,
<Tooltip
key={i}
placement="top"
title="جهت مشاهده ثبت کننده تلفات کلیک کنید"
>
<Button
style={{ color: "rgba(0,0,0,0.87)" }}
onClick={() => {
dispatch(
OPEN_MODAL({
title: "ویرایش تعداد جوجه ریزی",
content: (
<Grid container xs={12}>
{!item?.directLossesInputer &&
!item?.directLossesInputer ? (
<Typography variant="body1">
برای این جوجه ریزی تلفاتی ثبت نشده است.
</Typography>
) : (
<Grid xs={12}>
<Typography variant="body1">
ثبت کننده تلفات اتحادیه:{" "}
{item?.directLossesInputer
? `${
item?.directLossesInputer
} در تاریخ ${formatJustDate(
item?.directLossesDate
)}`
: " - "}
</Typography>
<Typography variant="body1">
ویرایش کننده تلفات اتحادیه:
{item?.directLossesEditor
? `${
item?.directLossesEditor
} در تاریخ ${formatJustDate(
item?.directLossesLastEditDate
)}`
: " - "}
</Typography>
</Grid>
)}
</Grid>
),
})
);
}}
>
{`${item?.directLosses?.toLocaleString()} (%${(
(item.directLosses * 100) /
item.quantity
).toFixed(0)})`}
</Button>
</Tooltip>,
`${item?.totalLosses?.toLocaleString()} (%${(
(item.totalLosses * 100) /
item.quantity
).toFixed(0)})`,
`${item?.totalCommitmentQuantity?.toLocaleString()}`,
`${item?.totalFreeCommitmentQuantity?.toLocaleString()}`,
`${item?.governmentalQuantity?.toLocaleString()}`,
`${item?.governmentalKilledQuantity?.toLocaleString()}`,
`${item?.freeQuantity?.toLocaleString()}`,
`${item?.freeKilledQuantity?.toLocaleString()}`,
`${item?.outProvinceKilledQuantity?.toLocaleString()}`,
`${item?.outProvinceKilledWeight?.toLocaleString()}`,
`${item?.barDifferenceRequestQuantity?.toLocaleString()}`,
`${item?.barDifferenceRequestWeight?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequests?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequestsQuantity?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequestsWeight?.toLocaleString()}`,
item?.killedQuantity?.toLocaleString() +
` (%${((item?.killedQuantity * 100) / item.quantity).toFixed(0)})`,
item?.leftOver?.toLocaleString(),
`%${((item?.leftOver * 100) / item?.quantity).toFixed(0)}`,
`%${((item.totalLosses * 100) / item.quantity).toFixed(0)}`,
`%${((item?.killedQuantity * 100) / item.quantity).toFixed(0)}`,
`%${((item?.leftOver * 100) / item?.quantity).toFixed(0)}`,
`%${(
((item?.killedQuantity + item?.totalLosses) * 100) /
item?.quantity
).toFixed(0)}`,
item?.samasatDischargePercentage
? `%${item?.samasatDischargePercentage}`
: "-",
item?.totalCommitment?.toLocaleString(),
item?.governmentalKilledQuantity?.toLocaleString(),
item?.freeKilledQuantity?.toLocaleString(),
item?.totalAverageKilledWeight?.toLocaleString(),
item?.totalKilledWeight?.toLocaleString(),
item?.activeKill?.activeKill ? "دارد" : "ندارد",
item?.activeKill?.countOfRequest ? item.activeKill.countOfRequest : "-",
item?.killingInfo?.killHouseRequests?.toLocaleString(),
item?.killingInfo?.killHouseRequestsFirstQuantity?.toLocaleString(),
item?.killingInfo?.killHouseRequestsFirstWeight?.toLocaleString(),
item?.killingInfo?.barCompleteWithKillHouse?.toLocaleString(),
item?.killingInfo?.acceptedRealWightFinal?.toLocaleString(),
item?.chainKilledQuantity?.toLocaleString(),
item?.chainKilledWeight?.toLocaleString(),
item?.exportKilledQuantity?.toLocaleString(),
item?.exportKilledWeight?.toLocaleString(),
item?.killingInfo?.wareHouseBars?.toLocaleString(),
item?.killingInfo?.wareHouseBarsQuantity?.toLocaleString(),
item?.killingInfo?.wareHouseBarsWeight?.toLocaleString(),
item?.killingInfo?.wareHouseBarsWeightLose?.toFixed(2),
item.lastChange
? `${item.lastChange.fullName} (${getFaUserRole(
item.lastChange.role
)}) در تاریخ ${formatTime(item.lastChange.date)}`
: "-",
item.latestHatchingChange
? `${item.latestHatchingChange.fullName} (${getFaUserRole(
item.latestHatchingChange.role
)}) در تاریخ ${formatTime(item.latestHatchingChange.date)}`
: "-",
item?.violationReport ? (
<Tooltip title="مشاهده گزارش" placement="top" key={i}>
<IconButton
color="primary"
onClick={() => {
dispatch(
OPEN_MODAL({
title: "گزارش ",
content: (
<SimpleTable
columns={[
"ثبت کننده",
"تاریخ ثبت",
"تخلف",
"متن گزارش",
"سند",
]}
data={[
[
item?.violationReporter,
formatJustDate(item?.violationReportDate),
item?.violation ? "دارد" : "ندارد",
item?.violationReport,
<Grid
key={i}
container
xs={12}
justifyContent="center"
gap={1}
>
{item?.violationImage?.map((option, index) => (
<ShowImage
key={`${option}-${index}`}
src={option}
/>
))}
</Grid>,
],
]}
/>
),
})
);
}}
>
<ArticleIcon />
</IconButton>
</Tooltip>
) : (
"-"
),
];
});
setTableData(d);
}, [data]);
const handleSubmit = async (event) => {
event.preventDefault();
dispatch(LOADING_START());
dispatch(
cityGetHatchingInfoFull({
age1: selectedAge1,
age2: selectedAge2,
tab: "all",
textValue: textValue,
})
);
try {
const response = await axios.get(
`poultry_hatching/?role=${getRoleFromUrl()}&age1=${
selectedAge1 ? selectedAge1 : 0
}&age2=${
selectedAge2 ? selectedAge2 : 0
}&search=filter&value=${textValue}&page=${1}&page_size=${perPage}&all_active_and_archive`
);
setData(response.data.results);
setTotalRows(response.data.count);
dispatch(LOADING_END());
} catch (error) {
console.error("Error fetching data:", error);
}
};
const handleRemoveFilter = async (event) => {
event.preventDefault();
setSelectedAge1(0);
setSelectedAge2(0);
dispatch(LOADING_START());
setTextValue("");
dispatch(
cityGetHatchingInfoFull({
age1: 0,
age2: 0,
tab: "all",
textValue: textValue,
})
);
try {
const response = await axios.get(
`poultry_hatching?role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&all_active_and_archive&search=filter&value=${textValue}`
);
setData(response.data.results);
setTotalRows(response.data.count);
} catch (error) {
console.error("Error fetching data:", error);
} finally {
dispatch(LOADING_END());
}
};
const [lastUpdateData, setLastUpdateData] = useState();
useEffect(() => {
async function fetchData() {
try {
const response = await axios.get(`last_update/?type=poultry_hatching`);
setLastUpdateData(response.data);
} catch (error) {
console.error("Error fetching data:", error);
}
}
fetchData();
}, []);
const tableTitle = (
<Grid
container
alignItems="center"
justifyContent="space-between"
gap={2}
paddingTop={2}
mb={1}
mt={2}
xs={12}
>
<form onSubmit={handleSubmit} style={{ flex: 1 }}>
<Grid container alignItems="center" gap={SPACING.SMALL} xs={12}>
<Grid sx={{ width: { xs: "72px", sm: "80px" } }}>
<TextField
fullWidth
size="small"
label="از سن"
id="outlined-controlled"
value={selectedAge1}
onChange={(event) => {
setSelectedAge1(event.target.value);
}}
/>
</Grid>
<Grid sx={{ width: { xs: "72px", sm: "80px" } }}>
<TextField
fullWidth
size="small"
label="تا سن"
id="outlined-controlled"
value={selectedAge2}
onChange={(event) => {
setSelectedAge2(event.target.value);
}}
/>
</Grid>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
value={textValue}
sx={{ maxWidth: { xs: "100%", sm: 250 } }}
onChange={handleTextChange}
onKeyDown={(e) => {
if (e.key === "Enter") {
handleSubmit(e);
}
}}
/>
<Button type="submit" endIcon={<RiSearchLine />}>
جستجو
</Button>
<Tooltip title="خروجی اکسل" px={0}>
<Button
color="success"
onClick={() => {
openNotif({
vertical: "top",
horizontal: "center",
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
severity: "success",
});
const link = `${
axios.defaults.baseURL
}0/hatching_excel/?role=${getRoleFromUrl()}&key=${userKey}&age1=${
selectedAge1 ? selectedAge1 : 0
}&age2=${
selectedAge2 ? selectedAge2 : 0
}&search=filter&value=${textValue}&all_active_and_archive`;
window.location.href = link;
}}
>
<RiFileExcel2Fill size={32} />
</Button>
</Tooltip>
</Grid>
</form>
<Button onClick={handleRemoveFilter} color="error">
حذف فیلتر
</Button>
</Grid>
);
const { hatchingInfoFull } = useSelector((state) => state.citySlice);
useEffect(() => {
dispatch(
cityGetHatchingInfoFull({
age1: selectedAge1,
age2: selectedAge2,
tab: "all",
textValue: textValue,
})
);
}, []);
return (
<Grid alignItems="center" justifyContent="center" mt={2}>
<Grid alignItems="center" justifyContent="center" isDashboard xs={12}>
<ResponsiveTable
noPagination
isDashboard
title={
lastUpdateData &&
`آخرین بروزرسانی : ${formatTime(lastUpdateData)} ${" "}`
}
columns={[
"تعداد فارم",
"تعداد جوجه ریزی",
"حجم کل جوجه ریزی",
"حجم باقی مانده در سالن",
"حجم کشتار شده",
"وزن کشتار شده",
"حجم کل تلفات",
"حجم تلفات اتحادیه",
"حجم تلفات دامپزشک",
"مانده سالن ( 20 تا 30 روزه)",
"مانده سالن ( 30 تا 40 روزه)",
"مانده سالن ( 40 تا 50 روزه)",
"مانده سالن ( 50 تا 60 روزه)",
"بیشتر از 60 روزه",
]}
data={[
[
hatchingInfoFull?.poultries?.toLocaleString(),
hatchingInfoFull?.hatchings?.toLocaleString(),
hatchingInfoFull?.totalHatchingQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingLeftOverQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingKilledQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingKilledWeight?.toLocaleString(),
hatchingInfoFull?.totalHatchingAllLosses?.toLocaleString(),
hatchingInfoFull?.totalHatchingUnionLosses?.toLocaleString(),
hatchingInfoFull?.totalHatchingVetLosses?.toLocaleString(),
hatchingInfoFull?.age2030?.toLocaleString(),
hatchingInfoFull?.age3040?.toLocaleString(),
hatchingInfoFull?.age4050?.toLocaleString(),
hatchingInfoFull?.age5060?.toLocaleString(),
hatchingInfoFull?.ageMoreThan60?.toLocaleString(),
],
]}
/>
</Grid>
{tableTitle}
<ResponsiveTable
data={tableData}
columns={[
"عملیات",
"جزئیات",
"ردیف",
"وضعیت",
"شماره مجوز جوجه ریزی",
"شناسه یکتا",
"مجوز بهداشتی جوجه ریزی",
"نام فارم",
"مرغدار",
"بهره برداری",
"مالکیت",
"ارتباط",
"شهر/تعاونی",
"دامپزشک فارم",
"سالن",
"دوره جوجه ریزی",
"تاریخ ثبت جوجه ریزی",
"تاریخ جوجه ریزی",
"میانگین سن کشتار",
"پیش بینی تاریخ کشتار",
"نژاد",
"سن",
"حجم جوجه ریزی",
"حجم افزایشی",
"تلفات دامپزشک",
"تلفات اتحادیه",
"تلفات کل",
"حجم تعهد دولتی",
"حجم تعهد آزاد",
"حجم کشتار دولتی",
"وزن کشتار دولتی",
"حجم کشتار آزاد",
"وزن کشتار شده آزاد",
"حجم فروش به خارج استان",
"وزن فروش به خارج استان",
"حجم اختلاف کشتار",
"وزن اختلاف کشتار",
"تخصیصات بدون بار",
"حجم تخصیصات بدون بار",
"وزن تخصیصات بدون بار",
"حجم کشتار شده",
"حجم مانده در سالن",
" درصد مانده در سالن",
" تلفات",
" کشتار شده",
" باقی مانده در سالن",
"تایید تخلیه رصدیار",
" تایید تخلیه در سماصط",
"وزن تعهد دولتی",
"وزن کشتار دولتی",
"وزن کشتار آزاد",
"میانگین وزن کشتار",
"وزن کل کشتار شده",
"تعداد کشتار فعال",
"تعداد درخواست کشتار",
"تعداد بارها",
"حجم بارها",
"وزن بارها",
"حجم بارهای تحویلی",
"وزن بارهای تحویلی",
"حجم زنجیره",
"وزن زنجیره",
"حجم صادرات",
"وزن صادرات",
"بارهای ورودی به انبار",
"حجم لاشه های انبار",
"وزن لاشه های انبار",
"درصد افت بارها",
"آخرین تغییر",
"سازنده جوجه ریزی",
"گزارش",
]}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
title="کل جوجه ریزی ها (فعال و بایگانی شده)"
/>
</Grid>
);
};

View File

@@ -0,0 +1,681 @@
import {
Button,
IconButton,
TextField,
Tooltip,
Typography,
} from "@mui/material";
import axios from "axios";
import { useContext, useEffect, useState } from "react";
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { formatTime, formatJustDate } from "../../../../utils/formatTime";
import { getFaUserRole } from "../../../../utils/getFaUserRole";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { CityManageHatchingsOperations } from "../city-manage-hatchings-operations/CityManageHatchingsOperations";
import { useDispatch, useSelector } from "react-redux";
import { AppContext } from "../../../../contexts/AppContext";
import { cityGetHatchingInfoFull } from "../../services/city-get-hatching-info-full";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import {
// DRAWER,
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../../../../lib/redux/slices/appSlice";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import ShowImage from "../../../../components/show-image/ShowImage";
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
import {
ROUTE_ADMINXـHATCHINGS,
ROUTE_CITY_JIHADـHATCHINGS,
ROUTE_CITY_POULTRYـHATCHINGS,
ROUTE_PROVINCE_SUPERVISORـHATCHINGS,
ROUTE_PROVINCEـHATCHINGS,
ROUTE_SUPER_ADMINـHATCHINGS,
ROUTE_SUPPORTERـHATCHINGS,
} from "../../../../routes/routes";
import { useNavigate } from "react-router-dom";
// import { CityHatchingShowTableDetail } from "../city-hatching-show-table-detail/CityHatchingShowTableDetail";
export const CityHatchings = ({ readOnly }) => {
const dispatch = useDispatch();
const isReadOnly = readOnly || false;
const [selectedAge1, setSelectedAge1] = useState(0);
const [selectedAge2, setSelectedAge2] = useState(0);
const [data, setData] = useState([]);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [textValue, setTextValue] = useState("");
const [page, setPage] = useState(1);
const [tableData, setTableData] = useState([]);
const userKey = useSelector((state) => state.userSlice.userProfile.key);
const navigate = useNavigate();
const [openNotif] = useContext(AppContext);
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const hatchingAdded = useSelector((state) => state.citySlice.hatchingAdded);
useEffect(() => {
fetchApiData(1);
}, [hatchingAdded]);
const fetchApiData = async (page) => {
dispatch(LOADING_START());
const response = await axios.get(
`poultry_hatching?search=filter&value=${textValue}&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&age1=${
selectedAge1 ? selectedAge1 : 0
}&age2=${
selectedAge2 ? selectedAge2 : 0
}&search=filter&value=${textValue}`
);
dispatch(LOADING_END());
setData(response.data.results);
setTotalRows(response.data.count);
};
const handlePageChange = (page) => {
fetchApiData(page);
setPage(page);
};
const handlePerRowsChange = (perRows) => {
setPerPage(perRows);
setPage(1);
};
useEffect(() => {
fetchApiData(1);
}, [dispatch, perPage]);
const updateTable = () => {
fetchApiData(page !== 0 ? page : 1);
};
// const killedNumber = (item) => {
// let killedNumber = "";
// killedNumber = item.quantity - item.losses - item.leftOver;
// return killedNumber;
// };
useEffect(() => {
const d = data?.map((item, i) => {
return [
<CityManageHatchingsOperations
selectedAge1={null}
selectedAge2={null}
updateTable={updateTable}
item={item}
key={"4"}
readOnly={isReadOnly}
/>,
<Tooltip placement="left" title="جزئیات جوجه ریزی" key={item?.key}>
<IconButton
color="primary"
onClick={() => {
navigate(
getRoleFromUrl() === "AdminX"
? `${ROUTE_ADMINXـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "Supporter"
? `${ROUTE_SUPPORTERـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "SuperAdmin"
? `${ROUTE_SUPER_ADMINـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "CityPoultry"
? `${ROUTE_CITY_POULTRYـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "ProvinceSupervisor"
? `${ROUTE_PROVINCE_SUPERVISORـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "ProvinceOperator"
? `${ROUTE_PROVINCEـHATCHINGS}/${item.key}`
: getRoleFromUrl() === "CityJahad"
? `${ROUTE_CITY_JIHADـHATCHINGS}/${item.key}`
: ""
);
}}
>
<RemoveRedEyeIcon />
</IconButton>
</Tooltip>,
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
<Tooltip
disableHoverListener={
!(item?.killingInfo?.violationMessage && item?.violation)
}
key={item?.key}
title={
item?.violation
? `متن گزارش تخلف: ${item?.killingInfo?.violationMessage}`
: null
}
sx={{
"&:hover": {
cursor: item?.violation ? "pointer" : "default",
},
}}
placement="top"
>
<Typography
variant="body2"
color={item?.violation ? "error" : "primary"}
>
{item?.violation ? "پیگیری" : "عادی"}
</Typography>
</Tooltip>,
item?.licenceNumber,
item?.poultry?.breedingUniqueId,
item?.CertId,
// item?.commitmentType === "free" ? "آزاد" : "دولتی",
item?.poultry?.unitName || "-",
`${item?.poultry?.userprofile?.fullName ?? "-"} (${
item?.poultry?.userprofile?.mobile ?? "-"
}) ${item?.violationReport ? "✉️" : ""}`,
item?.InteractTypeName ? (
<Typography
variant="body2"
color={item?.hasTenant ? "success.main" : ""}
fontWeight={item?.hasTenant ? "bold" : "normal"}
>
{item?.InteractTypeName}
</Typography>
) : (
"-"
),
item?.PersonTypeName,
item?.UnionTypeName,
`${item?.poultry?.address?.city?.name ?? "-"}/${
item?.poultry?.cityOperator
? item?.poultry?.cityOperator
: "بدون تعاونی"
}`,
item?.vetFarm?.vetFarmMobile
? `${item?.vetFarm?.vetFarmFullName} (${item?.vetFarm?.vetFarmMobile})`
: "-",
item.hall,
item.period,
formatTime(item?.createDate),
formatTime(item?.date),
item?.poultry?.killingAveAge?.toLocaleString(),
item?.predicateDate ? formatJustDate(item?.predicateDate) : "-",
item.chickenBreed,
item.age,
item?.quantity?.toLocaleString(),
item?.increaseQuantity?.toLocaleString(),
`${item.losses} (%${((item.losses * 100) / item.quantity).toFixed(0)})`,
<Tooltip
key={item?.key}
placement="top"
title="جهت مشاهده ثبت کننده تلفات کلیک کنید"
>
<Button
// variant="outlined"
style={{ color: "rgba(0,0,0,0.87)" }}
onClick={() => {
dispatch(
OPEN_MODAL({
title: "ویرایش تعداد جوجه ریزی",
content: (
<Grid container xs={12}>
{!item?.directLossesInputer &&
!item?.directLossesInputer ? (
<Typography variant="body1">
برای این جوجه ریزی تلفاتی ثبت نشده است.
</Typography>
) : (
<Grid xs={12}>
<Typography variant="body1">
ثبت کننده تلفات اتحادیه:{" "}
{item?.directLossesInputer
? `${
item?.directLossesInputer
} در تاریخ ${formatJustDate(
item?.directLossesDate
)}`
: " - "}
</Typography>
<Typography variant="body1">
ویرایش کننده تلفات اتحادیه:
{item?.directLossesEditor
? `${
item?.directLossesEditor
} در تاریخ ${formatJustDate(
item?.directLossesLastEditDate
)}`
: " - "}
</Typography>
</Grid>
)}
</Grid>
),
})
);
}}
>
{`${item?.directLosses?.toLocaleString()} (%${(
(item.directLosses * 100) /
item.quantity
).toFixed(0)})`}
</Button>
</Tooltip>,
`${item?.totalLosses?.toLocaleString()} (%${(
(item.totalLosses * 100) /
item.quantity
).toFixed(0)})`,
`${item?.totalCommitmentQuantity?.toLocaleString()}`,
`${item?.totalFreeCommitmentQuantity?.toLocaleString()}`,
`${item?.governmentalQuantity?.toLocaleString()}`,
`${item?.governmentalKilledQuantity?.toLocaleString()}`,
`${item?.freeQuantity?.toLocaleString()}`,
`${item?.freeKilledQuantity?.toLocaleString()}`,
`${item?.outProvinceKilledQuantity?.toLocaleString()}`,
`${item?.outProvinceKilledWeight?.toLocaleString()}`,
`${item?.barDifferenceRequestQuantity?.toLocaleString()}`,
`${item?.barDifferenceRequestWeight?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequests?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequestsQuantity?.toLocaleString()}`,
`${item?.killingInfo?.provinceKillRequestsWeight?.toLocaleString()}`,
item?.killedQuantity?.toLocaleString() +
` (%${((item?.killedQuantity * 100) / item.quantity).toFixed(0)})`,
item?.leftOver?.toLocaleString(),
`%${((item?.leftOver * 100) / item?.quantity).toFixed(0)}`,
// item?.totalCommitment?.toLocaleString(),
`%${((item.totalLosses * 100) / item.quantity).toFixed(0)}`,
`%${((item?.killedQuantity * 100) / item.quantity).toFixed(0)}`,
`%${((item?.leftOver * 100) / item?.quantity).toFixed(0)}`,
`%${(
((item?.killedQuantity + item?.totalLosses) * 100) /
item?.quantity
).toFixed(0)}`,
item?.samasatDischargePercentage
? `%${item?.samasatDischargePercentage}`
: "-",
item?.totalCommitment?.toLocaleString(),
item?.governmentalKilledQuantity?.toLocaleString(),
item?.freeKilledQuantity?.toLocaleString(),
item?.totalAverageKilledWeight?.toLocaleString(),
item?.totalKilledWeight?.toLocaleString(),
item?.activeKill?.activeKill ? "دارد" : "ندارد",
item?.activeKill?.countOfRequest ? item.activeKill.countOfRequest : "-",
item?.killingInfo?.killHouseRequests?.toLocaleString(),
item?.killingInfo?.killHouseRequestsFirstQuantity?.toLocaleString(),
item?.killingInfo?.killHouseRequestsFirstWeight?.toLocaleString(),
item?.killingInfo?.barCompleteWithKillHouse?.toLocaleString(),
item?.killingInfo?.acceptedRealWightFinal?.toLocaleString(),
item?.chainKilledQuantity?.toLocaleString(),
item?.chainKilledWeight?.toLocaleString(),
item?.exportKilledQuantity?.toLocaleString(),
item?.exportKilledWeight?.toLocaleString(),
item?.killingInfo?.wareHouseBars?.toLocaleString(),
item?.killingInfo?.wareHouseBarsQuantity?.toLocaleString(),
item?.killingInfo?.wareHouseBarsWeight?.toLocaleString(),
item?.killingInfo?.wareHouseBarsWeightLose?.toFixed(2),
item.lastChange
? `${item.lastChange.fullName} (${getFaUserRole(
item.lastChange.role
)}) در تاریخ ${formatTime(item.lastChange.date)}`
: "-",
item.latestHatchingChange
? `${item.latestHatchingChange.fullName} (${getFaUserRole(
item.latestHatchingChange.role
)}) در تاریخ ${formatTime(item.latestHatchingChange.date)}`
: "-",
item?.violationReport ? (
<Button
key={item?.key}
onClick={() => {
dispatch(
OPEN_MODAL({
title: "گزارش ",
content: (
<SimpleTable
columns={[
"ثبت کننده",
"تاریخ ثبت",
"تخلف",
"متن گزارش",
"سند",
]}
data={[
[
item?.violationReporter,
formatJustDate(item?.violationReportDate),
item?.violation ? "دارد" : "ندارد",
item?.violationReport,
<Grid
key={item?.key}
container
xs={12}
justifyContent="center"
gap={1}
>
{item?.violationImage?.map((option) => (
<ShowImage key={i} src={option} />
))}
</Grid>,
],
]}
/>
),
})
);
}}
>
مشاهده گزارش
</Button>
) : (
"بدون گزارش"
),
];
});
setTableData(d);
}, [data]);
const handleSubmit = async (event) => {
event.preventDefault();
dispatch(LOADING_START());
dispatch(
cityGetHatchingInfoFull({
age1: selectedAge1,
age2: selectedAge2,
tab: "active",
textValue: textValue,
})
);
try {
const response = await axios.get(
`poultry_hatching/?role=${getRoleFromUrl()}&age1=${
selectedAge1 ? selectedAge1 : 0
}&age2=${
selectedAge2 ? selectedAge2 : 0
}&search=filter&value=${textValue}&page=${1}&page_size=${perPage}`
);
setData(response.data.results);
setTotalRows(response.data.count);
dispatch(LOADING_END());
} catch (error) {
console.error("Error fetching data:", error);
}
};
const handleRemoveFilter = async (event) => {
event.preventDefault();
setSelectedAge1(0);
setSelectedAge2(0);
dispatch(LOADING_START());
setTextValue("");
dispatch(
cityGetHatchingInfoFull({
age1: 0,
age2: 0,
tab: "active",
textValue: textValue,
})
);
try {
const response = await axios.get(
`poultry_hatching?role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&search=filter&value=${textValue}`
);
setData(response.data.results);
setTotalRows(response.data.count);
} catch (error) {
console.error("Error fetching data:", error);
} finally {
dispatch(LOADING_END());
}
};
const [lastUpdateData, setLastUpdateData] = useState();
useEffect(() => {
async function fetchData() {
try {
const response = await axios.get(`last_update/?type=poultry_hatching`);
setLastUpdateData(response.data);
} catch (error) {
console.error("Error fetching data:", error);
}
}
fetchData();
}, []);
const tableTitle = (
<Grid
container
alignItems="center"
justifyContent="space-between"
gap={2}
paddingTop={2}
mb={1}
xs={12}
mt={2}
>
<form onSubmit={handleSubmit} style={{ flex: 1 }}>
<Grid container alignItems="center" gap={SPACING.SMALL} xs={12}>
<Grid sx={{ width: { xs: "72px", sm: "80px" } }}>
<TextField
fullWidth
size="small"
label="از سن"
id="outlined-controlled"
value={selectedAge1}
onChange={(event) => {
setSelectedAge1(event.target.value);
}}
/>
</Grid>
<Grid sx={{ width: { xs: "72px", sm: "80px" } }}>
<TextField
fullWidth
size="small"
label="تا سن"
id="outlined-controlled"
value={selectedAge2}
onChange={(event) => {
setSelectedAge2(event.target.value);
}}
/>
</Grid>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
value={textValue}
sx={{ maxWidth: { xs: "100%", sm: 250 } }}
onChange={handleTextChange}
onKeyDown={(e) => {
if (e.key === "Enter") {
handleSubmit(e);
}
}}
/>
<Button type="submit" endIcon={<RiSearchLine />}>
جستجو
</Button>
<Tooltip title="خروجی اکسل" px={0}>
<Button
color="success"
onClick={() => {
openNotif({
vertical: "top",
horizontal: "center",
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
severity: "success",
});
const link = `${
axios.defaults.baseURL
}0/hatching_excel/?role=${getRoleFromUrl()}&key=${userKey}&age1=${
selectedAge1 ? selectedAge1 : 0
}&age2=${
selectedAge2 ? selectedAge2 : 0
}&search=filter&value=${textValue}`;
window.location.href = link;
}}
>
<RiFileExcel2Fill size={32} />
</Button>
</Tooltip>
</Grid>
</form>
<Button onClick={handleRemoveFilter} color="error">
حذف فیلتر
</Button>
</Grid>
);
const { hatchingInfoFull } = useSelector((state) => state.citySlice);
useEffect(() => {
dispatch(
cityGetHatchingInfoFull({
age1: selectedAge1,
age2: selectedAge2,
tab: "active",
textValue: textValue,
})
);
}, []);
return (
<Grid alignItems="center" justifyContent="center" mt={2}>
<Grid alignItems="center" justifyContent="center" isDashboard xs={12}>
<ResponsiveTable
noPagination
isDashboard
title={
lastUpdateData &&
`آخرین بروزرسانی : ${formatTime(lastUpdateData)} ${" "}`
}
columns={[
"تعداد فارم",
"تعداد جوجه ریزی",
"حجم کل جوجه ریزی",
"حجم باقی مانده در سالن",
"حجم کشتار شده",
"وزن کشتار شده",
"حجم کل تلفات",
"حجم تلفات اتحادیه",
"حجم تلفات دامپزشک",
"مانده سالن ( 20 تا 30 روزه)",
"مانده سالن ( 30 تا 40 روزه)",
"مانده سالن ( 40 تا 50 روزه)",
"مانده سالن ( 50 تا 60 روزه)",
"بیشتر از 60 روزه",
]}
data={[
[
hatchingInfoFull?.poultries?.toLocaleString(),
hatchingInfoFull?.hatchings?.toLocaleString(),
hatchingInfoFull?.totalHatchingQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingLeftOverQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingKilledQuantity?.toLocaleString(),
hatchingInfoFull?.totalHatchingKilledWeight?.toLocaleString(),
hatchingInfoFull?.totalHatchingAllLosses?.toLocaleString(),
hatchingInfoFull?.totalHatchingUnionLosses?.toLocaleString(),
hatchingInfoFull?.totalHatchingVetLosses?.toLocaleString(),
hatchingInfoFull?.age2030?.toLocaleString(),
hatchingInfoFull?.age3040?.toLocaleString(),
hatchingInfoFull?.age4050?.toLocaleString(),
hatchingInfoFull?.age5060?.toLocaleString(),
hatchingInfoFull?.ageMoreThan60?.toLocaleString(),
],
]}
/>
</Grid>
{tableTitle}
<ResponsiveTable
data={tableData}
columns={[
"عملیات",
"جزئیات",
"ردیف",
"وضعیت",
"شماره مجوز جوجه ریزی",
"شناسه یکتا",
"مجوز بهداشتی جوجه ریزی",
// "نوع تعهد",
"نام فارم",
"مرغدار",
"بهره برداری",
"مالکیت",
"ارتباط",
"شهر/تعاونی",
"دامپزشک فارم",
"سالن",
"دوره جوجه ریزی",
"تاریخ ثبت جوجه ریزی",
"تاریخ جوجه ریزی",
"میانگین سن کشتار",
"پیش بینی تاریخ کشتار",
"نژاد",
"سن",
"حجم جوجه ریزی",
"حجم افزایشی",
"تلفات دامپزشک",
"تلفات اتحادیه",
"تلفات کل",
"حجم تعهد دولتی",
"حجم تعهد آزاد",
"حجم کشتار دولتی",
"وزن کشتار دولتی",
"حجم کشتار آزاد",
"وزن کشتار شده آزاد",
"حجم فروش به خارج استان",
"وزن فروش به خارج استان",
"حجم اختلاف کشتار",
"وزن اختلاف کشتار",
"تخصیصات بدون بار",
"حجم تخصیصات بدون بار",
"وزن تخصیصات بدون بار",
"حجم کشتار شده",
"حجم مانده در سالن",
"درصد مانده در سالن",
" تلفات",
" کشتار شده",
" باقی مانده در سالن",
"تایید تخلیه رصدیار",
" تایید تخلیه در سماصط",
"وزن تعهد دولتی",
"وزن کشتار دولتی",
"وزن کشتار آزاد",
"میانگین وزن کشتار",
"وزن کل کشتار شده",
"تعداد کشتار فعال",
"تعداد درخواست کشتار",
"تعداد بارها",
"حجم بارها",
"وزن بارها",
"حجم بارهای تحویلی",
"وزن بارهای تحویلی",
"حجم زنجیره",
"وزن زنجیره",
"حجم صادرات",
"وزن صادرات",
"بارهای ورودی به انبار",
"حجم لاشه های انبار",
"وزن لاشه های انبار",
"درصد افت بارها",
"آخرین تغییر",
"سازنده جوجه ریزی",
"گزارش",
]}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
title="جوجه ریزی های فعال"
/>
</Grid>
);
};

View File

@@ -0,0 +1,119 @@
import { Button, IconButton, Popover, Tooltip } from "@mui/material";
import { useContext, useState } from "react";
import { useDispatch } from "react-redux";
import { Grid } from "../../../../components/grid/Grid";
import TuneIcon from "@mui/icons-material/Tune";
import DeleteIcon from "@mui/icons-material/Delete";
import { CLOSE_MODAL, OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
import { AppContext } from "../../../../contexts/AppContext";
import { cityDeleteIncreaseHatchingeService } from "../../services/city-increase-hatching";
export const CityIncreaseHatchingOperation = ({ item, updateTable }) => {
const dispatch = useDispatch();
const [anchorEl, setAnchorEl] = useState(null);
const [openNotif] = useContext(AppContext);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const id = open ? "popover" : undefined;
return (
<div>
<IconButton
aria-describedby={id}
variant="contained"
color="primary"
onClick={handleClick}
>
<TuneIcon />
</IconButton>
<Popover
anchorOrigin={{
vertical: "bottom",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
>
<div style={{ padding: "20px" }}>
<Grid container direction="column">
<Tooltip title={"حذف"} placement="left-start">
<IconButton
aria-label="delete"
color="error"
onClick={() => {
handleClose();
dispatch(
OPEN_MODAL({
title: "آیا مطمئن هستید؟",
content: (
<Grid container spacing={2}>
<Grid item>
<Button
variant="contained"
color="error"
onClick={() => {
dispatch(
cityDeleteIncreaseHatchingeService(item?.key)
).then((r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
updateTable();
dispatch(CLOSE_MODAL());
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.data.result,
severity: "success",
});
}
});
}}
>
تایید
</Button>
</Grid>
<Grid item>
<Button
onClick={() => {
dispatch(CLOSE_MODAL());
}}
>
لغو
</Button>
</Grid>
</Grid>
),
})
);
}}
>
<DeleteIcon />
</IconButton>
</Tooltip>
</Grid>
</div>
</Popover>
</div>
);
};

View File

@@ -0,0 +1,240 @@
import React, { useContext, useEffect, useState } from "react";
import {
Autocomplete,
Button,
Stack,
TextField,
Typography,
Paper,
} from "@mui/material";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { useDispatch, useSelector } from "react-redux";
import { AppContext } from "../../../../contexts/AppContext";
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
import { slaughterGetPoultriesService } from "../../../slaughter-house/services/salughter-get-poultries";
import { avicultureGetHatchingDataForIncreaseHatching } from "../../../aviculture/services/aviculture-get-hatching-data";
import {
cityEditIncreaseHatchingeService,
cityIncreaseHatchingeService,
} from "../../services/city-increase-hatching";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
export const CityIncreaseHatchingSubmitDiffrence = ({
updateTable,
isEdit,
item,
}) => {
const [poultryData, setPoultryData] = useState([]);
const [selectedPoultryInfo, setSelectedPoultryInfo] = useState(null);
const [openNotif] = useContext(AppContext);
const dispatch = useDispatch();
const { slaughterGetPoultries } = useSelector(
(state) => state.slaughterSlice
);
useEffect(() => {
dispatch(slaughterGetPoultriesService());
}, []);
const initialValues = {
poultry: item?.poultrykey || null,
hatching_key: item?.hatchingkey || null,
quantity: item?.quantity || null,
message: item?.message || null,
};
const validationSchema = Yup.object().shape({
poultry: Yup.string().required("انتخاب مرغدار الزامی است"),
hatching_key: Yup.string().required("انتخاب محل پرورش الزامی است"),
quantity: Yup.number()
.typeError("عدد وارد کنید")
.required("حجم الزامی است"),
message: Yup.string()
.typeError("پر کردن این فیلد الزامی است")
.required("پیام الزامی است"),
});
const formik = useFormik({
initialValues,
validationSchema,
});
useEffect(() => {
if (formik.values.poultry) {
dispatch(
avicultureGetHatchingDataForIncreaseHatching(formik.values.poultry, {
increase: true,
})
).then((res) => {
setPoultryData(res.payload.data || []);
});
}
}, [formik.values.poultry]);
return (
<Stack spacing={2}>
<Autocomplete
id="poultry"
disableClearable
options={slaughterGetPoultries?.map((item) => ({
label: `${item.unitName} (${item.user?.fullname})(${item.user?.mobile})`,
value: item.key,
}))}
getOptionLabel={(option) => option.label}
onChange={(_, value) => {
formik.setFieldValue("poultry", value.value);
formik.setFieldValue("hatching_key", null);
}}
renderInput={(params) => (
<TextField
{...params}
label="انتخاب مرغدار"
error={formik.touched.poultry && Boolean(formik.errors.poultry)}
helperText={formik.touched.poultry && formik.errors.poultry}
/>
)}
/>
<Autocomplete
id="hatching_key"
disableClearable
disabled={!formik.values.poultry}
options={poultryData?.map((item) => ({
label: item?.poultry?.unitName || "-",
value: item?.key,
}))}
getOptionLabel={(option) => option.label}
onChange={(_, value) => {
formik.setFieldValue("hatching_key", value?.value);
const selected = poultryData.find((i) => i.key === value?.value);
setSelectedPoultryInfo(selected);
}}
renderInput={(params) => (
<TextField
{...params}
label="انتخاب محل پرورش"
error={
formik.touched.hatching_key && Boolean(formik.errors.hatching_key)
}
helperText={
formik.touched.hatching_key && formik.errors.hatching_key
}
/>
)}
/>
{selectedPoultryInfo && (
<Paper variant="outlined" sx={{ p: 2, borderRadius: 2 }}>
<Typography>
شماره مجوز جوجه ریزی:{" "}
{selectedPoultryInfo?.licenceNumber?.toLocaleString()}
</Typography>
<Typography>
شناسه یکتا مرغدار :{" "}
{selectedPoultryInfo?.poultry?.breedingUniqueId?.toLocaleString()}
</Typography>
<Typography>
حجم جوجه ریزی:
{selectedPoultryInfo?.quantity?.toLocaleString()}قطعه
</Typography>
<Typography>
سن جوجه: {selectedPoultryInfo?.chickenAge?.toLocaleString()} روز
</Typography>
<Typography>
مانده در سالن: {selectedPoultryInfo?.leftOver?.toLocaleString()}
قطعه
</Typography>
<Typography>
حجم کشتار شده:
{selectedPoultryInfo?.killedQuantity?.toLocaleString()} قطعه
</Typography>
<Typography>
نژاد: {selectedPoultryInfo?.chickenBreed?.toLocaleString()}
</Typography>
<Typography>
تلفات: {selectedPoultryInfo?.totalLosses?.toLocaleString("fa-IR")}
قطعه
</Typography>
</Paper>
)}
<TextField
label="تعداد (قطعه)"
name="quantity"
value={formik.values.quantity}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.quantity && Boolean(formik.errors.quantity)}
helperText={formik.touched.quantity && formik.errors.quantity}
fullWidth
/>
<TextField
label="دلیل افزایش حجم"
name="message"
multiline
rows={3}
value={formik.values.message}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.message && Boolean(formik.errors.message)}
helperText={formik.touched.message && formik.errors.message}
fullWidth
/>
<Button
variant="contained"
fullWidth
disabled={
!(
formik.isValid &&
formik.values.poultry &&
formik.values.hatching_key &&
formik.values.quantity &&
formik.values.message
)
}
onClick={() => {
const payload = {
hatching_key: formik.values.hatching_key,
quantity: parseInt(formik.values.quantity),
message: formik.values.message,
registerer_role: getRoleFromUrl(),
};
const action = isEdit
? cityEditIncreaseHatchingeService({
...payload,
key: item?.key,
})
: cityIncreaseHatchingeService(payload);
dispatch(action).then((res) => {
if (res.payload.error) {
openNotif({
msg: "مشکلی پیش آمده است!",
severity: "error",
vertical: "top",
horizontal: "center",
});
} else {
openNotif({
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
vertical: "top",
horizontal: "center",
});
updateTable();
dispatch(DRAWER({ right: false, bottom: false, content: null }));
}
});
}}
>
{isEdit ? "ویرایش" : "ثبت"}
</Button>
</Stack>
);
};

View File

@@ -0,0 +1,182 @@
import React, { useEffect, useState } from "react";
import { Button, TextField } from "@mui/material";
import { useDispatch } from "react-redux";
import axios from "axios";
import { RiSearchLine } from "react-icons/ri";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { Grid } from "../../../../components/grid/Grid";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import { formatTime } from "../../../../utils/formatTime";
import { CityIncreaseHatchingOperation } from "../city-increase-hatching-operation/CityIncreaseHatchingOperation";
import { CityIncreaseHatchingSubmitDiffrence } from "../city-increase-hatching-submit-diffrence/CityIncreaseHatchingSubmitDiffrence";
export const CityIncreaseHatching = ({ state }) => {
const dispatch = useDispatch();
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const [data, setData] = useState([]);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [textValue, setTextValue] = useState("");
const [page, setPage] = useState(1);
const [tableData, setTableData] = useState([]);
const fetchApiData = async (page) => {
dispatch(LOADING_START());
const response = await axios.get(
`hatching-increase-request/?search=filter&value=${textValue}&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}`
);
dispatch(LOADING_END());
setData(response.data.results);
setTotalRows(response.data.count);
};
const handlePageChange = (page) => {
fetchApiData(page);
setPage(page);
};
const handlePerRowsChange = (perRows) => {
setPerPage(perRows);
setPage(1);
};
const updateTable = () => {
fetchApiData(page !== 0 ? page : 1);
};
useEffect(() => {
const d = data?.map((item, i) => {
return [
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
`${item?.hatching?.poultry?.unitName} (${item?.hatching?.poultry?.user?.mobile})`,
item?.hatching?.licenceNumber,
item?.hatching?.poultry?.breedingUniqueId,
item?.hatchingQuantity?.toLocaleString(),
item?.hatchingKillQuantity?.toLocaleString(),
item?.hatchingLosses?.toLocaleString(),
item?.hatchingLeftOver?.toLocaleString(),
item?.quantity?.toLocaleString(),
`${item?.registererName} (${item?.registererMobile})`,
formatTime(item?.date),
item?.message,
<CityIncreaseHatchingOperation
key={i}
updateTable={updateTable}
item={item}
/>,
];
});
setTableData(d);
}, [data, state]);
useEffect(() => {
fetchApiData(1);
}, [dispatch, perPage, state]);
const handleSubmit = async (event) => {
event.preventDefault();
dispatch(LOADING_START());
try {
const response = await axios.get(
`hatching-increase-request/?role=${getRoleFromUrl()}&search=filter&value=${textValue}&page=${1}&page_size=${perPage}`
);
setData(response.data.results);
setTotalRows(response.data.count);
dispatch(LOADING_END());
} catch (error) {
console.error("Error fetching data:", error);
}
};
return (
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
<Grid
container
xs={12}
justifyContent="start"
alignItems="center"
gap={2}
>
{getRoleFromUrl() !== "KillHouse" && (
<Grid>
<Button
variant="contained"
onClick={() => {
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
content: (
<CityIncreaseHatchingSubmitDiffrence
updateTable={updateTable}
/>
),
title: "افزایش جوجه ریزی",
})
);
}}
>
افزایش جوجه ریزی
</Button>
</Grid>
)}
<Grid>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button
// disabled={!textValue}
type="submit"
onClick={handleSubmit}
endIcon={<RiSearchLine />}
>
جستجو
</Button>
</form>
</Grid>
</Grid>
<ResponsiveTable
data={tableData}
columns={[
"ردیف",
"مرغدار",
"شماره مجوز جوجه ریزی",
"شناسه یکتا فارم",
"حجم جوجه ریزی",
"حجم کشتار",
"حجم تلفات",
"مانده در سالن",
"حجم افزایشی",
"ثبت کننده",
"تاریخ ثبت",
"پیغام",
"عملیات",
]}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
title="افزایش حجم جوجه ریزی"
/>
</Grid>
);
};

View File

@@ -0,0 +1,240 @@
import React, { useContext, useState } from "react";
import {
Grid,
TextField,
Button,
Paper,
IconButton,
Typography,
Box,
} from "@mui/material";
import EditIcon from "@mui/icons-material/Edit";
import DeleteIcon from "@mui/icons-material/Delete";
import { useDispatch } from "react-redux";
import { useFormik } from "formik";
import * as Yup from "yup";
import { citySubmitManageHatchingRenterService } from "../../services/city-submit-manage-hatching-renter";
import { AppContext } from "../../../../contexts/AppContext";
import {
CLOSE_MODAL,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { cityHatchingDeleteRenterService } from "../../services/city-delete-manage-hatching-renter";
export const CityManageHatchingRenter = ({ item, updateTable, readOnly }) => {
const [editing, setEditing] = useState(false);
const dispatch = useDispatch();
const [openNotif] = useContext(AppContext);
const formik = useFormik({
initialValues: {
fullName: item?.tenantFullname || "",
nationalCode: item?.tenantNationalCode || "",
phoneNumber: item?.tenantMobile || "",
city: item?.tenantCity || "",
},
validationSchema: Yup.object({
fullName: Yup.string().required("نام و نام خانوادگی الزامی است"),
nationalCode: Yup.string()
.required("کد ملی الزامی است")
.matches(/^[0-9]{10}$/, "کد ملی باید 10 رقم باشد"),
phoneNumber: Yup.string()
.required("شماره تلفن الزامی است")
.matches(/^[0-9]{11}$/, "شماره تلفن باید 11 رقم باشد"),
city: Yup.string().required("شهر الزامی است"),
}),
onSubmit: (values) => {
dispatch(LOADING_START());
dispatch(
citySubmitManageHatchingRenterService({
key: item?.key,
tenant_fullname: values.fullName,
tenant_national_code: values.nationalCode,
tenant_mobile: values.phoneNumber,
tenant_city: values.city,
has_tenant: true,
})
).then((r) => {
dispatch(CLOSE_MODAL());
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
formik.resetForm();
updateTable();
setEditing(false);
}
dispatch(LOADING_END());
});
},
enableReinitialize: true,
});
const handleEdit = () => {
setEditing(true);
};
const handleDelete = () => {
dispatch(LOADING_START());
dispatch(
cityHatchingDeleteRenterService({ delete_tenant: true, key: item?.key })
).then((r) => {
dispatch(CLOSE_MODAL());
if (!r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مستاجر با موفقیت حذف شد.",
severity: "success",
});
formik.resetForm();
updateTable();
}
});
};
const hasRenter = item?.hasTenant && item?.tenantFullname;
return (
<Grid container spacing={3} direction="column">
{hasRenter && !editing ? (
<Grid item>
<Paper elevation={3}>
<Box
p={2}
display="flex"
justifyContent="space-between"
alignItems="center"
>
<div>
<Typography variant="subtitle1">
<strong>نام مستاجر:</strong> {item.tenantFullname}
</Typography>
<Typography variant="body2">
<strong>کد ملی:</strong> {item.tenantNationalCode}
</Typography>
<Typography variant="body2">
<strong>شماره تلفن:</strong> {item.tenantMobile}
</Typography>
<Typography variant="body2">
<strong>شهر:</strong> {item.tenantCity}
</Typography>
</div>
{!readOnly && (
<div>
<IconButton onClick={handleEdit} color="primary">
<EditIcon />
</IconButton>
<IconButton onClick={handleDelete} color="error">
<DeleteIcon />
</IconButton>
</div>
)}
</Box>
</Paper>
</Grid>
) : (
<Grid item>
<Paper elevation={3}>
<Box p={2} component="form" onSubmit={formik.handleSubmit}>
<Grid container spacing={2}>
<Grid item xs={12} md={4}>
<TextField
fullWidth
label="نام و نام خانوادگی"
name="fullName"
value={formik.values.fullName}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={
formik.touched.fullName && Boolean(formik.errors.fullName)
}
helperText={
formik.touched.fullName && formik.errors.fullName
}
disabled={readOnly}
/>
</Grid>
<Grid item xs={12} md={4}>
<TextField
fullWidth
label="کد ملی"
name="nationalCode"
value={formik.values.nationalCode}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={
formik.touched.nationalCode &&
Boolean(formik.errors.nationalCode)
}
helperText={
formik.touched.nationalCode && formik.errors.nationalCode
}
disabled={readOnly}
/>
</Grid>
<Grid item xs={12} md={4}>
<TextField
fullWidth
label="شماره تلفن"
name="phoneNumber"
value={formik.values.phoneNumber}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={
formik.touched.phoneNumber &&
Boolean(formik.errors.phoneNumber)
}
helperText={
formik.touched.phoneNumber && formik.errors.phoneNumber
}
disabled={readOnly}
/>
</Grid>
<Grid item xs={12} md={4}>
<TextField
fullWidth
label="شهر"
name="city"
value={formik.values.city}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.city && Boolean(formik.errors.city)}
helperText={formik.touched.city && formik.errors.city}
disabled={readOnly}
/>
</Grid>
</Grid>
{!readOnly && (
<Box mt={2}>
<Button
type="submit"
variant="contained"
color="primary"
disabled={formik.isSubmitting}
>
{hasRenter ? "ذخیره تغییرات" : "ثبت اطلاعات"}
</Button>
</Box>
)}
</Box>
</Paper>
</Grid>
)}
</Grid>
);
};

View File

@@ -0,0 +1,551 @@
import {
IconButton,
Popover,
Tooltip,
List,
ListItemButton,
ListItemIcon,
ListItemText,
} from "@mui/material";
import { useContext, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
// import DeleteIcon from "@mui/icons-material/Delete";
import ArchiveIcon from "@mui/icons-material/Archive";
import AddIcon from "@mui/icons-material/Add";
import {
DRAWER,
OPEN_MODAL,
LOADING_START,
LOADING_END,
} from "../../../../lib/redux/slices/appSlice";
import { CityNewKillRequest } from "../city-new-kill-request/CityNewKillRequest";
import { CityArchiveHatchingDrawer } from "../city-archive-hatching-drawer/CityArchiveHatchingDrawer";
import TuneIcon from "@mui/icons-material/Tune";
// import { CityEditHatchingQuantity } from "../city-edit-hatching-quantity/CityEditHatchingQuantity";
import axios from "axios";
import { RiFileExcel2Fill } from "react-icons/ri";
import SmsIcon from "@mui/icons-material/Sms";
import { CitySubmitHatchingReport } from "../city-submit-hatching-report/CitySubmitHatchingReport";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
// import { cityGetHatchingsByAge } from "../../services/city-get-hatchings-by-age";
import EditIcon from "@mui/icons-material/Edit";
import AssignmentReturnedIcon from "@mui/icons-material/AssignmentReturned";
import KeyboardReturnIcon from "@mui/icons-material/KeyboardReturn";
import { archiveHatchingService } from "../../services/archive-hatching";
import { AppContext } from "../../../../contexts/AppContext";
import { CitySubmitLooses } from "../city-submit-looses/CitySubmitLooses";
import PlaylistRemoveIcon from "@mui/icons-material/PlaylistRemove";
import { VetFarmSubmitFarmInfoLosses } from "../../../vet-farm/components/vet-farm-submit-farm-info-losses/VetFarmSubmitFarmInfoLosses";
import InsertPageBreakIcon from "@mui/icons-material/InsertPageBreak";
import { CityManageHatchingRenter } from "../city-manage-hatching-renter/CityManageHatchingRenter";
import PersonAddAlt1Icon from "@mui/icons-material/PersonAddAlt1";
import { cityGetTicketDiffrentClearanceCode } from "../../services/city-get-ticket-different-clearance-code";
import PlayArrowIcon from "@mui/icons-material/PlayArrow";
export const CityManageHatchingsOperations = ({
item,
selectedAge1,
selectedAge2,
updateTable,
readOnly,
}) => {
const { userProfile } = useSelector((state) => state.userSlice);
const dispatch = useDispatch();
const [anchorEl, setAnchorEl] = useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const id = open ? "popover" : undefined;
const [openNotif] = useContext(AppContext);
return (
<div>
<IconButton
aria-describedby={id}
variant="contained"
color="primary"
onClick={handleClick}
>
<TuneIcon />
</IconButton>
<Popover
anchorOrigin={{
vertical: "bottom",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
>
<List sx={{ py: 1, minWidth: 200 }}>
{!readOnly && (
<>
<Tooltip title={"ثبت درخواست کشتار"} placement="left-start">
<ListItemButton
onClick={() => {
handleClose();
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
title: "ثبت درخواست کشتار جدید",
content: (
<CityNewKillRequest
selectedAge1={selectedAge1}
selectedAge2={selectedAge2}
userCheck={item.poultry.userprofile.baseOrder}
updateTable={updateTable}
/>
),
})
);
}}
>
<ListItemIcon sx={{ minWidth: 36, color: "secondary.main" }}>
<AddIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="ثبت درخواست کشتار"
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
</Tooltip>
{item?.InteractTypeName === "مستاجر" && (
<Tooltip title={"ثبت مستاجر"} placement="left-start">
<ListItemButton
onClick={() => {
handleClose();
dispatch(
OPEN_MODAL({
title: "ثبت مستاجر ",
content: (
<CityManageHatchingRenter
item={item}
updateTable={updateTable}
/>
),
})
);
}}
>
<ListItemIcon sx={{ minWidth: 36, color: "primary.main" }}>
<PersonAddAlt1Icon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="ثبت مستاجر"
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
</Tooltip>
)}
{(getRoleFromUrl() === "ProvinceOperator" ||
getRoleFromUrl() === "CityOperator" ||
getRoleFromUrl() === "CityPoultry" ||
getRoleFromUrl() === "CityJahad" ||
getRoleFromUrl() === "CityCommerce" ||
getRoleFromUrl() === "AdminX" ||
getRoleFromUrl() === "SuperAdmin") && (
<Tooltip
title={item?.violationReport ? "ویرایش گزارش" : "ثبت گزارش"}
placement="left-start"
>
<ListItemButton
onClick={() => {
handleClose();
dispatch(
OPEN_MODAL({
title: item?.violationReport
? "ویرایش گزارش"
: "ثبت گزارش",
content: (
<CitySubmitHatchingReport
updateTable={updateTable}
item={item}
/>
),
})
);
}}
>
<ListItemIcon sx={{ minWidth: 36, color: "primary.main" }}>
<EditIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary={
item?.violationReport ? "ویرایش گزارش" : "ثبت گزارش"
}
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
</Tooltip>
)}
<Tooltip title={"انتقال به بایگانی"} placement="left-start">
<ListItemButton
onClick={() => {
handleClose();
dispatch(
DRAWER({
title: "انتقال به آرشیو",
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
content: (
<CityArchiveHatchingDrawer
selectedAge1={selectedAge1}
selectedAge2={selectedAge2}
item={item}
updateTable={updateTable}
/>
),
})
);
}}
>
<ListItemIcon sx={{ minWidth: 36, color: "primary.main" }}>
<ArchiveIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="انتقال به بایگانی"
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
</Tooltip>
{(getRoleFromUrl() === "ProvinceOperator" ||
getRoleFromUrl() === "CityOperator" ||
getRoleFromUrl() === "AdminX" ||
getRoleFromUrl() === "SuperAdmin") && (
<Tooltip title={"ثبت تلفات"} placement="left-start">
<ListItemButton
onClick={() => {
handleClose();
dispatch(
OPEN_MODAL({
title: "ثبت تلفات",
content: (
<CitySubmitLooses
updateTable={updateTable}
item={item}
/>
),
})
);
}}
>
<ListItemIcon sx={{ minWidth: 36, color: "error.main" }}>
<PlaylistRemoveIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="ثبت تلفات"
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
</Tooltip>
)}
<Tooltip
title={item?.violation ? "بازگشت از تخلف" : "جوجه ریزی متخلف"}
placement="left-start"
>
<ListItemButton
onClick={() => {
handleClose();
dispatch(
archiveHatchingService({
key: item?.key,
violation: item?.violation ? false : true,
})
).then((r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
updateTable();
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
<ListItemIcon
sx={{
minWidth: 36,
color: item?.violation ? "primary.main" : "error.main",
}}
>
{item?.violation ? (
<KeyboardReturnIcon fontSize="small" />
) : (
<AssignmentReturnedIcon fontSize="small" />
)}
</ListItemIcon>
<ListItemText
primary={
item?.violation ? "بازگشت از تخلف" : "جوجه ریزی متخلف"
}
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
</Tooltip>
</>
)}
{(getRoleFromUrl() === "VetFarm" ||
getRoleFromUrl() === "CityVet" ||
getRoleFromUrl() === "VetSupervisor") && (
<Tooltip title={"ثبت تلفات پایان دوره"} placement="left-start">
<ListItemButton
onClick={() => {
handleClose();
dispatch(
OPEN_MODAL({
title: "ثبت تلفات پایان دوره",
content: (
<VetFarmSubmitFarmInfoLosses
item={item}
updateTable={updateTable}
/>
),
})
);
}}
>
<ListItemIcon sx={{ minWidth: 36, color: "error.main" }}>
<InsertPageBreakIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="ثبت تلفات پایان دوره"
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
</Tooltip>
)}
<Tooltip title="خروجی اکسل" placement="left-start">
<ListItemButton
component="a"
href={`${axios.defaults.baseURL}process-for-each-hatching/?key=${item.key}`}
rel="noreferrer"
>
<ListItemIcon sx={{ minWidth: 36, color: "success.main" }}>
<RiFileExcel2Fill size={18} />
</ListItemIcon>
<ListItemText
primary="خروجی اکسل"
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
</Tooltip>
<Tooltip title="تیکت گزارش کشتار جوجه ریزی" placement="left-start">
<ListItemButton
onClick={() => {
handleClose();
dispatch(
cityGetTicketDiffrentClearanceCode({
licence_number: item?.licenceNumber,
mobile: userProfile?.mobile,
})
).then((r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
updateTable();
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
<ListItemIcon sx={{ minWidth: 36, color: "error.main" }}>
<SmsIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="تیکت گزارش کشتار"
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
</Tooltip>
</List>
</Popover>
</div>
);
};
export const CityManageHatchingsArchiveActions = ({
item,
selectedAge1,
selectedAge2,
updateTable,
readOnly,
}) => {
const dispatch = useDispatch();
const [openNotif] = useContext(AppContext);
const [anchorEl, setAnchorEl] = useState(null);
const open = Boolean(anchorEl);
const popoverId = open ? "archive-activate-popover" : undefined;
const handleOpen = (event) => {
if (readOnly) {
return;
}
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleArchiveClick = () => {
if (readOnly) {
return;
}
handleClose();
dispatch(
DRAWER({
title: "انتقال به آرشیو",
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
content: (
<CityArchiveHatchingDrawer
selectedAge1={selectedAge1}
selectedAge2={selectedAge2}
item={item}
updateTable={updateTable}
/>
),
})
);
};
const handleActivateClick = async () => {
if (readOnly) {
return;
}
dispatch(LOADING_START());
try {
const { data } = await axios.put("poultry_hatching/0/", {
key: item?.key,
unknown: false,
});
dispatch(LOADING_END());
if (data?.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: data?.error || "فعال‌سازی ناموفق بود.",
severity: "error",
});
return;
}
updateTable();
handleClose();
openNotif({
vertical: "top",
horizontal: "center",
msg: "فعال‌سازی با موفقیت انجام شد.",
severity: "success",
});
} catch (error) {
dispatch(LOADING_END());
const message =
error?.response?.data?.result ||
error?.response?.data?.error ||
error?.message ||
"فعال‌سازی ناموفق بود.";
openNotif({
vertical: "top",
horizontal: "center",
msg: message,
severity: "error",
});
handleClose();
}
};
return (
<>
<IconButton
aria-describedby={popoverId}
color="primary"
onClick={handleOpen}
size="small"
disabled={readOnly}
>
<TuneIcon />
</IconButton>
<Popover
id={popoverId}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<List sx={{ py: 1, minWidth: 160 }}>
<ListItemButton onClick={handleArchiveClick} disabled={readOnly}>
<ListItemIcon sx={{ minWidth: 36, color: "primary.main" }}>
<ArchiveIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="بایگانی"
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
<ListItemButton onClick={handleActivateClick} disabled={readOnly}>
<ListItemIcon sx={{ minWidth: 36, color: "success.main" }}>
<PlayArrowIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="فعال سازی"
primaryTypographyProps={{ variant: "body2" }}
/>
</ListItemButton>
</List>
</Popover>
</>
);
};

View File

@@ -0,0 +1,589 @@
import {
Box,
Button,
// FormControl,
// InputLabel,
// MenuItem,
// Select,
// TextField,
Tab,
Tabs,
// Tooltip,
// Typography,
} from "@mui/material";
import { useContext, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
// import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
// import { ExcelUploadButton } from "../../../../components/excel-upload-button/ExcelUploadButton";
import { Grid } from "../../../../components/grid/Grid";
import { AppContext } from "../../../../contexts/AppContext";
import { SPACING } from "../../../../data/spacing";
import { OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
// import { formatJustDate } from "../../../../utils/formatTime";
// import { cityGetHatchings } from "../../services/city-get-hatchings";
// import { getSlaughtersKillRequestService } from "../../services/get-slaughters-kill-request";
// import { avicultureHatchingRequestsService } from "../../../aviculture/services/aviculture-hatching-requests";
import { useFormik } from "formik";
// import { RiFileExcel2Fill } from "react-icons/ri";
// import axios from "axios";
// import { DatePicker } from "@mui/x-date-pickers";
// import moment from "moment/moment";
// import { CityManageHatchingsOperations } from "../city-manage-hatchings-operations/CityManageHatchingsOperations";
// import { cityGetHatchingsByAge } from "../../services/city-get-hatchings-by-age";
// import { getFaUserRole } from "../../../../utils/getFaUserRole";
import { CityArchiveOldHatchings } from "../city-archive-old-hatchings/CityArchvieOldHatchings";
import { cityGetArchiveHatchingsService } from "../../services/city-get-archive-hatchings";
import { CityHatchings } from "../city-hatchings/CityHatchings";
import { CityHatchingsArchive } from "../city-hatchings-archive/CityHatchingsArchive";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { CityHatchingInfo } from "../city-hatching-info/CityHatchingInfo";
import { CityUpdateHatching } from "../city-update-hatching/CityUpdateHatching";
import { ProvinceBarDifference } from "../../../province/components/province-bar-difference/ProvinceBarDifference";
import { TransportChickens } from "../transport-chickens/TransportChickens";
import { CityHatchingsTotal } from "../city-hatchings-total/CityHatchingsTotal";
import { CityHatchingUnassigned } from "../city-hatching-unassigned/CityHatchingUnassigned";
export const CityManageHatchings = () => {
const dispatch = useDispatch();
const [, , selectedDate1, , selectedDate2] = useContext(AppContext);
// const [dataTable, setDataTable] = useState([]);
// const [searchClick, setSearchClick] = useState(true);
// const [dataTableHatchingArchive, setDataTableHatchingArchive] = useState([]);
// const [selectedAge1, setSelectedAge1] = useState(45);
// const [selectedAge2, setSelectedAge2] = useState(75);
// const [filterType, setFilterType] = useState("سن");
const formik = useFormik({
initialValues: {
numberInput: 0,
},
});
const { hatchings, poultryRequestsTotalQuantity, cityGetArchiveHatchings } =
useSelector((state) => state.citySlice);
// const { hourLimitKillRequest } = useSelector((state) => state.citySlice);
const { getSlaughtersKillRequest } = useSelector((state) => state.citySlice);
// useEffect(() => {
// dispatch(getSlaughtersKillRequestService());
// dispatch(
// avicultureHatchingRequestsService({ selectedDate1, selectedDate2 })
// );
// }, [selectedDate1, selectedDate2]);
// useEffect(() => {
// const past50Day = new Date();
// past50Day.setDate(past50Day.getDate() - 45);
// setSelectedDate1(moment(past50Day).format("YYYY-MM-DD"));
// return () => {
// const date = new Date();
// setSelectedDate1(moment(date).format("YYYY-MM-DD"));
// };
// }, []);
// useEffect(() => {
// dispatch(cityGetHatchings({ selectedDate1, selectedDate2 }));
// }, [searchClick]);
// useEffect(() => {
// if (searchClick) {
// dispatch(cityGetHatchings({ selectedDate1, selectedDate2 }));
// setSearchClick(false);
// }
// }, [selectedDate1]);
useEffect(() => {
if (poultryRequestsTotalQuantity) {
formik.setFieldValue(
"numberInput",
poultryRequestsTotalQuantity?.quantity
);
}
}, [poultryRequestsTotalQuantity]);
useEffect(() => {
// const d = hatchings
// ?.filter((item) => item.allowHatching === "pending")
// ?.map((item, i) => {
// const killedNumber = item.quantity - item.losses - item.leftOver;
// const lastChange =
// item.lastChange &&
// `${item.lastChange.fullName} (${getFaUserRole(
// item.lastChange.role
// )}) در تاریخ ${formatJustDate(item.lastChange.date)}`;
// return [
// i + 1,
// item.poultry.unitName,
// `${item.poultry.userprofile.fullName} (${item.poultry.userprofile.mobile})`,
// `${item?.poultry?.address.city.name}/${
// item?.poultry?.cityOperator
// ? item?.poultry?.cityOperator
// : "بدون تعاونی"
// }`,
// item?.vetFarm?.vetFarmMobile
// ? `${item?.vetFarm?.vetFarmFullName} (${item?.vetFarm?.vetFarmMobile})`
// : "-",
// item.hall,
// item.period,
// formatJustDate(item?.createDate),
// formatJustDate(item?.date),
// item.chickenBreed,
// item.age,
// item.quantity.toLocaleString(),
// `${item.losses} (%${((item.losses * 100) / item.quantity).toFixed(
// 0
// )})`,
// killedNumber.toLocaleString() +
// ` (%${((killedNumber * 100) / item.quantity).toFixed(0)})`,
// `${item.leftOver.toLocaleString()} (%${(
// (item.leftOver * 100) /
// item.quantity
// ).toFixed(0)})`,
// item?.activeKill?.activeKill ? "دارد" : "ندارد",
// item?.activeKill?.countOfRequest
// ? item.activeKill.countOfRequest
// : "-",
// item.lastChange ? lastChange : "-",
// // <CityManageHatchingsOperations
// // selectedAge1={selectedAge1}
// // selectedAge2={selectedAge2}
// // item={item}
// // key={i}
// // />,
// ];
// });
// setDataTable(d);
// const hatchingArchiveData = cityGetArchiveHatchings?.map((item, i) => {
// const killedNumber = item.quantity - item.losses - item.leftOver;
// return [
// i + 1,
// item.poultry.unitName,
// item.poultry.userprofile.baseOrder,
// item.poultry.userprofile.mobile,
// item.hall,
// item.period,
// formatJustDate(item?.createDate),
// formatJustDate(item?.date),
// item.chickenBreed,
// item.age,
// item.quantity,
// `${item.losses} (%${((item.losses * 100) / item.quantity).toFixed(0)})`,
// killedNumber +
// ` (%${((killedNumber * 100) / item.quantity).toFixed(0)})`,
// `${item.leftOver} (%${((item.leftOver * 100) / item.quantity).toFixed(
// 0
// )})`,
// ];
// });
// setDataTableHatchingArchive(hatchingArchiveData);
}, [hatchings, getSlaughtersKillRequest, cityGetArchiveHatchings]);
const [view, setView] = useState("active");
const handleChange = (event, newValue) => {
setView(newValue);
};
// const selectAges = Array.from({ length: 75 }, (_, i) => i + 1);
// useEffect(() => {
// dispatch(cityGetHatchingsByAge({ selectedAge1, selectedAge2 }));
// }, [selectedAge1, selectedAge2]);
useEffect(() => {
dispatch(cityGetArchiveHatchingsService({ selectedDate1, selectedDate2 }));
}, [selectedDate1, selectedDate2]);
return (
<Grid
container
gap={SPACING.SMALL}
// justifyContent={{ xs: "center", lg: "space-between" }}
alignSelf="center"
alignItems="center"
style={{ display: "block" }}
// direction={{ xs: "column", lg: "row" }}
>
<Grid container alignItems="center" justifyContent="center">
<Tabs
value={view}
onChange={handleChange}
centered
aria-label="hatching tabs"
scrollButtons="auto"
variant="scrollable"
allowScrollButtonsMobile
sx={{
width: "100%",
overflow: "hidden",
borderBottom: "1px solid #E0E0E0",
}}
>
<Tab label="جوجه ریزی های فعال" value="active" />
<Tab label="تعیین تکلیف نشده‌ها" value="pending" />
<Tab label="بایگانی جوجه ریزی ها" value="archive" />
<Tab label="کل جوجه ریزی‌ها" value="total" />
{getRoleFromUrl() !== "CityPoultry" && (
<Tab label="گزارش فارم ها" value="info" />
)}
{/* {(getRoleFromUrl() === "CityOperator" ||
getRoleFromUrl() === "ProvinceOperator" ||
getRoleFromUrl() === "AdminX" ||
getRoleFromUrl() === "SuperAdmin") && (
<Tab label="اختلاف کشتار" value="bar-difference" />
)} */}
{/* {(getRoleFromUrl() === "AdminX" ||
getRoleFromUrl() === "SuperAdmin") && (
<Tab label="آپدیت جوجه ریزی" value="hatchingUpdate" />
)} */}
{/* {(getRoleFromUrl() === "AdminX" ||
getRoleFromUrl() === "SuperAdmin") && (
<Tab label="گزارش حمل مرغ زنده" value="transport-chickens" />
)} */}
{/* {(getRoleFromUrl() === "AdminX" ||
getRoleFromUrl() === "SuperAdmin") && (
<Tab label="پایش کشوری" value="national-info" />
)}*/}
</Tabs>
</Grid>
{view === "hatchingUpdate" && <CityUpdateHatching />}
{view === "transport-chickens" && <TransportChickens />}
{/* {view === "national-info" && <NationalInfo />} */}
{view === "active" && (
<Box
container
alignItems="center"
justifyContent="space-between"
// display="flex"
style={{ width: "100%" }}
pt={2}
>
<Grid
container
gap={SPACING.SMALL}
justifyContent="space-between"
mt={SPACING.TINY}
px={{
xs: 2,
sm: 0,
}}
>
{/* <Button
className="first-step"
variant={"contained"}
disabled={true}
onClick={() => {
dispatch(
DRAWER({
title: "ثبت اطلاعات جوجه ریزی",
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
content: <CityNewHatchingRequest />,
})
);
}}
>
ثبت جوجه ریزی جدید
</Button> */}
{getRoleFromUrl() !== "CityOperator" && (
<Button
className="first-step"
variant={"contained"}
onClick={() => {
dispatch(
OPEN_MODAL({
title: "انتقال به بایگانی",
content: <CityArchiveOldHatchings />,
})
);
}}
>
انتقال به بایگانی
</Button>
)}
</Grid>
{/* <ExcelUploadButton uploadUrl={""} /> */}
</Box>
)}
<Grid
alignItems={"center"}
gap={SPACING.SMALL}
direction={"column"}
px={1}
>
<Grid container mt={SPACING.SMALL}>
{view === "active" && <CityHatchings />}
{view === "info" && <CityHatchingInfo />}
{view === "bar-difference" && <ProvinceBarDifference />}
{view === "total" && <CityHatchingsTotal />}
{view === "pending" && <CityHatchingUnassigned />}
{/* {view === "active" && (
<Grid container xs={12}>
<AdvancedTable
name={
<Grid
container
alignItems="center"
gap={SPACING.SMALL}
justifyContent="space-between"
>
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Grid>
<Typography fontWeight={"bold"}>
دوره های فعال جوجه ریزی
</Typography>
</Grid>
<Grid>
<Button
variant="outlined"
onClick={() => {
if (filterType === "سن") {
setFilterType("تاریخ");
} else {
setFilterType("سن");
}
}}
>
فیلتر جستجو
</Button>
</Grid>
{filterType === "سن" && (
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Grid>
<Typography variant="caption">
فیلتر براساس سن:
</Typography>
</Grid>
<Grid style={{ width: "80px" }}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">
از سن
</InputLabel>
<Select
MenuProps={{
PaperProps: {
style: {
maxHeight: 200, // Change the maximum height as needed
width: 80, // Change the width as needed
},
},
}}
labelId="demo-simple-select-label"
id="demo-simple-select"
value={selectedAge1}
label="از سن"
onChange={(event) =>
setSelectedAge1(event.target.value)
}
>
{selectAges.map((age) => (
<MenuItem key={age} value={age}>
{age}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
<Grid style={{ width: "80px" }}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">
تا سن
</InputLabel>
<Select
MenuProps={{
PaperProps: {
style: {
maxHeight: 200, // Change the maximum height as needed
width: 80, // Change the width as needed
},
},
}}
labelId="demo-simple-select-label"
id="demo-simple-select"
value={selectedAge2}
label="تا سن"
onChange={(event) =>
setSelectedAge2(event.target.value)
}
>
{selectAges.map((age) => (
<MenuItem key={age} value={age}>
{age}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
</Grid>
)}
</Grid>
{filterType === "تاریخ" && (
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Grid>
<Typography variant="caption">
فیلتر براساس تاریخ:
</Typography>
</Grid>
<Grid>
<DatePicker
label="از تاریخ"
id="date"
renderInput={(params) => (
<TextField
style={{ width: "160px" }}
{...params}
/>
)}
value={selectedDate1}
onChange={(e) => {
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<DatePicker
label="تا تاریخ"
id="date"
renderInput={(params) => (
<TextField
style={{ width: "160px" }}
{...params}
/>
)}
value={selectedDate2}
onChange={(e) => {
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<Button
variant="contained"
onClick={() => {
dispatch(
cityGetHatchings({
selectedDate1,
selectedDate2,
})
);
}}
>
جستجو
</Button>
</Grid>
<Tooltip title="خروجی اکسل">
<a
href={`${axios.defaults.baseURL}0/hatching_excel/?start=${selectedDate1}&end=${selectedDate2}`}
rel="noreferrer"
>
<Button color="success">
<RiFileExcel2Fill size={32} />
</Button>
</a>
</Tooltip>
</Grid>
)}
</Grid>
}
data={dataTable}
columns={[
"ردیف",
"نام فارم",
"مرغدار",
"شهر/تعاونی",
"دامپزشک فارم",
"سالن",
"دوره جوجه ریزی",
"تاریخ ثبت جوجه ریزی",
"تاریخ جوجه ریزی",
"نژاد",
"سن",
"تعداد جوجه ریزی",
"تلفات دوره",
"کشتار شده",
"مانده در سالن",
"کشتار فعال",
"تعداد درخواست کشتار",
"آخرین تغییر",
"عملیات",
]}
/>
</Grid>
)} */}
{view === "archive" && (
<CityHatchingsArchive />
// <Grid container width="100%" flex="1">
// <AdvancedTable
// name={
// <Grid container alignItems="center" gap={SPACING.SMALL}>
// <Grid>
// <Typography>بایگانی جوجه ریزی</Typography>
// </Grid>
// <Grid>
// <DatePicker
// label="از تاریخ"
// id="date"
// renderInput={(params) => (
// <TextField style={{ width: "160px" }} {...params} />
// )}
// value={selectedDate1}
// onChange={(e) => {
// setSelectedDate1(moment(e).format("YYYY-MM-DD"));
// }}
// />
// </Grid>
// <Grid>
// <DatePicker
// label="تا تاریخ"
// id="date"
// renderInput={(params) => (
// <TextField style={{ width: "160px" }} {...params} />
// )}
// value={selectedDate2}
// onChange={(e) => {
// setSelectedDate2(moment(e).format("YYYY-MM-DD"));
// }}
// />
// </Grid>
// <Tooltip title="خروجی اکسل">
// <a
// href={`${axios.defaults.baseURL}0/hatching_excel/?start=${selectedDate1}&end=${selectedDate2}`}
// rel="noreferrer"
// >
// <Button color="success">
// <RiFileExcel2Fill size={32} />
// </Button>
// </a>
// </Tooltip>
// </Grid>
// }
// data={dataTableHatchingArchive}
// columns={[
// "ردیف",
// "نام فارم",
// "کدکاربری",
// "تلفن",
// "سالن",
// "دوره جوجه ریزی",
// "تاریخ ثبت جوجه ریزی",
// "تاریخ جوجه ریزی",
// "نژاد",
// "سن",
// "تعداد جوجه ریزی",
// "تلفات دوره",
// "کشتار شده",
// "مانده در سالن",
// ]}
// />
// </Grid>
)}
</Grid>
</Grid>
</Grid>
);
};

View File

@@ -0,0 +1,326 @@
import { SPACING } from "../../../../data/spacing";
import { Grid } from "../../../../components/grid/Grid";
import {
Autocomplete,
Button,
FormControl,
FormHelperText,
IconButton,
InputLabel,
MenuItem,
Select,
TextField,
Typography,
} from "@mui/material";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { useEffect } from "react";
import moment from "moment/moment";
import { DatePicker } from "@mui/x-date-pickers";
import { useDispatch } from "react-redux";
import { useState } from "react";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import SearchIcon from "@mui/icons-material/Search";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { NumberInput } from "../../../../components/number-format-custom/NumberFormatCustom";
import { cityGetPoultryData } from "../../services/city-get-poultry-data";
import { avicultureNewHatching } from "../../../aviculture/services/aviculture-new-hatching";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { cityGetHatchings } from "../../services/city-get-hatchings";
import { reloadHatchings } from "../../../../lib/redux/slices/citySlice";
export const CityNewHatchingRequest = () => {
const dispatch = useDispatch();
const [poultryKey, setPolutryKey] = useState("");
const [polutryData, setpolutryData] = useState("");
const [enableHall, setEnableHall] = useState(true);
const [numberOfhalls, setNumberOfHalls] = useState(1);
const [numberOfhallSelected, setNumberOfHallSelected] = useState(null);
const [openNotif, , selectedDate1, , selectedDate2] = useContext(AppContext);
const formik2 = useFormik({
initialValues: {
userInfoCheck: "",
},
validationSchema: Yup.object({
userInfoCheck: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا فیلد را به درستی وارد کنید!"),
}),
});
const formik = useFormik({
initialValues: {
quantity: "",
hatchingDate: moment(Date()).format("YYYY-MM-DD hh:mm:ss"),
race: "آرین",
},
validationSchema: Yup.object({
quantity: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
}),
});
useEffect(() => {
formik.validateForm();
formik2.validateForm();
}, []);
useEffect(() => {
if (poultryKey) {
if (numberOfhalls === 0) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "ابتدا برای این مرغداری جوجه ریزی ثبت کنید.",
severity: "error",
});
dispatch(DRAWER({ right: false, bottom: false, content: null }));
} else {
setEnableHall(false);
}
}
}, [poultryKey]);
return (
<>
{!polutryData ? (
<Grid>
<Typography>جستجو کاربر</Typography>
<Grid mt={SPACING.SMALL} display="flex" width={1}>
<TextField
fullWidth
id="userInfoCheck"
label="شماره موبایل یا کد ملی یا شناسه یکتا"
variant="outlined"
value={formik2.values.userInfoCheck}
error={
formik2.touched.userInfoCheck
? Boolean(formik2.errors.userInfoCheck)
: null
}
onChange={formik2.handleChange}
onBlur={formik2.handleBlur}
helperText={
formik2.touched.userInfoCheck &&
Boolean(formik2.errors.userInfoCheck)
? formik2.errors.userInfoCheck
: null
}
/>
<IconButton
disabled={!formik2.isValid}
aria-label="delete"
color="primary"
onClick={() => {
dispatch(LOADING_START());
dispatch(cityGetPoultryData(formik2.values.userInfoCheck)).then(
(r) => {
dispatch(LOADING_END());
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "کاربر یافت نشد",
severity: "error",
});
}
setpolutryData(r.payload.data);
}
);
}}
>
<SearchIcon />
</IconButton>
</Grid>
<FormHelperText>شماره موبایل با صفر شروع میشود!</FormHelperText>
</Grid>
) : (
<Grid
container
gap={SPACING.SMALL}
direction="column"
flex="1"
height="100%"
justifyContent="space-between"
>
<Grid container direction="column" gap={SPACING.SMALL}>
<Grid>
<Autocomplete
disablePortal
id="hatching"
options={
polutryData
? polutryData.map((i) => ({
id: i.key,
label: i.unitName,
halls: i.numberOfHalls,
}))
: []
}
onChange={(event, value) => {
setPolutryKey(value.id);
setNumberOfHalls(value.halls);
}}
renderInput={(params) => (
<TextField {...params} label="محل پرورش" />
)}
/>
</Grid>
<Grid>
<Autocomplete
disabled={enableHall}
disablePortal
options={[...Array(numberOfhalls)].map((e, i) => ({
label: "سالن شماره " + (i + 1),
id: i,
}))}
onChange={(event, value) => {
setNumberOfHallSelected(value.id + 1);
}}
renderInput={(params) => (
<TextField {...params} label="سالن را انتخاب کنید" />
)}
/>
</Grid>
<NumberInput
allowLeadingZeros
thousandSeparator=","
id="quantity"
value={formik.values.quantity}
error={
formik.touched.quantity ? Boolean(formik.errors.quantity) : null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.quantity && Boolean(formik.errors.quantity)
? formik.errors.quantity
: null
}
label="تعداد"
variant="outlined"
/>
<DatePicker
label="تاریخ جوجه ریزی"
id="hatchingDate"
renderInput={(params) => <TextField {...params} />}
value={formik.values.hatchingDate}
error={
formik.touched.hatchingDate
? Boolean(formik.errors.hatchingDate)
: null
}
onChange={(e) => {
formik.setFieldValue(
"hatchingDate",
moment(e).format("YYYY-MM-DD hh:mm:ss")
);
}}
onBlur={formik.handleBlur}
helperText={
formik.touched.hatchingDate &&
Boolean(formik.errors.hatchingDate)
? formik.errors.hatchingDate
: null
}
/>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">نژاد مرغ</InputLabel>
<Select
labelId="demo-simple-select-label"
id="race"
label="نژاد مرغ"
value={formik.values.race}
error={formik.touched.race ? Boolean(formik.errors.race) : null}
onChange={(e) => {
formik.setFieldValue("race", e.target.value);
}}
onBlur={formik.handleBlur}
>
<MenuItem value={"آرین"}>آرین</MenuItem>
<MenuItem value={"راس"}>راس</MenuItem>
<MenuItem value={"آربراکرز (آپلاس)"}>آربراکرز (آپلاس)</MenuItem>
<MenuItem value={"کاب"}>کاب</MenuItem>
<MenuItem value={"هوبارد"}>هوبارد</MenuItem>
<MenuItem value={"ترکیبی"}>ترکیبی</MenuItem>
<MenuItem value={"وارداتی"}>وارداتی</MenuItem>
</Select>
<FormHelperText>
{formik.touched.race && Boolean(formik.errors.race)
? formik.errors.race
: null}
</FormHelperText>
</FormControl>
</Grid>
<Grid>
<Button
disabled={
formik.isValid && poultryKey.length && numberOfhallSelected
? false
: true
}
fullWidth
variant="contained"
onClick={() => {
dispatch(LOADING_START());
dispatch(
avicultureNewHatching({
role: getRoleFromUrl(),
key: poultryKey,
quantity: formik.values.quantity,
date: formik.values.hatchingDate,
chicken_breed: formik.values.race,
hall: numberOfhallSelected,
})
).then((r) => {
dispatch(reloadHatchings());
dispatch(cityGetHatchings({ selectedDate1, selectedDate2 }));
if (r.error) {
if (r.error.message.includes("403")) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "قبلا برای این تاریخ یا این سالن جوجه ریزی ثبت شده است.",
severity: "error",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
}
} else {
dispatch(
DRAWER({ right: false, bottom: false, content: null })
);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
dispatch(LOADING_END());
});
}}
>
ثبت اطلاعات
</Button>
</Grid>
</Grid>
)}
</>
);
};

View File

@@ -0,0 +1,77 @@
import { Tab, Tabs } from "@mui/material";
import { useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { ProvinceManagePoultryRequest } from "../../../province/components/province-manage-poultry-request/ProvinceManagePoultryRequest";
import { ProvinceManageSlaughterRequest } from "../../../province/components/province-manage-slaughter-request/ProvinceManageSlaughterRequest";
import { CityManageHatchings } from "../city-manage-hatchings/CityManageHatchings";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
export const CityHatching = () => {
// const handleSubmit = (event) => {
// event.preventDefault();
// // Handle form submission here
// dispatch(
// updatePoultryRequestsTotalQuantityService({
// key: poultryRequestsTotalQuantity?.key,
// input_quantity: Number(formik.values.numberInput),
// })
// ).then((r) => {
// openNotif({
// vertical: "top",
// horizontal: "center",
// msg: "عملیات با موفقیت انجام شد.",
// severity: "success",
// });
// });
// };
const [activeTab, setActiveTab] = useState(0);
const handleTabChange = (event, newValue) => {
setActiveTab(newValue);
};
return (
<Grid container gap={SPACING.MEDIUM} alignItems="center" direction="column">
<>
<Tabs
scrollButtons="auto"
variant="scrollable"
allowScrollButtonsMobile
value={activeTab}
onChange={handleTabChange}
>
<Tab label="درخواست مرغدار" />
{getRoleFromUrl() !== "CityPoultry" && (
<Tab label="درخواست کشتارگاه" />
)}
{/* <Tab label="جوجه ریزی" /> */}
</Tabs>
<TabPanel value={activeTab} index={2}>
<CityManageHatchings />
</TabPanel>
<TabPanel value={activeTab} index={0}>
<ProvinceManagePoultryRequest />
</TabPanel>
<TabPanel value={activeTab} index={1}>
{getRoleFromUrl() !== "CityPoultry" ? (
<ProvinceManageSlaughterRequest />
) : (
<CityManageHatchings />
)}
</TabPanel>
</>
</Grid>
);
};
function TabPanel(props) {
const { children, value, index } = props;
return (
<div role="tabpanel" hidden={value !== index}>
{value === index && <>{children}</>}
</div>
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
import { Button, Card } from "@mui/material";
import React from "react";
import { useDispatch } from "react-redux";
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
import { Grid } from "../../../../components/grid/Grid";
import { columnsName } from "../../../../data/columnsName";
import { SPACING } from "../../../../data/spacing";
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
import { AvicultureNewRequest } from "../../../aviculture/components/aviculture-new-request/AvicultureNewRequest";
export const CityNewRequest = () => {
const dispatch = useDispatch();
return (
<Grid container gap={SPACING.MEDIUM} direction="column" xs={12}>
<Grid
container
gap={SPACING.SMALL}
justifyContent={{ xs: "center", lg: "space-between" }}
alignSelf="center"
alignItems="center"
xs={12}
direction={{ xs: "column", lg: "row" }}
>
<Grid
container
xs={12}
gap={SPACING.SMALL}
alignItems={"start"}
direction={"column"}
>
<Grid container width="100%" justifyContent="space-between">
<Button
className="avicultureNewRequestBtn"
variant={"contained"}
onClick={() => {
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
title: "اطلاعات جوجه ریزی",
content: <AvicultureNewRequest />,
})
);
}}
>
ثبت درخواست کشتار جدید
</Button>
</Grid>
<Grid width="100%" className="avicultureActiveRequestsView">
<Card>
<AdvancedTable
name={"درخواست های فعال کشتار"}
columns={columnsName}
data={[["sjsjsj"]]}
/>
</Card>
</Grid>
</Grid>
</Grid>
</Grid>
);
};

View File

@@ -0,0 +1,461 @@
import { Button, TextField, Typography } from "@mui/material";
import { useContext, useEffect, useState } from "react";
import PlagiarismIcon from "@mui/icons-material/Plagiarism";
// import { ROUTE_CITY_FILE } from "../../../../routes/routes";
// import { avicultureGetRequests } from "../../../aviculture/services/aviculture-requests";
import CreateIcon from "@mui/icons-material/Create";
import CityFileOperations from "../../../file/components/city-file-operations/CityFileOperations";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { AppContext } from "../../../../contexts/AppContext";
import { PageTable } from "../../../../components/page-table/PageTable";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import axios from "axios";
import { DatePicker } from "@mui/x-date-pickers";
import moment from "moment/moment";
import { formatJustDate } from "../../../../utils/formatTime";
import { IconButton } from "@mui/material";
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
import { useDispatch } from "react-redux";
import { ROUTE_CITY_FILE } from "../../../../routes/routes";
import { useNavigate } from "react-router-dom";
import { RiSearchLine } from "react-icons/ri";
export const CityNewRequests = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
useContext(AppContext);
useEffect(() => {
const currentDate = moment(new Date()).format("YYYY-MM-DD");
setSelectedDate1(currentDate);
setSelectedDate2(currentDate);
}, []);
// page table
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [textValue, setTextValue] = useState("");
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const fetchApiData = async (page, textValue) => {
setLoading(true);
let response = await axios.get(
`Poultry_Request/?state=pending&date1=${selectedDate1}&date2=${selectedDate2}&search=filter&value=${
textValue ? textValue : ""
}&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}`
);
setData(response.data.results);
setTotalRows(response.data.count);
setLoading(false);
};
const handlePageChange = (page) => {
fetchApiData(page, textValue);
};
const handlePerRowsChange = async (newPerPage, page) => {
setLoading(true);
let response = await axios.get(
`Poultry_Request/?state=pending&date1=${selectedDate1}&date2=${selectedDate2}&search=filter&value=${
textValue ? textValue : ""
}&page=${page}&page_size=${newPerPage}`
);
setData(response.data.results);
setTotalRows(response.data.count);
setPerPage(newPerPage);
setLoading(false);
};
useEffect(() => {
fetchApiData(1);
}, [selectedDate1, selectedDate2, perPage]);
const handleSubmit = async (event) => {
event.preventDefault();
setLoading(true);
try {
const response = await axios.get(
`Poultry_Request/?state=pending&date1=${selectedDate1}&date2=${selectedDate2}&role=${getRoleFromUrl()}&search=filter&value=${
textValue ? textValue : ""
}`
);
setData(response.data.results);
setTotalRows(response.data.count);
} catch (error) {
console.error("Error fetching data:", error);
} finally {
setLoading(false);
}
};
const updateTable = () => {
fetchApiData(1);
};
const columns = [
{
name: "کدسفارش",
selector: (item) => item?.orderCode,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "تاریخ ثبت درخواست",
selector: (item) => formatJustDate(item?.createDate),
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "نوع کشتار",
selector: (item) => {
return item?.freezing ? "انجماد" : item?.export ? "صادرات" : "عادی";
},
sortable: true,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "تاریخ کشتار",
selector: (item) => formatJustDate(item?.sendDate),
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "مرغداری",
selector: (item) =>
`${item?.poultry?.unitName} (${item?.poultry?.user?.mobile})`,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "دامپزشک فارم",
selector: (item) =>
`${item?.vetFarm?.vetFarmFullname} (${item?.vetFarm?.vetFarmMobile})`,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "استان/شهر",
selector: (item) =>
`${item?.poultry?.address?.province?.name}/${item?.poultry?.address?.city?.name}`,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "تعاونی",
selector: (item) => {
return item?.poultry?.cityOperator;
},
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "تاریخ جوجه ریزی",
selector: (item) => formatJustDate(item?.hatching?.hatchingDate),
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "سن",
selector: (item) => item?.hatching?.age,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "میانگین وزن (کیلوگرم)",
selector: (item) => {
return item?.IndexWeight;
},
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "تعداد (قطعه)",
selector: (item) => item?.quantity,
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "وزن بار (کیلوگرم)",
selector: (item) => (item?.quantity * item?.IndexWeight).toLocaleString(),
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
width: "90px",
},
{
name: "عملیات",
selector: (item) => {
return (
<IconButton
color="primary"
onClick={() =>
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
content: (
<CityFileOperations
updateTable={updateTable}
id={item.id}
file={item}
/>
),
title: "انجام عملیات شهرستان",
})
)
}
>
<CreateIcon />
</IconButton>
);
},
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
{
name: "مشاهده",
selector: (item) => {
return (
<IconButton
aria-label="delete"
color="primary"
onClick={() => navigate(ROUTE_CITY_FILE + item?.id)}
>
<PlagiarismIcon />
</IconButton>
);
},
sortable: false,
wrap: true,
allowOverflow: true,
center: true,
},
];
// useEffect(() => {
// dispatch(LOADING_START());
// dispatch(avicultureGetRequests({ selectedDate1, selectedDate2 })).then(
// (r) => {
// dispatch(LOADING_END());
// }
// );
// }, [selectedDate1, selectedDate2]);
// useEffect(() => {
// const filteredData = avicultureRequests?.filter(
// (item, i) => item.stateProcess === "pending"
// );
// const d = filteredData?.map((item, i) => {
// return [
// i + 1,
// item.orderCode,
// item.poultry.userprofile.baseOrder,
// formatJustDate(item.createDate),
// formatJustDate(item.sendDate),
// item?.process?.poultry?.poultryName,
// item?.process?.poultry?.poultryMobile,
// item?.process?.poultry?.poultryCity,
// item?.process?.poultry?.poultryProvince,
// formatJustDate(item.hatching.date),
// item?.process?.poultry?.age,
// item?.process?.poultry?.poultryQuantity,
// <IconButton
// key={i}
// color="primary"
// onClick={() =>
// dispatch(
// DRAWER({
// right: !(window.innerWidth <= 600),
// bottom: window.innerWidth <= 600,
// content: (
// <CityFileOperations id={item.id} file={item?.process} />
// ),
// title: "انجام عملیات شهرستان",
// })
// )
// }
// >
// <CreateIcon />
// </IconButton>,
// <IconButton
// key={i}
// aria-label="delete"
// color="primary"
// onClick={() =>
// navigate(ROUTE_CITY_FILE + item?.process?.poultry?.poultryRequestId)
// }
// >
// <PlagiarismIcon />
// </IconButton>,
// ];
// });
// setDataTable(d);
// }, [avicultureRequests]);
return (
<>
{/* <AdvancedTable
name={
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Grid container gap={SPACING.TINY}>
<Typography>درخواست های جدید فروش اتحادیه</Typography>
</Grid>
<Grid container gap={SPACING.SMALL}>
<Grid>
<DatePicker
label="از تاریخ"
id="date"
renderInput={(params) => (
<TextField style={{ width: "160px" }} {...params} />
)}
value={selectedDate1}
onChange={(e) => {
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<DatePicker
label="تا تاریخ"
id="date"
renderInput={(params) => (
<TextField style={{ width: "160px" }} {...params} />
)}
value={selectedDate2}
onChange={(e) => {
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
</Grid>
</Grid>
}
columns={columnsName}
data={dataTable}
/> */}
<Grid alignItems="center" justifyContent="center" mt={4}>
<PageTable
title={
<Grid
container
alignItems="center"
justifyContent="space-between"
gap={2}
paddingTop={2}
mb={1}
>
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Typography>درخواست های جدید فروش اتحادیه</Typography>
<Grid container gap={SPACING.SMALL}>
<Grid>
<DatePicker
label="از تاریخ"
id="date"
renderInput={(params) => (
<TextField style={{ width: "160px" }} {...params} />
)}
value={selectedDate1}
onChange={(e) => {
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<DatePicker
label="تا تاریخ"
id="date"
renderInput={(params) => (
<TextField style={{ width: "160px" }} {...params} />
)}
value={selectedDate2}
onChange={(e) => {
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
</Grid>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button
// disabled={!textValue}
type="submit"
onClick={handleSubmit}
endIcon={<RiSearchLine />}
>
جستجو
</Button>
</form>
</Grid>
</Grid>
}
columns={columns}
data={data}
progressPending={loading}
pagination
paginationServer
paginationTotalRows={totalRows}
onChangeRowsPerPage={handlePerRowsChange}
onChangePage={handlePageChange}
/>
</Grid>
</>
);
};

View File

@@ -0,0 +1,135 @@
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { NavLink } from "../../../../components/nav-link/NavLink";
import { useLocation } from "react-router-dom";
import {
ROUTE_CITY_ACTIVE_REQUESTS,
ROUTE_CITY_ARCHIVED_REQUESTS,
ROUTE_CITY_AWAITING_INSPECTION_REQUESTS,
ROUTE_CITY_REJECTED_REQUESTS,
ROUTE_CITY_AWAITING_PAYMENT_REQUESTS,
ROUTE_CITY_NEW_REQUESTS,
ROUTE_CITY_FREE_SALES_REQUESTS,
} from "../../../../routes/routes";
import LinkItem from "../../../../components/link-item/LinkItem";
import { VscFolderActive, VscNewFolder } from "react-icons/vsc";
import { GiMoneyStack } from "react-icons/gi";
import { GrInspect } from "react-icons/gr";
import { RiFolderWarningLine } from "react-icons/ri";
import { FaArchive } from "react-icons/fa";
export const CityOperations = () => {
const { pathname } = useLocation();
return (
<Grid
container
gap={SPACING.SMALL}
p={SPACING.SMALL}
direction={{ xs: "column", md: "row" }}
justifyContent="center"
style={{ placeContent: "baseline" }}
>
<Grid container direction="column" style={{ width: "100%" }}>
<Grid container gap={SPACING.SMALL} justifyContent="center">
<NavLink
to={ROUTE_CITY_NEW_REQUESTS}
active={pathname === ROUTE_CITY_NEW_REQUESTS ? "true" : null}
>
<LinkItem
icon={<VscNewFolder size={30} color="#244CCC" />}
title="درخواست های جدید"
description="درخواست های در انتظار بررسی"
/>
</NavLink>
<NavLink
to={ROUTE_CITY_ACTIVE_REQUESTS}
active={pathname === ROUTE_CITY_ACTIVE_REQUESTS ? "true" : null}
>
<LinkItem
icon={<VscFolderActive size={30} color="#244CCC" />}
title="درخواست های فعال"
description="مشاهده درخواست های در جریان"
/>
</NavLink>
<NavLink
to={ROUTE_CITY_AWAITING_PAYMENT_REQUESTS}
active={
pathname === ROUTE_CITY_AWAITING_PAYMENT_REQUESTS ? "true" : null
}
>
<LinkItem
icon={<GiMoneyStack size={30} color="#244CCC" />}
title="در انتظار پرداخت"
description="مشاهده درخواست های در انتظار پرداخت کشتارگاه"
/>
</NavLink>
<NavLink
to={ROUTE_CITY_AWAITING_INSPECTION_REQUESTS}
active={
pathname === ROUTE_CITY_AWAITING_INSPECTION_REQUESTS
? "true"
: null
}
>
<LinkItem
icon={
<GrInspect
className="svg-icon-color"
color="#244CCC"
size={30}
/>
}
title="در انتظار بازرسی"
description="درخواست های در انتظار بررسی بازرس"
/>
</NavLink>
<NavLink
to={ROUTE_CITY_REJECTED_REQUESTS}
active={pathname === ROUTE_CITY_REJECTED_REQUESTS ? "true" : null}
>
<LinkItem
icon={
<RiFolderWarningLine
className="svg-icon-color"
color="#244CCC"
size={30}
/>
}
title="درخواست های رد شده"
description="مشاهده درخواست هایی که به دلایل مختلف توسط اتحادیه رد شده است"
/>
</NavLink>
<NavLink
to={ROUTE_CITY_FREE_SALES_REQUESTS}
active={pathname === ROUTE_CITY_FREE_SALES_REQUESTS ? "true" : null}
>
<LinkItem
icon={<VscFolderActive size={30} color="#244CCC" />}
title="فروش خارج از استان"
/>
</NavLink>
<NavLink
to={ROUTE_CITY_ARCHIVED_REQUESTS}
active={pathname === ROUTE_CITY_ARCHIVED_REQUESTS ? "true" : null}
>
<LinkItem
icon={
<FaArchive
className="svg-icon-color"
color="#244CCC"
size={30}
/>
}
title="بایگانی"
description="درخواست های پایان یافته"
/>
</NavLink>
</Grid>
</Grid>
</Grid>
);
};

View File

@@ -0,0 +1,197 @@
import {
Grid,
IconButton,
List,
ListItemButton,
ListItemIcon,
ListItemText,
Popover,
} from "@mui/material";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import { SPACING } from "../../../../data/spacing";
import { useDispatch, useSelector } from "react-redux";
import { useEffect, useState } from "react";
import { DRAWER, OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
import { CitySubmitTenantForm } from "../city-submit-tenant-form/CitySubmitTenantForm";
import { CityEditAvicultureInfoForm } from "../city-edit-aviculture-info-form/CityEditAvicultureInfoForm";
import { cityGetPoultryFarm } from "../../services/city-get-poultry-farms";
import { CityTenantOwnerInfo } from "../city-tenant-owner-info/CityTenantOwnerInfo";
import TuneIcon from "@mui/icons-material/Tune";
import PersonAddAltIcon from "@mui/icons-material/PersonAddAlt";
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
import EditOutlinedIcon from "@mui/icons-material/EditOutlined";
const PoultryFarmActions = ({ item }) => {
const dispatch = useDispatch();
const [anchorPosition, setAnchorPosition] = useState(null);
const hasTenant = Object.keys(item.poultryTenant).length !== 0;
const handleOpen = (event) => {
const rect = event.currentTarget.getBoundingClientRect();
setAnchorPosition({
top: rect.bottom + window.scrollY,
left: rect.left + rect.width / 2 + window.scrollX,
});
};
const handleClose = () => {
setAnchorPosition(null);
};
const handleAddTenant = () => {
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
title: "ایجاد مستاجر جدید",
content: <CitySubmitTenantForm id={item.key} />,
})
);
handleClose();
};
const handleShowTenantInfo = () => {
dispatch(
OPEN_MODAL({
title: "اطلاعات مستاجر",
content: <CityTenantOwnerInfo item={item} />,
})
);
handleClose();
};
const handleEditInfo = () => {
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
title: "ویرایش اطلاعات مرغدار",
content: <CityEditAvicultureInfoForm item={item} />,
})
);
handleClose();
};
return (
<Grid container justifyContent="center">
<IconButton color="primary" size="small" onClick={handleOpen}>
<TuneIcon />
</IconButton>
<Popover
anchorReference="anchorPosition"
anchorPosition={anchorPosition || undefined}
open={Boolean(anchorPosition)}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<List sx={{ p: 0 }}>
{hasTenant ? (
<ListItemButton onClick={handleShowTenantInfo}>
<ListItemIcon sx={{ minWidth: 36, color: "info.main" }}>
<InfoOutlinedIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="اطلاعات مستاجر"
primaryTypographyProps={{
variant: "body2",
color: "info",
}}
/>
</ListItemButton>
) : (
<ListItemButton onClick={handleAddTenant}>
<ListItemIcon sx={{ minWidth: 36, color: "success.main" }}>
<PersonAddAltIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="افزودن مستاجر"
primaryTypographyProps={{
variant: "body2",
color: "success",
}}
/>
</ListItemButton>
)}
<ListItemButton onClick={handleEditInfo}>
<ListItemIcon sx={{ minWidth: 36, color: "warning.main" }}>
<EditOutlinedIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary="ویرایش اطلاعات"
primaryTypographyProps={{
variant: "body2",
color: "warning",
}}
/>
</ListItemButton>
</List>
</Popover>
</Grid>
);
};
export const CityPoultryFarms = () => {
const [dataTable, setDataTable] = useState([]);
const { poultryFarms } = useSelector((state) => state.citySlice);
const dispatch = useDispatch();
useEffect(() => {
dispatch(cityGetPoultryFarm());
}, []);
useEffect(() => {
const d = poultryFarms
?.filter((item) => Object.keys(item.poultryOwner).length === 0)
.map((item, i) => {
return [
i + 1,
item.unitName,
item.userprofile.fullName,
item.userprofile.breedingUniqueId,
item.address.province.name,
item.address.city.name,
item.userprofile.mobile,
<PoultryFarmActions key={`operation-${item.key}`} item={item} />,
];
});
setDataTable(d);
}, [poultryFarms]);
const [tableDataCol] = useState([
"ردیف",
"نام مرغداری",
"نام صاحب",
"شناسه یکتا",
"استان",
"شهر",
"تلفن همراه",
"عملیات",
]);
return (
<Grid
container
alignItems="center"
justifyContent="space-between"
gap={SPACING.SMALL}
mt={SPACING.MEDIUM}
>
<ResponsiveTable
title="مرغداران زیرمجموعه"
columns={tableDataCol}
data={dataTable}
customWidth="100%"
/>
</Grid>
);
};

View File

@@ -0,0 +1,61 @@
import { Box } from "@mui/system";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { SPACING } from "../../../../data/spacing";
import {
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { ChangeCardInfo } from "../../../authentication/components/change-card-info/ChangeCardInfo";
// import { ChangeCardInfo } from "../../../authentication/components/change-card-info/ChangeCardInfo";
// import { ChangeCardInfo } from "../../../authentication/components/change-card-info/ChangeCardInfo";
import { cityGetProfile } from "../../services/city-get-profile";
export const CityProfile = () => {
const { profile } = useSelector((state) => state.citySlice);
const dispatch = useDispatch();
useEffect(() => {
dispatch(LOADING_START());
dispatch(cityGetProfile()).then((r) => {
dispatch(LOADING_END());
});
}, []);
return (
<Box>
<Grid container gap={SPACING.LARGE}>
<Grid container direction="column" xs={12}>
<Grid
container
direction="column"
justifyContent="space-between"
gap={SPACING.SMALL}
>
<>
<Grid>
<SimpleTable
name={`اطلاعات شهرستان ${profile?.user.fullname}`}
columns={["نام کامل", "تلفن", "آدرس", "کد پستی"]}
data={[
[
profile?.user.fullname,
profile?.user.mobile,
profile?.address.address,
profile?.address.postalCode,
],
]}
/>
</Grid>
<Grid>
<ChangeCardInfo item={profile} />
</Grid>
</>
</Grid>
</Grid>
</Grid>
</Box>
);
};

View File

@@ -0,0 +1,74 @@
import { Card, IconButton } from "@mui/material";
import { useEffect, useState } from "react";
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
import PlagiarismIcon from "@mui/icons-material/Plagiarism";
import { useNavigate } from "react-router-dom";
import { ROUTE_CITY_FILE } from "../../../../routes/routes";
import { FileInformation } from "../../../file/components/file-information/FileInformation";
import useAvicultureRequests from "../../../aviculture/hooks/useAvicultureRequests";
import { formatJustDate } from "../../../../utils/formatTime";
export const CityRejectedRequests = () => {
const navigate = useNavigate();
const [dataTable, setDataTable] = useState([]);
const avicultureRequests = useAvicultureRequests("CityOperator");
useEffect(() => {
const filteredData = avicultureRequests?.filter(
(item, i) => item.stateProcess === "rejected"
);
const d = filteredData?.map((item, i) => {
return [
i + 1,
item.orderCode,
formatJustDate(item?.createDate),
formatJustDate(item?.sendDate),
item?.process?.poultry?.poultryName,
item?.process?.poultry?.poultryMobile,
item?.process?.poultry?.poultryCity,
item?.process?.poultry?.poultryProvince,
item?.process?.poultry?.age,
item?.process?.poultry?.poultryQuantity,
<IconButton
key={i}
aria-label="delete"
color="primary"
onClick={() =>
navigate(ROUTE_CITY_FILE + item?.process?.poultry?.poultryRequestId)
}
>
<PlagiarismIcon />
</IconButton>,
];
});
setDataTable(d);
}, []);
const [tableDataCol] = useState([
"ردیف",
"کد سفارش",
"تاریخ ثبت درخواست",
"تاریخ درخواست",
"مرغدار",
"تلفن مرغدار",
"شهر",
"استان",
"سن مرغ",
"تعداد",
"مشاهده",
]);
return (
<Card>
<AdvancedTable
expandable
name={"درخواست های رد شده"}
columns={tableDataCol}
expandedComponentHandler={(rowData) => (
<FileInformation id={rowData[0]} />
)}
data={dataTable}
/>
</Card>
);
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,192 @@
import React, { useContext, useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import {
Button,
FormControlLabel,
Switch,
TextField,
Typography,
} from "@mui/material";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { useDispatch } from "react-redux";
import { archiveHatchingService } from "../../services/archive-hatching";
import { AppContext } from "../../../../contexts/AppContext";
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
import { FileUploader } from "../../../../components/file-uploader/FileUploader";
export const CitySubmitHatchingReport = ({ item, updateTable, isArchive }) => {
const [checked, setChecked] = useState(item?.violation);
const [sendToArchive, setSendToArchive] = useState(false);
const dispatch = useDispatch();
const handleChange = (event) => {
setChecked(event.target.checked);
};
const handleChangeArchive = (event) => {
setSendToArchive(event.target.checked);
};
const [openNotif] = useContext(AppContext);
const [filesList, setFilesList] = useState([]);
const hanleFilesChange = (e) => {
setFilesList(e);
};
const formik = useFormik({
initialValues: {
reportText: item?.violationReport,
bar_image: "",
},
validationSchema: Yup.object({
reportText: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا گزارش خود را بیان کنید."),
bar_image: Yup.array(),
}),
});
useEffect(() => {
formik.validateForm();
}, []);
// const factorPaymentHandler = (imageList, addUpdateIndex) => {
// if (imageList[0]) {
// formik.setFieldValue(
// "bar_image",
// imageList.map((img) => fixBase64(img.data_url))
// );
// }
// setProfileImages(imageList);
// };
return (
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
<FormControlLabel
control={
<Switch checked={checked} onChange={handleChange} color="primary" />
}
label={checked ? "متخلف" : "بدون تخلف"}
style={{
justifyContent: "center",
alignItems: "center",
display: "flex",
}}
/>
{!isArchive && (
<FormControlLabel
control={
<Switch
checked={sendToArchive}
onChange={handleChangeArchive}
color="primary"
/>
}
label={"انتقال به بایگانی"}
style={{
justifyContent: "center",
alignItems: "center",
display: "flex",
}}
/>
)}
<TextField
multiline
rows={4}
fullWidth
id="reportText"
label="متن گزارش"
variant="outlined"
value={formik.values.reportText}
error={
formik.touched.reportText ? Boolean(formik.errors.reportText) : null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.reportText && Boolean(formik.errors.reportText)
? formik.errors.reportText
: null
}
/>
<Typography color="error">
در صورت آپلود فایل جدید، سندهای پیشین حذف میشوند!
</Typography>
{/* <ImageUpload
onChange={factorPaymentHandler}
images={profileImages}
maxNumber={5}
title={"بارگذاری سند"}
/> */}
<FileUploader onChange={hanleFilesChange} />
{/* {item?.violationImage?.length && !profileImages?.length && (
<>
{item?.violationImage?.map((option, i) => (
<img
key={i}
src={option}
alt="تصویر گزارش"
style={{ width: "100px", borderRadius: "5px" }}
/>
))}
</>
)} */}
<Button
mt={2}
disabled={!formik.isValid || formik.isSubmitting}
fullWidth
variant="contained"
onClick={async () => {
try {
const req = {
key: item?.key,
violation_check: true,
violation: checked,
violation_report: formik.values.reportText,
archive: sendToArchive,
};
const formData = new FormData();
Object.entries(req).forEach(([key, value]) => {
formData.append(key, value);
});
filesList.forEach((file, index) => {
formData.append(`violation_image_${index}`, file);
});
const response = await dispatch(
archiveHatchingService(filesList.length ? formData : req)
);
if (response.error) {
throw new Error(response.error);
}
updateTable(1);
dispatch(CLOSE_MODAL());
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
} catch (error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: error.message || "خطا در ارسال اطلاعات",
severity: "error",
});
}
}}
>
{formik.isSubmitting ? "در حال ثبت..." : "ثبت"}
</Button>
</Grid>
);
};

View File

@@ -0,0 +1,77 @@
import React, { useContext } from "react";
import { TextField, Button } from "@mui/material";
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
import { useDispatch } from "react-redux";
import { archiveHatchingService } from "../../services/archive-hatching";
import { AppContext } from "../../../../contexts/AppContext";
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
const validationSchema = Yup.object().shape({
looses_amount: Yup.number()
.required("این فیلد اجباری است!")
.min(0, "عدد مثبت وارد کنید!"),
});
export const CitySubmitLooses = ({ updateTable, item }) => {
const dispatch = useDispatch();
const [openNotif] = useContext(AppContext);
const handleSubmit = (values, { resetForm }) => {
dispatch(
archiveHatchingService({
key: item?.key,
direct_losses: values.looses_amount,
})
).then((r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
updateTable();
dispatch(CLOSE_MODAL());
}
});
resetForm();
};
return (
<div>
<Formik
initialValues={{ looses_amount: "" }}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{({ handleChange, handleBlur }) => (
<Form>
<Field
as={TextField}
name="looses_amount"
label="حجم تلفات"
type="number"
onChange={handleChange}
onBlur={handleBlur}
fullWidth
variant="outlined"
margin="normal"
helperText={<ErrorMessage name="looses_amount" />}
/>
<Button type="submit" variant="contained" color="primary" fullWidth>
ثبت
</Button>
</Form>
)}
</Formik>
</div>
);
};

View File

@@ -0,0 +1,378 @@
import { Autocomplete, Button, TextField } from "@mui/material";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import React, { useEffect } from "react";
import { Yup } from "../../../../lib/yup/yup";
import { useFormik } from "formik";
import { useState } from "react";
import { useDispatch } from "react-redux";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { cityGetProvinces } from "../../services/CityGetProvinces";
import { cityGetCity } from "../../services/city-get-city";
import { citySubmitNewTenant } from "../../services/city-submit-new-tenant";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { PropTypes } from "prop-types";
import { provinceGetUserByKey } from "../../../province/services/province-get-user-by-key";
export const CitySubmitTenantForm = ({ id, userid }) => {
const [openNotif] = useContext(AppContext);
const dispatch = useDispatch();
const [provinceData, setProvinceData] = useState();
const [cityData, setCityData] = useState();
const [provinceKey, setProvinceKey] = useState();
const [cityKey, setCityKey] = useState();
const [isExistProvince, setIsExistProvince] = useState(true);
const formik = useFormik({
initialValues: {
mobile: "",
fname: "",
lname: "",
nationalcode: "",
address: "",
postal: "",
password: "",
uniqueID: "",
},
validationSchema: Yup.object({
mobile: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا فیلد را به صورت عددی وارد کنید!")
.test("len", "شماره تلفن باید با 0 شروع شود", (val, context) => {
return context.originalValue && context.originalValue.startsWith("0");
})
.test("len", "شماره تماس 11 رقم باید باشد", (val, context) => {
if (context.originalValue) {
return context.originalValue.length === 11;
}
}),
fname: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا فیلد را پر کنید!"),
lname: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا فیلد را پر کنید!"),
nationalcode: Yup.number()
.required("این فیلد اجباری است!")
.test("len", "کد ملی میبایست ده رقم باشد.", (val, context) => {
if (context.originalValue) {
return context.originalValue.length === 10;
}
}),
address: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا فیلد را پر کنید!"),
postal: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا فیلد را به صورت عددی وارد کنید!"),
uniqueID: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا فیلد را به صورت عددی وارد کنید!"),
password: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا مقادیر را به درستی وارد کنید!")
.test(
"len",
"لطفا حداقل 5 حرف و حداکثر 12 حرف وارد کنید",
(val) => val.toString().length >= 5 && val.toString().length <= 12
),
}),
});
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
dispatch(LOADING_START());
dispatch(cityGetProvinces())?.then((r) => {
dispatch(LOADING_END());
setProvinceData(r.payload.data);
});
}, []);
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
if (provinceKey) {
dispatch(LOADING_START());
dispatch(cityGetCity(provinceKey)).then((r) => {
setCityData(r.payload.data);
setIsExistProvince(false);
dispatch(LOADING_END());
});
}
}, [provinceKey]);
return (
<Grid
container
display="block"
gap={SPACING.SMALL}
direction="column"
flex="1"
height="100%"
justifyContent="space-between"
>
<Grid container direction="column" gap={SPACING.SMALL}>
<Grid>
<Autocomplete
disablePortal
id="province"
options={
provinceData
? provinceData?.map((i) => ({ id: i.key, label: i.name }))
: []
}
onChange={(event, value) => {
setProvinceKey(value.id);
}}
renderInput={(params) => (
<TextField {...params} label="استان را انتخاب کنید" />
)}
/>
</Grid>
<Grid>
<Autocomplete
disabled={isExistProvince}
disablePortal
id="city"
options={
cityData
? cityData.map((i) => ({ id: i.key, label: i.name }))
: []
}
onChange={(event, value) => {
setCityKey(value.id);
}}
renderInput={(params) => (
<TextField {...params} label="شهر را انتخاب کنید" />
)}
/>
</Grid>
<Grid>
<TextField
id="uniqueID"
label="شناسه یکتا مرغدار"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.uniqueID}
error={
formik.touched.uniqueID ? Boolean(formik.errors.uniqueID) : null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.uniqueID && Boolean(formik.errors.uniqueID)
? formik.errors.uniqueID
: null
}
/>
</Grid>
<Grid>
<TextField
id="fname"
label="نام"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.fname}
error={formik.touched.fname ? Boolean(formik.errors.fname) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.fname && Boolean(formik.errors.fname)
? formik.errors.fname
: null
}
/>
</Grid>
<Grid>
<TextField
id="lname"
label="نام خانوادگی "
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.lname}
error={formik.touched.lname ? Boolean(formik.errors.lname) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.lname && Boolean(formik.errors.lname)
? formik.errors.lname
: null
}
/>
</Grid>
<Grid>
<TextField
id="password"
label="رمز عبور"
type="password"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.password}
error={
formik.touched.password ? Boolean(formik.errors.password) : null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.password && Boolean(formik.errors.password)
? formik.errors.password
: null
}
/>
</Grid>
<Grid>
<TextField
id="mobile"
label="موبایل"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.mobile}
error={formik.touched.mobile ? Boolean(formik.errors.mobile) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.mobile && Boolean(formik.errors.mobile)
? formik.errors.mobile
: null
}
/>
</Grid>
<Grid>
<TextField
id="nationalcode"
label="کد ملی"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.nationalcode}
error={
formik.touched.nationalcode
? Boolean(formik.errors.nationalcode)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.nationalcode && Boolean(formik.errors.nationalcode)
? formik.errors.nationalcode
: null
}
/>
</Grid>
<Grid>
<TextField
id="address"
label="آدرس"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.address}
error={
formik.touched.address ? Boolean(formik.errors.address) : null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.address && Boolean(formik.errors.address)
? formik.errors.address
: null
}
/>
</Grid>
<Grid>
<TextField
id="postal"
label="کد پستی"
variant="outlined"
sx={{ width: "100%" }}
value={formik.values.postal}
error={formik.touched.postal ? Boolean(formik.errors.postal) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.postal && Boolean(formik.errors.postal)
? formik.errors.postal
: null
}
/>
</Grid>
<Grid mb={SPACING.SMALL}>
<Button
fullWidth
variant="contained"
disabled={!formik.isValid}
onClick={() => {
dispatch(
citySubmitNewTenant({
username: formik.values.mobile,
password: formik.values.password,
api_key: "11d89a11-bd11-2111-a02f-2cc1cbf4e1d4",
role: "Poultry",
tenant: {
poultry_key: id,
unique_id: formik.values.uniqueID,
province: provinceKey,
city: cityKey,
first_name: formik.values.fname,
last_name: formik.values.lname,
national_code: formik.values.nationalcode,
address: formik.values.address,
postal_code: formik.values.postal,
},
})
).then((r) => {
dispatch(LOADING_END());
dispatch(provinceGetUserByKey(userid));
if (r.error) {
dispatch(LOADING_END());
if (r.error.message.includes("403")) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "این مستاجر موجود است!",
severity: "error",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
}
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
dispatch(
DRAWER({ right: false, bottom: false, content: null })
);
}
});
}}
>
ثبت اطلاعات
</Button>
</Grid>
</Grid>
</Grid>
);
};
CitySubmitTenantForm.propTypes = {
id: PropTypes.any,
userid: PropTypes.any,
};

View File

@@ -0,0 +1,64 @@
import { Divider, List, ListItem, ListItemText } from "@mui/material";
import React from "react";
import { Grid } from "../../../../components/grid/Grid";
import { PropTypes } from "prop-types";
export const CityTenantOwnerInfo = ({ item }) => {
return (
<>
<Divider />
<Grid container direction="row" flexWrap="nowrap" flex="1">
<Grid>
<List
sx={{
width: "100%",
maxWidth: 360,
bgcolor: "background.paper",
}}
>
<ListItem>
<ListItemText
primary="نام"
secondary={item?.poultryTenant.fullName}
/>
</ListItem>{" "}
<Divider />
<ListItem>
<ListItemText
primary="شناسه یکتا"
secondary={item?.poultryTenant.breedingUniqueId}
/>
</ListItem>{" "}
</List>
</Grid>
<Grid>
<List
sx={{
width: "100%",
maxWidth: 360,
bgcolor: "background.paper",
}}
>
<ListItem>
<ListItemText
primary="موبایل"
secondary={item?.poultryTenant.mobile}
/>
</ListItem>{" "}
<Divider />
<ListItem>
<ListItemText
primary="کد ملی"
secondary={item?.poultryTenant.nationalId}
/>
</ListItem>
</List>
</Grid>
</Grid>
</>
);
};
CityTenantOwnerInfo.propTypes = {
item: PropTypes.object,
};

View File

@@ -0,0 +1,180 @@
import React, { useContext, useEffect, useState } from "react";
import { styled } from "@mui/material/styles";
import Button from "@mui/material/Button";
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
import { Grid } from "../../../../components/grid/Grid";
import { Typography } from "@mui/material";
import { useDispatch } from "react-redux";
import { cityUpdateHatchingService } from "../../services/city-update-hatching";
import { AppContext } from "../../../../contexts/AppContext";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { cityUpdateChickenBreedService } from "../../services/city-update-chicken-breen";
const VisuallyHiddenInput = styled("input")({
clip: "rect(0 0 0 0)",
clipPath: "inset(50%)",
height: 1,
overflow: "hidden",
position: "absolute",
bottom: 0,
left: 0,
whiteSpace: "nowrap",
width: 1,
});
export const CityUpdateHatching = () => {
const dispatch = useDispatch();
const [openNotif] = useContext(AppContext);
const [response, setResponse] = useState();
const [tableData, setTableData] = useState();
const handleFileUpload = async (event) => {
const file = event.target.files[0];
if (!file) return;
const formData = new FormData();
formData.append("file", file);
dispatch(cityUpdateHatchingService(formData))
.unwrap()
.then((r) => {
setResponse(r.data);
if (r.status === 201) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "فایل اکسل به درستی ارسال نشده است!",
severity: "error",
});
}
});
};
const handleUpdateChickenBreed = async (event) => {
const file = event.target.files[0];
if (!file) return;
const formData = new FormData();
formData.append("file", file);
dispatch(cityUpdateChickenBreedService(formData))
.unwrap()
.then((r) => {
if (r.status === 201) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "فایل اکسل به درستی ارسال نشده است!",
severity: "error",
});
}
});
};
useEffect(() => {
const d = response?.map((item, i) => {
return [i + 1, item];
});
setTableData(d);
}, [response]);
return (
<Grid
container
alignItems="center"
justifyContent="space-between"
spacing={2}
mb={1}
style={{ width: "80vw" }}
>
<Grid
xs={12}
md={6}
sm={6}
container
alignItems="center"
mt={6}
spacing={2}
justifyContent="center"
style={
window.innerWidth >= 800 && {
borderStyle: "solid",
borderWidth: "0px 0px 0px 1px",
borderColor: "gray",
}
}
>
<Grid>
<Typography variant="body1" style={{ color: "gray" }}>
آپدیت جوجه ریزی
</Typography>
</Grid>
<Grid>
<Button
component="label"
role={undefined}
variant="contained"
tabIndex={-1}
startIcon={<CloudUploadIcon />}
>
آپلود فایل اکسل
<VisuallyHiddenInput type="file" onChange={handleFileUpload} />
</Button>
{response?.length ? (
<Grid container xs={12} justifyContent="start">
<SimpleTable
columns={["ردیف", "شناسه یکتا"]}
name={"مرغداران ناموجود در سامانه"}
data={tableData}
/>
</Grid>
) : (
<></>
)}
</Grid>
</Grid>
<Grid
xs={12}
md={6}
sm={6}
container
alignItems="center"
mt={6}
spacing={2}
justifyContent="center"
>
<Grid>
<Typography variant="body1" style={{ color: "gray" }}>
آپدیت نژاد
</Typography>
</Grid>
<Grid>
<Button
component="label"
role={undefined}
variant="contained"
tabIndex={-1}
startIcon={<CloudUploadIcon />}
>
آپلود فایل اکسل
<VisuallyHiddenInput
type="file"
onChange={handleUpdateChickenBreed}
/>
</Button>
</Grid>
</Grid>
</Grid>
);
};

View File

@@ -0,0 +1,111 @@
import { Button, Grid } from "@mui/material";
import { useFormik } from "formik";
import { useContext, useEffect } from "react";
import { useDispatch } from "react-redux";
import { NumberInput } from "../../../../components/number-format-custom/NumberFormatCustom";
import { AppContext } from "../../../../contexts/AppContext";
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { avicultureHatchingRequestsService } from "../../../aviculture/services/aviculture-hatching-requests";
import { avicultureGetRequests } from "../../../aviculture/services/aviculture-requests";
import { updateKillPoultryRequest } from "../../../province/services/update-kill-poultry-request";
import { cityGetHatchings } from "../../services/city-get-hatchings";
import { getSlaughtersKillRequestService } from "../../services/get-slaughters-kill-request";
export const CityUpdateKillRequest = ({ item, updateTable }) => {
const [openNotif] = useContext(AppContext);
const dispatch = useDispatch();
const [, , selectedDate1, , selectedDate2] = useContext(AppContext);
const formik = useFormik({
initialValues: {
quantity: "",
},
validate: (values) => {
const errors = {};
if (!values.quantity) {
errors.quantity = "Required";
} else if (isNaN(values.quantity)) {
errors.quantity = "Must be a number";
}
// else if (
// values.quantity > item.process?.poultry?.poultryPreviousQuantity
// ) {
// errors.quantity =
// "Quantity cannot be greater than poultryPreviousQuantity";
// } else if (0 >= item.process?.poultry?.poultryRemainQuantity) {
// errors.quantity =
// "Quantity cannot be greater than poultryPreviousQuantity";
// }
return errors;
},
onSubmit: (values) => {
// console.log(values);
},
});
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
formik.setFieldValue("quantity", item.quantity);
}, [item.quantity]);
return (
<Grid direction="row" display="flex" key="ooo">
<NumberInput
allowLeadingZeros
thousandSeparator=","
id="quantity"
onChange={formik.handleChange}
value={formik.values.quantity}
style={{ width: 80, textAlign: "center" }}
/>
<Button
disabled={!formik.isValid}
onClick={() => {
dispatch(
updateKillPoultryRequest({
key: item.key,
quantity: Number(formik.values.quantity),
state: "accepted_quantity",
})
).then((r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
dispatch(CLOSE_MODAL());
updateTable();
dispatch(
avicultureHatchingRequestsService({
selectedDate1,
selectedDate2,
})
);
dispatch(getSlaughtersKillRequestService());
dispatch(avicultureGetRequests());
dispatch(cityGetHatchings(getRoleFromUrl()));
dispatch(avicultureGetRequests());
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
ثبت
</Button>
</Grid>
);
};

View File

@@ -0,0 +1,411 @@
import {
Button,
FormControlLabel,
IconButton,
Switch,
Tooltip,
Typography,
} from "@mui/material";
import React from "react";
import { useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import NavigateNextIcon from "@mui/icons-material/NavigateNext";
import { useDispatch, useSelector } from "react-redux";
import { useState } from "react";
import EditIcon from "@mui/icons-material/Edit";
import InfoIcon from "@mui/icons-material/Info";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { provinceGetUserByKey } from "../../../province/services/province-get-user-by-key";
import { InspectorEditUserProfile } from "../../../inspector/components/inspector-edit-user-profile/InspectorEditUserProfile";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { inspectorChangeUserState } from "../../../inspector/services/inspector-change-user-state";
import { CitySubmitTenantForm } from "../city-submit-tenant-form/CitySubmitTenantForm";
import { InspectorEditAviculture } from "../../../inspector/components/inspector-edit-aviculture/InspectorEditAviculture";
import { format } from "date-fns-jalali";
// import { inspectorUpdateUserProfile } from "../../services/inspector-update-user-profile";
export const CityUserFileInfo = () => {
const { userid } = useParams();
const dispatch = useDispatch();
const navigate = useNavigate();
const [dataTable, setDataTable] = useState([]);
const { provinceUserInfo } = useSelector((state) => state.provinceSlice);
useEffect(() => {
dispatch(LOADING_START());
dispatch(provinceGetUserByKey(userid)).then(() => {
dispatch(LOADING_END());
});
}, []);
useEffect(() => {
const userRoles = provinceUserInfo?.profile.role?.map((item, i) => {
let name = "";
switch (item) {
case "ProvinceOperator":
name = "اپراتور تخصیص استان";
break;
case "CityOperator":
name = "اپراتور شهرستان";
break;
case "KillHouseVet":
name = "دامپزشک کشتارگاه";
break;
case "VetFarm":
name = "دامپزشک";
break;
case "Poultry":
name = "مرغدار";
break;
case "KillHouse":
name = "کشتارگاه";
break;
case "Vet":
name = "دامپزشک";
break;
case "ProvinceInspector":
name = "بازرس استان";
break;
case "ProvinceFinancial":
name = "اپراتور مالی";
break;
case "Driver":
name = "راننده";
break;
case "Admin":
name = "ادمین";
break;
default:
name = "کاربر پایه";
break;
}
return <div key={i}>{name}</div>;
});
const userProfilePic =
provinceUserInfo?.profile?.image > 5 ? (
<a href={provinceUserInfo?.profile.image}>
<img
width="80"
height="80"
alt="img"
src={provinceUserInfo?.profile.image}
/>
</a>
) : (
"موجود نیست"
);
const b = [
[
provinceUserInfo?.profile?.fullname
? provinceUserInfo?.profile?.fullname
: provinceUserInfo?.profile?.firstName +
" " +
provinceUserInfo?.profile?.lastName,
userRoles,
provinceUserInfo?.profile?.mobile,
provinceUserInfo?.profile?.birthday
? format(new Date(provinceUserInfo?.profile?.birthday), "yyyy/MM/dd")
: "نامشخص",
provinceUserInfo?.profile?.city,
<Typography variant="caption" key="password">
{provinceUserInfo?.profile?.password}
</Typography>,
userProfilePic,
<IconButton
key={provinceUserInfo}
aria-label="delete"
color="primary"
className="avicultureActiveRequestsBtn"
onClick={() => {
// dispatch(inspectorUpdateUserProfile());
dispatch(
DRAWER({
title: "ویرایش پروفایل کاربر",
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
content: (
<InspectorEditUserProfile
id={provinceUserInfo?.profile?.key}
birthday={provinceUserInfo?.profile?.birthday}
nationalCode={provinceUserInfo?.profile?.nationalCode}
nationalId={provinceUserInfo?.profile?.nationalId}
firstName={provinceUserInfo?.profile?.firstName}
lastName={provinceUserInfo?.profile?.lastName}
password={provinceUserInfo?.profile?.password}
phone={provinceUserInfo?.profile?.mobile}
/>
),
})
);
}}
>
<EditIcon />
</IconButton>,
],
];
setDataTable(b);
}, [provinceUserInfo]);
return (
<>
<Grid container alignItems="center" mt={SPACING.SMALL}>
<IconButton
aria-label="delete"
color="primary"
onClick={() => navigate(-1)}
>
<NavigateNextIcon />
<Typography>بازگشت</Typography>
</IconButton>
</Grid>
<Grid
container
xs={12}
alignItems={"start"}
gap={SPACING.SMALL}
direction={"column"}
>
<Grid
width="100%"
container
alignItems="center"
justifyContent="space-between"
>
<Grid width="100%" className="second">
<SimpleTable
name="اطلاعات پایه کاربر"
columns={[
"نام کامل",
"نوع کاربری",
"شمار تلفن",
"تاریخ تولد",
"شهر",
"کلمه عبور",
"تصویر پروفایل",
"ویرایش",
]}
data={dataTable}
/>
{provinceUserInfo?.rolesData?.map((item, i) => {
if (Object.keys(item).includes("Poultry")) {
return (
<>
<SimpleTable
key={i}
name="اطلاعات مرغدار"
columns={[
"نام فارم",
"آدرس",
"استان",
"شهر",
"کد پستی",
"موبایل",
"شناسه یکتا",
"کد اقتصادی",
"کد اپیدمیولوژیک",
"تعداد سالن",
"ویرایش",
"وضعیت",
]}
data={[
[
item.Poultry?.unitName,
item.Poultry.address?.address,
item.Poultry.address?.province?.name,
item.Poultry.address?.city?.name,
Number(item.Poultry.address?.postalCode),
item.Poultry.address?.phone,
item.Poultry.breedingUniqueId,
item.Poultry.economicCode,
item.Poultry.epidemiologicalCode,
item.Poultry.numberOfHalls,
<Tooltip
key={i}
title={"ویرایش کاربر"}
placement="bottom-start"
>
<IconButton
aria-label="delete"
color="primary"
className="avicultureActiveRequestsBtn"
onClick={() => {
dispatch(
DRAWER({
title: "ویرایش اطلاعات مرغدار",
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
content: (
<InspectorEditAviculture
farmName={item.Poultry?.unitName}
id={provinceUserInfo?.profile.key}
type="Poultry"
uniqueId={
item.Poultry?.breedingUniqueId
}
address={item.Poultry.address?.address}
poultry={item.Poultry?.key}
halls={item.Poultry.numberOfHalls}
postal={Number(
item.Poultry.address?.postalCode
)}
accountHolder={
item.Poultry.userBankInfo
?.nameOfBankUser
}
card={item.Poultry.userBankInfo?.card}
shaba={item.Poultry.userBankInfo?.shaba}
account={
item.Poultry.userBankInfo?.account
}
name_of_bank_user={
item.Poultry.userBankInfo?.bankName
}
/>
),
})
);
}}
>
<EditIcon />
</IconButton>
</Tooltip>,
<Tooltip
key={i}
title={
item.Poultry.trash === true
? "فعالسازی کاربر"
: "غیر فعال کردن کاربر"
}
placement="bottom-start"
>
<FormControlLabel
label={
item.Poultry.trash === true
? "غیرفعال"
: " فعال"
}
control={
<Switch
checked={!item.Poultry.trash}
onClick={() => {
dispatch(LOADING_START());
dispatch(
inspectorChangeUserState({
type:
item.Poultry.trash === true
? "Activate"
: "Deactivate",
role_data_key: item.Poultry.key,
role: "Poultry",
})
).then((r) => {
dispatch(LOADING_END());
window.location.reload(false);
});
}}
/>
}
/>
</Tooltip>,
],
]}
/>
<SimpleTable
key={i}
name="اطلاعات بانکی مرغدار"
expandable
columns={[
"نام صاحب حساب",
"نام بانک",
"شماره حساب",
"شماره کارت",
"شماره شبا",
]}
data={[
[
item.Poultry.userBankInfo?.nameOfBankUser,
item.Poultry.userBankInfo?.bankName,
Number(item.Poultry.userBankInfo?.account),
Number(item.Poultry.userBankInfo?.card),
item.Poultry.userBankInfo?.shaba,
],
]}
/>
{Object.keys(item.Poultry?.poultryTenant).length > 0 ? (
<SimpleTable
key={i}
name="اطلاعات مستاجر مرغدار"
expandable
columns={[
"شناسه یکتا",
"نام کامل",
"تلفن همراه",
"کد ملی",
]}
data={[
[
item.Poultry.poultryTenant?.breedingUniqueId,
item.Poultry.poultryTenant?.fullName,
item.Poultry.poultryTenant?.mobile,
item.Poultry.poultryTenant?.nationalId,
],
]}
/>
) : (
!item.Poultry.poultryOwner.length > 0 && (
<Grid
display="flex"
mt={SPACING.MEDIUM}
gap={SPACING.SMALL}
alignItems="center"
mb={SPACING.MEDIUM}
>
<Grid display="flex" gap={SPACING.TINY}>
<InfoIcon color="primary" />
<Typography>مرغدار مستاجر ندارد</Typography>
</Grid>
<Button
variant="outlined"
onClick={() => {
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
title: "ایجاد مستاجر جدید",
content: (
<CitySubmitTenantForm
id={item.Poultry.key}
userid={userid}
/>
),
})
);
}}
>
افزودن مستاجر
</Button>
</Grid>
)
)}
</>
);
}
return null;
})}
</Grid>
</Grid>
</Grid>
</>
);
};

View File

@@ -0,0 +1,199 @@
import {
Button,
Checkbox,
FormControlLabel,
IconButton,
Tooltip,
Typography,
} from "@mui/material";
import { useState } from "react";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import ContactPageIcon from "@mui/icons-material/ContactPage";
import { useNavigate } from "react-router-dom";
import { ROUTE_CITY_USER_FILE } from "../../../../routes/routes";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
import { CitySubmitAviculture } from "../city-submit-aviculture/CitySubmitAviculture";
import { cityGetUserProfiles } from "../../services/city-get-user-profiles";
export const CityUsers = () => {
const dispatch = useDispatch();
const [dataTable, setDataTable] = useState([]);
const navigate = useNavigate();
const { cityUsers } = useSelector((state) => state.citySlice);
useEffect(() => {
dispatch(LOADING_START());
dispatch(cityGetUserProfiles()).then((r) => {
dispatch(LOADING_END());
});
}, []);
const [justBaseUsers, setJustBaseUsers] = useState(false);
const handleChange = (event) => {
setJustBaseUsers(!justBaseUsers);
};
const [filteredData, setFilteredData] = useState(cityUsers);
useEffect(() => {
if (justBaseUsers) {
const newUsers = cityUsers?.filter((item, i) => {
return item?.profile?.role.length === 0;
});
setFilteredData(newUsers);
} else {
setFilteredData(cityUsers);
}
const d = filteredData?.map((item, i) => {
return [
i + 1,
item?.profile?.fullname
? item?.profile?.fullname
: item?.profile?.firstName + " " + item?.profile?.lastName,
<Grid key={i}>
{!(item?.profile?.role.length > 0) && "کاربر پایه"}
{item?.profile?.role?.map((item, i) => {
var name = "";
switch (item) {
case "ProvinceOperator":
name = "اپراتور تخصیص استان";
break;
case "CityOperator":
name = "اپراتور شهرستان";
break;
case "KillHouseVet":
name = "دامپزشک کشتارگاه";
break;
case "VetFarm":
name = "دامپزشک";
break;
case "Poultry":
name = "مرغدار";
break;
case "KillHouse":
name = "کشتارگاه";
break;
case "Vet":
name = "دامپزشک";
break;
case "ProvinceInspector":
name = "بازرس استان";
break;
case "ProvinceFinancial":
name = "اپراتور مالی";
break;
case "Driver":
name = "راننده";
break;
case "Admin":
name = "ادمین";
break;
default:
break;
}
return [<Grid key={i}>{name}</Grid>];
})}
</Grid>,
item?.profile?.mobile,
item?.profile?.baseOrder,
item?.profile?.city,
<Typography key="s" variant="caption">
{item?.profile?.password}
</Typography>,
<Grid key={i}>
<Tooltip key={i} title={"پرونده کاربر"} placement="right-start">
<IconButton
aria-label="delete"
color="primary"
className="avicultureActiveRequestsBtn"
onClick={() => {
navigate(ROUTE_CITY_USER_FILE + item?.profile?.key);
}}
>
<ContactPageIcon />
</IconButton>
</Tooltip>
</Grid>,
];
});
setDataTable(d);
}, [cityUsers, justBaseUsers, filteredData]);
return (
<Grid
container
xs={12}
alignItems={"start"}
gap={SPACING.SMALL}
direction={"column"}
>
<Grid
width="100%"
container
alignItems="center"
justifyContent="space-between"
>
<Grid
alignItems="center"
flexDirection="inherit"
container
mt={SPACING.MEDIUM}
gap={SPACING.SMALL}
>
<Button
className="first-step"
variant={"contained"}
onClick={() => {
dispatch(
DRAWER({
title: "ثبت کاربر جدید",
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
content: <CitySubmitAviculture />,
})
);
}}
>
ثبت کاربر جدید
</Button>
<FormControlLabel
mt={SPACING.SMALL}
control={<Checkbox />}
label="فقط نمایش کاربران پایه"
onChange={handleChange}
/>
</Grid>
<Grid width="100%" className="second">
<AdvancedTable
expandable
columns={[
"ردیف",
"نام کامل",
"نوع کاربری",
"شمار تلفن",
"کد کاربری",
"شهر",
"کلمه عبور",
"پرونده",
]}
data={dataTable}
/>
</Grid>
</Grid>
</Grid>
);
};

View File

@@ -0,0 +1,67 @@
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { NavLink } from "../../../../components/nav-link/NavLink";
import LinkItem from "../../../../components/link-item/LinkItem";
import { VscCompassDot } from "react-icons/vsc";
import { IoIosArrowDropupCircle } from "react-icons/io";
import {
ROUTE_ADMINX_DIFFRENCE_KILLER_SLAUGHTER,
ROUTE_ADMINX_INCREASE_HATCHING,
ROUTE_CITY_DIFFRENCE_KILLER_SLAUGHTER,
ROUTE_CITY_INCREASE_HATCHING,
ROUTE_PROVINCE_DIFFRENCE_KILLER_SLAUGHTER,
ROUTE_PROVINCE_INCREASE_HATCHING,
ROUTE_SUPER_ADMIN_DIFFRENCE_KILLER_SLAUGHTER,
ROUTE_SUPER_ADMIN_INCREASE_HATCHING,
} from "../../../../routes/routes";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
export const CityManageDiffrenceKillerOperation = () => {
return (
<Grid
container
gap={SPACING.SMALL}
p={SPACING.SMALL}
direction={{ xs: "row", md: "row" }}
justifyContent="center"
>
<NavLink
to={
getRoleFromUrl() === "AdminX"
? ROUTE_ADMINX_DIFFRENCE_KILLER_SLAUGHTER
: getRoleFromUrl() === "SuperAdmin"
? ROUTE_SUPER_ADMIN_DIFFRENCE_KILLER_SLAUGHTER
: getRoleFromUrl() === "ProvinceOperator"
? ROUTE_PROVINCE_DIFFRENCE_KILLER_SLAUGHTER
: getRoleFromUrl() === "CityOperator"
? ROUTE_CITY_DIFFRENCE_KILLER_SLAUGHTER
: ""
}
>
<LinkItem
icon={<VscCompassDot size={30} color="#244CCC" />}
title="اختلاف کشتار در کشتارگاه"
/>
</NavLink>
<NavLink
to={
getRoleFromUrl() === "AdminX"
? ROUTE_ADMINX_INCREASE_HATCHING
: getRoleFromUrl() === "SuperAdmin"
? ROUTE_SUPER_ADMIN_INCREASE_HATCHING
: getRoleFromUrl() === "ProvinceOperator"
? ROUTE_PROVINCE_INCREASE_HATCHING
: getRoleFromUrl() === "CityOperator"
? ROUTE_CITY_INCREASE_HATCHING
: ""
}
>
<LinkItem
icon={<IoIosArrowDropupCircle size={30} color="#244CCC" />}
title="افزایش حجم جوجه ریزی"
/>
</NavLink>
</Grid>
);
};

View File

@@ -0,0 +1,45 @@
import React, { useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
import { CheckCleanceCode } from "../../../../components/check-clearance-code/ChechClearanceCode";
export const NationalInfoDetails = ({ data }) => {
const [tableData, setTableData] = useState([]);
useEffect(() => {
const d = data?.bars?.map((item, i) => {
return [
i + 1,
<CheckCleanceCode key={i} clearanceCode={item?.TrackingCode} />,
item?.IssueDatePersian,
item?.GoodAmount?.toLocaleString(),
item?.TrackingStatusDescription,
item?.GoodName,
item?.DesPartIdCode,
item?.DesUnitName,
item?.ResideDatePersian,
];
});
setTableData(d);
}, [data]);
return (
<Grid xs={12} container justifyContent="center">
<AdvancedTable
name="اطلاعات حمل مرغ زنده"
columns={[
"ردیف",
"کد رهگیری",
"تاریخ ثبت وضعیت",
"تعداد",
"وضعیت",
"نام کالا",
"شناسه یکتا کشتارگاه",
"کشتارگاه",
"تاریخ ثبت وضعیت",
]}
data={tableData}
/>
</Grid>
);
};

View File

@@ -0,0 +1,394 @@
import { Grid } from "../../../../components/grid/Grid";
import React, { useContext, useEffect, useState } from "react";
import {
Autocomplete,
Button,
Checkbox,
IconButton,
TextField,
Tooltip,
} from "@mui/material";
import { DatePicker } from "@mui/x-date-pickers";
import moment from "moment";
import { useDispatch } from "react-redux";
import axios from "axios";
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
import { AppContext } from "../../../../contexts/AppContext";
import {
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import { CheckCleanceCode } from "../../../../components/check-clearance-code/ChechClearanceCode";
import { provinceNationalTransportManagementInfoDashboardService } from "../../../province/services/province-national-transport-managemant-info-dashboard-service";
import { useParams } from "react-router-dom";
import { getSamasatProvinces } from "../../../../utils/getSamasatProvinces";
import { formatJustDate } from "../../../../utils/formatTime";
import ToggleOffOutlinedIcon from "@mui/icons-material/ToggleOffOutlined";
import ToggleOnIcon from "@mui/icons-material/ToggleOn";
export const NationalInfoTransports = () => {
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
useContext(AppContext);
const [selectedProvince, setSelectedProvince] = useState("");
const getProvince = () => {
if (key === undefined) {
return selectedProvince === "همه" ? "" : selectedProvince;
} else {
return key;
}
};
const getDashboardData = () => {
dispatch(
provinceNationalTransportManagementInfoDashboardService({
date1: withDate ? selectedDate1 : null,
date2: withDate ? selectedDate2 : null,
search: textValue,
province: getProvince(),
PartIdCode: unitkey !== undefined ? unitkey : null,
})
).then((r) => {
setDashboardData(r.payload.data);
});
};
const dispatch = useDispatch();
useEffect(() => {
const currentDate = moment(new Date()).format("YYYY-MM-DD");
setSelectedDate1(currentDate);
setSelectedDate2(currentDate);
}, []);
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const [data, setData] = useState([]);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [textValue, setTextValue] = useState("");
const [page, setPage] = useState(1);
const [tableData, setTableData] = useState([]);
const [withDate, setWithDate] = useState(true);
const [dashboardData, setDashboardData] = useState([]);
const { key, unitkey, name } = useParams();
const fetchApiData = async (page) => {
let response;
dispatch(LOADING_START());
response = await axios.get(
`https://rsibackend.rasadyar.com/app/transporting-detail/?search=${textValue}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}&page=${page}&page_size=${perPage}${
unitkey !== undefined ? "&PartIdCode=" + unitkey : ""
}&province=${getProvince()}`
);
dispatch(LOADING_END());
getDashboardData();
setData(response.data.results);
setTotalRows(response.data.count);
};
const handlePageChange = (page) => {
fetchApiData(page);
setPage(page);
};
const handlePerRowsChange = (perRows) => {
setPerPage(perRows);
setPage(1);
};
// const updateTable = () => {
// fetchApiData(page !== 0 ? page : 1);
// };
useEffect(() => {
const d = data?.map((item, i) => {
return [
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
<CheckCleanceCode key={i} clearanceCode={item?.TrackingCode} />,
formatJustDate(item?.Date),
item?.DesUnitName,
item?.DesPartIdCode,
item?.Province,
item?.City,
item?.GoodAmount?.toLocaleString(),
item?.TrackingStatusDescription,
item?.Out ? "خارج استان" : "داخل استان",
item?.SourceUnitName,
item?.hatching?.poultry?.PartIdCode,
item?.hatching?.RequestCode,
item?.hatching?.poultry?.Province,
item?.hatching?.poultry?.City,
item?.Age,
item?.hatching?.PedigreeName,
// <Button
// key={i}
// variant="contained"
// size="small"
// color="primary"
// onClick={() => {
// dispatch(
// DRAWER({
// top: true,
// content: <NationalInfoDetails data={item} size={1000} />,
// title: "گزارش حمل مرغ زنده",
// })
// );
// }}
// >
// مشاهده
// </Button>,
];
});
setTableData(d);
}, [data]);
useEffect(() => {
fetchApiData(1);
}, [
dispatch,
selectedDate1,
selectedDate2,
perPage,
withDate,
selectedProvince,
]);
const handleSubmit = async (event) => {
event.preventDefault();
getDashboardData();
dispatch(LOADING_START());
try {
const response = await axios.get(
`https://rsibackend.rasadyar.com/app/transporting-detail/?search=${textValue}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}&page=${1}&page_size=${perPage}${
unitkey !== undefined ? "&PartIdCode=" + unitkey : ""
}&province=${getProvince()}`
);
setData(response.data.results);
setTotalRows(response.data.count);
dispatch(LOADING_END());
} catch (error) {
console.error("Error fetching data:", error);
}
};
const getProvinceList = () => {
return [{ name: "همه" }, ...getSamasatProvinces()];
};
return (
<Grid
container
xs={12}
justifyContent="center"
alignItems="center"
gap={2}
mt={4}
>
<Grid
container
xs={12}
justifyContent="start"
alignItems="center"
gap={2}
>
{key === undefined && unitkey === undefined && name === undefined && (
<Grid minWidth={210}>
<Autocomplete
size="small"
disablePortal
id="hatching"
options={getProvinceList().map((i) => {
return {
label: i.name,
};
})}
onChange={(event, value) => {
if (value.label !== "همه") {
setSelectedProvince(value.label);
} else {
setSelectedProvince("");
}
}}
renderInput={(params) => (
<TextField {...params} label="انتخاب استان" />
)}
/>
</Grid>
)}
<Grid
container
gap={1}
style={{
borderStyle: "solid",
borderWidth: "1px",
padding: "5px",
borderRadius: "15px",
borderColor: "gray",
justifyContent: "left",
}}
alignItems="center"
>
<Checkbox
icon={<ToggleOffOutlinedIcon />}
checkedIcon={<ToggleOnIcon />}
checked={withDate}
onChange={() => setWithDate(!withDate)}
color="primary"
size="large"
/>
<Grid>
<DatePicker
disabled={!withDate}
label="از تاریخ"
id="date"
renderInput={(params) => (
<TextField
size="small"
sx={{ width: { xs: "126px", md: "160px" } }}
{...params}
/>
)}
value={selectedDate1}
onChange={(e) => {
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<DatePicker
disabled={!withDate}
label="تا تاریخ"
id="date"
renderInput={(params) => (
<TextField
size="small"
sx={{ width: { xs: "126px", md: "160px" } }}
{...params}
/>
)}
value={selectedDate2}
onChange={(e) => {
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
</Grid>
<Grid>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button
// disabled={!textValue}
type="submit"
onClick={handleSubmit}
endIcon={<RiSearchLine />}
>
جستجو
</Button>
</form>
</Grid>
<Grid>
<Tooltip
placement="right"
title={
withDate
? "دانلود اکسل"
: "برای دانلود اکسل، بازه تاریخی را فعال کنید"
}
>
<IconButton
size="small"
color="success"
component="a"
href={`https://rsibackend.rasadyar.com/app/all_send_different_bar_excel/?search=${textValue}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}&province=${getProvince()}`}
disabled={!withDate}
>
<RiFileExcel2Fill size={36} style={{ cursor: "pointer" }} />
</IconButton>
</Tooltip>
</Grid>
</Grid>
<Grid container mt={2} mb={4} isDashboard xs={12}>
<ResponsiveTable
noPagination
isDashboard
columns={[
"تعداد بار",
"حجم بار",
"میانگین سن کشتار",
"تعداد بار داخل استان",
"حجم بار داخل استان",
"درصد داخل استان",
"تعداد بار خارج استان",
"حجم بار خارج استان",
"درصد خارج استان",
]}
data={[
[
dashboardData?.barCount?.toLocaleString(),
dashboardData?.barQuantity?.toLocaleString(),
Math.floor(dashboardData?.totalBarKillingAge),
dashboardData?.inputBarCount?.toLocaleString(),
dashboardData?.inputBarQuantity?.toLocaleString(),
dashboardData?.inputBarPercent?.toFixed(1),
dashboardData?.outputBar?.toLocaleString(),
dashboardData?.outputBarQuantity?.toLocaleString(),
dashboardData?.outputBarPercent?.toFixed(1),
],
]}
title={"خلاصه اطلاعات"}
/>
</Grid>
<ResponsiveTable
data={tableData}
columns={[
"ردیف",
"کد رهگیری قرنطینه",
"تاریخ کشتار",
"نام کشتارگاه",
"شناسه یکتا کشتار گاه",
"استان کشتارگاه",
"شهر کشتارگاه",
"تعداد ",
"وضعیت ",
"مقصد کشتار",
"نام مرغدار",
"شناسه یکتا مرغداری",
"شناسه جوجه ریزی",
"استان مرغدار",
"شهرستان مرغدار",
"سن کشتار",
"نژاد",
]}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
title={
key || name
? `گزارش اطلاعات بار ${key || name} `
: `گزارش اطلاعات بار`
}
/>
</Grid>
);
};

View File

@@ -0,0 +1,284 @@
import { Grid } from "../../../../components/grid/Grid";
import React, { useContext, useEffect, useState } from "react";
import { Button, Checkbox, FormControlLabel, TextField } from "@mui/material";
import { DatePicker } from "@mui/x-date-pickers";
import moment from "moment";
import { useDispatch } from "react-redux";
import axios from "axios";
import { RiSearchLine } from "react-icons/ri";
import { AppContext } from "../../../../contexts/AppContext";
import {
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import { CheckCleanceCode } from "../../../../components/check-clearance-code/ChechClearanceCode";
import { useParams } from "react-router-dom";
import { formatJustDate } from "../../../../utils/formatTime";
import { provinceNationalTransportManagementInfoDashboardService } from "../../../province/services/province-national-transport-managemant-info-dashboard-service";
export const NationalInfoHatchingDetails = () => {
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
useContext(AppContext);
const getDashboardData = () => {
dispatch(
provinceNationalTransportManagementInfoDashboardService({
date1: withDate ? selectedDate1 : null,
date2: withDate ? selectedDate2 : null,
search: textValue,
RequestCode: key,
})
).then((r) => {
setDashboardData(r.payload.data);
});
};
const dispatch = useDispatch();
useEffect(() => {
const currentDate = moment(new Date()).format("YYYY-MM-DD");
setSelectedDate1(currentDate);
setSelectedDate2(currentDate);
}, []);
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const [data, setData] = useState([]);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [textValue, setTextValue] = useState("");
const [page, setPage] = useState(1);
const [tableData, setTableData] = useState([]);
const [withDate, setWithDate] = useState(false);
const [dashboardData, setDashboardData] = useState([]);
const { key, name } = useParams();
const fetchApiData = async (page) => {
dispatch(LOADING_START());
const response = await axios.get(
`https://rsibackend.rasadyar.com/app/transporting-detail/?search=${textValue}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}&page=${page}&page_size=${perPage}&RequestCode=${key}`
);
dispatch(LOADING_END());
getDashboardData();
setData(response.data.results);
setTotalRows(response.data.count);
};
const handlePageChange = (page) => {
fetchApiData(page);
setPage(page);
};
const handlePerRowsChange = (perRows) => {
setPerPage(perRows);
setPage(1);
};
// const updateTable = () => {
// fetchApiData(page !== 0 ? page : 1);
// };
useEffect(() => {
const d = data?.map((item, i) => {
return [
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
<CheckCleanceCode key={i} clearanceCode={item?.TrackingCode} />,
formatJustDate(item?.Date),
item?.DesUnitName,
item?.DesPartIdCode,
item?.Province,
item?.City,
item?.GoodAmount?.toLocaleString(),
item?.TrackingStatusDescription,
item?.Out ? "خارج استان" : "داخل استان",
item?.SourceUnitName,
item?.hatching?.poultry?.PartIdCode,
item?.hatching?.RequestCode,
item?.hatching?.poultry?.Province,
item?.hatching?.poultry?.City,
item?.Age,
item?.hatching?.PedigreeName,
];
});
setTableData(d);
}, [data]);
useEffect(() => {
fetchApiData(1);
}, [dispatch, selectedDate1, selectedDate2, perPage, withDate]);
const handleSubmit = async (event) => {
event.preventDefault();
dispatch(LOADING_START());
try {
const response = await axios.get(
`https://rsibackend.rasadyar.com/app/transporting-detail/?search=${textValue}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}&page=${1}&page_size=${perPage}&RequestCode=${key}`
);
setData(response.data.results);
setTotalRows(response.data.count);
getDashboardData();
dispatch(LOADING_END());
} catch (error) {
console.error("Error fetching data:", error);
}
};
return (
<Grid container xs={12} justifyContent="center" mt={3}>
<Grid
container
xs={12}
justifyContent="start"
alignItems="center"
gap={2}
>
<Grid
container
style={{
borderStyle: "solid",
borderWidth: "1px",
padding: "10px",
borderRadius: "15px",
borderColor: "gray",
justifyContent: "left",
}}
>
<Grid>
<FormControlLabel
control={
<Checkbox
checked={withDate}
onChange={() => setWithDate(!withDate)}
color="primary"
/>
}
/>
</Grid>
<Grid>
<DatePicker
disabled={!withDate}
label="از تاریخ"
id="date"
renderInput={(params) => (
<TextField
size="small"
style={{ width: "160px" }}
{...params}
/>
)}
value={selectedDate1}
onChange={(e) => {
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<DatePicker
disabled={!withDate}
label="تا تاریخ"
id="date"
renderInput={(params) => (
<TextField
size="small"
style={{ width: "160px" }}
{...params}
/>
)}
value={selectedDate2}
onChange={(e) => {
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
</Grid>
<Grid>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button
// disabled={!textValue}
type="submit"
onClick={handleSubmit}
endIcon={<RiSearchLine />}
>
جستجو
</Button>
</form>
</Grid>
</Grid>
<Grid container mt={2} mb={4} isDashboard xs={12}>
<ResponsiveTable
noPagination
isDashboard
columns={[
"تعداد بار",
"حجم بار",
"میانگین سن کشتار",
"تعداد بار داخل استان",
"حجم بار داخل استان",
"درصد داخل استان",
"تعداد بار خارج استان",
"حجم بار خارج استان",
"درصد خارج استان",
]}
data={[
[
dashboardData?.barCount?.toLocaleString(),
dashboardData?.barQuantity?.toLocaleString(),
Math.floor(dashboardData?.totalBarKillingAge),
dashboardData?.inputBarCount?.toLocaleString(),
dashboardData?.inputBarQuantity?.toLocaleString(),
dashboardData?.inputBarPercent?.toFixed(1),
dashboardData?.outputBar?.toLocaleString(),
dashboardData?.outputBarQuantity?.toLocaleString(),
dashboardData?.outputBarPercent?.toFixed(1),
],
]}
title={"خلاصه اطلاعات"}
/>
</Grid>
<ResponsiveTable
data={tableData}
columns={[
"ردیف",
"کد رهگیری قرنطینه",
"تاریخ کشتار",
"نام کشتارگاه",
"شناسه یکتا کشتار گاه",
"استان کشتارگاه",
"شهر کشتارگاه",
"تعداد ",
"وضعیت ",
"مقصد کشتار",
"نام مرغدار",
"شناسه یکتا مرغداری",
"شناسه جوجه ریزی",
"استان مرغدار",
"شهرستان مرغدار",
"سن کشتار",
"نژاد",
]}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
title={`جزئیات مجوز جوجه ریزی ${name}`}
/>
</Grid>
);
};

View File

@@ -0,0 +1,458 @@
import { Grid } from "../../../../components/grid/Grid";
import React, { useContext, useEffect, useState } from "react";
import {
Autocomplete,
Button,
Checkbox,
IconButton,
Tab,
Tabs,
TextField,
Tooltip,
} from "@mui/material";
import { DatePicker } from "@mui/x-date-pickers";
import moment from "moment";
import { useDispatch } from "react-redux";
import axios from "axios";
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
import { AppContext } from "../../../../contexts/AppContext";
import {
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import { useParams } from "react-router-dom";
import { formatJustDate } from "../../../../utils/formatTime";
import { nationalInfoGetDashboardService } from "../../services/national-info-get-dashboard-info-service";
import { getSamasatProvinces } from "../../../../utils/getSamasatProvinces";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import {
ROUTE_ADMINX_ROUTE_NATIONAL_INFO,
ROUTE_PROVINCE_SUPERVISOR_ROUTE_NATIONAL_INFO,
ROUTE_SUPER_ADMIN_ROUTE_NATIONAL_INFO,
} from "../../../../routes/routes";
import ToggleOffOutlinedIcon from "@mui/icons-material/ToggleOffOutlined";
import ToggleOnIcon from "@mui/icons-material/ToggleOn";
import VisibilityIcon from "@mui/icons-material/Visibility";
export const NationalInfoHatchings = () => {
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
useContext(AppContext);
const dispatch = useDispatch();
useEffect(() => {
const currentDate = moment(new Date()).format("YYYY-MM-DD");
setSelectedDate1(currentDate);
setSelectedDate2(currentDate);
}, []);
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const [selectedProvince, setSelectedProvince] = useState("");
const { key } = useParams();
const [dashboardData, setDashboardData] = useState([]);
const [data, setData] = useState([]);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [textValue, setTextValue] = useState("");
const [page, setPage] = useState(1);
const [tableData, setTableData] = useState([]);
const [withDate, setWithDate] = useState(false);
const [value, setValue] = useState("0");
const handleChange = (event, newValue) => {
setValue(newValue);
};
const getDashboardData = () => {
dispatch(
nationalInfoGetDashboardService({
date1: withDate ? selectedDate1 : null,
date2: withDate ? selectedDate2 : null,
search: textValue,
province: selectedProvince === "همه" ? "" : selectedProvince,
})
).then((r) => {
setDashboardData(r.payload.data);
});
};
const fetchApiData = async (page) => {
let response;
dispatch(LOADING_START());
response = await axios.get(
`https://rsibackend.rasadyar.com/app/hatchings/?search=${textValue}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}&page=${page}&page_size=${perPage}&province=${
key || selectedProvince ? selectedProvince : ""
}&state=${value === "0" ? "pending" : "archive"}`
);
dispatch(LOADING_END());
getDashboardData();
setData(response.data.results);
setTotalRows(response.data.count);
};
const handlePageChange = (page) => {
fetchApiData(page);
setPage(page);
};
const handlePerRowsChange = (perRows) => {
setPerPage(perRows);
setPage(1);
};
// const updateTable = () => {
// fetchApiData(page !== 0 ? page : 1);
// };
useEffect(() => {
const d = data?.map((item, i) => {
return [
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
item?.poultry?.Province || "-",
item?.poultry?.City || "-",
item?.poultry?.UnitName,
`${item?.poultry?.FirstName} ${item?.poultry?.LastName || ""}`,
item?.RequestCode,
item?.CertId,
item?.CapacityFemale?.toLocaleString(),
formatJustDate(item?.Date),
Math.floor(item?.Age),
item?.PedigreeName,
item?.ChickCountSum?.toLocaleString(),
item?.Period?.toLocaleString(),
item?.Evacuation?.toLocaleString(),
item?.info?.percentHatchingLicense?.toFixed(2),
item?.LeftOver?.toLocaleString(),
Math.floor(item?.KillingAve),
item?.info?.numberLoads?.toLocaleString(),
item?.info?.loadVolume?.toLocaleString(),
<Tooltip placement="right" title="جزئیات" key={i}>
<IconButton
size="small"
color="success"
onClick={() =>
window.open(
getRoleFromUrl() === "AdminX"
? `${ROUTE_ADMINX_ROUTE_NATIONAL_INFO}/${item.RequestCode}/${item?.poultry?.UnitName}`
: getRoleFromUrl() === "SuperAdmin"
? `${ROUTE_SUPER_ADMIN_ROUTE_NATIONAL_INFO}/${item.RequestCode}/${item?.poultry?.UnitName}`
: `${ROUTE_PROVINCE_SUPERVISOR_ROUTE_NATIONAL_INFO}/${item.RequestCode}/${item?.poultry?.UnitName}`,
"_blank"
)
}
>
<VisibilityIcon />
</IconButton>
</Tooltip>,
];
});
setTableData(d);
}, [data]);
useEffect(() => {
fetchApiData(1);
}, [
dispatch,
selectedDate1,
selectedDate2,
perPage,
withDate,
value,
selectedProvince,
]);
const handleSubmit = async (event) => {
event.preventDefault();
dispatch(LOADING_START());
try {
const response = await axios.get(
`https://rsibackend.rasadyar.com/app/hatchings/?search=${textValue}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}&page=${1}&page_size=${perPage}&province=${
key || selectedProvince ? selectedProvince : ""
}&state=${value === "0" ? "pending" : "archive"}`
);
setData(response.data.results);
setTotalRows(response.data.count);
dispatch(LOADING_END());
getDashboardData();
} catch (error) {
console.error("Error fetching data:", error);
}
};
const getProvinceList = () => {
return [{ name: "همه" }, ...getSamasatProvinces()];
};
return (
<Grid
container
xs={12}
justifyContent="center"
alignItems="center"
gap={2}
mt={2}
>
<Grid
container
xs={12}
justifyContent="center"
alignItems="center"
gap={2}
>
<Tabs value={value} onChange={handleChange}>
<Tab value="0" label="فعال" />
<Tab value="1" label="بایگانی شده" />
</Tabs>
</Grid>
<Grid container xs={12} alignItems="center" gap={2}>
{!key && (
<Grid minWidth={210}>
<Autocomplete
size="small"
disablePortal
id="hatching"
options={getProvinceList().map((i) => {
return {
label: i.name,
};
})}
onChange={(event, value) => {
if (value.label !== "همه") {
setSelectedProvince(value.label);
} else {
setSelectedProvince("");
}
}}
renderInput={(params) => (
<TextField {...params} label="انتخاب استان" />
)}
/>
</Grid>
)}
<Grid>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button
// disabled={!textValue}
type="submit"
onClick={handleSubmit}
endIcon={<RiSearchLine />}
>
جستجو
</Button>
</form>
</Grid>
<Grid
container
gap={1}
style={{
borderStyle: "solid",
borderWidth: "1px",
padding: "5px",
borderRadius: "15px",
borderColor: "gray",
justifyContent: "left",
}}
alignItems="center"
sx={{
width: { xs: "auto", md: "auto" },
}}
>
<Checkbox
icon={<ToggleOffOutlinedIcon />}
checkedIcon={<ToggleOnIcon />}
checked={withDate}
onChange={() => setWithDate(!withDate)}
color="primary"
size="large"
/>
<Grid>
<DatePicker
disabled={!withDate}
label="از تاریخ"
id="date"
renderInput={(params) => (
<TextField
size="small"
sx={{ width: { xs: "126px", md: "160px" } }}
{...params}
/>
)}
value={selectedDate1}
onChange={(e) => {
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<DatePicker
disabled={!withDate}
label="تا تاریخ"
id="date"
renderInput={(params) => (
<TextField
size="small"
sx={{ width: { xs: "126px", md: "160px" } }}
{...params}
/>
)}
value={selectedDate2}
onChange={(e) => {
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
</Grid>
<Tooltip placement="right" title="دانلود اکسل">
<IconButton
size="small"
color="success"
component="a"
href={`https://rsibackend.rasadyar.com/app/all_hatching_excel/?search=${textValue}${
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
}&province=${
key || selectedProvince ? selectedProvince : ""
}&state=${value === "0" ? "pending" : "archive"}`}
>
<RiFileExcel2Fill size={36} />
</IconButton>
</Tooltip>
</Grid>
<Grid container mt={2} mb={4} isDashboard gap={3}>
<ResponsiveTable
noPagination
isDashboard
columns={[
"تعداد دوره جوجه ریزی",
"حجم کل جوجه ریزی",
"تلفات",
"درصد تلفات",
"کشتار شده",
" درصد کشتار شده",
"میانگین سن کشتار",
"تعداد بارها",
"کمترین سن",
"بیشترین سن",
"مانده در سالن",
"درصد مانده در سالن نسبت به جوجه ریزی",
]}
data={[
[
dashboardData?.totalHatchingCount?.toLocaleString(),
dashboardData?.totalHatchingQuantity?.toLocaleString(),
dashboardData?.totalHatchingEvacuation?.toLocaleString(),
dashboardData?.totalHatchingEvacuationPercent?.toLocaleString(),
dashboardData?.totalHatchingKillingQuantity?.toLocaleString(),
dashboardData?.totalHatchingKillingQuantityPercent?.toLocaleString(),
Math.floor(dashboardData?.totalHatchingKillingAge),
dashboardData?.totalHatchingBars?.toLocaleString(),
Math.floor(dashboardData?.leastAge),
Math.floor(dashboardData?.mostAge),
dashboardData?.totalHatchingLeftOver?.toLocaleString(),
dashboardData?.totalHatchingLeftOverPercent?.toLocaleString(),
],
]}
title={"خلاصه اطلاعات کل جوجه ریزی ها"}
/>
<ResponsiveTable
noPagination
isDashboard
columns={[
"تعداد دوره جوجه ریزی",
"حجم کل جوجه ریزی",
"تلفات",
"درصد تلفات",
"کشتار شده",
"درصد کشتار شده",
"میانگین سن کشتار",
"تعداد بارها",
"حجم جوجه ریزی فعال",
"کمترین سن",
"بیشترین سن",
"مانده در سالن",
"درصد مانده در سالن",
"مانده در سالن آماده به کشتار",
"درصد مانده در سالن آماده به کشتار",
]}
data={[
[
dashboardData?.totalActiveHatchingCount?.toLocaleString(),
dashboardData?.totalActiveHatchingQuantity?.toLocaleString(),
dashboardData?.totalActiveHatchingEvacuation?.toLocaleString(),
dashboardData?.totalActiveHatchingEvacuationPercent?.toLocaleString(),
dashboardData?.totalActiveHatchingKillingQuantity?.toLocaleString(),
dashboardData?.totalActiveHatchingKillingQuantityPercent?.toLocaleString(),
Math.floor(dashboardData?.totalActiveHatchingKillingAge),
dashboardData?.totalActiveHatchingBars?.toLocaleString(),
// dashboardData?.totalActiveHatchingCount?.toLocaleString(),
dashboardData?.totalActiveHatchingQuantity?.toLocaleString(),
Math.floor(dashboardData?.leastAge),
Math.floor(dashboardData?.mostAge),
dashboardData?.totalActiveHatchingLeftOver?.toLocaleString(),
dashboardData?.totalActiveHatchingLeftOverPercent?.toLocaleString(),
dashboardData?.totalReadyActiveHatchingLeftOver?.toLocaleString(),
dashboardData?.totalReadyHatchingLeftOverPercent?.toLocaleString(),
],
]}
title={"خلاصه اطلاعات جوجه ریزی های فعال"}
customColors={[{ rest: true, color: "#6262c4" }]}
/>
</Grid>
<ResponsiveTable
data={tableData}
columns={[
"ردیف",
"استان",
"شهرستان",
"نام واحد",
"نام مالک",
"شماره مجوز",
"شماره گواهی بهداشتی",
"ظرفیت",
"تاریخ جوجه ریزی",
"سن گله",
"نژاد",
"تعداد جوجه ریزی",
"دوره جوجه ریزی",
"مجموع تلفات",
"درصد جوجه ریزی به مجوز",
"مانده در سالن",
"میانگین سن کشتار",
"تعداد بارها",
"حجم بارها",
"جزئیات",
]}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
title={
value === "0"
? `پایش جوجه ریزی ${key || ""}`
: `بایگانی جوجه ریزی ${key || ""}`
}
/>
</Grid>
);
};

View File

@@ -0,0 +1,66 @@
import React, { useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { Tab, Tabs } from "@mui/material";
import { NationalInfoHatchings } from "../national-info-hatchings/NationalInfoHatchings";
import { NationalInfoTransports } from "../national-info-bars/NationalInfoTransports";
// import { NationalinfokillingReport } from "../national-info-killing-report/NationalinfokillingReport";
import NationalMap from "../national-map/NationalMap";
import { ProvinceNationalInfoFarms } from "../../../province/components/province-national-info-farms/ProvinceNationalInfoFarms";
import { ProvinceNationalInfoSlaughterhouse } from "../../../province/components/province-national-info-Slaughterhouse/ProvinceNationalInfoSlaughterhouse";
import { ProvinceChickenDistributionsAndSales } from "../../../province/components/province-chicken-distribution-and-sales/ProvinceChickenDistributionsAndSales";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { ProvinceChickenStewardSales } from "../../../province/components/province-chicken-steward-sales/ProvinceChickenStewardSales";
import { TotalCargoInformation } from "../../../province/components/total-cargo-information/TotalCargoInformation";
export const NationalInfo = () => {
const [value, setValue] = useState(0);
const ableToSee =
getRoleFromUrl() === "AdminX" ||
getRoleFromUrl() === "SuperAdmin" ||
getRoleFromUrl() === "ProvinceOperator";
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<Grid container xs={12} justifyContent="center" alignItems="center">
<Grid
container
xs={12}
justifyContent="center"
alignItems="center"
mt={4}
>
<Tabs
value={value}
onChange={handleChange}
aria-label="simple tabs example"
scrollButtons="auto"
variant="scrollable"
allowScrollButtonsMobile
>
<Tab value={0} label="مدیریت فارم ها" />
<Tab value={1} label="جوجه ریزی ها " />
<Tab value={2} label="اطلاعات بارها " />
<Tab value={3} label="پایش کشتارگاه ها " />
<Tab value={4} label="نقشه کشوری" />
{ableToSee && <Tab value={5} label="توزیع / فروش گوشت مرغ" />}
{ableToSee && <Tab value={6} label="خرید صنوف" />}
{ableToSee && <Tab value={7} label="اطلاعات حمل محصولات" />}
</Tabs>
</Grid>
<Grid container xs={12} justifyContent="center" mt={2} px={2}>
{value === 0 && <ProvinceNationalInfoFarms />}
{value === 1 && <NationalInfoHatchings />}
{value === 2 && <NationalInfoTransports />}
{value === 3 && <ProvinceNationalInfoSlaughterhouse />}
{value === 4 && <NationalMap />}
{value === 5 && <ProvinceChickenDistributionsAndSales />}
{value === 6 && <ProvinceChickenStewardSales />}
{value === 7 && <TotalCargoInformation />}
</Grid>
</Grid>
);
};

View File

@@ -0,0 +1,142 @@
import { useEffect, useState } from "react";
import Grid from "@mui/material/Grid";
import { useDispatch } from "react-redux";
import { AllProvinceDetailsForMap } from "../../services/all-province-details-for-map";
import NationalMapOverview from "./NationalMapOverview";
import NationalMapGuidline from "./NationalMapGuidline";
import NationalMapSumTotal from "./NationalMapSumTotal";
import NationalMapRadioBtn from "./NationalMapRadioBtn";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
const NationalMap = () => {
const [tableData, setTableData] = useState([]);
const [percentageType, setPercentageType] = useState("hatching"); // hatching or active
const [provinceData, setProvinceData] = useState([]);
const dispatch = useDispatch();
const fetchTableData = () => {
dispatch(AllProvinceDetailsForMap()).then((r) => {
const data = r.payload?.data || [];
setProvinceData(data);
// const sum = data.reduce((total, item) => {
// return total + (item?.totalQuantity || 0);
// }, 0);
const d = data.map((item, i) => {
return [
i + 1,
item?.provinceName || "",
item?.totalQuantity?.toLocaleString() || "0",
item?.totalKilledQuantity?.toLocaleString() || "0",
item?.totalLeftOver?.toLocaleString() || "0",
// sum.toLocaleString(),
`% ${item?.totalHatchingLeftOverPercent.toLocaleString()} `,
item?.totalActiveLeft.toLocaleString(),
` % ${item?.totalActiveLeftPercent.toLocaleString()}`,
];
});
setTableData(d);
});
};
useEffect(() => {
fetchTableData();
}, []);
const getColorByPercentage = (percent) => {
if (percent < 25) return "#F18989";
if (percent < 50) return "#FF944D";
if (percent < 75) return "#F4C430";
return "#61D8BA";
};
const provincePercentages = {};
provinceData.forEach((item) => {
if (item?.provinceName && item?.totalHatchingLeftOverPercent) {
provincePercentages[item?.provinceName] =
item?.totalHatchingLeftOverPercent;
}
});
const getProvinceColor = (provinceName) => {
const province = provinceData.find((p) => p?.provinceName === provinceName);
if (!province) return "#B0B0B0";
const percent =
percentageType === "hatching"
? province?.totalHatchingLeftOverPercent
: province?.totalActiveLeftPercent;
return percent ? getColorByPercentage(percent) : "#B0B0B0";
};
const handlePercentageTypeChange = (type) => {
setPercentageType(type);
};
return (
<Grid xs={12} md={12} container spacing={2} justifyContent="center">
<Grid
item
xs={12}
md={4}
gap={2}
sx={{
maxHeight: { xs: "auto", md: "668px" },
overflowY: "scroll",
}}
>
<ResponsiveTable
title="اطلاعات کشتار زنده کشتارگاه"
columns={[
"ردیف",
" استان",
" جوجه ریزی",
"کشتار شده",
"مانده در سالن",
" مانده در سالن",
"آماده کشتار",
" آماده کشتار",
]}
data={tableData}
sx={{
"& .MuiTableCell-root": {
fontSize: "0.75rem",
padding: "8px",
},
"& .MuiTableHead-root": {
"& .MuiTableCell-root": {
fontWeight: 600,
},
},
}}
/>
</Grid>
<Grid
xs={12}
md={7}
gap={2}
sx={{
display: "flex",
flexDirection: "column",
marginLeft: { xs: "0px", md: "33px" },
}}
>
<NationalMapSumTotal />
<NationalMapRadioBtn
onPercentageTypeChange={handlePercentageTypeChange}
selectedPercentageType={percentageType}
/>
<NationalMapOverview getProvinceColor={getProvinceColor} />
<NationalMapGuidline />
</Grid>
</Grid>
);
};
export default NationalMap;

View File

@@ -0,0 +1,142 @@
import { Grid, Typography } from "@mui/material";
function NationalMapGuidline() {
return (
<Grid
xs={12}
sx={{
display: "flex",
flexDirection: "rowReverse",
border: "1px solid #A8A8A8",
borderRadius: "20px",
padding: "10px",
gap: "5px",
alignItems: "center",
marginLeft: {
xs: "0px",
md: "173px",
},
width: {
xs: "100%",
md: "480px",
},
}}
>
<Grid
xs={6}
item
sx={{
display: "flex",
alignItems: "center",
marginLeft: "10px",
}}
>
<Grid
sx={{
backgroundColor: "#F18989",
width: "15px",
height: "15px",
borderRadius: "8px",
}}
></Grid>
<Typography
sx={{
marginLeft: "10px",
color: "#717171",
fontWeight: "400",
fontSize: "14px",
}}
>
کمتر از 25%
</Typography>
</Grid>
<Grid
xs={6}
item
sx={{
display: "flex",
alignItems: "center",
marginLeft: "10px",
}}
>
<Grid
sx={{
backgroundColor: "#FF944D",
width: "15px",
height: "15px",
borderRadius: "8px",
}}
></Grid>
<Typography
sx={{
marginLeft: "10px",
color: "#717171",
fontWeight: "400",
fontSize: "14px",
}}
>
25% تا 50%
</Typography>
</Grid>
<Grid
xs={6}
item
sx={{
display: "flex",
alignItems: "center",
marginLeft: "10px",
}}
>
<Grid
sx={{
backgroundColor: "#F4C430",
width: "15px",
height: "15px",
borderRadius: "8px",
}}
></Grid>
<Typography
sx={{
marginLeft: "10px",
color: "#717171",
fontWeight: "400",
fontSize: "14px",
}}
>
50% تا 75%
</Typography>
</Grid>
<Grid
xs={6}
item
sx={{
display: "flex",
alignItems: "center",
marginLeft: "10px",
}}
>
<Grid
sx={{
backgroundColor: "#61D8BA",
width: "15px",
height: "15px",
borderRadius: "8px",
}}
></Grid>
<Typography
sx={{
marginLeft: "10px",
color: "#717171",
fontWeight: "400",
fontSize: "14px",
}}
>
75% تا 100%
</Typography>
</Grid>
</Grid>
);
}
export default NationalMapGuidline;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,40 @@
import * as React from "react";
import Radio from "@mui/material/Radio";
import RadioGroup from "@mui/material/RadioGroup";
import FormControlLabel from "@mui/material/FormControlLabel";
import FormControl from "@mui/material/FormControl";
export default function NationalMapRadioBtn({
onPercentageTypeChange,
selectedPercentageType,
}) {
const handleChange = (event) => {
onPercentageTypeChange(event.target.value);
};
return (
<FormControl>
<RadioGroup
sx={{
justifyContent: "center",
}}
aria-labelledby="percentage-type-radio-buttons-group"
name="percentage-type-radio-buttons-group"
value={selectedPercentageType}
onChange={handleChange}
row
>
<FormControlLabel
value="hatching"
control={<Radio />}
label="مانده در سالن"
/>
<FormControlLabel
value="active"
control={<Radio />}
label="آماده کشتار"
/>
</RadioGroup>
</FormControl>
);
}

View File

@@ -0,0 +1,173 @@
import { useEffect, useState } from "react";
import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import { useDispatch } from "react-redux";
import { DashboardProvinceDetailsForMap } from "../../services/dashboard-province-details-for-map";
const NationalMapSumTotal = () => {
const [data, setData] = useState({
totalQuantity: 0,
totalLeftOver: 0,
totalKilledQuantity: 0,
totalHatchingLeftOverPercent: 0,
totalActiveLeft: 0,
totalActiveLeftPercent: 0,
});
const dispatch = useDispatch();
const fetchData = () => {
dispatch(DashboardProvinceDetailsForMap()).then((r) => {
if (r.payload?.data) {
setData(r.payload.data);
}
});
};
useEffect(() => {
fetchData();
}, []);
return (
<Grid
sx={{
display: "flex",
flexDirection: "row",
border: "1px solid #A8A8A8",
borderRadius: "20px",
padding: "10px",
maxHeight: "156px",
marginTop: "20px",
backgroundColor: "white",
flexWrap: "wrap",
}}
>
<Grid item sx={{ marginTop: "10px", display: "flex" }}>
<Typography
sx={{ color: "#717171", fontWeight: "600", fontSize: "12px" }}
>
حجم کل جوجه ریزی:
</Typography>
<Typography
sx={{
color: "#333",
fontWeight: "700",
fontSize: "12px",
marginLeft: "10px",
}}
>
{data?.totalQuantity.toLocaleString()} قطعه
</Typography>
</Grid>
<Grid
item
sx={{ marginTop: "10px", display: "flex", marginRight: "10px" }}
>
<Typography
sx={{
color: "#717171",
fontWeight: "600",
fontSize: "12px",
marginLeft: "10px",
}}
>
حجم مانده در سالن:
</Typography>
<Typography
sx={{
color: "#333",
fontWeight: "700",
fontSize: "12px",
marginLeft: "10px",
}}
>
{data?.totalLeftOver?.toLocaleString()} قطعه
</Typography>
</Grid>
<Grid item sx={{ marginTop: "10px", display: "flex" }}>
<Typography
sx={{
color: "#333",
fontWeight: "700",
fontSize: "12px",
marginLeft: "10px",
}}
>
حجم کل کشتار شده:
</Typography>
<Typography
sx={{
color: "#333",
fontWeight: "700",
fontSize: "12px",
marginLeft: "10px",
}}
>
{data?.totalKilledQuantity.toLocaleString()}
</Typography>
</Grid>
<Grid item sx={{ marginTop: "10px", display: "flex" }}>
<Typography
sx={{
color: "#333",
fontWeight: "700",
fontSize: "12px",
marginLeft: "10px",
}}
>
درصد مانده در سالن :
</Typography>
<Grid sx={{ display: "flex", alignItems: "center" }}>
<Grid
sx={{
borderRadius: "8px",
marginLeft: "5px",
}}
/>
<Typography
sx={{
color: "#333",
fontWeight: "700",
fontSize: "12px",
}}
>
{data?.totalHatchingLeftOverPercent}%
</Typography>
</Grid>
</Grid>
<Grid item sx={{ marginTop: "10px", display: "flex" }}>
<Typography
sx={{
color: "#333",
fontWeight: "700",
fontSize: "12px",
marginLeft: "10px",
}}
>
درصد آماده کشتار:
</Typography>
<Grid sx={{ display: "flex", alignItems: "center" }}>
<Grid
sx={{
borderRadius: "8px",
marginLeft: "5px",
}}
/>
<Typography
sx={{
color: "#333",
fontWeight: "700",
fontSize: "12px",
marginLeft: "10px",
}}
>
{data.totalActiveLeftPercent}%
</Typography>
</Grid>
</Grid>
</Grid>
);
};
export default NationalMapSumTotal;

View File

@@ -0,0 +1,293 @@
import {
Button,
Switch,
TextField,
Typography,
Radio,
RadioGroup,
FormControlLabel,
FormControl,
} from "@mui/material";
import DoneIcon from "@mui/icons-material/Done";
import { useDispatch } from "react-redux";
import { useContext, useState, useEffect } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { AppContext } from "../../../../contexts/AppContext";
import { SPACING } from "../../../../data/spacing";
import { provincePolicyWagesEditKillhouse } from "../../../province/services/province-policy-wages-edit-killhouse";
export const ProvinceManageSellingForceGovernmentalBuy = ({
item,
fetchdata,
}) => {
const dispatch = useDispatch();
const [openNotif] = useContext(AppContext);
const [state, setState] = useState({
minimumSaleState: item?.quota || false,
quotaOption: item?.quotaMaxKillLimit
? "max_kill_limit"
: item?.quotaRequest
? "request"
: item?.quotaCustom
? "custom"
: "",
qoutaCustomQuntity: item?.quotaCustomQuantity || 0,
percent: item?.governmentalQuota || 0,
});
const [errors, setErrors] = useState({
percent: false,
qoutaCustomQuntity: false,
});
useEffect(() => {
if (!state.minimumSaleState) {
setState((prev) => ({
...prev,
quotaOption: "",
qoutaCustomQuntity: 0,
percent: 0,
}));
setErrors({ percent: false, qoutaCustomQuntity: false });
}
}, [state.minimumSaleState]);
const handleToggle = (key, value) => {
setState((prev) => ({ ...prev, [key]: value }));
};
const handleRadioChange = (event) => {
const newOption = event.target.value;
setState((prev) => ({
...prev,
quotaOption: newOption,
...(newOption !== "custom" && { qoutaCustomQuntity: 0 }),
...(newOption === "custom" && { percent: 0 }),
}));
setErrors({ percent: false, qoutaCustomQuntity: false });
};
const handleInputChange = (field, value) => {
setState((prev) => ({ ...prev, [field]: value }));
setErrors((prev) => ({ ...prev, [field]: false }));
};
const validateForm = () => {
const newErrors = {
percent: false,
qoutaCustomQuntity: false,
};
if (state.minimumSaleState) {
if (
(state.quotaOption === "max_kill_limit" ||
state.quotaOption === "request") &&
(!state.percent || state.percent <= 0 || state.percent > 100)
) {
newErrors.percent = true;
}
if (
state.quotaOption === "custom" &&
(!state.qoutaCustomQuntity || state.qoutaCustomQuntity <= 0)
) {
newErrors.qoutaCustomQuntity = true;
}
}
setErrors(newErrors);
return !Object.values(newErrors).some((error) => error);
};
const handleSubmit = () => {
if (!validateForm()) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "لطفاً مقادیر الزامی را به درستی وارد کنید",
severity: "error",
});
return;
}
dispatch(
provincePolicyWagesEditKillhouse({
kill_house_key: item?.key,
quota: state.minimumSaleState,
quota_max_kill_limit: state.quotaOption === "max_kill_limit",
quota_request: state.quotaOption === "request",
quota_custom: state.quotaOption === "custom",
quota_custom_quantity: state.qoutaCustomQuntity,
governmental_quota: state.percent,
})
).then((r) => {
if (r.payload?.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "تغییرات با موفقیت ذخیره شد",
severity: "success",
});
fetchdata();
}
});
};
const isFormValid = () => {
if (!state.minimumSaleState) return true;
if (
state.quotaOption === "max_kill_limit" ||
state.quotaOption === "request"
) {
return state.percent > 0 && state.percent <= 100;
}
if (state.quotaOption === "custom") {
return state.qoutaCustomQuntity > 0;
}
return false;
};
return (
<Grid xs={12} container direction="column" gap={SPACING.SMALL}>
<Grid xs={12} container alignItems="center" gap={1}>
<Grid item>
<Switch
checked={state.minimumSaleState}
onChange={(e) => {
handleToggle("minimumSaleState", e.target.checked);
if (!e.target.checked) {
dispatch(
provincePolicyWagesEditKillhouse({
kill_house_key: item?.key,
quota: false,
quota_max_kill_limit: false,
quota_request: false,
quota_custom: false,
quota_custom_quantity: 0,
governmental_quota: 0,
})
).then((r) => {
if (r.payload?.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "تغییرات با موفقیت ذخیره شد",
severity: "success",
});
fetchdata();
}
});
}
}}
inputProps={{
"aria-label": "in-province-selling-limitation-switch",
}}
/>
</Grid>
<Grid item>
<Typography>الزام به خرید دولتی</Typography>
</Grid>
</Grid>
{state.minimumSaleState && (
<Grid xs={12} container direction="column" gap={1}>
<Grid item>
<FormControl component="fieldset" fullWidth>
<RadioGroup
value={state.quotaOption}
onChange={handleRadioChange}
>
<FormControlLabel
value="max_kill_limit"
control={<Radio />}
label="بر اساس سقف کشتار"
/>
<FormControlLabel
value="request"
control={<Radio />}
label="بر اساس اعلام نیازها"
/>
<FormControlLabel
value="custom"
control={<Radio />}
label="بر اساس حجم از سقف کشتار"
/>
</RadioGroup>
</FormControl>
</Grid>
{(state.quotaOption === "max_kill_limit" ||
state.quotaOption === "request") && (
<TextField
label="درصد خرید دولتی"
size="small"
fullWidth
type="number"
value={state.percent}
onChange={(e) =>
handleInputChange(
"percent",
Math.max(0, Math.min(100, e.target.value))
)
}
inputProps={{ min: 1, max: 100 }}
error={errors.percent}
helperText={errors.percent ? "درصد باید بین ۱ تا ۱۰۰ باشد" : ""}
/>
)}
{state.quotaOption === "custom" && (
<TextField
label="حجم"
size="small"
fullWidth
type="number"
value={state.qoutaCustomQuntity}
onChange={(e) =>
handleInputChange(
"qoutaCustomQuntity",
Math.max(0, e.target.value)
)
}
inputProps={{ min: 1 }}
error={errors.qoutaCustomQuntity}
helperText={
errors.qoutaCustomQuntity ? "حجم باید بزرگتر از صفر باشد" : ""
}
/>
)}
<Button
fullWidth
variant="contained"
color="primary"
onClick={handleSubmit}
disabled={!isFormValid()}
startIcon={<DoneIcon />}
>
ذخیره تغییرات
</Button>
</Grid>
)}
</Grid>
);
};

View File

@@ -0,0 +1,125 @@
import { Switch, TextField, Typography, Button } from "@mui/material";
import DoneIcon from "@mui/icons-material/Done";
import { useDispatch } from "react-redux";
import { useContext, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { AppContext } from "../../../../contexts/AppContext";
import { SPACING } from "../../../../data/spacing";
import { provincePolicyWagesEditKillhouse } from "../../../province/services/province-policy-wages-edit-killhouse";
export const ProvinceManageSellingMaxLimitation = ({ item, fetchdata }) => {
const dispatch = useDispatch();
const [openNotif] = useContext(AppContext);
const [percent, setPercent] = useState(
item?.outProvinceSellingLimitationPercent
);
const [minimumSaleState, setMinimumSaleState] = useState(
item?.outProvinceSellingLimitation
);
const handleToggle = (value) => {
dispatch(
provincePolicyWagesEditKillhouse({
kill_house_key: item?.key,
out_province_selling_limitation: value,
out_province_selling_limitation_percent: value ? percent || 0 : 0,
})
).then((r) => {
setMinimumSaleState(value);
if (r.payload?.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
fetchdata();
}
});
};
const handleUpdatePercent = () => {
if (percent > 100 || percent < 1) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "درصد باید بین ۱ تا ۱۰۰ باشد.",
severity: "error",
});
return;
}
dispatch(
provincePolicyWagesEditKillhouse({
kill_house_key: item?.key,
out_province_selling_limitation: true,
out_province_selling_limitation_percent: percent,
})
).then((r) => {
if (r.payload?.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
fetchdata();
}
});
};
return (
<Grid container direction="column" gap={SPACING.SMALL}>
<Grid container alignItems="center" spacing={1}>
<Grid item>
<Switch
checked={minimumSaleState}
onChange={(e) => handleToggle(e.target.checked)}
inputProps={{
"aria-label": "in-province-selling-limitation-switch",
}}
/>
</Grid>
<Grid item>
<Typography>حداکثر فروش به خارج استان</Typography>
</Grid>
</Grid>
{minimumSaleState && (
<Grid container alignItems="center" spacing={1}>
<Grid item xs container alignItems="center" spacing={1}>
<Grid item xs>
<TextField
label="درصد فروش"
size="small"
fullWidth
value={percent}
onChange={(e) => {
setPercent(e.target.value);
}}
inputProps={{ min: 1, max: 100 }}
/>
</Grid>
<Grid item>
<Button
variant="contained"
color="primary"
onClick={handleUpdatePercent}
disabled={percent > 100 || percent < 1}
sx={{
minWidth: "40px",
}}
>
<DoneIcon />
</Button>
</Grid>
</Grid>
</Grid>
)}
</Grid>
);
};

View File

@@ -0,0 +1,66 @@
import React, { useContext, useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { useDispatch } from "react-redux";
import { cityFetchSamasatTransportChickensDetails } from "../../../visors/services/fetch-samasat-transport-chickens";
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
import { AppContext } from "../../../../contexts/AppContext";
export const TransportChickensDetails = ({ code, cookie }) => {
const dispatch = useDispatch();
const [openNotif] = useContext(AppContext);
const [tableData, setTableData] = useState([]);
useEffect(() => {
dispatch(
cityFetchSamasatTransportChickensDetails({
cookie,
certId: code,
})
).then((r) => {
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "کوکی معتبر نیست!",
severity: "error",
});
} else {
const d = r.payload.data?.map((item, i) => {
return [
i + 1,
item?.TrackingCode,
item?.ResideDatePersian,
item?.GoodAmount?.toLocaleString(),
item?.TrackingStatusDescription,
item?.GoodName,
item?.DesPartIdCode,
item?.DesUnitName,
item?.IssueDatePersian,
];
});
setTableData(d);
}
});
}, []);
return (
<Grid container xs={12}>
<AdvancedTable
columns={[
"ردیف",
"کد رهگیری",
"تاریخ ثبت",
"تعداد",
"وضعیت",
"نام کالا",
"شناسه یکتا کشتارگاه مقصد",
"نام کشتارگاه",
"تاریخ ثبت وضعیت",
]}
data={tableData}
name="جزئیات حمل مرغ زنده"
/>
</Grid>
);
};

View File

@@ -0,0 +1,131 @@
import React, { useContext, useEffect, useState } from "react";
import { IconButton, Tooltip } from "@mui/material";
import { Grid } from "../../../../components/grid/Grid";
import { useDispatch } from "react-redux";
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
import {
cityFetchSamasatTransportChickens,
visorsGetSamasatCookieService,
} from "../../../visors/services/fetch-samasat-transport-chickens";
import { DRAWER, LOADING_END } from "../../../../lib/redux/slices/appSlice";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import { TransportChickensDetails } from "../transport-chickens-details/TransportChickensDetails";
import { AppContext } from "../../../../contexts/AppContext";
import { useProvinceName } from "../../../../utils/getProvinceName";
export const TransportChickens = () => {
const [tableData, setTableData] = useState([]);
const [openNotif] = useContext(AppContext);
const [data, setData] = useState([]);
const dispatch = useDispatch();
const province = useProvinceName();
const [cookie, setCookie] = useState();
useEffect(() => {
dispatch(visorsGetSamasatCookieService()).then((r) => {
setCookie(r.payload.data.cookie);
dispatch(
cityFetchSamasatTransportChickens({
cookie: r.payload.data.cookie,
province:
province === "hamedan"
? "65550"
: province === "bushehr"
? "65527"
: "65548",
})
).then((r) => {
dispatch(LOADING_END());
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "کوکی معتبر نیست!",
severity: "error",
});
} else {
setData(r.payload.data);
}
});
});
}, []);
useEffect(() => {
const d = data?.map((item, i) => {
return [
i + 1,
item?.LocationNameProvince,
item?.LocationNameCity,
item?.PersonFullName,
item?.PartIdCode,
item?.UnitName,
item?.EpidemiologicCode,
item?.PostalCode,
item?.CapacityFemale.toLocaleString(),
item?.RequestCode,
item?.SourceCertId,
item?.HatchingDatePersian,
item?.HatchingCount?.toLocaleString(),
item?.RemoveCount,
item?.RemoveCountTakhlie,
item?.RemovePartyCount,
<Tooltip placement="right" title="جزئیات" key={i}>
<IconButton
size="small"
color="primary"
onClick={() => {
dispatch(
DRAWER({
right: false,
top: true,
content: (
<TransportChickensDetails
code={item?.SourceCertId}
cookie={cookie}
/>
),
title: "جزئیات حمل مرغ زنده",
})
);
}}
>
<RemoveRedEyeIcon />
</IconButton>
</Tooltip>,
];
});
setTableData(d);
}, [data]);
return (
<Grid container xs={12} mt={2} justifyContent="center">
<Grid container xs={12} mt={2} justifyContent="center">
<ResponsiveTable
paginated
data={tableData}
columns={[
"ردیف",
"استان",
"شهر",
"نام مالک",
"شناسه یکتا واحد",
"نام واحد",
"کد اپیدمیولوژیک واحد",
"کد پستی",
"ظرفیت",
"شماره مجوز",
"شماره گواهی بهداشتی",
"تاریخ جوجه ریزی",
"تعداد جوجه ریزی",
"مجموع حمل مرغ (تخلیه/ بارگیری)",
"مجموع حمل مرغ (تایید تخلیه)",
"تعداد ماشین حمل",
"جزئیات",
]}
title="گزارش حمل مرغ زنده گله ها بر اساس حمل "
/>
</Grid>
</Grid>
);
};