push rasad front on new repo
This commit is contained in:
@@ -0,0 +1,297 @@
|
||||
import { Button, Chip, Divider, TextField, Typography } from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import ChartBar from "../../../../components/chart-bar/ChartBar";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { useFormik } from "formik";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { adminGetHatchingByPeriod } from "../../services/admin-get-hatching-by-period";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import moment from "moment";
|
||||
import { EMPTY_HATCHING } from "../../../../lib/redux/slices/adminSlice";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
|
||||
export const AdminHatchingByPeriod = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const { hatchingByPeriod } = useSelector((state) => state.adminSlice);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(EMPTY_HATCHING());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (hatchingByPeriod && Array.isArray(hatchingByPeriod)) {
|
||||
setHatchingByPeriodData({
|
||||
labels: hatchingByPeriod.map((data) => formatJustDate(data?.date)),
|
||||
datasets: [
|
||||
{
|
||||
label: "تعداد",
|
||||
backgroundColor: ["rgba(33, 72, 214, 0.7)"],
|
||||
data: hatchingByPeriod.map((data) => data?.quantity || 0),
|
||||
borderRadius: 5,
|
||||
},
|
||||
{
|
||||
label: "تلفات",
|
||||
backgroundColor: ["rgba(100, 130, 160, 0.7)"],
|
||||
data: hatchingByPeriod.map((data) => data?.losses || 0),
|
||||
borderRadius: 5,
|
||||
},
|
||||
// {
|
||||
// type: "line",
|
||||
// label: "مقدار استاندارد",
|
||||
// backgroundColor: ["rgba(0, 120, 10, 0.7)"],
|
||||
// data: [
|
||||
// 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500,
|
||||
// 2500,
|
||||
// ],
|
||||
// },
|
||||
],
|
||||
});
|
||||
}
|
||||
}, [hatchingByPeriod?.length]);
|
||||
|
||||
const [hatchingByPeriodData, setHatchingByPeriodData] = useState({
|
||||
datasets: [],
|
||||
});
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
periodfrom: moment(Date()).format("YYYY-MM-DD"),
|
||||
periodto: moment(Date()).format("YYYY-MM-DD"),
|
||||
chickenAge: "5",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
periodfrom: Yup.string()
|
||||
.typeError("لطفا فیلد را به درستی وارد کنید.!")
|
||||
.required("این فیلد اجباری است!"),
|
||||
periodto: Yup.string()
|
||||
.typeError("لطفا فیلد را به درستی وارد کنید.!")
|
||||
.required("این فیلد اجباری است!"),
|
||||
chickenAge: Yup.number()
|
||||
.typeError("لطفا فیلد را به صورت عددی وارد کنید.!")
|
||||
.required("این فیلد اجباری است!")
|
||||
.test("len", "سن مرغ را در بازه 45 روزه وارد کنید", (val, context) => {
|
||||
if (context.originalValue) {
|
||||
return context.originalValue <= 45 && context.originalValue > 0;
|
||||
}
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
const chartTooltipData = (data) => {
|
||||
if (!data || !data.parsed || typeof data.parsed.x === "undefined") {
|
||||
return "";
|
||||
}
|
||||
|
||||
const index = data.parsed.x;
|
||||
|
||||
if (!data?.dataset?.label) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (data.dataset.label === "تلفات") {
|
||||
return "مرغداری صداقت با مقدار 2000 در تاریخ 1400/02/03";
|
||||
} else if (data.dataset.label === "مقدار استاندارد") {
|
||||
return `میزان استاندارد جوجه ریزی در روز ${
|
||||
data?.formattedValue || ""
|
||||
} عدد میباشد`;
|
||||
} else {
|
||||
const hatchingItem = hatchingByPeriod?.[index];
|
||||
if (!hatchingItem || !Array.isArray(hatchingItem?.poultry)) {
|
||||
return "";
|
||||
}
|
||||
return hatchingItem.poultry
|
||||
.map(
|
||||
(poultryData, i) =>
|
||||
i +
|
||||
1 +
|
||||
"- مرغداری " +
|
||||
(poultryData?.unitname || "") +
|
||||
" از استان " +
|
||||
(poultryData?.province || "") +
|
||||
" شهر " +
|
||||
(poultryData?.city || "")
|
||||
)
|
||||
.join(", ");
|
||||
}
|
||||
};
|
||||
|
||||
const chartTooltipTitle = (data) => {
|
||||
if (!data?.dataset?.label) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (data.dataset.label === "تلفات") {
|
||||
return "تلفات برای این مرغداری ها ثبت شده است";
|
||||
} else if (data.dataset.label === "مقدار استاندارد") {
|
||||
return "لاین کنترلی";
|
||||
} else {
|
||||
return "جوجه ریزی ها توسط این مرغداری ها ثبت شده است";
|
||||
}
|
||||
};
|
||||
|
||||
const [dataObject, setDataObject] = useState({
|
||||
date1: "",
|
||||
date2: "",
|
||||
age: "",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setDataObject({
|
||||
date1: formik.values.periodfrom,
|
||||
date2: formik.values.periodto,
|
||||
age: formik.values.chickenAge,
|
||||
});
|
||||
}, [formik.values]);
|
||||
|
||||
const options = {
|
||||
plugins: {
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
title: (data) => {
|
||||
if (!data || !Array.isArray(data) || !data[0]) {
|
||||
return "";
|
||||
}
|
||||
return chartTooltipTitle(data[0]);
|
||||
},
|
||||
label: (data) => {
|
||||
if (!data) {
|
||||
return "";
|
||||
}
|
||||
return chartTooltipData(data);
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
const isFormvalid = (formik) => {
|
||||
const date =
|
||||
(new Date(formik.values.periodto) - new Date(formik.values.periodfrom)) /
|
||||
(1000 * 60 * 60 * 24);
|
||||
if (date > 0 && date <= 30) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid
|
||||
sx={{ backgroundColor: "#fff2fd", borderRadius: "25px" }}
|
||||
mt={SPACING.SMALL}
|
||||
xs={12}
|
||||
container
|
||||
justifyContent="center"
|
||||
>
|
||||
<Grid xs={10} lg={10} mb={SPACING.MEDIUM} mt={SPACING.SMALL}>
|
||||
<Divider mb={SPACING.SMALL}>
|
||||
<Chip label="پیش بینی جوجه ریزی" />
|
||||
</Divider>
|
||||
<Grid
|
||||
xs={12}
|
||||
sm={12}
|
||||
md={12}
|
||||
lg={8}
|
||||
display="flex"
|
||||
mt={SPACING.SMALL}
|
||||
mb={SPACING.SMALL}
|
||||
gap={SPACING.SMALL}
|
||||
alignItems="center"
|
||||
>
|
||||
<Typography sx={{ width: "100%" }} color="primary" variant="body2">
|
||||
دریافت بر اساس بازه دلخواه :
|
||||
</Typography>
|
||||
<DatePicker
|
||||
label="بازه از"
|
||||
id="periodfrom"
|
||||
renderInput={(params) => <TextField size="small" {...params} />}
|
||||
value={formik.values.periodfrom}
|
||||
error={
|
||||
formik.touched.periodfrom
|
||||
? Boolean(formik.errors.periodfrom)
|
||||
: null
|
||||
}
|
||||
onChange={(e) => {
|
||||
formik.setFieldValue(
|
||||
"periodfrom",
|
||||
moment(e).format("YYYY-MM-DD")
|
||||
);
|
||||
}}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.periodfrom && Boolean(formik.errors.periodfrom)
|
||||
? formik.errors.periodfrom
|
||||
: null
|
||||
}
|
||||
/>
|
||||
|
||||
<DatePicker
|
||||
label="تا"
|
||||
id="periodto"
|
||||
renderInput={(params) => <TextField size="small" {...params} />}
|
||||
value={formik.values.periodto}
|
||||
error={
|
||||
formik.touched.periodto ? Boolean(formik.errors.periodto) : null
|
||||
}
|
||||
onChange={(e) => {
|
||||
formik.setFieldValue("periodto", moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.periodto && Boolean(formik.errors.periodto)
|
||||
? formik.errors.periodto
|
||||
: null
|
||||
}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
id="chickenAge"
|
||||
size="small"
|
||||
label="سن جوجه"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%" }}
|
||||
value={formik.values.chickenAge}
|
||||
error={
|
||||
formik.touched.chickenAge
|
||||
? Boolean(formik.errors.chickenAge)
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.chickenAge && Boolean(formik.errors.chickenAge)
|
||||
? formik.errors.chickenAge
|
||||
: null
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
disabled={isFormvalid(formik)}
|
||||
sx={{ width: "100%" }}
|
||||
size="small"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(adminGetHatchingByPeriod(dataObject)).then(() => {
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}}
|
||||
>
|
||||
ارسال اطلاعات
|
||||
</Button>
|
||||
</Grid>
|
||||
<ChartBar options={options} chartData={hatchingByPeriodData} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
296
src/features/admin/components/admin-hatching/AdminHatching.js
Normal file
296
src/features/admin/components/admin-hatching/AdminHatching.js
Normal file
@@ -0,0 +1,296 @@
|
||||
import { Button, IconButton, Tooltip } from "@mui/material";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useFormik } from "formik";
|
||||
import moment from "moment";
|
||||
import { useState } from "react";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import { useContext } from "react";
|
||||
import Tour from "reactour";
|
||||
import { AvicultureNewHatching } from "../../../aviculture/components/aviculture-new-hatching/AvicultureNewHatching";
|
||||
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { avicultureGetHatchings } from "../../../aviculture/services/aviculture-get-hatchings";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { avicultureDeleteHatching } from "../../../aviculture/services/aviculture-delete-hatching";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
|
||||
const steps = [
|
||||
{
|
||||
selector: ".first-step",
|
||||
content: () => <div>برای ثبت جوجه ریزی اینجا کلیک کنید!</div>,
|
||||
},
|
||||
{
|
||||
selector: ".second",
|
||||
content: () => (
|
||||
<div>در این قسمت جوجه ریزی های ثبت شده توسط شما نمایش داده می شود.</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
export const AdminHatching = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const { avicultureHatchings } = useSelector((state) => state.avicultureSlice);
|
||||
const [isTourOpen, setIsTourOpen] = useState(false);
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const [dataTableArchived, setDataTableArchuved] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(avicultureGetHatchings());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const filteredData = avicultureHatchings?.filter(
|
||||
(item) => item.allowHatching === "pending"
|
||||
);
|
||||
|
||||
const filteredDataArchived = avicultureHatchings?.filter(
|
||||
(item) => item.allowHatching === "True"
|
||||
);
|
||||
|
||||
const d = filteredData?.map((item, i) => {
|
||||
const quantity = item?.quantity || 0;
|
||||
const losses = item?.losses || 0;
|
||||
const leftOver = item?.leftOver || 0;
|
||||
const killedNumber = quantity - losses - leftOver;
|
||||
const percentage =
|
||||
quantity > 0
|
||||
? (value) => ((value * 100) / quantity).toFixed(0)
|
||||
: () => "0";
|
||||
|
||||
return [
|
||||
i + 1,
|
||||
item?.poultry?.unitName || "",
|
||||
item?.hall || "",
|
||||
item?.period || "",
|
||||
formatJustDate(item?.createDate),
|
||||
formatJustDate(item?.date),
|
||||
item?.chickenBreed || "",
|
||||
item?.age || "",
|
||||
quantity,
|
||||
`${losses} (%${percentage(losses)})`,
|
||||
killedNumber + ` (%${percentage(killedNumber)})`,
|
||||
`${leftOver} (%${percentage(leftOver)})`,
|
||||
<Tooltip key={item?.key} title={"حذف جوجه ریزی"} placement="left-start">
|
||||
<IconButton
|
||||
aria-label="delete"
|
||||
color="error"
|
||||
onClick={() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(avicultureDeleteHatching(item?.key)).then((r) => {
|
||||
dispatch(LOADING_END());
|
||||
if (r?.error) {
|
||||
const errorMessage = r.error?.message || "";
|
||||
if (errorMessage.includes("403")) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "برای این جوجه ریزی درخواست کشتار ثبت شده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else if (errorMessage.includes("400")) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "برای این جوجه ریزی بازرسی ثبت شده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
dispatch(avicultureGetHatchings());
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</Tooltip>,
|
||||
];
|
||||
});
|
||||
|
||||
setDataTable(d);
|
||||
|
||||
const b = filteredDataArchived?.map((item, i) => {
|
||||
const quantity = item?.quantity || 0;
|
||||
const losses = item?.losses || 0;
|
||||
const leftOver = item?.leftOver || 0;
|
||||
const killedNumber = quantity - losses - leftOver;
|
||||
const percentage =
|
||||
quantity > 0
|
||||
? (value) => ((value * 100) / quantity).toFixed(0)
|
||||
: () => "0";
|
||||
|
||||
return [
|
||||
i + 1,
|
||||
item?.poultry?.unitName || "",
|
||||
item?.hall || "",
|
||||
item?.period || "",
|
||||
formatJustDate(item?.createDate),
|
||||
formatJustDate(item?.date),
|
||||
item?.chickenBreed || "",
|
||||
item?.age || "",
|
||||
quantity,
|
||||
`${losses} (%${percentage(losses)})`,
|
||||
killedNumber + ` (%${percentage(killedNumber)})`,
|
||||
`${leftOver} (%${percentage(leftOver)})`,
|
||||
];
|
||||
});
|
||||
|
||||
setDataTableArchuved(b);
|
||||
}, [avicultureHatchings]);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
noChicken: "",
|
||||
slaughterDate: moment(Date()).format("YYYY-MM-DD hh:mm:ss"),
|
||||
race: "آرین",
|
||||
weight: "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
noChicken: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا عدد وارد کنید!"),
|
||||
weight: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا وزن را وارد کنید!"),
|
||||
}),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
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}
|
||||
alignItems={"start"}
|
||||
gap={SPACING.SMALL}
|
||||
direction={"column"}
|
||||
>
|
||||
<Grid
|
||||
width="100%"
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Grid>
|
||||
<Button
|
||||
className="first-step"
|
||||
variant={"contained"}
|
||||
disabled={true}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
title: "ثبت اطلاعات جوجه ریزی",
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: <AvicultureNewHatching />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت جوجه ریزی جدید
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
{/* <Button
|
||||
onClick={() => setIsTourOpen(!isTourOpen)}
|
||||
variant="outlined"
|
||||
endIcon={<HelpOutlineIcon />}
|
||||
>
|
||||
راهنما
|
||||
</Button> */}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Tour
|
||||
steps={steps}
|
||||
isOpen={isTourOpen}
|
||||
onRequestClose={() => setIsTourOpen(false)}
|
||||
styles={{
|
||||
popover: (base) => ({
|
||||
...base,
|
||||
borderRadius: "10px",
|
||||
"--reactor-accent": "red",
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
<Grid width="100%" className="second">
|
||||
<AdvancedTable
|
||||
name="دوره های فعال جوجه ریزی"
|
||||
data={dataTable}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"نام فارم",
|
||||
"سالن",
|
||||
"دوره جوجه ریزی",
|
||||
"تاریخ ثبت جوجه ریزی",
|
||||
"تاریخ جوجه ریزی",
|
||||
"نژاد",
|
||||
"سن",
|
||||
"تعداد جوجه ریزی",
|
||||
"تلفات دوره",
|
||||
"کشتار شده",
|
||||
"مانده برای کشتار",
|
||||
"اقدام",
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid mt={SPACING.SMALL} width="100%" className="second">
|
||||
<AdvancedTable
|
||||
name="بایگانی جوجه ریزی"
|
||||
data={dataTableArchived}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"نام فارم",
|
||||
"سالن",
|
||||
"دوره جوجه ریزی",
|
||||
"تاریخ ثبت جوجه ریزی",
|
||||
"تاریخ جوجه ریزی",
|
||||
"نژاد",
|
||||
"سن",
|
||||
"تعداد جوجه ریزی",
|
||||
"تلفات دوره",
|
||||
"کشتار شده",
|
||||
"مانده در سالن",
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,247 @@
|
||||
import {
|
||||
Card,
|
||||
CardActionArea,
|
||||
CardContent,
|
||||
CardMedia,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import React from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { PropTypes } from "prop-types";
|
||||
|
||||
import img1 from "../../../../assets/images/document.jpg";
|
||||
import img2 from "../../../../assets/images/chicken.svg";
|
||||
import img3 from "../../../../assets/images/users.jpg";
|
||||
import img4 from "../../../../assets/images/price.jpg";
|
||||
|
||||
export default function AdminStaticInfoInBox({ infoData }) {
|
||||
return (
|
||||
<Grid xs={12} sm={8} md={8} lg={12}>
|
||||
<Grid
|
||||
container
|
||||
mt={SPACING.MEDIUM}
|
||||
gap={SPACING.SMALL}
|
||||
justifyContent="space-around"
|
||||
>
|
||||
<Card>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
component="img"
|
||||
height="240"
|
||||
image={img1}
|
||||
alt="green iguana"
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="body1">
|
||||
پرونده ها
|
||||
</Typography>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
فعال:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.numberOfActiveFiles}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
رد شده:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.numberOfRejectedFiles}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
بایگانی شده:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.numberOfArchiveFiles}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
component="img"
|
||||
height="240"
|
||||
image={img2}
|
||||
alt="green iguana"
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="body1">
|
||||
جوجه ریزی
|
||||
</Typography>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
جوجه ریزی:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.realHatching}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
تلفات:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.totalLossess}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
مجموع:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.totalHatching}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
component="img"
|
||||
height="240"
|
||||
image={img3}
|
||||
alt="green iguana"
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="body1">
|
||||
کاربران
|
||||
</Typography>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
کل:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.totalUsers}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
کاربر:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.numberOfUsers}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
اپراتور:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.numberOfOperators}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
component="img"
|
||||
height="240"
|
||||
image={img4}
|
||||
alt="green iguana"
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="body1">
|
||||
نرخ مرغ
|
||||
</Typography>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
قیمت روز:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.price} ریال
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
کف قیمت:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.floorPrice} ریال
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
سقف قیمت:
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{infoData?.cellingPrice} ریال
|
||||
</Typography>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
AdminStaticInfoInBox.propTypes = {
|
||||
infoData: PropTypes.any,
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { Button } from "@mui/material";
|
||||
import {
|
||||
ROUTE_ADMIN_ARCHIVED_REQUESTS,
|
||||
ROUTE_ADMIN_AWAITING_INSPECTION_REQUESTS,
|
||||
ROUTE_ADMIN_AWAITING_PAYMENT_REQUESTS,
|
||||
ROUTE_ADMIN_HATCHING,
|
||||
ROUTE_ADMIN_REJECTED_REQUESTS,
|
||||
ROUTE_ADMIN_REQUESTS,
|
||||
} from "../../../../routes/routes";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { NavLink } from "../../../../components/nav-link/NavLink";
|
||||
|
||||
export const AdminRequestsOperations = () => {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
p={SPACING.SMALL}
|
||||
direction={{ xs: "column", md: "row" }}
|
||||
>
|
||||
<NavLink
|
||||
to={ROUTE_ADMIN_HATCHING}
|
||||
active={pathname === ROUTE_ADMIN_HATCHING ? "true" : null}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
ثبت اطلاعات جوجه ریزی
|
||||
</Button>
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
to={ROUTE_ADMIN_REQUESTS}
|
||||
active={pathname === ROUTE_ADMIN_REQUESTS ? "true" : null}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
ثبت درخواست کشتار
|
||||
</Button>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_ADMIN_AWAITING_PAYMENT_REQUESTS}
|
||||
active={
|
||||
pathname === ROUTE_ADMIN_AWAITING_PAYMENT_REQUESTS ? "true" : null
|
||||
}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
در انتظار پرداخت
|
||||
</Button>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_ADMIN_AWAITING_INSPECTION_REQUESTS}
|
||||
active={
|
||||
pathname === ROUTE_ADMIN_AWAITING_INSPECTION_REQUESTS ? "true" : null
|
||||
}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
در انتظار بازرسی
|
||||
</Button>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_ADMIN_REJECTED_REQUESTS}
|
||||
active={pathname === ROUTE_ADMIN_REJECTED_REQUESTS ? "true" : null}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
سفارشات رد شده
|
||||
</Button>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_ADMIN_ARCHIVED_REQUESTS}
|
||||
active={pathname === ROUTE_ADMIN_ARCHIVED_REQUESTS ? "true" : null}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
سفارشات بایگانی شده
|
||||
</Button>
|
||||
</NavLink>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
7
src/features/admin/services/admin-get-charts.js
Normal file
7
src/features/admin/services/admin-get-charts.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const adminGetCharts = createAsyncThunk("ADMIN_GET_CHARTS", async () => {
|
||||
const { data, status } = await axios.get("chart");
|
||||
return { data, status };
|
||||
});
|
||||
17
src/features/admin/services/admin-get-hatching-by-period.js
Normal file
17
src/features/admin/services/admin-get-hatching-by-period.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const adminGetHatchingByPeriod = createAsyncThunk(
|
||||
"ADMIN_GET_HATCHING_BY_PERIOD",
|
||||
async (dataObject) => {
|
||||
const { data, status } = await axios.get(
|
||||
"forcast_hatching/?date1=" +
|
||||
dataObject.date1 +
|
||||
"&date2=" +
|
||||
dataObject.date2 +
|
||||
"&day=" +
|
||||
dataObject.age
|
||||
);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,222 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { reportsList } from "./reportList";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import moment from "moment";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import { Button, IconButton, TextField, Typography } from "@mui/material";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { adminXGetReportStatusService } from "../../services/admin-x-get-report-status-service";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import ManageSearchIcon from "@mui/icons-material/ManageSearch";
|
||||
|
||||
export const AdminCExcelStatus = () => {
|
||||
const [tableData, setTableData] = useState([]);
|
||||
const userKey = useSelector((state) => state.userSlice?.userProfile?.key);
|
||||
const authToken = useSelector((state) => state.userSlice?.authToken);
|
||||
const [loadingIndex, setLoadingIndex] = useState(null);
|
||||
const [allReports, setAllReports] = useState([]);
|
||||
const [update, setUpdate] = useState(false);
|
||||
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, [setSelectedDate1, setSelectedDate2]);
|
||||
|
||||
useEffect(() => {
|
||||
const newData = reportsList.map((report) => ({
|
||||
...report,
|
||||
status: "",
|
||||
}));
|
||||
setAllReports(newData);
|
||||
}, []);
|
||||
|
||||
function replaceUrlParams(url, date1, date2, role, key, token) {
|
||||
if (!url || typeof url !== "string") {
|
||||
return url || "";
|
||||
}
|
||||
|
||||
const [baseUrl, queryString] = url.split("?");
|
||||
|
||||
if (!queryString) {
|
||||
return url;
|
||||
}
|
||||
|
||||
const params = new URLSearchParams(queryString);
|
||||
|
||||
if (params.has("date1")) {
|
||||
params.set("date1", date1);
|
||||
}
|
||||
if (params.has("date2")) {
|
||||
params.set("date2", date2);
|
||||
}
|
||||
|
||||
if (params.has("start")) {
|
||||
params.set("start", date1);
|
||||
}
|
||||
if (params.has("end")) {
|
||||
params.set("end", date2);
|
||||
}
|
||||
|
||||
if (params.has("role")) {
|
||||
params.set("role", role);
|
||||
}
|
||||
|
||||
if (params.has("token")) {
|
||||
params.set("token", token);
|
||||
}
|
||||
|
||||
if (params.has("key")) {
|
||||
params.set("key", key);
|
||||
}
|
||||
|
||||
return `${baseUrl}?${params.toString()}`;
|
||||
}
|
||||
|
||||
const handleCheckAll = async () => {
|
||||
const updatedData = [...allReports];
|
||||
for (let i = 0; i < allReports.length; i++) {
|
||||
setLoadingIndex(i);
|
||||
try {
|
||||
const response = await dispatch(
|
||||
adminXGetReportStatusService({
|
||||
url: replaceUrlParams(
|
||||
allReports[i]?.url,
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
getRoleFromUrl(),
|
||||
userKey,
|
||||
authToken
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
if (response?.payload?.data?.status) {
|
||||
updatedData[i].status = response.payload.data.status;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching report status:", error);
|
||||
}
|
||||
}
|
||||
setLoadingIndex(null);
|
||||
setAllReports(updatedData);
|
||||
setUpdate((prevUpdate) => !prevUpdate);
|
||||
};
|
||||
|
||||
const handleSingleCheck = async (index) => {
|
||||
setLoadingIndex(index);
|
||||
try {
|
||||
const response = await dispatch(
|
||||
adminXGetReportStatusService({
|
||||
url: replaceUrlParams(
|
||||
allReports[index]?.url,
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
getRoleFromUrl(),
|
||||
userKey,
|
||||
authToken
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
const newData = [...allReports];
|
||||
if (response?.payload?.data?.status) {
|
||||
newData[index].status = response.payload.data.status;
|
||||
}
|
||||
setAllReports(newData);
|
||||
} catch (error) {
|
||||
console.error("Error fetching report status:", error);
|
||||
} finally {
|
||||
setLoadingIndex(null);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const d = allReports.map((item, i) => [
|
||||
i + 1,
|
||||
item?.title || "",
|
||||
item?.url ? item.url.split("/")[0] : "",
|
||||
<IconButton
|
||||
color="primary"
|
||||
key={`button-${i}`}
|
||||
onClick={() => handleSingleCheck(i)}
|
||||
disabled={loadingIndex === i}
|
||||
>
|
||||
<ManageSearchIcon />
|
||||
</IconButton>,
|
||||
item?.status ? (
|
||||
<Typography
|
||||
key={`status-${i}`}
|
||||
style={{
|
||||
color:
|
||||
parseInt(item.status) === 200 || item.status === "200"
|
||||
? "green"
|
||||
: "red",
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
({item.status}){" "}
|
||||
{parseInt(item.status) === 200 || item.status === "200"
|
||||
? "سالم"
|
||||
: "مشکل دارد"}
|
||||
</Typography>
|
||||
) : (
|
||||
"-"
|
||||
),
|
||||
]);
|
||||
|
||||
setTableData(d);
|
||||
}, [allReports, loadingIndex, update]);
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center">
|
||||
<Grid container gap={SPACING.SMALL} alignItems="center">
|
||||
<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={handleCheckAll}>
|
||||
تست همگانی
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<ResponsiveTable
|
||||
title="بررسی اکسل"
|
||||
noPagination
|
||||
data={tableData}
|
||||
columns={["ردیف", "عنوان", "آدرس", "بررسی", "وضعیت"]}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,219 @@
|
||||
export const reportsList = [
|
||||
{
|
||||
title: "مدیریت بار",
|
||||
url: "bar_excel/?start=2024-08-03&end=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&role=ProvinceOperator&search=filter&value=",
|
||||
},
|
||||
{
|
||||
title: "گزارش جزییات کشتار",
|
||||
url: "detail_of_killing_excel/?date1=2024-08-03&date2=2024-08-03&role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "گزارش جامع کشتارگاه",
|
||||
url: "comprehensive_report_of_the_slaughterhouse_excel/?date1=2024-08-03&date2=2024-08-03",
|
||||
},
|
||||
{
|
||||
title: "پایش کلی بارها",
|
||||
url: "monitor_loads_excel/?role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&date1=2024-08-03&date2=2024-08-03",
|
||||
},
|
||||
{
|
||||
title: "مدیریت بارهای تکمیل نشده",
|
||||
url: "bar_excel/?start=2024-05-21&end=2024-08-03&role=ProvinceOperator&state=bar_pending&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&search=filter&value=",
|
||||
},
|
||||
{
|
||||
title: "مدیریت بارهای تکمیل شده",
|
||||
url: "bar_excel/?start=2024-07-22&end=2024-08-03&state=completed&role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&search=filter&value=",
|
||||
},
|
||||
{
|
||||
title: "بارهای حذف شده",
|
||||
url: "bar_excel_trash_true/?start=2024-08-03&end=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&role=ProvinceOperator&search=filter&value=",
|
||||
},
|
||||
{
|
||||
title: "فروش خارج از استان",
|
||||
url: "bar_free_excel/?date1=2024-08-03&date2=2024-08-03&state=accepted&role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "مدیریت بارهای زنجیره",
|
||||
url: "bar_chain_excel/?key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&role=ProvinceOperator&search=filter&value=&state=accepted&date1=2024-08-03&date2=2024-08-03",
|
||||
},
|
||||
{
|
||||
title: "خرید خارج از استان زنده",
|
||||
url: "kill_house_free_bar_excel/?role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&date1=2024-08-03&date2=2024-08-03&type=live",
|
||||
},
|
||||
{
|
||||
title: "خرید خارج از استان لاشه",
|
||||
url: "kill_house_free_bar_excel/?role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&date1=2024-08-03&date2=2024-08-03&type=carcass",
|
||||
},
|
||||
{
|
||||
title: "درخواست مرغدار",
|
||||
url: "poultry_kill_request_excel/?start=2024-08-03&end=2024-08-03&role=ProvinceOperator&token=vamptUktoL9b1htBgvjE14XTZg7Bg4",
|
||||
},
|
||||
{
|
||||
title: "درخواست کشتارگاه",
|
||||
url: "kill_house_excel/?start=2024-08-03&end=2024-08-03",
|
||||
},
|
||||
{
|
||||
title: "جوجه ریزی",
|
||||
url: "0/hatching_excel/?role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&search=filter&value=",
|
||||
},
|
||||
{
|
||||
title: "بایگانی جوجه ریزی",
|
||||
url: "archive_hatching_excel/?search=filter&value=&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&role=ProvinceOperator",
|
||||
},
|
||||
{
|
||||
title: "جوجه ریزی در بازه تاریخی",
|
||||
url: "hatching_date_range_excel/?date1=2024-08-03&date2=2024-08-03",
|
||||
},
|
||||
{
|
||||
title: "وضعیت پرونده",
|
||||
url: "poultry_request_report_excel/?start=2024-08-03&end=2024-08-03&role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "گزارش مغایرت اطلاعات کشتار و عدم فعالیت نقش ها",
|
||||
url: "discrepancy_report_excel/?date1=2024-08-02&date2=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&role=ProvinceOperator",
|
||||
},
|
||||
{
|
||||
title:
|
||||
"گزارش کلی فارم های فعال مرغ گوشتی دارای مانده در سالن بیشتر از 10 درصد و بازه سنی 55 تا 90 روزه",
|
||||
url: "poultry_hatching_between_50age_70age_excel/",
|
||||
},
|
||||
{
|
||||
title: "گزارش کشتار روزانه",
|
||||
url: "daily_process_klling_proccess_excel/?date=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "گزارش پخش روزانه",
|
||||
url: "daily_process_excel/?date=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "تراکنش های موفق",
|
||||
url: "successful_transactions_excel/?date1=2024-08-03&date2=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "تراکنش های ناموفق",
|
||||
url: "unsuccessful_transactions_excel/?date1=2024-08-03&date2=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "مدیریت اصناف",
|
||||
url: "guilds_excel/?key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&search=filter&value=&role=ProvinceOperator",
|
||||
},
|
||||
{
|
||||
title: "مدیریت مباشرین",
|
||||
url: "stewards_excel/",
|
||||
},
|
||||
{
|
||||
title: "خودروها",
|
||||
url: "car_province_excel/?key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&role=Province",
|
||||
},
|
||||
{
|
||||
title: "مدیریت کاربران",
|
||||
url: "get_all_user_excel/",
|
||||
},
|
||||
{
|
||||
title: "مدیریت مرغداران",
|
||||
url: "management_poultry/?key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&role=ProvinceOperator",
|
||||
},
|
||||
{
|
||||
title: "مدیریت خریداران",
|
||||
url: "kill_house_user_excel/",
|
||||
},
|
||||
{
|
||||
title: "گزارش پخش لاشه مرغ گرم",
|
||||
url: "all_inventory_excel/?date1=2024-07-22&date2=2024-08-03",
|
||||
},
|
||||
{
|
||||
title: "گزارش پخش لاشه مرغ گرم از مباشر به صنف",
|
||||
url: "steward_ware_house_total_report_daily_excel/?date1=2024-06-21&date2=2024-08-03",
|
||||
},
|
||||
{
|
||||
title: "کارمزد پرداخت شده کشتارگاه",
|
||||
url: "kill_house_total_transactions_wage_payid_excel/?key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&search=filter&value=&role=ProvinceOperator",
|
||||
},
|
||||
{
|
||||
title: "پرداختی زنجیره ها",
|
||||
url: "chain-company-total-transactions_not_payid_excel/?token=vamptUktoL9b1htBgvjE14XTZg7Bg4",
|
||||
},
|
||||
{
|
||||
title: "ریز تراکنش ها",
|
||||
url: "payment_transactions_province_excel/?role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "اطلاعات تعرفه بارهای روزانه",
|
||||
url: "kill_house_total_wage_excel/?token=vamptUktoL9b1htBgvjE14XTZg7Bg4&date1=2024-08-03&date2=2024-08-03",
|
||||
},
|
||||
{
|
||||
title: "پایش تعرفه برای استان",
|
||||
url: "kill_house_total_transactions_wage_payid_super_admin_excel/?key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&role=AdminX",
|
||||
},
|
||||
{
|
||||
title: "پایش تعرفه برای ادمین ایکس",
|
||||
url: "kill_house_total_transactions_wage_payid_admin_x_excel/?role=AdminX&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "خرید مستقیم",
|
||||
url: "direct_purchase_excel/?date1=2024-08-03&date2=2024-08-03&role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "بایگانی خرید مستقیم",
|
||||
url: "direct_purchase_archive_excel/?date1=2024-08-03&date2=2024-08-03&role=ProvinceOperator&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "بایگانی صادرات",
|
||||
url: "export_kill_house_excel/?date1=2024-08-03&date2=2024-08-03&role=AdminX&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "گزارش کلی بار خارج از استان",
|
||||
url: "general_free_bar_excel/?date1=2024-08-03&date2=2024-08-03&role=AdminX&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&search=filter&value=",
|
||||
},
|
||||
{
|
||||
title: "بار خارج از استان",
|
||||
url: "bar_free_excel/?date1=2024-08-03&date2=2024-08-03&state=pending&role=AdminX&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "بارهای تایید شده خارج از استان",
|
||||
url: "bar_free_excel/?date1=2024-08-03&date2=2024-08-03&state=accepted&role=AdminX&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "بارهای رد شده خارج از استان",
|
||||
url: "bar_free_excel/?date1=2024-08-03&date2=2024-08-03&state=rejected&role=AdminX&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "خریداران خارج از استان",
|
||||
url: "out_province_poultry_request_buyers_excel/?key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&role=AdminX&search=filter&value=",
|
||||
},
|
||||
{
|
||||
title: "جوجه ریزی زنجیره",
|
||||
url: "0/hatching_excel/?role=AdminX&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&chain=true",
|
||||
},
|
||||
{
|
||||
title: "مدیریت بار زنجیره ها",
|
||||
url: "bar_chain_excel/?key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&role=AdminX&search=filter&value=&state=accepted&date1=2024-08-03&date2=2024-08-03",
|
||||
},
|
||||
{
|
||||
title: "شرکت زنجیره",
|
||||
url: "chain_company_buyers_excel/?role=AdminX&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904&search=filter&value=",
|
||||
},
|
||||
{
|
||||
title: "جوجه ریزی بایگانی شرکت زنجیره",
|
||||
url: "archive_hatching_excel/?chain=true",
|
||||
},
|
||||
{
|
||||
title: "مدیریت تخصیصات",
|
||||
url: "allocated_excel/?start=2024-08-03&end=2024-08-03",
|
||||
},
|
||||
{
|
||||
title: "گزارش کشتار روزانه",
|
||||
url: "daily_process_klling_proccess_excel/?date=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "گزارش پخش روزانه",
|
||||
url: "daily_process_excel/?date=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "تراکنش های موفق",
|
||||
url: "successful_transactions_excel/?date1=2024-08-03&date2=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
{
|
||||
title: "تراکنش های ناموفق",
|
||||
url: "unsuccessful_transactions_excel/?date1=2024-08-03&date2=2024-08-03&key=fde6fff6-7f4c-4e10-5604-0d45f8b41904",
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const adminXGetReportStatusService = createAsyncThunk(
|
||||
"ADMINX_REPORT_STATUS",
|
||||
async (d, { dispatch }) => {
|
||||
const { data, status } = await axios.get("check_excel/", {
|
||||
params: { url: d.url },
|
||||
});
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
111
src/features/auction/components/auction-bids/AuctionBids.js
Normal file
111
src/features/auction/components/auction-bids/AuctionBids.js
Normal file
@@ -0,0 +1,111 @@
|
||||
import { Button } from "@mui/material";
|
||||
// import moment from "moment";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
// import { Timer } from "../../../../components/timer/Timer";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { ROUTE_SLAUGHTER_FILE } from "../../../../routes/routes";
|
||||
import { formatTime } from "../../../../utils/formatTime";
|
||||
import { auctionSlaughterRequests } from "../../services/auction-slaughter-requests";
|
||||
|
||||
export const AuctionsBids = () => {
|
||||
const [tableRows, setTableRows] = useState([]);
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const { auctionSlaughterRequestsData } = useSelector(
|
||||
(state) => state.auctionSlice
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(auctionSlaughterRequests());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!auctionSlaughterRequestsData ||
|
||||
!Array.isArray(auctionSlaughterRequestsData)
|
||||
) {
|
||||
setTableRows([]);
|
||||
return;
|
||||
}
|
||||
|
||||
setTableRows(
|
||||
auctionSlaughterRequestsData.map((item) => {
|
||||
// const auctionFinishDate = moment(new Date(item.date));
|
||||
// const currentDate = moment();
|
||||
// const diff = auctionFinishDate.diff(currentDate);
|
||||
// let auctionRemainedSeconds = moment.duration(diff).asSeconds();
|
||||
const auctionState =
|
||||
item?.state === "accepted"
|
||||
? "برنده شده اید!"
|
||||
: item?.state === "pending"
|
||||
? "در حال انجام مزایده"
|
||||
: "درخواست شما پذیرفته نشد.";
|
||||
return [
|
||||
item?.poultryRequest?.id || "",
|
||||
item?.poultryRequest?.orderCode || "",
|
||||
(item?.fee || 0) + " ﷼",
|
||||
(item?.poultryRequest?.quantity || 0) + " قطعه",
|
||||
item?.poultryRequest?.hatching?.date || "",
|
||||
(item?.poultryRequest?.chickenBreed || "") +
|
||||
(item?.poultryRequest?.chickenBreed &&
|
||||
item?.poultryRequest?.process?.poultry?.age
|
||||
? " - "
|
||||
: "") +
|
||||
(item?.poultryRequest?.process?.poultry?.age || ""),
|
||||
(item?.poultryRequest?.IndexWeight || 0) + " کیلوگرم",
|
||||
item?.poultryRequest?.poultry?.address?.province?.name || "",
|
||||
item?.poultryRequest?.poultry?.address?.city?.name || "",
|
||||
item?.date ? formatTime(item.date) : "",
|
||||
auctionState === "برنده شده اید!" ? (
|
||||
<Grid container alignItems="center" justifyContent="center">
|
||||
{auctionState}
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigate(
|
||||
ROUTE_SLAUGHTER_FILE + (item?.poultryRequest?.id || "")
|
||||
);
|
||||
}}
|
||||
>
|
||||
ادامه خرید
|
||||
</Button>
|
||||
</Grid>
|
||||
) : (
|
||||
auctionState
|
||||
),
|
||||
];
|
||||
})
|
||||
);
|
||||
}, [auctionSlaughterRequestsData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{auctionSlaughterRequestsData &&
|
||||
Array.isArray(auctionSlaughterRequestsData) &&
|
||||
auctionSlaughterRequestsData.length > 0 && (
|
||||
<Grid container gap={SPACING.SMALL} p={SPACING.SMALL} width="100%">
|
||||
<AdvancedTable
|
||||
name="مزایده های شما"
|
||||
columns={[
|
||||
"شماره مزایده",
|
||||
"کدسفارش",
|
||||
"قیمت پیشنهادی شما",
|
||||
"تعداد",
|
||||
"تاریخ جوجه ریزی",
|
||||
"نژاد و سن به روز",
|
||||
"وزن",
|
||||
"استان",
|
||||
"شهرستان",
|
||||
"تاریخ ثبت پیشنهاد",
|
||||
"وضعیت",
|
||||
]}
|
||||
data={tableRows}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,221 @@
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
Slider,
|
||||
} from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { useFormik } from "formik";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { PropTypes } from "prop-types";
|
||||
import {
|
||||
auctionFilterByAge,
|
||||
auctionFilterByPrice,
|
||||
auctionFilterByQuantity,
|
||||
auctionFilterByRace,
|
||||
auctionFilterByWeight,
|
||||
} from "../../../../lib/redux/slices/auctionSlice";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { useEffect } from "react";
|
||||
import { avicultureGetChickenPrice } from "../../../aviculture/services/aviculture-get-chicken-price";
|
||||
|
||||
export const AuctionFilterRequestAdvance = ({
|
||||
minQuantity = 0,
|
||||
maxQuantity = 1000,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const { avicultureChickenPrice } = useSelector(
|
||||
(state) => state.avicultureSlice
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(avicultureGetChickenPrice());
|
||||
dispatch(LOADING_END());
|
||||
}, []);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
age: "",
|
||||
race: "همه",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
age: Yup.number().typeError("لطفا سن مرغ را وارد کنید."),
|
||||
}),
|
||||
});
|
||||
|
||||
const [number, setNumber] = useState([minQuantity || 0, maxQuantity || 1000]);
|
||||
const [weight, setWeight] = useState([1, 5]);
|
||||
const [age, setAge] = useState([30, 70]);
|
||||
const [price, setPrice] = useState([
|
||||
avicultureChickenPrice?.floorPrice || 0,
|
||||
avicultureChickenPrice?.ceilingPrice || 100000,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
avicultureChickenPrice?.floorPrice &&
|
||||
avicultureChickenPrice?.ceilingPrice
|
||||
) {
|
||||
setPrice([
|
||||
avicultureChickenPrice.floorPrice,
|
||||
avicultureChickenPrice.ceilingPrice,
|
||||
]);
|
||||
}
|
||||
}, [avicultureChickenPrice]);
|
||||
|
||||
const handleChangeNumber = (event, newNumber) => {
|
||||
setNumber(newNumber);
|
||||
};
|
||||
|
||||
const handleChangeWeight = (event, newWeight) => {
|
||||
setWeight(newWeight);
|
||||
};
|
||||
|
||||
const handleChangeAge = (event, newAge) => {
|
||||
setAge(newAge);
|
||||
};
|
||||
|
||||
const handleChangePrice = (event, newPrice) => {
|
||||
setPrice(newPrice);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
p={SPACING.MEDIUM}
|
||||
direction="column"
|
||||
flex="1"
|
||||
justifyContent="space-between"
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
<Grid container direction="column" gap={SPACING.SMALL}>
|
||||
<Grid>
|
||||
<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>
|
||||
</Select>
|
||||
<FormHelperText>
|
||||
{formik.touched.race && Boolean(formik.errors.race)
|
||||
? formik.errors.race
|
||||
: null}
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
{number &&
|
||||
Array.isArray(number) &&
|
||||
number[0] !== undefined &&
|
||||
number[0] !== Infinity &&
|
||||
minQuantity !== undefined &&
|
||||
maxQuantity !== undefined ? (
|
||||
<Grid display="flex" gap={SPACING.SMALL}>
|
||||
تعداد:
|
||||
<Slider
|
||||
size="small"
|
||||
getAriaLabel={() => "تعداد"}
|
||||
value={number}
|
||||
min={minQuantity || 0}
|
||||
max={maxQuantity || 1000}
|
||||
step={100}
|
||||
onChange={handleChangeNumber}
|
||||
valueLabelDisplay="auto"
|
||||
/>
|
||||
</Grid>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
|
||||
<Grid display="flex" gap={SPACING.SMALL}>
|
||||
سن:
|
||||
<Slider
|
||||
size="small"
|
||||
value={age}
|
||||
min={30}
|
||||
max={70}
|
||||
onChange={handleChangeAge}
|
||||
valueLabelDisplay="auto"
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex" gap={SPACING.SMALL}>
|
||||
وزن:
|
||||
<Slider
|
||||
size="small"
|
||||
getAriaLabel={() => "Temperature range"}
|
||||
value={weight}
|
||||
min={1}
|
||||
max={5}
|
||||
onChange={handleChangeWeight}
|
||||
valueLabelDisplay="auto"
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex" gap={SPACING.SMALL}>
|
||||
قیمت:
|
||||
<Slider
|
||||
size="small"
|
||||
getAriaLabel={() => "سقف و کف قیمت امروز"}
|
||||
value={price}
|
||||
step={5000}
|
||||
min={avicultureChickenPrice?.floorPrice || 0}
|
||||
max={avicultureChickenPrice?.ceilingPrice || 100000}
|
||||
onChange={handleChangePrice}
|
||||
valueLabelDisplay="auto"
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(auctionFilterByQuantity(number));
|
||||
dispatch(auctionFilterByAge(age));
|
||||
dispatch(
|
||||
auctionFilterByRace(
|
||||
formik.values.race === "همه" ? "" : formik.values.race
|
||||
)
|
||||
);
|
||||
dispatch(auctionFilterByWeight(weight));
|
||||
dispatch(auctionFilterByPrice(price));
|
||||
dispatch(DRAWER({ right: false, bottom: false, content: null }));
|
||||
}}
|
||||
>
|
||||
ثبت اطلاعات
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
AuctionFilterRequestAdvance.propTypes = {
|
||||
minQuantity: PropTypes.number,
|
||||
maxQuantity: PropTypes.number,
|
||||
};
|
||||
@@ -0,0 +1,173 @@
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControl,
|
||||
FormControlLabel,
|
||||
InputLabel,
|
||||
ListItemText,
|
||||
MenuItem,
|
||||
OutlinedInput,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
Select,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useEffect, useState } from "react";
|
||||
import { format } from "date-fns-jalali";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { auctionFilterByDate } from "../../../../lib/redux/slices/auctionSlice";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const AuctionFilterRequestDate = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const ITEM_HEIGHT = 48;
|
||||
const ITEM_PADDING_TOP = 8;
|
||||
|
||||
const { auctions } = useSelector((state) => state.auctionSlice || {});
|
||||
const [selectedDates, setSelectedDates] = useState([]);
|
||||
const [availableDates, setAvailableDates] = useState([]);
|
||||
const [value, setValue] = useState("all");
|
||||
|
||||
const handleChangeRadioButton = (event) => {
|
||||
setValue(event.target.value);
|
||||
};
|
||||
|
||||
const handleChange = (event) => {
|
||||
const {
|
||||
target: { value },
|
||||
} = event;
|
||||
setSelectedDates(
|
||||
// On autofill we get a stringified value.
|
||||
typeof value === "string" ? value.split(",") : value
|
||||
);
|
||||
};
|
||||
|
||||
const MenuProps = {
|
||||
PaperProps: {
|
||||
style: {
|
||||
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
|
||||
width: 250,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (auctions && Array.isArray(auctions)) {
|
||||
const data = auctions
|
||||
.filter((item) => item?.sendDate)
|
||||
.map((item) => {
|
||||
try {
|
||||
return format(new Date(item.sendDate), "yyyy/MM/dd");
|
||||
} catch (error) {
|
||||
console.error("Error formatting date:", error);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter((date) => date !== null);
|
||||
setAvailableDates(data);
|
||||
} else {
|
||||
setAvailableDates([]);
|
||||
}
|
||||
}, [auctions]);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
p={SPACING.MEDIUM}
|
||||
gap={SPACING.SMALL}
|
||||
direction="column"
|
||||
flex="1"
|
||||
height="100%"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Grid container direction="column" gap={SPACING.SMALL}>
|
||||
<Grid>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
aria-labelledby="demo-controlled-radio-buttons-group"
|
||||
name="controlled-radio-buttons-group"
|
||||
value={value}
|
||||
onChange={handleChangeRadioButton}
|
||||
>
|
||||
<FormControlLabel
|
||||
value="all"
|
||||
control={<Radio />}
|
||||
label="بدون فیلتر"
|
||||
/>
|
||||
<FormControlLabel
|
||||
value="filter"
|
||||
control={<Radio />}
|
||||
label="انتخاب تاریخ"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
{value === "filter" && (
|
||||
<>
|
||||
<Grid>
|
||||
<Typography variant="body2">
|
||||
تاریخ هایی که مایل به رویت مناقصات آنها هستید را انتخاب کنید.
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<FormControl sx={{ width: "100%" }}>
|
||||
<InputLabel id="demo-multiple-checkbox-label">
|
||||
تاریخ های انتخاب شده
|
||||
</InputLabel>
|
||||
<Select
|
||||
multiple
|
||||
labelId="demo-multiple-checkbox-label"
|
||||
id="demo-multiple-checkbox"
|
||||
value={selectedDates}
|
||||
onChange={handleChange}
|
||||
input={<OutlinedInput label="تاریخ های انتخاب شده" />}
|
||||
renderValue={(selected) =>
|
||||
Array.isArray(selected) ? selected.join(", ") : ""
|
||||
}
|
||||
MenuProps={MenuProps}
|
||||
>
|
||||
{availableDates.map((date, i) => (
|
||||
<MenuItem key={(date || "") + i} value={date || ""}>
|
||||
<Checkbox
|
||||
checked={
|
||||
Array.isArray(selectedDates) &&
|
||||
selectedDates.indexOf(date) > -1
|
||||
}
|
||||
/>
|
||||
<ListItemText primary={date || ""} />
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Grid>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
if (value === "all") {
|
||||
dispatch(auctionFilterByDate(null));
|
||||
} else {
|
||||
dispatch(
|
||||
auctionFilterByDate(
|
||||
Array.isArray(selectedDates) ? selectedDates : []
|
||||
)
|
||||
);
|
||||
}
|
||||
dispatch(DRAWER({ right: false, bottom: false, content: null }));
|
||||
}}
|
||||
>
|
||||
ثبت اطلاعات
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,149 @@
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { Autocomplete, Button, TextField } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { cityGetProvinces } from "../../../city/services/CityGetProvinces";
|
||||
import { useEffect } from "react";
|
||||
import { cityGetCity } from "../../../city/services/city-get-city";
|
||||
import {
|
||||
auctionFilterByCity,
|
||||
auctionFilterByProvince,
|
||||
} from "../../../../lib/redux/slices/auctionSlice";
|
||||
|
||||
export const AuctionFilterRequestZone = () => {
|
||||
const [provinceData, setProvinceData] = useState();
|
||||
const [cityData, setCityData] = useState();
|
||||
const [provinceKey, setProvinceKey] = useState();
|
||||
|
||||
const [selectedProvince, setSelectedProvince] = useState();
|
||||
const [selectedCity, setSelectedCity] = useState();
|
||||
|
||||
const [, setCityKey] = useState();
|
||||
const [isExistProvince, setIsExistProvince] = useState(true);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(cityGetProvinces())
|
||||
?.then((r) => {
|
||||
if (r?.payload?.data) {
|
||||
setProvinceData(r.payload.data);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error fetching provinces:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (provinceKey) {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(cityGetCity(provinceKey))
|
||||
.then((r) => {
|
||||
if (r?.payload?.data) {
|
||||
setCityData(r.payload.data);
|
||||
setIsExistProvince(false);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error fetching cities:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
} else {
|
||||
setCityData([]);
|
||||
setIsExistProvince(true);
|
||||
}
|
||||
}, [provinceKey]);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
p={SPACING.MEDIUM}
|
||||
direction="column"
|
||||
flex="1"
|
||||
height="100%"
|
||||
justifyContent="space-between"
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
<Grid container direction="column" gap={SPACING.SMALL}>
|
||||
<Grid>
|
||||
<Autocomplete
|
||||
disablePortal
|
||||
id="province"
|
||||
options={
|
||||
provinceData && Array.isArray(provinceData)
|
||||
? provinceData
|
||||
.filter((i) => i?.key && i?.name)
|
||||
.map((i) => ({ id: i.key, label: i.name }))
|
||||
: []
|
||||
}
|
||||
onChange={(e, value) => {
|
||||
if (value) {
|
||||
setProvinceKey(value.id);
|
||||
setSelectedProvince(value.label);
|
||||
} else {
|
||||
setProvinceKey(undefined);
|
||||
setSelectedProvince(undefined);
|
||||
}
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="استان را انتخاب کنید" />
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<Autocomplete
|
||||
disabled={isExistProvince}
|
||||
disablePortal
|
||||
id="city"
|
||||
options={
|
||||
cityData && Array.isArray(cityData)
|
||||
? cityData
|
||||
.filter((i) => i?.key && i?.name)
|
||||
.map((i) => ({ id: i.key, label: i.name }))
|
||||
: []
|
||||
}
|
||||
onChange={(e, value) => {
|
||||
if (value) {
|
||||
setCityKey(value.id);
|
||||
setSelectedCity(value.label);
|
||||
} else {
|
||||
setCityKey(undefined);
|
||||
setSelectedCity(undefined);
|
||||
}
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="شهر را انتخاب کنید" />
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(auctionFilterByCity(selectedCity));
|
||||
dispatch(auctionFilterByProvince(selectedProvince));
|
||||
dispatch(DRAWER({ right: false, bottom: false, content: null }));
|
||||
}}
|
||||
>
|
||||
ثبت اطلاعات
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,314 @@
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import {
|
||||
Button,
|
||||
Divider,
|
||||
InputAdornment,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { PropTypes } from "prop-types";
|
||||
import { Timer } from "../../../../components/timer/Timer";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { AuctionOfferPrice } from "../../services/auction-offer-price";
|
||||
import { useContext } from "react";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { auctionGetAuctions } from "../../services/auction-get-auctions";
|
||||
import { auctionSlaughterRequests } from "../../services/auction-slaughter-requests";
|
||||
|
||||
export const AuctionOfferPriceForm = ({
|
||||
data,
|
||||
floorPrice,
|
||||
ceilingPrice,
|
||||
highestBidedPrice,
|
||||
auctionRemainedSeconds,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
offer: "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
offer: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا عدد وارد کنید!"),
|
||||
}),
|
||||
});
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.TINY}
|
||||
direction="column"
|
||||
flex="1"
|
||||
height="100%"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Grid container direction="column" gap={SPACING.TINY}>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body2"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
مانده تا پایان مناقصه :
|
||||
</Typography>
|
||||
<Timer key={"auctiontimer"} seconds={auctionRemainedSeconds} />
|
||||
</Grid>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body2"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
استان :
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{data?.poultry?.address?.province?.name || ""}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body2"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
شهر :
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{data?.poultry?.address?.city?.name || ""}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body2"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
مرغدار :
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{data?.poultry?.userprofile?.fullName || ""}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body2"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
محل پرورش :
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{data?.poultry?.address?.address || ""}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body2"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
نژاد :
|
||||
</Typography>
|
||||
<Typography variant="body2">{data?.chickenBreed || ""}</Typography>
|
||||
</Grid>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body2"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
تعداد :
|
||||
</Typography>
|
||||
<Typography variant="body2" mr={SPACING.TINY}>
|
||||
{data?.quantity || 0}
|
||||
</Typography>
|
||||
قطعه
|
||||
</Grid>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body2"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
سن :
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{data?.process?.poultry?.age || 0} روز
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body2"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
وزن :
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{data?.IndexWeight || 0} کیلوگرم
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Divider />
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
direction="column"
|
||||
flex="1"
|
||||
height="100%"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
قیمت پایه :
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{floorPrice || 0}
|
||||
</Typography>
|
||||
ریال
|
||||
</Grid>
|
||||
|
||||
<Grid display="flex">
|
||||
<Typography
|
||||
variant="body1"
|
||||
mr={SPACING.TINY}
|
||||
color={(prop) => prop.palette.grey["A700"]}
|
||||
>
|
||||
بالاترین قیمت پیشنهادی :
|
||||
</Typography>
|
||||
<Typography mr={SPACING.TINY} fontWeight="bold">
|
||||
{highestBidedPrice || "پیشنهادی وجود ندارد!"}
|
||||
</Typography>
|
||||
{highestBidedPrice === "پیشنهادی وجود ندارد!" || !highestBidedPrice
|
||||
? ""
|
||||
: "ریال"}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid mt={SPACING.SMALL}>
|
||||
<TextField
|
||||
id="offer"
|
||||
label="قیمت پیشنهادی"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">ریال</InputAdornment>
|
||||
),
|
||||
}}
|
||||
variant="outlined"
|
||||
sx={{ width: "100%" }}
|
||||
value={formik.values.offer}
|
||||
error={formik.touched.offer ? Boolean(formik.errors.offer) : null}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.offer && Boolean(formik.errors.offer)
|
||||
? formik.errors.offer
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid mt={SPACING.SMALL}>
|
||||
<Button
|
||||
disabled={!formik.isValid}
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(LOADING_START());
|
||||
const offerValue = Number(formik.values.offer) || 0;
|
||||
const floorPriceNum = Number(floorPrice) || 0;
|
||||
const ceilingPriceNum = Number(ceilingPrice) || 0;
|
||||
const highestBidedPriceNum =
|
||||
highestBidedPrice === "پیشنهادی وجود ندارد!" ||
|
||||
!highestBidedPrice
|
||||
? 0
|
||||
: Number(highestBidedPrice) || 0;
|
||||
|
||||
if (
|
||||
(highestBidedPrice === "پیشنهادی وجود ندارد!" ||
|
||||
!highestBidedPrice ||
|
||||
(offerValue - highestBidedPriceNum >= 1000 &&
|
||||
offerValue > floorPriceNum &&
|
||||
offerValue <= ceilingPriceNum)) &&
|
||||
data?.key
|
||||
) {
|
||||
dispatch(
|
||||
AuctionOfferPrice({
|
||||
key: data.key,
|
||||
fee: offerValue,
|
||||
})
|
||||
)
|
||||
.then((r) => {
|
||||
if (r?.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(auctionGetAuctions());
|
||||
dispatch(auctionSlaughterRequests());
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error submitting offer:", error);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "قیمت پیشنهادی باید از بیشترین قیمت پیشنهاد شده بیشتر باشد و از حداکثر قیمت روز کمتر باشد.",
|
||||
severity: "error",
|
||||
});
|
||||
dispatch(LOADING_END());
|
||||
}
|
||||
}}
|
||||
>
|
||||
ثبت اطلاعات
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
AuctionOfferPriceForm.propTypes = {
|
||||
data: PropTypes.any,
|
||||
floorPrice: PropTypes.string,
|
||||
ceilingPrice: PropTypes.string,
|
||||
highestBidedPrice: PropTypes.string,
|
||||
auctionRemainedSeconds: PropTypes.string,
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { NavLink } from "../../../../components/nav-link/NavLink";
|
||||
import { Button } from "@mui/material";
|
||||
|
||||
export const AuctionOperations = () => {
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
p={SPACING.SMALL}
|
||||
direction={{ xs: "column", md: "row" }}
|
||||
>
|
||||
<NavLink to={null} active={null}>
|
||||
<Button variant="text" color="inherit">
|
||||
مناقصه
|
||||
</Button>
|
||||
</NavLink>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
314
src/features/auction/components/auctions-view/AuctionsView.js
Normal file
314
src/features/auction/components/auctions-view/AuctionsView.js
Normal file
@@ -0,0 +1,314 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { auctionGetAuctions } from "../../services/auction-get-auctions";
|
||||
import { Button, ButtonGroup, Typography } from "@mui/material";
|
||||
import { AuctionFilterRequestDate } from "../auction-filter-request-date/AuctionFilterRequestDate";
|
||||
import { AuctionFilterRequestAdvance } from "../auction-filter-request-advance/AuctionFilterRequestAdvance";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { getAuctionItemForTable } from "../../utils/get-auction-item-for-table";
|
||||
import { format } from "date-fns-jalali";
|
||||
import { AuctionFilterRequestZone } from "../auction-filter-request-zone/AuctionFilterRequestZone";
|
||||
import {
|
||||
auctionFilterByAge,
|
||||
auctionFilterByCity,
|
||||
auctionFilterByDate,
|
||||
auctionFilterByPrice,
|
||||
auctionFilterByProvince,
|
||||
auctionFilterByQuantity,
|
||||
auctionFilterByRace,
|
||||
auctionFilterByWeight,
|
||||
} from "../../../../lib/redux/slices/auctionSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
|
||||
export const AuctionsView = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { auctions } = useSelector((state) => state.auctionSlice || {});
|
||||
const { filterByDate } = useSelector((state) => state.auctionSlice || {});
|
||||
const { filterByCity } = useSelector((state) => state.auctionSlice || {});
|
||||
const { filterByProvince } = useSelector((state) => state.auctionSlice || {});
|
||||
const {
|
||||
filterByQuantity,
|
||||
filterByAge,
|
||||
filterByRace,
|
||||
filterByWeight,
|
||||
filterByPrice,
|
||||
} = useSelector((state) => state.auctionSlice || {});
|
||||
const [tableRows, setTableRows] = useState([]);
|
||||
const [minQuantity, setMinQuantity] = useState(0);
|
||||
const [maxQuantity, setMaxQuantity] = useState(0);
|
||||
|
||||
// useEffect(() => {
|
||||
// setInterval(() => {
|
||||
// dispatch(auctionGetAuctions());
|
||||
// }, 60000);
|
||||
// }, []);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(auctionGetAuctions());
|
||||
}, [
|
||||
filterByDate,
|
||||
filterByCity,
|
||||
filterByQuantity,
|
||||
filterByPrice,
|
||||
filterByWeight,
|
||||
filterByAge,
|
||||
filterByRace,
|
||||
]);
|
||||
useEffect(() => {
|
||||
if (auctions && Array.isArray(auctions) && auctions.length > 0) {
|
||||
const quantities = auctions
|
||||
.map((object) => object?.quantity)
|
||||
.filter((qty) => qty !== undefined && qty !== null);
|
||||
if (quantities.length > 0) {
|
||||
setMinQuantity(Math.min(...quantities));
|
||||
setMaxQuantity(Math.max(...quantities));
|
||||
}
|
||||
}
|
||||
}, [auctions]);
|
||||
|
||||
useEffect(() => {
|
||||
if (auctions && Array.isArray(auctions)) {
|
||||
let data = [];
|
||||
const dateFilterCallback = (item) => {
|
||||
if (!filterByDate || !Array.isArray(filterByDate)) {
|
||||
return true;
|
||||
}
|
||||
if (!item?.sendDate) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const formattedDate = format(new Date(item.sendDate), "yyyy/MM/dd");
|
||||
return filterByDate.includes(formattedDate);
|
||||
} catch (error) {
|
||||
console.error("Error formatting date:", error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
const provinceCityFilterCallback = (item) => {
|
||||
if (filterByCity || filterByProvince) {
|
||||
if (filterByCity) {
|
||||
return item?.process?.city?.cityOperatorCity === filterByCity;
|
||||
} else if (filterByProvince) {
|
||||
return (
|
||||
item?.process?.city?.cityOperatorProvince === filterByProvince
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const advanceFilterCallback = (item) => {
|
||||
if (filterByRace) {
|
||||
return item?.chickenBreed === filterByRace;
|
||||
}
|
||||
if (filterByQuantity && Array.isArray(filterByQuantity)) {
|
||||
const quantity = item?.quantity;
|
||||
if (quantity === undefined || quantity === null) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
quantity >= (filterByQuantity[0] || 0) &&
|
||||
quantity <= (filterByQuantity[1] || Infinity)
|
||||
);
|
||||
}
|
||||
if (filterByPrice && Array.isArray(filterByPrice)) {
|
||||
if (item?.process?.killHouseAuctionsList) {
|
||||
const auctionsList = item.process.killHouseAuctionsList;
|
||||
if (Array.isArray(auctionsList) && auctionsList.length > 0) {
|
||||
const lastAuction = auctionsList[auctionsList.length - 1];
|
||||
const fee = lastAuction?.fee;
|
||||
if (fee === undefined || fee === null) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
fee >= (filterByPrice[0] || 0) &&
|
||||
fee <= (filterByPrice[1] || Infinity)
|
||||
);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (filterByWeight && Array.isArray(filterByWeight)) {
|
||||
const weight = item?.IndexWeight;
|
||||
if (weight === undefined || weight === null) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
weight >= (filterByWeight[0] || 0) &&
|
||||
weight <= (filterByWeight[1] || Infinity)
|
||||
);
|
||||
}
|
||||
if (filterByAge !== undefined && filterByAge !== null) {
|
||||
const age = item?.process?.poultry?.age;
|
||||
if (age === undefined || age === null) {
|
||||
return false;
|
||||
}
|
||||
return age <= filterByAge;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (
|
||||
filterByDate ||
|
||||
filterByCity ||
|
||||
filterByProvince ||
|
||||
filterByQuantity ||
|
||||
filterByPrice ||
|
||||
filterByWeight ||
|
||||
filterByAge !== undefined ||
|
||||
filterByRace
|
||||
) {
|
||||
data = auctions
|
||||
.filter(dateFilterCallback)
|
||||
.filter(provinceCityFilterCallback)
|
||||
.filter(advanceFilterCallback)
|
||||
.map((item, i) => {
|
||||
return getAuctionItemForTable(item, i, dispatch);
|
||||
});
|
||||
} else {
|
||||
data = auctions.map((item, i) => {
|
||||
return getAuctionItemForTable(item, i, dispatch);
|
||||
});
|
||||
}
|
||||
setTableRows(data);
|
||||
} else {
|
||||
setTableRows([]);
|
||||
}
|
||||
}, [
|
||||
auctions,
|
||||
filterByDate,
|
||||
filterByCity,
|
||||
filterByProvince,
|
||||
filterByQuantity,
|
||||
filterByPrice,
|
||||
filterByWeight,
|
||||
filterByAge,
|
||||
filterByRace,
|
||||
dispatch,
|
||||
]);
|
||||
|
||||
const columns =
|
||||
getRoleFromUrl() === "KillHouse"
|
||||
? [
|
||||
"شماره مزایده",
|
||||
"کدسفارش",
|
||||
// "فروشنده",
|
||||
"قیمت کف",
|
||||
"قیمت سقف",
|
||||
"بالاترین قیمت پیشنهادی",
|
||||
"تعداد",
|
||||
"تاریخ درخواست کشتار",
|
||||
"نژاد و سن به روز",
|
||||
"وزن",
|
||||
"استان",
|
||||
"شهرستان",
|
||||
"زمان تا پایان",
|
||||
"عملیات",
|
||||
]
|
||||
: [
|
||||
"شماره مزایده",
|
||||
"کدسفارش",
|
||||
// "فروشنده",
|
||||
"قیمت کف",
|
||||
"قیمت سقف",
|
||||
|
||||
"بالاترین قیمت پیشنهادی",
|
||||
"تعداد",
|
||||
"تاریخ درخواست کشتار",
|
||||
"نژاد و سن به روز",
|
||||
"وزن",
|
||||
"استان",
|
||||
"شهرستان",
|
||||
"زمان تا پایان",
|
||||
];
|
||||
|
||||
return (
|
||||
<Grid container gap={SPACING.SMALL} p={SPACING.SMALL} width="100%">
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
<Grid>
|
||||
<Typography color={(prop) => prop.palette.grey["A700"]}>
|
||||
فیلتر کردن مزایده ها
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<ButtonGroup variant="text" aria-label="outlined button group">
|
||||
<Button
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: <AuctionFilterRequestDate />,
|
||||
title: " فیلتر تاریخ",
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
فیلتر تاریخ
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: " فیلتر بر اساس شهر و استان",
|
||||
content: <AuctionFilterRequestZone />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
فیلتر استان و شهرستان
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: "فیلتر پیشرفته",
|
||||
content: (
|
||||
<AuctionFilterRequestAdvance
|
||||
maxQuantity={maxQuantity}
|
||||
minQuantity={minQuantity}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
فیلتر پیشرفته
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(auctionFilterByDate(""));
|
||||
dispatch(auctionFilterByCity(""));
|
||||
dispatch(auctionFilterByProvince(""));
|
||||
dispatch(auctionFilterByQuantity(""));
|
||||
dispatch(auctionFilterByAge(""));
|
||||
dispatch(auctionFilterByRace(""));
|
||||
dispatch(auctionFilterByWeight(""));
|
||||
dispatch(auctionFilterByPrice(""));
|
||||
dispatch(auctionGetAuctions());
|
||||
dispatch(LOADING_END());
|
||||
}}
|
||||
>
|
||||
حذف همه فیلترها
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<AdvancedTable
|
||||
name="مزایده های در حال انجام"
|
||||
columns={columns}
|
||||
data={tableRows}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
13
src/features/auction/services/auction-get-auctions.js
Normal file
13
src/features/auction/services/auction-get-auctions.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const auctionGetAuctions = createAsyncThunk(
|
||||
"AUCTION_GET_AUCTIONS",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get(`Poultry_Request/?type=auction`);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
16
src/features/auction/services/auction-offer-price.js
Normal file
16
src/features/auction/services/auction-offer-price.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// {
|
||||
// "key":"3175f8ee-ec0d-4865-b568-b0ab7880151c",
|
||||
// "fee":"620000"
|
||||
|
||||
// }
|
||||
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const AuctionOfferPrice = createAsyncThunk(
|
||||
"AuctionOfferPrice",
|
||||
async (d) => {
|
||||
const { data, status } = await axios.post("kill_house_Request_auction/", d);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
13
src/features/auction/services/auction-slaughter-requests.js
Normal file
13
src/features/auction/services/auction-slaughter-requests.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const auctionSlaughterRequests = createAsyncThunk(
|
||||
"AUCTION_SLAUGHTER_REQUESTS",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get(`kill_house_Request_auction/`);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
64
src/features/auction/utils/get-auction-item-for-table.js
Normal file
64
src/features/auction/utils/get-auction-item-for-table.js
Normal file
@@ -0,0 +1,64 @@
|
||||
import { Button } from "@mui/material";
|
||||
import moment from "moment";
|
||||
import { Timer } from "../../../components/timer/Timer";
|
||||
import GavelIcon from "@mui/icons-material/Gavel";
|
||||
import { AuctionOfferPriceForm } from "../components/auction-offer-price-form/AuctionOfferPriceForm";
|
||||
import { DRAWER } from "../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../utils/getRoleFromUrl";
|
||||
|
||||
export function getAuctionItemForTable(item, i, dispatch) {
|
||||
const auctionFinishDate = moment(
|
||||
new Date(item?.process?.auctionsList[0]?.date)
|
||||
);
|
||||
const currentDate = moment();
|
||||
const diff = auctionFinishDate.diff(currentDate);
|
||||
const auctionRemainedSeconds = moment.duration(diff).asSeconds();
|
||||
const highestBidedPrice = item.process?.killHouseAuctionsList
|
||||
? item?.process?.killHouseAuctionsList[
|
||||
item?.process?.killHouseAuctionsList.length - 1
|
||||
].fee
|
||||
: "پیشنهادی وجود ندارد!";
|
||||
|
||||
return [
|
||||
item.id,
|
||||
item.orderCode,
|
||||
// item?.process?.provinceRequestAuctionList ? "استان" : "مرغدار",
|
||||
item?.process?.auctionsList[0]?.floorPrice,
|
||||
item?.process?.auctionsList[0]?.ceilingPrice,
|
||||
highestBidedPrice,
|
||||
item.quantity,
|
||||
item.sendDate,
|
||||
item.chickenBreed + " - " + item?.process?.poultry?.age,
|
||||
item.IndexWeight,
|
||||
item?.process?.city.cityOperatorProvince,
|
||||
item?.process?.city.cityOperatorCity,
|
||||
<Timer key={"auctiontimer" + i} seconds={auctionRemainedSeconds} />,
|
||||
getRoleFromUrl() === "KillHouse" && (
|
||||
<Button
|
||||
key={"auctionbidsumbmit" + i}
|
||||
variant="outlined"
|
||||
startIcon={<GavelIcon />}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: true,
|
||||
size: 500,
|
||||
title: "ثبت قیمت در مزایده",
|
||||
content: (
|
||||
<AuctionOfferPriceForm
|
||||
data={item}
|
||||
floorPrice={item?.process?.auctionsList[0]?.floorPrice}
|
||||
ceilingPrice={item?.process?.auctionsList[0]?.ceilingPrice}
|
||||
highestBidedPrice={highestBidedPrice}
|
||||
auctionRemainedSeconds={auctionRemainedSeconds}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت قیمت
|
||||
</Button>
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import React from "react";
|
||||
import { Grid, Divider } from "@mui/material";
|
||||
import { Typography } from "@mui/material";
|
||||
import { PrivacyTip, Security, Info } from "@mui/icons-material"; // Import icons
|
||||
|
||||
export const AuthPrivacyText = () => {
|
||||
return (
|
||||
<Grid
|
||||
sx={{
|
||||
height: "400px",
|
||||
overflow: "auto",
|
||||
p: 3,
|
||||
borderRadius: 2,
|
||||
"&::-webkit-scrollbar": {
|
||||
width: "8px",
|
||||
},
|
||||
"&::-webkit-scrollbar-thumb": {
|
||||
backgroundColor: "primary.main",
|
||||
borderRadius: "4px",
|
||||
},
|
||||
"&::-webkit-scrollbar-track": {
|
||||
backgroundColor: "grey.100",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<Typography
|
||||
variant="h5"
|
||||
color="primary"
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<PrivacyTip fontSize="medium" />
|
||||
بيانيه حريم خصوصی
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{ mt: 2, color: "text.secondary" }}>
|
||||
اطلاعات مربوط به هر شخص، حریم خصوصی وی محسوب میشود. حفاظت و حراست
|
||||
از اطلاعات شخصی در سامانه رصد یار، نه تنها موجب حفظ امنیت کاربران
|
||||
میشود، بلکه باعث اعتماد بیشتر و مشارکت آنها در فعالیتهای جاری
|
||||
میگردد. هدف از این بیانیه، آگاه ساختن شما درباره ی نوع و نحوه ی
|
||||
استفاده از اطلاعاتی است که در هنگام استفاده از سامانه رصد یار ، از
|
||||
جانب شما دریافت میگردد. شرکت هوشمند سازان خود را ملزم به رعایت حریم
|
||||
خصوصی همه شهروندان و کاربران سامانه دانسته و آن دسته از اطلاعات
|
||||
کاربران را که فقط به منظور ارائه خدمات کفایت میکند، دریافت کرده و
|
||||
از انتشار آن یا در اختیار قرار دادن آن به دیگران خودداری مینماید.
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<Divider sx={{ my: 2 }} />
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
color="primary"
|
||||
sx={{ display: "flex", alignItems: "center", gap: 1 }}
|
||||
>
|
||||
<Info fontSize="medium" />
|
||||
چگونگی جمع آوری و استفاده از اطلاعات کاربران:
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{ mt: 2, color: "text.secondary" }}>
|
||||
<strong>الف:</strong> اطلاعاتی که شما خود در اختيار این سامانه قرار
|
||||
میدهيد، شامل موارد زيرهستند:
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{ pl: 2, color: "text.secondary" }}>
|
||||
اقلام اطلاعاتی شامل شماره تلفن همراه، تاریخ تولد، کد پستی و کد ملی
|
||||
کاربران را دریافت مینماییم که از این اقلام، صرفا جهت احراز هویت
|
||||
کاربران استفاده خواهد شد.
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body1" sx={{ mt: 2, color: "text.secondary" }}>
|
||||
<strong>ب:</strong> برخی اطلاعات ديگر که به صورت خودکار از شما
|
||||
دريافت میشود شامل موارد زير میباشد:
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{ pl: 2, color: "text.secondary" }}>
|
||||
⦁ دستگاهی که از طریق آن سامانه رصد یار را مشاهده مینمایید( تلفن
|
||||
همراه، تبلت، رایانه). <br />
|
||||
⦁ نام و نسخه سیستم عامل و browser کامپیوتر شما. <br />
|
||||
⦁ اطلاعات صفحات بازدید شده. <br />
|
||||
⦁ تعداد بازدیدهای روزانه در درگاه. <br />⦁ هدف ما از دریافت این
|
||||
اطلاعات استفاده از آنها در تحلیل عملکرد کاربران درگاه می باشد تا
|
||||
بتوانیم در خدمت رسانی بهتر عمل کنیم.
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<Divider sx={{ my: 2 }} />
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
color="primary"
|
||||
sx={{ display: "flex", alignItems: "center", gap: 1 }}
|
||||
>
|
||||
<Security fontSize="medium" />
|
||||
امنیت اطلاعات
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{ mt: 2, color: "text.secondary" }}>
|
||||
متعهدیم که امنیت اطلاعات شما را تضمین نماییم و برای جلوگیری از هر
|
||||
نوع دسترسی غیرمجاز و افشای اطلاعات شما از همه شیوههای لازم استفاده
|
||||
میکنیم تا امنیت اطلاعاتی را که به صورت آنلاین گردآوری میکنیم، حفظ
|
||||
شود. لازم به ذکر است در سامانه ما، ممکن است به سایت های دیگری لینک
|
||||
شوید، وقتی که شما از طریق این لینکها از سامانه ما خارج میشوید،
|
||||
توجه داشته باشید که ما بر دیگر سایت ها کنترل نداریم و سازمان تعهدی
|
||||
بر حفظ حریم شخصی آنان در سایت مقصد نخواهد داشت و مراجعه کنندگان
|
||||
میبایست به بیانیه حریم شخصی آن سایت ها مراجعه نمایند.
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,519 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
Typography,
|
||||
Box,
|
||||
Paper,
|
||||
Divider,
|
||||
IconButton,
|
||||
Grid,
|
||||
useTheme,
|
||||
Button,
|
||||
TextField,
|
||||
Autocomplete,
|
||||
} from "@mui/material";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import PersonIcon from "@mui/icons-material/Person";
|
||||
import PhoneIcon from "@mui/icons-material/Phone";
|
||||
import BadgeIcon from "@mui/icons-material/Badge";
|
||||
import CakeIcon from "@mui/icons-material/Cake";
|
||||
import LocationCityIcon from "@mui/icons-material/LocationCity";
|
||||
import LockIcon from "@mui/icons-material/Lock";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import { getUserProfile } from "../../services/getUserProfile";
|
||||
import { ChangeProfile } from "../change-profile/ChangeProfile";
|
||||
import { motion } from "framer-motion";
|
||||
import { ChangePasswordForm } from "../change-password-form/ChangePasswordForm";
|
||||
import { useFormik } from "formik";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { changeProfileFactorInfo } from "../../services/changeProfileInfo";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import {
|
||||
slaughterGetCitiesService,
|
||||
slaughterGetProvinceService,
|
||||
} from "../../../slaughter-house/services/slaughter-get-provinces";
|
||||
|
||||
const fadeInVariant = {
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
visible: { opacity: 1, y: 0, transition: { duration: 0.5 } },
|
||||
};
|
||||
|
||||
export const BasicProfileInformation = () => {
|
||||
const { userProfile } = useSelector((state) => state.userSlice);
|
||||
const dispatch = useDispatch();
|
||||
const theme = useTheme();
|
||||
const [provinceData, setProvinceData] = useState([]);
|
||||
const [cityData, setCityData] = useState([]);
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const getProfile = () => {
|
||||
dispatch(getUserProfile());
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getProfile();
|
||||
}, [dispatch]);
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
nationalId: Yup.string().required("شناسه ملی الزامی است"),
|
||||
registrationNumber: Yup.string().required("شماره ثبت الزامی است"),
|
||||
economicalCode: Yup.string().required("کد اقتصادی الزامی است"),
|
||||
address: Yup.string().required("نشانی الزامی است"),
|
||||
unitName: Yup.string().required("نام واحد الزامی است"),
|
||||
postalCode: Yup.string()
|
||||
.matches(/^[0-9]{10}$/, "کد پستی باید 10 رقم باشد")
|
||||
.required("کد پستی الزامی است"),
|
||||
province: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را به درستی وارد کنید!"),
|
||||
city: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را به درستی وارد کنید!"),
|
||||
});
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
nationalId: userProfile?.unitNationalId || "",
|
||||
registrationNumber: userProfile?.unitRegistrationNumber || "",
|
||||
address: userProfile?.unitAddress || "",
|
||||
postalCode: userProfile?.unitPostalCode || "",
|
||||
economicalCode: userProfile?.unitEconomicalNumber || "",
|
||||
unitName: userProfile?.unitName || "",
|
||||
province: userProfile?.unitProvince || "",
|
||||
city: userProfile?.unitCity || "",
|
||||
},
|
||||
validationSchema,
|
||||
onSubmit: (values) => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(
|
||||
changeProfileFactorInfo({
|
||||
userprofile_key: userProfile?.key,
|
||||
unit_name: values.unitName,
|
||||
unit_national_id: values.nationalId,
|
||||
unit_registration_number: values.registrationNumber,
|
||||
unit_province: values.province,
|
||||
unit_city: values.city,
|
||||
unit_postal_code: values.postalCode,
|
||||
unit_address: values.address,
|
||||
unit_economical_number: values.economicalCode,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(getUserProfile());
|
||||
dispatch(LOADING_END());
|
||||
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(slaughterGetProvinceService()).then((r) => {
|
||||
setProvinceData(r.payload.data);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (formik.values.province) {
|
||||
setCityData(
|
||||
[],
|
||||
dispatch(slaughterGetCitiesService(formik.values.province)).then(
|
||||
(r) => {
|
||||
setCityData(r.payload.data);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}, [formik.values.province]);
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, [dispatch, userProfile]);
|
||||
|
||||
const userData = [
|
||||
{
|
||||
icon: <PersonIcon color="primary" />,
|
||||
label: "نام و نام خانوادگی",
|
||||
value: userProfile?.fullname || "نامشخص",
|
||||
},
|
||||
{
|
||||
icon: <PhoneIcon color="secondary" />,
|
||||
label: "موبایل",
|
||||
value: userProfile?.mobile || "نامشخص",
|
||||
},
|
||||
{
|
||||
icon: <BadgeIcon color="error" />,
|
||||
label: "کدملی",
|
||||
value: userProfile?.nationalId || "نامشخص",
|
||||
},
|
||||
{
|
||||
icon: <BadgeIcon color="info" />,
|
||||
label: "شماره شناسنامه",
|
||||
value: userProfile?.nationalCode || "نامشخص",
|
||||
},
|
||||
{
|
||||
icon: <CakeIcon color="success" />,
|
||||
label: "تاریخ تولد",
|
||||
value: userProfile?.birthday
|
||||
? formatJustDate(userProfile?.birthday)
|
||||
: "نامشخص",
|
||||
},
|
||||
{
|
||||
icon: <LocationCityIcon color="warning" />,
|
||||
label: "استان",
|
||||
value: userProfile?.province || "نامشخص",
|
||||
},
|
||||
{
|
||||
icon: <LocationCityIcon color="warning" />,
|
||||
label: "شهر",
|
||||
value: userProfile?.city || "نامشخص",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
gap={1}
|
||||
sx={{ width: "100%", padding: 1 }}
|
||||
>
|
||||
<motion.div
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={fadeInVariant}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<Paper
|
||||
elevation={4}
|
||||
sx={{
|
||||
padding: 2,
|
||||
borderRadius: 3,
|
||||
bgcolor: theme.palette.background.paper,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
display="flex"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
mb={1}
|
||||
>
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
<PersonIcon color="primary" />
|
||||
<Typography variant="subtitle2" fontWeight="bold" color="primary">
|
||||
اطلاعات کاربری
|
||||
</Typography>
|
||||
</Box>
|
||||
<IconButton
|
||||
color="primary"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: <ChangeProfile user={userProfile} />,
|
||||
title: "ویرایش اطلاعات کاربری",
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
</Box>
|
||||
|
||||
<Grid container spacing={1}>
|
||||
{userData.map((item, index) => (
|
||||
<Grid item xs={12} sm={4} md={3} key={index}>
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
{item.icon}
|
||||
<Box>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight="500"
|
||||
color="text.secondary"
|
||||
>
|
||||
{item.label}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight="600"
|
||||
color="text.primary"
|
||||
>
|
||||
{item.value}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
<Divider sx={{ marginY: 2 }} />
|
||||
|
||||
{(userProfile?.role?.includes("ProvinceOperator") ||
|
||||
userProfile?.role?.includes("KillHouse")) && (
|
||||
<>
|
||||
<Box
|
||||
display="flex"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
mb={2}
|
||||
>
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
<PersonIcon color="primary" />
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
fontWeight="bold"
|
||||
color="primary"
|
||||
>
|
||||
اطلاعات صدور فاکتور
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
<Grid container spacing={2} alignItems="center">
|
||||
<Grid item xs={12} sm={4}>
|
||||
<TextField
|
||||
size="small"
|
||||
fullWidth
|
||||
label="نام واحد"
|
||||
name="unitName"
|
||||
value={formik.values.unitName}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.unitName &&
|
||||
Boolean(formik.errors.unitName)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.unitName && formik.errors.unitName
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<TextField
|
||||
size="small"
|
||||
fullWidth
|
||||
label="شناسه ملی"
|
||||
name="nationalId"
|
||||
value={formik.values.nationalId}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.nationalId &&
|
||||
Boolean(formik.errors.nationalId)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.nationalId && formik.errors.nationalId
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<TextField
|
||||
size="small"
|
||||
fullWidth
|
||||
label="شماره ثبت"
|
||||
name="registrationNumber"
|
||||
value={formik.values.registrationNumber}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.registrationNumber &&
|
||||
Boolean(formik.errors.registrationNumber)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.registrationNumber &&
|
||||
formik.errors.registrationNumber
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} sm={4}>
|
||||
<TextField
|
||||
size="small"
|
||||
fullWidth
|
||||
label="کد اقتصادی"
|
||||
name="economicalCode"
|
||||
value={formik.values.economicalCode}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.economicalCode &&
|
||||
Boolean(formik.errors.economicalCode)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.economicalCode &&
|
||||
formik.errors.economicalCode
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} sm={4}>
|
||||
<TextField
|
||||
size="small"
|
||||
fullWidth
|
||||
label="کد پستی"
|
||||
name="postalCode"
|
||||
value={formik.values.postalCode}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.postalCode &&
|
||||
Boolean(formik.errors.postalCode)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.postalCode && formik.errors.postalCode
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} sm={4}>
|
||||
<TextField
|
||||
size="small"
|
||||
fullWidth
|
||||
label="نشانی"
|
||||
name="address"
|
||||
value={formik.values.address}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.address && Boolean(formik.errors.address)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.address && formik.errors.address
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Autocomplete
|
||||
size="small"
|
||||
style={{ width: "100%" }}
|
||||
disablePortal
|
||||
id="province"
|
||||
options={
|
||||
provinceData
|
||||
? provinceData.map((i) => ({
|
||||
id: i.name,
|
||||
label: i.name,
|
||||
}))
|
||||
: []
|
||||
}
|
||||
onChange={(e, value) => {
|
||||
formik.setFieldValue("province", value ? value.id : "");
|
||||
formik.setFieldValue("city", "");
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label={
|
||||
userProfile?.unitProvince
|
||||
? `استان ${userProfile?.unitProvince}`
|
||||
: "استان را انتخاب کنید"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Autocomplete
|
||||
size="small"
|
||||
minWidth={210}
|
||||
style={{ width: "100%" }}
|
||||
disabled={!formik.values.province}
|
||||
disablePortal
|
||||
id="city"
|
||||
options={
|
||||
cityData
|
||||
? cityData.map((i) => ({ id: i.name, label: i.name }))
|
||||
: []
|
||||
}
|
||||
onChange={(e, value) => {
|
||||
formik.setFieldValue("city", value ? value.id : "");
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label={
|
||||
userProfile?.unitCity
|
||||
? `شهر ${userProfile?.unitCity}`
|
||||
: "شهر را انتخاب کنید"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item container xs={12} sm={4}>
|
||||
<Button
|
||||
disabled={!formik.isValid}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Box
|
||||
display="flex"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
mt={2}
|
||||
>
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
<LockIcon color="secondary" />
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
fontWeight="bold"
|
||||
color="secondary"
|
||||
>
|
||||
تغییر رمز عبور
|
||||
</Typography>
|
||||
</Box>
|
||||
<IconButton
|
||||
color="secondary"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: "تغییر رمز عبور",
|
||||
content: <ChangePasswordForm />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</Paper>
|
||||
</motion.div>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,296 @@
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
InputAdornment,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import SaveIcon from "@mui/icons-material/Save";
|
||||
import { PropTypes } from "prop-types";
|
||||
import { changeBankForm } from "../../services/change-bank-form";
|
||||
import { useDispatch } from "react-redux";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { useContext } from "react";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { updateBankForm } from "../../services/update-bank-form";
|
||||
import { avicultureGetProfile } from "../../../aviculture/services/aviculture-get-profile";
|
||||
import { slaughterGetProfile } from "../../../slaughter-house/services/slaughter-get-profile";
|
||||
import { provinceGetProfile } from "../../../province/services/province-get-profile";
|
||||
import { cityGetProfile } from "../../../city/services/city-get-profile";
|
||||
import { slaughterHouseVetGetProfile } from "../../../slaughter-house-vet/services/slaughter-house-vet-get-profile";
|
||||
import { vatFarmGetProfile } from "../../../vet-farm/services/vet-farm-get-profile";
|
||||
|
||||
export const ChangeBankForm = ({ item }) => {
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const dispatch = useDispatch();
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
bankName: item?.userBankInfo?.bankName,
|
||||
cardNumber: item?.userBankInfo?.card,
|
||||
accountNumber: item?.userBankInfo?.account,
|
||||
shabaNumber: item?.userBankInfo?.shaba,
|
||||
accountHolder: item?.userBankInfo?.nameOfBankUser,
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
cardNumber: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا شماره کارتتان را وارد کنید!"),
|
||||
accountNumber: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا شماره حسابتان را وارد کنید!"),
|
||||
shabaNumber: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا شماره شبا را وارد کنید!"),
|
||||
accountHolder: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا نام صاحب حساب را وارد کنید!"),
|
||||
}),
|
||||
});
|
||||
|
||||
return (
|
||||
<Grid container gap={SPACING.SMALL} direction="column" display={"flex"}>
|
||||
<Grid container gap={SPACING.SMALL} direction={"column"}>
|
||||
<Grid>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel id="demo-simple-select-label">بانک</InputLabel>
|
||||
<Select
|
||||
fullWidth
|
||||
value={formik.values.bankName}
|
||||
id="bankName"
|
||||
label="بانک"
|
||||
onChange={(e) => {
|
||||
formik.setFieldValue("bankName", e.target.value);
|
||||
}}
|
||||
>
|
||||
<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
|
||||
fullWidth
|
||||
id="cardNumber"
|
||||
label="شماره کارت"
|
||||
value={formik.values.cardNumber}
|
||||
error={
|
||||
formik.touched.cardNumber
|
||||
? Boolean(formik.errors.cardNumber)
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.cardNumber && Boolean(formik.errors.cardNumber)
|
||||
? formik.errors.cardNumber
|
||||
: null
|
||||
}
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="accountNumber"
|
||||
label="شماره حساب"
|
||||
value={formik.values.accountNumber}
|
||||
error={
|
||||
formik.touched.accountNumber
|
||||
? Boolean(formik.errors.accountNumber)
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.accountNumber &&
|
||||
Boolean(formik.errors.accountNumber)
|
||||
? formik.errors.accountNumber
|
||||
: null
|
||||
}
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="shabaNumber"
|
||||
label="شماره شبا"
|
||||
value={formik.values.shabaNumber}
|
||||
error={
|
||||
formik.touched.shabaNumber
|
||||
? Boolean(formik.errors.shabaNumber)
|
||||
: null
|
||||
}
|
||||
InputProps={{
|
||||
endAdornment: <InputAdornment position="end">IR</InputAdornment>,
|
||||
}}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.shabaNumber && Boolean(formik.errors.shabaNumber)
|
||||
? formik.errors.shabaNumber
|
||||
: null
|
||||
}
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="accountHolder"
|
||||
label="نام صاحب حساب"
|
||||
value={formik.values.accountHolder}
|
||||
error={
|
||||
formik.touched.accountHolder
|
||||
? Boolean(formik.errors.accountHolder)
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.accountHolder &&
|
||||
Boolean(formik.errors.accountHolder)
|
||||
? formik.errors.accountHolder
|
||||
: null
|
||||
}
|
||||
variant="outlined"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Button
|
||||
onClick={() => {
|
||||
dispatch(LOADING_START());
|
||||
if (item.userBankInfo) {
|
||||
dispatch(
|
||||
updateBankForm({
|
||||
name_of_bank_user: formik.values.accountHolder,
|
||||
bank_name: formik.values.bankName,
|
||||
card: formik.values.cardNumber,
|
||||
shaba: formik.values.shabaNumber,
|
||||
account: formik.values.accountNumber,
|
||||
key: item.userBankInfo.key,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(LOADING_END());
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(avicultureGetProfile());
|
||||
dispatch(slaughterGetProfile());
|
||||
dispatch(provinceGetProfile());
|
||||
dispatch(cityGetProfile());
|
||||
dispatch(slaughterHouseVetGetProfile());
|
||||
dispatch(vatFarmGetProfile());
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
dispatch(
|
||||
changeBankForm({
|
||||
name_of_bank_user: formik.values.accountHolder,
|
||||
bank_name: formik.values.bankName,
|
||||
card: formik.values.cardNumber,
|
||||
shaba: formik.values.shabaNumber,
|
||||
account: formik.values.accountNumber,
|
||||
key: item.key ? item.key : null,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(LOADING_END());
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(avicultureGetProfile());
|
||||
dispatch(slaughterGetProfile());
|
||||
dispatch(provinceGetProfile());
|
||||
dispatch(cityGetProfile());
|
||||
dispatch(slaughterHouseVetGetProfile());
|
||||
dispatch(vatFarmGetProfile());
|
||||
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
fullWidth
|
||||
size="large"
|
||||
variant="contained"
|
||||
startIcon={<SaveIcon />}
|
||||
>
|
||||
ذخیره تغییرات
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
ChangeBankForm.propTypes = {
|
||||
item: PropTypes.object,
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Button, Chip, Divider, Typography } from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { ChangeBankForm } from "../change-bank-form/ChangeBankForm";
|
||||
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { PropTypes } from "prop-types";
|
||||
|
||||
export const ChangeCardInfo = ({ item }) => {
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<Grid container direction="column" gap={SPACING.SMALL}>
|
||||
<Grid textAlign="start">
|
||||
<Divider textAlign="left">
|
||||
<Chip
|
||||
label={
|
||||
<Grid display="flex" alignItems="center">
|
||||
<Typography variant="body2">اطلاعات بانکی</Typography>
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: "تغییر اطلاعات بانکی",
|
||||
content: <ChangeBankForm item={item} />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
(ویرایش)
|
||||
</Button>
|
||||
</Grid>
|
||||
}
|
||||
/>
|
||||
</Divider>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<SimpleTable
|
||||
// name={`اطلاعات بانکی مرغداری ${item.unitName}`}
|
||||
columns={[
|
||||
"نام بانک",
|
||||
"نام صاحب حساب",
|
||||
"شماره کارت",
|
||||
"شماره حساب",
|
||||
"شماره شبا",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
item?.userBankInfo?.bankName,
|
||||
item?.userBankInfo?.nameOfBankUser,
|
||||
item?.userBankInfo?.card,
|
||||
Number(item?.userBankInfo?.account),
|
||||
item?.userBankInfo?.shaba,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
ChangeCardInfo.propTypes = {
|
||||
item: PropTypes.object,
|
||||
};
|
||||
@@ -0,0 +1,154 @@
|
||||
import { Button, TextField } from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import SaveIcon from "@mui/icons-material/Save";
|
||||
import { changePassword } from "../../services/login";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useContext } from "react";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const ChangePasswordForm = () => {
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const { userProfile } = useSelector((state) => state.userSlice);
|
||||
const dispatch = useDispatch();
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
lastPassword: "",
|
||||
newPassword: "",
|
||||
renewPassword: "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
lastPassword: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا رمز را وارد کنید!"),
|
||||
newPassword: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا رمز را وارد کنید!"),
|
||||
renewPassword: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا رمز را وارد کنید!"),
|
||||
}),
|
||||
});
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
flex="1"
|
||||
justifyContent="space-between"
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
<Grid container direction="column" gap={SPACING.SMALL}>
|
||||
<Grid>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="lastPassword"
|
||||
value={formik.values.lastPassword}
|
||||
error={
|
||||
formik.touched.lastPassword
|
||||
? Boolean(formik.errors.lastPassword)
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.lastPassword && Boolean(formik.errors.lastPassword)
|
||||
? formik.errors.lastPassword
|
||||
: null
|
||||
}
|
||||
label="رمز قبلی"
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="newPassword"
|
||||
value={formik.values.newPassword}
|
||||
error={
|
||||
formik.touched.newPassword
|
||||
? Boolean(formik.errors.newPassword)
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.newPassword && Boolean(formik.errors.newPassword)
|
||||
? formik.errors.newPassword
|
||||
: null
|
||||
}
|
||||
label="رمز جدید"
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="renewPassword"
|
||||
value={formik.values.renewPassword}
|
||||
error={
|
||||
formik.touched.renewPassword
|
||||
? Boolean(formik.errors.renewPassword)
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.renewPassword &&
|
||||
Boolean(formik.errors.renewPassword)
|
||||
? formik.errors.renewPassword
|
||||
: null
|
||||
}
|
||||
label="تکرار رمز جدید"
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Button
|
||||
fullWidth
|
||||
size="large"
|
||||
variant="contained"
|
||||
startIcon={<SaveIcon />}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
changePassword({
|
||||
username: userProfile.mobile,
|
||||
password: formik.values.newPassword,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.error) {
|
||||
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>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
import React from "react";
|
||||
import { Button, Typography, Box, Paper } from "@mui/material";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { ChangePasswordForm } from "../change-password-form/ChangePasswordForm";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
const fadeInVariant = {
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
visible: { opacity: 1, y: 0, transition: { duration: 0.5 } },
|
||||
};
|
||||
|
||||
export const ChangePassword = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
gap={SPACING.SMALL}
|
||||
sx={{ width: "100%" }}
|
||||
>
|
||||
<motion.div
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={fadeInVariant}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<Paper
|
||||
elevation={3}
|
||||
sx={{ padding: 3, borderRadius: 3, marginBottom: 2 }}
|
||||
>
|
||||
<Box
|
||||
display="flex"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
mb={2}
|
||||
>
|
||||
<Typography variant="h6" fontWeight="bold">
|
||||
تغییر رمز عبور
|
||||
</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: "تغییر رمز عبور",
|
||||
content: <ChangePasswordForm />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ویرایش
|
||||
</Button>
|
||||
</Box>
|
||||
</Paper>
|
||||
</motion.div>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,266 @@
|
||||
import { 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 { PropTypes } from "prop-types";
|
||||
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { changeProfileInfo } from "../../services/changeProfileInfo";
|
||||
import { useDispatch } from "react-redux";
|
||||
import moment from "moment";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import { ImageUpload } from "../../../../components/image-upload/ImageUpload";
|
||||
import { fixBase64 } from "../../../../utils/toBase64";
|
||||
import { useContext } from "react";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { getUserProfile } from "../../services/getUserProfile";
|
||||
|
||||
export const ChangeProfile = ({ user }) => {
|
||||
const [profileImages, setProfileImages] = React.useState([]);
|
||||
const [profileImg, setProfileImg] = React.useState();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const factorPaymentHandler = (imageList) => {
|
||||
if (imageList[0]) {
|
||||
setProfileImg(fixBase64(imageList[0]?.data_url));
|
||||
}
|
||||
setProfileImages(imageList);
|
||||
};
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
firstname: user.firstName ? user.firstName : "",
|
||||
lastname: user.lastName ? user.lastName : "",
|
||||
natioanlId: user.nationalId ? user.nationalId : "",
|
||||
natioanlCode: user.nationalCode ? user.nationalCode : "",
|
||||
birthday: user.birthday ? new Date(user.birthday) : Date(),
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
firstname: Yup.string().typeError("لطفا فیلد را به درستی وارد کنید.!"),
|
||||
lastname: Yup.string().typeError("لطفا فیلد را به درستی وارد کنید.!"),
|
||||
natioanlId: Yup.number().typeError(
|
||||
"لطفا فیلد را به صورت عددی وارد کنید!"
|
||||
),
|
||||
natioanlCode: Yup.number().typeError(
|
||||
"لطفا فیلد را به صورت عددی وارد کنید!"
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
direction="column"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Grid container direction="column" gap={SPACING.SMALL}>
|
||||
<Grid>
|
||||
<TextField
|
||||
id="firstname"
|
||||
label="نام"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%", height: "100%" }}
|
||||
value={formik.values.firstname}
|
||||
error={
|
||||
formik.touched.firstname ? Boolean(formik.errors.firstname) : null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.firstname && Boolean(formik.errors.firstname)
|
||||
? formik.errors.firstname
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<TextField
|
||||
id="lastname"
|
||||
label="نام خانوادگی"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%", height: "100%" }}
|
||||
value={formik.values.lastname}
|
||||
error={
|
||||
formik.touched.lastname ? Boolean(formik.errors.lastname) : null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.lastname && Boolean(formik.errors.lastname)
|
||||
? formik.errors.lastname
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<TextField
|
||||
id="natioanlId"
|
||||
label="کد ملی"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%", height: "100%" }}
|
||||
value={formik.values.natioanlId}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.natioanlId
|
||||
? Boolean(formik.errors.natioanlId)
|
||||
: null
|
||||
}
|
||||
helperText={
|
||||
formik.touched.natioanlId && Boolean(formik.errors.natioanlId)
|
||||
? formik.errors.natioanlId
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<TextField
|
||||
id="natioanlCode"
|
||||
label="شماره شناسنامه"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%", height: "100%" }}
|
||||
value={formik.values.natioanlCode}
|
||||
error={
|
||||
formik.touched.natioanlCode
|
||||
? Boolean(formik.errors.natioanlCode)
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.natioanlCode && Boolean(formik.errors.natioanlCode)
|
||||
? formik.errors.natioanlCode
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid display="contents">
|
||||
<DatePicker
|
||||
fullWidth
|
||||
label="تاریخ تولد"
|
||||
id="birthday"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={formik.values.birthday}
|
||||
error={
|
||||
formik.touched.birthday ? Boolean(formik.errors.birthday) : null
|
||||
}
|
||||
onChange={(e) => {
|
||||
const selectedDate = new Date(e);
|
||||
// moment(e).format("YYYY-MM-DD hh:mm:ss")
|
||||
formik.setFieldValue("birthday", selectedDate);
|
||||
}}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.birthday && Boolean(formik.errors.birthday)
|
||||
? formik.errors.birthday
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<ImageUpload
|
||||
onChange={factorPaymentHandler}
|
||||
images={profileImages}
|
||||
maxNumber={1}
|
||||
title={"عکس پروفایل"}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
disabled={!formik.isValid}
|
||||
onClick={() => {
|
||||
const birthday = moment(new Date(formik.values.birthday)).format(
|
||||
"YYYY-MM-DD hh:mm:ss"
|
||||
);
|
||||
if (
|
||||
formik.values.firstname ||
|
||||
formik.values.lastname ||
|
||||
formik.values.natioanlCode ||
|
||||
formik.values.natioanlId ||
|
||||
profileImg
|
||||
) {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(
|
||||
changeProfileInfo({
|
||||
type: "self_profile",
|
||||
fullname:
|
||||
formik.values.firstname + " " + formik.values.lastname,
|
||||
first_name: formik.values.firstname
|
||||
? formik.values.firstname
|
||||
: null,
|
||||
last_name: formik.values.lastname
|
||||
? formik.values.lastname
|
||||
: null,
|
||||
national_code: formik.values.natioanlCode
|
||||
? formik.values.natioanlCode
|
||||
: null,
|
||||
national_id: formik.values.natioanlId
|
||||
? formik.values.natioanlId
|
||||
: null,
|
||||
birthday: birthday,
|
||||
image: profileImg ? profileImg : "",
|
||||
person_type: "self",
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(getUserProfile());
|
||||
dispatch(LOADING_END());
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "لطفا حداقل یکی از موارد را تغییر دهید.",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
ثبت اطلاعات
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
ChangeProfile.propTypes = {
|
||||
user: PropTypes.any,
|
||||
};
|
||||
@@ -0,0 +1,507 @@
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
InputAdornment,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import {
|
||||
forgetPassword,
|
||||
forgetPasswordChangePassword,
|
||||
forgetPasswordSendOpt,
|
||||
loginWithPassword,
|
||||
} from "../../services/login";
|
||||
import { PropTypes } from "prop-types";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { useContext, useEffect } from "react";
|
||||
import {
|
||||
CLOSE_MODAL,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
OPEN_MODAL,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { useState } from "react";
|
||||
import Visibility from "@mui/icons-material/Visibility";
|
||||
import VisibilityOff from "@mui/icons-material/VisibilityOff";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { slaughterGetPermisionState } from "../../../slaughter-house/services/slaughter-get-permision";
|
||||
import { getUserAnnouncement } from "../../services/get-announcement";
|
||||
import { getUserMovingTextsService } from "../../services/getUserMovingTexts";
|
||||
|
||||
const modalContentStyle = {
|
||||
backgroundColor: "#ffffff",
|
||||
padding: "20px",
|
||||
borderRadius: "4px",
|
||||
outline: "none",
|
||||
minWidth: "300px",
|
||||
maxWidth: "600px",
|
||||
textAlign: "center",
|
||||
};
|
||||
|
||||
const descriptionStyle = {
|
||||
marginBottom: "10px",
|
||||
};
|
||||
|
||||
const buttonStyle = {
|
||||
marginTop: "10px",
|
||||
};
|
||||
|
||||
export const EnterPassword = ({ mobile, isUserHandler }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const formikMain = useFormik({
|
||||
initialValues: {
|
||||
password: "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
password: Yup.mixed().required("این فیلد اجباری است!"),
|
||||
}),
|
||||
});
|
||||
|
||||
const getUserMovingTexts = () => {
|
||||
dispatch(getUserMovingTextsService());
|
||||
};
|
||||
|
||||
const getSlaughterState = (role) => {
|
||||
dispatch(slaughterGetPermisionState());
|
||||
dispatch(getUserAnnouncement(role)).then((r) => {
|
||||
if (r.payload.data?.active) {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "اطلاعیه سیستم",
|
||||
content: (
|
||||
<Grid style={modalContentStyle}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="secondary"
|
||||
style={descriptionStyle}
|
||||
>
|
||||
{r.payload.data?.description}
|
||||
</Typography>
|
||||
<Grid container justifyContent="center">
|
||||
<Grid item xs={12}>
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
onClick={() => dispatch(CLOSE_MODAL())}
|
||||
style={buttonStyle}
|
||||
>
|
||||
متوجه شدم
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
),
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
forgetOtp: "",
|
||||
newPassword: "",
|
||||
newPasswordRepeat: "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
forgetOtp: Yup.mixed().required("این فیلد اجباری است!"),
|
||||
newPassword: Yup.mixed().required("این فیلد اجباری است!"),
|
||||
newPasswordRepeat: Yup.mixed().required("این فیلد اجباری است!"),
|
||||
}),
|
||||
});
|
||||
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [forgetPasswordKey, setForgetPasswordKey] = useState(null);
|
||||
const [isForgetOtpCodeCorrect, setIsForgetOtpCodeCorrect] = useState(false);
|
||||
|
||||
const handleClickShowPassword = () => {
|
||||
setShowPassword(!showPassword);
|
||||
};
|
||||
|
||||
const handleMouseDownPassword = (event) => {
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
formikMain.validateForm();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{forgetPasswordKey ? (
|
||||
<>
|
||||
{isForgetOtpCodeCorrect ? (
|
||||
<Grid>
|
||||
<Typography variant="body1" py={SPACING.SMALL}>
|
||||
رمزعبور جدید خود را وارد کنید.
|
||||
</Typography>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<TextField
|
||||
type={showPassword ? "text" : "password"}
|
||||
id="newPassword"
|
||||
label="رمزعبور جدید"
|
||||
variant="outlined"
|
||||
onChange={formik.handleChange}
|
||||
value={formik.values.newPassword}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.newPassword
|
||||
? Boolean(formik.errors.newPassword)
|
||||
: null
|
||||
}
|
||||
helperText={
|
||||
formik.touched.newPassword &&
|
||||
Boolean(formik.errors.newPassword)
|
||||
? formik.errors.newPassword
|
||||
: null
|
||||
}
|
||||
fullWidth
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="نمایش رمزعبور"
|
||||
onClick={handleClickShowPassword}
|
||||
edge="end"
|
||||
onMouseDown={handleMouseDownPassword}
|
||||
>
|
||||
{showPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
type={showPassword ? "text" : "password"}
|
||||
id="newPasswordRepeat"
|
||||
label="تکرار رمزعبور جدید"
|
||||
variant="outlined"
|
||||
onChange={formik.handleChange}
|
||||
value={formik.values.newPasswordRepeat}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.newPasswordRepeat
|
||||
? Boolean(formik.errors.newPasswordRepeat)
|
||||
: null
|
||||
}
|
||||
helperText={
|
||||
formik.touched.newPasswordRepeat &&
|
||||
Boolean(formik.errors.newPasswordRepeat)
|
||||
? formik.errors.newPasswordRepeat
|
||||
: null
|
||||
}
|
||||
fullWidth
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="نمایش رمزعبور"
|
||||
onClick={handleClickShowPassword}
|
||||
edge="end"
|
||||
onMouseDown={handleMouseDownPassword}
|
||||
>
|
||||
{showPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid container mt={SPACING.SMALL} gap={SPACING.MEDIUM}>
|
||||
<Grid flexGrow="1">
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={
|
||||
!(
|
||||
formik.values.newPassword ===
|
||||
formik.values.newPasswordRepeat
|
||||
)
|
||||
}
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(
|
||||
forgetPasswordChangePassword({
|
||||
username: mobile,
|
||||
password: formik.values.newPassword,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "رمزعبور با موفقیت تغییر یافت!",
|
||||
severity: "success",
|
||||
});
|
||||
setForgetPasswordKey(null);
|
||||
}
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}}
|
||||
>
|
||||
تغییر رمزعبور
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
) : (
|
||||
<Grid>
|
||||
<Typography variant="body1" py={SPACING.SMALL}>
|
||||
کد یکبارمصرف دریافتی را وارد کنید.
|
||||
</Typography>
|
||||
<TextField
|
||||
type={showPassword ? "text" : "password"}
|
||||
id="forgetOtp"
|
||||
label="کد دریافتی"
|
||||
variant="outlined"
|
||||
onChange={formik.handleChange}
|
||||
value={formik.values.forgetOtp}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.forgetOtp
|
||||
? Boolean(formik.errors.forgetOtp)
|
||||
: null
|
||||
}
|
||||
helperText={
|
||||
formik.touched.forgetOtp && Boolean(formik.errors.forgetOtp)
|
||||
? formik.errors.forgetOtp
|
||||
: null
|
||||
}
|
||||
fullWidth
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="نمایش کد"
|
||||
onClick={handleClickShowPassword}
|
||||
edge="end"
|
||||
onMouseDown={handleMouseDownPassword}
|
||||
>
|
||||
{showPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Grid container mt={SPACING.SMALL} gap={SPACING.MEDIUM}>
|
||||
<Grid flexGrow="1">
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={!formik.values.forgetOtp}
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(
|
||||
forgetPasswordSendOpt({
|
||||
key: forgetPasswordKey,
|
||||
code: formik.values.forgetOtp,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
setIsForgetOtpCodeCorrect(r.payload.data.code);
|
||||
}
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Typography variant="body1" py={SPACING.SMALL}>
|
||||
رمز عبور را وارد کرده و بر روی ورود کلیک نمایید.
|
||||
</Typography>
|
||||
<TextField
|
||||
type={showPassword ? "text" : "password"}
|
||||
id="password"
|
||||
label="رمزعبور"
|
||||
variant="outlined"
|
||||
onChange={formikMain.handleChange}
|
||||
value={formikMain.values.password}
|
||||
onBlur={formikMain.handleBlur}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(
|
||||
loginWithPassword({
|
||||
mobile,
|
||||
password: formikMain.values.password,
|
||||
})
|
||||
).then((r) => {
|
||||
if (
|
||||
r.payload?.data?.role?.includes("CityOperator") ||
|
||||
r.payload?.data?.role?.includes("KillHouse") ||
|
||||
r.payload?.data?.role?.includes("CityJahad") ||
|
||||
r.payload?.data?.role?.includes("ProvinceSupervisor") ||
|
||||
r.payload?.data?.role?.includes("ProvinceOperator")
|
||||
) {
|
||||
getUserMovingTexts();
|
||||
}
|
||||
|
||||
if (r.payload?.data?.role?.includes("KillHouse")) {
|
||||
getSlaughterState("KillHouse");
|
||||
} else if (r.payload?.data?.role?.includes("CityOperator")) {
|
||||
getSlaughterState("CityOperator");
|
||||
}
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "رمزعبور اشتباه است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}
|
||||
}}
|
||||
error={
|
||||
formikMain.touched.password
|
||||
? Boolean(formikMain.errors.password)
|
||||
: null
|
||||
}
|
||||
helperText={
|
||||
formikMain.touched.password && Boolean(formikMain.errors.password)
|
||||
? formikMain.errors.password
|
||||
: null
|
||||
}
|
||||
fullWidth
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="نمایش رمز عبور"
|
||||
onClick={handleClickShowPassword}
|
||||
edge="end"
|
||||
onMouseDown={handleMouseDownPassword}
|
||||
>
|
||||
{showPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
mt={SPACING.SMALL}
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
<Grid container>
|
||||
<Grid flexGrow="1">
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={!formikMain.isValid}
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(
|
||||
loginWithPassword({
|
||||
mobile,
|
||||
password: formikMain.values.password,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload?.data?.role?.includes("KillHouse")) {
|
||||
getSlaughterState("KillHouse");
|
||||
} else if (
|
||||
r.payload?.data?.role?.includes("CityOperator")
|
||||
) {
|
||||
getSlaughterState("CityOperator");
|
||||
}
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "رمزعبور اشتباه است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}}
|
||||
>
|
||||
ورود به سامانه
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid
|
||||
flexGrow="1"
|
||||
alignItems="center"
|
||||
alignSelf="center"
|
||||
justifyContent="center"
|
||||
display="flex"
|
||||
>
|
||||
<Button
|
||||
onClick={() => {
|
||||
isUserHandler();
|
||||
}}
|
||||
>
|
||||
بازگشت به صفحه قبل
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid flexGrow="1">
|
||||
<Button
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(
|
||||
forgetPassword({
|
||||
mobile,
|
||||
state: "forget_password",
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
setForgetPasswordKey(r.payload.data.key);
|
||||
}
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}}
|
||||
>
|
||||
رمزعبور را فراموش کرده ام (استفاده از پیامک)
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
EnterPassword.propTypes = {
|
||||
mobile: PropTypes.any,
|
||||
isUserHandler: PropTypes.any,
|
||||
};
|
||||
@@ -0,0 +1,190 @@
|
||||
import { Box, Button, Chip, Divider, Typography } from "@mui/material";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { NavLink } from "../../../../components/nav-link/NavLink";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import {
|
||||
Home,
|
||||
Business,
|
||||
House,
|
||||
LocalHospital,
|
||||
DirectionsCar,
|
||||
AccountBalance,
|
||||
Public,
|
||||
} from "@mui/icons-material"; // Example icons
|
||||
import { motion } from "framer-motion";
|
||||
import useUserProfile from "../../hooks/useUserProfile";
|
||||
import {
|
||||
DRIVER_USER_PROFILE,
|
||||
ROUTE_AVICULTURE_USER_PROFILE,
|
||||
ROUTE_CHAIN_COMPANY_USER_PROFILE,
|
||||
ROUTE_CITYVET_USER_PROFILE,
|
||||
ROUTE_CITY_USER_PROFILE,
|
||||
ROUTE_GENERAL_USER_PROFILE,
|
||||
ROUTE_STEWARD_USER_PROFILE,
|
||||
ROUTE_INSPECTOR_USER_PROFILE,
|
||||
ROUTE_LIVE_STOCK_USER_PROFILE,
|
||||
ROUTE_PROVINCE_FINANCIAL_USER_PROFILE,
|
||||
ROUTE_PROVINCE_USER_PROFILE,
|
||||
ROUTE_SLAUGHTER_HOUSE_VET_USER_PROFILE,
|
||||
ROUTE_SLAUGHTER_USER_PROFILE,
|
||||
ROUTE_VETFARM_USER_PROFILE,
|
||||
} from "../../../../routes/routes";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
|
||||
const routesMap = {
|
||||
General: {
|
||||
path: ROUTE_GENERAL_USER_PROFILE,
|
||||
label: "کاربری",
|
||||
icon: <Home />,
|
||||
},
|
||||
CityOperator: {
|
||||
path: ROUTE_CITY_USER_PROFILE,
|
||||
label: "شهرستان",
|
||||
icon: <Business />,
|
||||
},
|
||||
Poultry: {
|
||||
path: ROUTE_AVICULTURE_USER_PROFILE,
|
||||
label: "مرغداری",
|
||||
icon: <House />,
|
||||
},
|
||||
ProvinceOperator: {
|
||||
path: ROUTE_PROVINCE_USER_PROFILE,
|
||||
label: "تخصیص استان",
|
||||
icon: <AccountBalance />,
|
||||
},
|
||||
KillHouse: {
|
||||
path: ROUTE_SLAUGHTER_USER_PROFILE,
|
||||
label: "کشتارگاه",
|
||||
icon: <LocalHospital />,
|
||||
},
|
||||
VetFarm: {
|
||||
path: ROUTE_VETFARM_USER_PROFILE,
|
||||
label: "دامپزشک فارم",
|
||||
icon: <LocalHospital />,
|
||||
},
|
||||
KillHouseVet: {
|
||||
path: ROUTE_SLAUGHTER_HOUSE_VET_USER_PROFILE,
|
||||
label: "دامپزشک کشتارگاه",
|
||||
icon: <LocalHospital />,
|
||||
},
|
||||
Driver: {
|
||||
path: DRIVER_USER_PROFILE,
|
||||
label: "راننده",
|
||||
icon: <DirectionsCar />,
|
||||
},
|
||||
ProvinceFinancial: {
|
||||
path: ROUTE_PROVINCE_FINANCIAL_USER_PROFILE,
|
||||
label: "مالی",
|
||||
icon: <AccountBalance />,
|
||||
},
|
||||
ProvinceInspector: {
|
||||
path: ROUTE_INSPECTOR_USER_PROFILE,
|
||||
label: "بازرس",
|
||||
icon: <Public />,
|
||||
},
|
||||
Guilds: {
|
||||
path: ROUTE_STEWARD_USER_PROFILE,
|
||||
label: "صنف",
|
||||
icon: <Business />,
|
||||
},
|
||||
CityVet: {
|
||||
path: ROUTE_CITYVET_USER_PROFILE,
|
||||
label: "دامپزشک شهرستان",
|
||||
icon: <LocalHospital />,
|
||||
},
|
||||
LiveStockSupport: {
|
||||
path: ROUTE_LIVE_STOCK_USER_PROFILE,
|
||||
label: "پشتیبانی امور دام",
|
||||
icon: <LocalHospital />,
|
||||
},
|
||||
ChainCompany: {
|
||||
path: ROUTE_CHAIN_COMPANY_USER_PROFILE,
|
||||
label: "شرکت زنجیره",
|
||||
icon: <Business />,
|
||||
},
|
||||
};
|
||||
|
||||
export const GeneralDashboardOperations = () => {
|
||||
const { pathname } = useLocation();
|
||||
const [roles] = useUserProfile();
|
||||
|
||||
return (
|
||||
<Box p={SPACING.SMALL} display="flex" flexDirection="column">
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
gap={1}
|
||||
direction={{ xs: "column", md: "row" }}
|
||||
>
|
||||
<Divider sx={{ width: "100%" }}>
|
||||
<Chip
|
||||
label={
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{ fontSize: "18px", color: "darkcyan" }}
|
||||
>
|
||||
نقش ها
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</Divider>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<NavLink
|
||||
to={ROUTE_GENERAL_USER_PROFILE}
|
||||
active={
|
||||
pathname === ROUTE_GENERAL_USER_PROFILE || pathname === "/"
|
||||
? "true"
|
||||
: null
|
||||
}
|
||||
style={{ textDecoration: "none" }}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
fullWidth
|
||||
startIcon={<Home />}
|
||||
sx={{ borderRadius: 3, padding: "4px 8px" }}
|
||||
>
|
||||
حساب کاربری
|
||||
</Button>
|
||||
</NavLink>
|
||||
</motion.div>
|
||||
|
||||
{roles.map((role, i) => {
|
||||
const route = routesMap[role];
|
||||
return route ? (
|
||||
<motion.div
|
||||
key={role + i}
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, delay: i * 0.1 }}
|
||||
>
|
||||
<NavLink
|
||||
to={route.path}
|
||||
active={pathname === route.path ? "true" : null}
|
||||
style={{ textDecoration: "none" }}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
size="small"
|
||||
startIcon={route.icon}
|
||||
sx={{ borderRadius: 3, padding: "4px 8px", color: "gray" }}
|
||||
>
|
||||
{route.label}
|
||||
</Button>
|
||||
</NavLink>
|
||||
</motion.div>
|
||||
) : null;
|
||||
})}
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
163
src/features/authentication/components/login/Login.js
Normal file
163
src/features/authentication/components/login/Login.js
Normal file
@@ -0,0 +1,163 @@
|
||||
import { Button, TextField, Typography } from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { loginSendMobile } from "../../services/login";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useFormik } from "formik";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import Captcha from "../../../../components/captcha/Captcha";
|
||||
import { useEffect, useState } from "react";
|
||||
import { EnterPassword } from "../enter-password/EnterPassword";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { useContext } from "react";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
|
||||
export const Login = () => {
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [isValidCaptcha, setIsValidCaptcha] = useState(false);
|
||||
const [isUser, setIsUser] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
mobile: "",
|
||||
captcha: "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
mobile: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا اعداد انگلیسی وارد کنید!")
|
||||
.test("len", "شماره تلفن باید 11 رقم باشد!", (val, context) => {
|
||||
return context.originalValue && context.originalValue.length === 11;
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
const isUserHandler = () => {
|
||||
setIsUser(false);
|
||||
setIsValidCaptcha(false);
|
||||
};
|
||||
|
||||
const submitForm = (e) => {
|
||||
e.preventDefault();
|
||||
dispatch(LOADING_START());
|
||||
dispatch(
|
||||
loginSendMobile({
|
||||
mobile: formik.values.mobile,
|
||||
state: "",
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(LOADING_END());
|
||||
if (!r.payload.data.isUser) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "شماره تلفن شما در سامانه وجود ندارد!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی به وجود آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
setIsUser(r.payload.data.isUser);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<Grid container justifyContent="center" alignItems="center">
|
||||
<Grid
|
||||
container
|
||||
mx={{ xs: SPACING.SMALL, sm: SPACING.SMALL, md: 0 }}
|
||||
justifyContent="center"
|
||||
>
|
||||
<Grid p={SPACING.MEDIUM} minWidth={{ md: "520px" }}>
|
||||
{isUser ? (
|
||||
<EnterPassword
|
||||
isUserHandler={isUserHandler}
|
||||
mobile={formik.values.mobile}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<Typography variant="h6" color="primary">
|
||||
سامانه رصدیار
|
||||
</Typography>
|
||||
<Typography variant="body1" py={SPACING.SMALL}>
|
||||
شماره موبایل تان را وارد کنید.
|
||||
</Typography>
|
||||
<form onSubmit={submitForm}>
|
||||
<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
|
||||
container
|
||||
justifyContent="space-between"
|
||||
flexWrap="nowrap"
|
||||
sx={{
|
||||
flexDirection: { xs: "column", sm: "row" },
|
||||
}}
|
||||
gap={SPACING.SMALL}
|
||||
mt={SPACING.SMALL}
|
||||
>
|
||||
<Captcha onChange={(status) => setIsValidCaptcha(status)} />
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
justifyContent="space-between"
|
||||
gap={SPACING.MEDIUM}
|
||||
direction="row"
|
||||
mt={SPACING.SMALL}
|
||||
>
|
||||
<Grid flexGrow="2">
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
type="submit"
|
||||
disabled={!(isValidCaptcha && formik.isValid)}
|
||||
onSubmit={submitForm}
|
||||
>
|
||||
ادامه
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
26
src/features/authentication/hooks/useSelectedSubUser.js
Normal file
26
src/features/authentication/hooks/useSelectedSubUser.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
/**
|
||||
* Hook to get the currently selected sub user from Redux state
|
||||
* @returns {Object|null} - The selected sub user object with { key, name, unit, mobile, fullname } or null
|
||||
*/
|
||||
export const useSelectedSubUser = () => {
|
||||
const selectedSubUser = useSelector(
|
||||
(state) => state.userSlice.selectedSubUser
|
||||
);
|
||||
return selectedSubUser;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to get only the selected sub user key
|
||||
* @returns {string|null} - The sub user key or null
|
||||
*/
|
||||
export const useSelectedSubUserKey = () => {
|
||||
const selectedSubUser = useSelector(
|
||||
(state) => state.userSlice.selectedSubUser
|
||||
);
|
||||
return selectedSubUser?.key || null;
|
||||
};
|
||||
|
||||
export default useSelectedSubUser;
|
||||
|
||||
18
src/features/authentication/hooks/useUserProfile.js
Normal file
18
src/features/authentication/hooks/useUserProfile.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { getUserProfile } from "../services/getUserProfile";
|
||||
|
||||
const useUserProfile = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { role, userProfile } = useSelector((state) => state.userSlice);
|
||||
|
||||
useEffect(() => {
|
||||
if (!userProfile) {
|
||||
dispatch(getUserProfile());
|
||||
}
|
||||
}, []);
|
||||
|
||||
return [role, userProfile];
|
||||
};
|
||||
|
||||
export default useUserProfile;
|
||||
15
src/features/authentication/services/change-bank-form.js
Normal file
15
src/features/authentication/services/change-bank-form.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { getActualRoleFromRole } from "../../../utils/getRoleFromUrl";
|
||||
|
||||
export const changeBankForm = createAsyncThunk(
|
||||
"CHANGE_BANK_FORM",
|
||||
async (d) => {
|
||||
const role = window.location.pathname.split("/")[3];
|
||||
const { data, status } = await axios.post(
|
||||
`user-bank_card/?role=${getActualRoleFromRole(role)}`,
|
||||
d
|
||||
);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
21
src/features/authentication/services/changeProfileInfo.js
Normal file
21
src/features/authentication/services/changeProfileInfo.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const changeProfileInfo = createAsyncThunk(
|
||||
"CHANGE_PROFILE_INFO",
|
||||
async (d) => {
|
||||
const { data, status } = await axios.put("system_user_profile/0/", d);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
|
||||
export const changeProfileFactorInfo = createAsyncThunk(
|
||||
"CHANGE_PROFILE_FACTOR_INFO",
|
||||
async (d) => {
|
||||
const { data, status } = await axios.put(
|
||||
"system_user_profile-for-factor/0/",
|
||||
d
|
||||
);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
23
src/features/authentication/services/get-announcement.js
Normal file
23
src/features/authentication/services/get-announcement.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const getAnnouncement = createAsyncThunk(
|
||||
"GET_ANNOUNCEMENT",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get("announcements/?total=true");
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
|
||||
export const getUserAnnouncement = createAsyncThunk(
|
||||
"GET_ANNOUNCEMENT",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get(`announcements/?role=${d}`);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
10
src/features/authentication/services/getUnseenMessage.js
Normal file
10
src/features/authentication/services/getUnseenMessage.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const getUnseenMessages = createAsyncThunk(
|
||||
"GET_UNSEEN_MESSAGES",
|
||||
async (d, { dispatch }) => {
|
||||
const { data, status } = await axios.get(`get_num_message/`);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
13
src/features/authentication/services/getUserMovingTexts.js
Normal file
13
src/features/authentication/services/getUserMovingTexts.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
import axios from "axios";
|
||||
|
||||
export const getUserMovingTextsService = createAsyncThunk(
|
||||
"GET_USER_MOVING_TEXTS",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get(`moving-text/?dashboard=true`);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
7
src/features/authentication/services/getUserProfile.js
Normal file
7
src/features/authentication/services/getUserProfile.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const getUserProfile = createAsyncThunk("GET_USER_PROFILE", async () => {
|
||||
const { data, status } = await axios.get("system_user_profile/?self-profile");
|
||||
return { data, status };
|
||||
});
|
||||
23
src/features/authentication/services/getUserRoleInfo.js
Normal file
23
src/features/authentication/services/getUserRoleInfo.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const getUserRoleInfo = createAsyncThunk(
|
||||
"GET_USER_ROLE_INFO",
|
||||
async ({ userKey, role }, { dispatch }) => {
|
||||
try {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get("user-role-info/", {
|
||||
params: {
|
||||
user_key: userKey,
|
||||
role: role,
|
||||
},
|
||||
});
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
} catch (error) {
|
||||
dispatch(LOADING_END());
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
);
|
||||
98
src/features/authentication/services/login.js
Normal file
98
src/features/authentication/services/login.js
Normal file
@@ -0,0 +1,98 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const loginSendMobile = createAsyncThunk(
|
||||
"LOGIN_SEND_MOBILE",
|
||||
async ({ mobile, state }) => {
|
||||
const { data, status } = await axios.post("api/send/", { mobile, state });
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
//buildchange
|
||||
export const loginWithPassword = createAsyncThunk(
|
||||
"LOGIN_WITH_PASSWORD",
|
||||
async ({ mobile, password }) => {
|
||||
const { data, status } = await axios.post("api/login/", {
|
||||
username: mobile,
|
||||
password,
|
||||
// bushehr
|
||||
// api_key: "44d89a44-bd44-2144-a02f-2cc2cbf4e2d4",
|
||||
// kermanshah
|
||||
// api_key: "4b124231-62c7-41c6-8081-66191536c0b7",
|
||||
// test
|
||||
// api_key: "11d89a11-bd11-2111-a02f-2cc1cbf4e1d4",
|
||||
// markazi arak
|
||||
// api_key: "44d89a99-bd12-4152-a02f-5cc5cbf7e5d5",
|
||||
// hamedan
|
||||
// api_key: "33374d79-e8ee-4947-b0b4-4a6d31935814",
|
||||
// lorestan
|
||||
// api_key: "2b773c7e-f6de-4dd2-af43-a012a8b78d04",
|
||||
// test
|
||||
// api_key: "11d89a11-bd11-2111-a02f-2cc1cbf4e1d4",
|
||||
// ardebil (AR)
|
||||
// api_key: "14d14a14-bd14-1414-a03f-2cc1cbf5e1d1",
|
||||
// tabriz (sharghi)
|
||||
// api_key: "23d23a32-bd23-2311-a03f-2cc1cbf3e1d4",
|
||||
});
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
|
||||
export const forgetPassword = createAsyncThunk(
|
||||
"LOGIN_FORGET_PASSWORD",
|
||||
async ({ mobile, state }) => {
|
||||
const { data, status } = await axios.post("api/send/", { mobile, state });
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
|
||||
export const checkUserPath = createAsyncThunk(
|
||||
"CHECK_USER_PATH",
|
||||
async ({ mobile, state }) => {
|
||||
const { data, status } = await axios.post(
|
||||
"https://userbackend.rasadyar.com/api/send_otp/",
|
||||
{ mobile, state }
|
||||
);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
|
||||
export const checkActiveUsers = createAsyncThunk(
|
||||
"CHECK_ACTIVE_USERS",
|
||||
async () => {
|
||||
const { data, status } = await axios.get(
|
||||
"https://userbackend.rasadyar.com/api/active-users/"
|
||||
);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
|
||||
export const forgetPasswordSendOpt = createAsyncThunk(
|
||||
"LOGIN_FORGET_PASSWORD_SEND_OTP",
|
||||
async ({ key, code }) => {
|
||||
const { data, status } = await axios.post("api/check/", { key, code });
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
|
||||
export const forgetPasswordChangePassword = createAsyncThunk(
|
||||
"LOGIN_FORGET_PASSWORD_CHANGE_PASSWORD",
|
||||
async ({ username, password }) => {
|
||||
const { data, status } = await axios.post("api/forget/", {
|
||||
username,
|
||||
password,
|
||||
});
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
|
||||
export const changePassword = createAsyncThunk(
|
||||
"LOGIN_CHANGE_PASSWORD",
|
||||
async ({ username, password }) => {
|
||||
const { data, status } = await axios.post("api/change_password/", {
|
||||
username,
|
||||
password,
|
||||
});
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
12
src/features/authentication/services/token-verifiction.js
Normal file
12
src/features/authentication/services/token-verifiction.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const tokenVerifiction = createAsyncThunk(
|
||||
"GET_USER_RAVANDNO_INFO",
|
||||
async (d) => {
|
||||
const { data, status } = await axios.post("token-verification/", {
|
||||
token: d.token,
|
||||
});
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
10
src/features/authentication/services/update-bank-form.js
Normal file
10
src/features/authentication/services/update-bank-form.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const updateBankForm = createAsyncThunk(
|
||||
"UPDATE_BANK_FORM",
|
||||
async (d) => {
|
||||
const { data, status } = await axios.put(`user-bank_card/0/`, d);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,15 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
import axios from "axios";
|
||||
|
||||
export const wagePaymentGetUserInfo = createAsyncThunk(
|
||||
"WAGE_PAYMENT_GET_USER_INFO",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get(
|
||||
`https://${d.province}backend.rasadyar.com/get-payer-info/?${d.key}`
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,225 @@
|
||||
import { Button, IconButton, TextField } from "@mui/material";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
// import { AvicultureNewRequest } from "../aviculture-new-request/AvicultureNewRequest";
|
||||
// import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { avicultureGetRequests } from "../../services/aviculture-requests";
|
||||
import { archiveDeleteKillRequestService } from "../../services/aviculture-delete-kill-request";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment/moment";
|
||||
import { CityNewKillRequest } from "../../../city/components/city-new-kill-request/CityNewKillRequest";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
|
||||
export const AvicultureActiveRequests = () => {
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const { avicultureRequests } = useSelector((state) => state.avicultureSlice);
|
||||
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(avicultureGetRequests({ selectedDate1, selectedDate2 }));
|
||||
}, [selectedDate1, selectedDate2]);
|
||||
|
||||
useEffect(() => {
|
||||
const filteredData =
|
||||
Array.isArray(avicultureRequests) &&
|
||||
avicultureRequests?.filter(
|
||||
(item) =>
|
||||
(item.stateProcess === "accepted" ||
|
||||
item.stateProcess === "pending") &&
|
||||
item.finalState !== "archive"
|
||||
);
|
||||
let d;
|
||||
if (filteredData) {
|
||||
d = filteredData?.map((item, i) => {
|
||||
let sellType = "";
|
||||
if (item.directBuying) {
|
||||
sellType = "خرید مستقیم";
|
||||
} else if (item.union) {
|
||||
sellType = "خرید خارج از استان";
|
||||
} else {
|
||||
sellType = "اتحادیه";
|
||||
}
|
||||
return [
|
||||
i + 1,
|
||||
item.orderCode,
|
||||
sellType,
|
||||
item?.freezing ? "انجماد" : item?.export ? "صادرات" : "عادی",
|
||||
item?.directBuyingBuyerInfo
|
||||
? `${item?.directBuyingBuyerInfo?.buyerFullname} (${item?.directBuyingBuyerInfo?.buyerMobile})`
|
||||
: "-",
|
||||
item.directBuyingKillPlace ? item.directBuyingKillPlace : "-",
|
||||
item?.createDate ? formatJustDate(item?.createDate) : "",
|
||||
item?.sendDate ? formatJustDate(item?.sendDate) : "",
|
||||
`${item.process?.poultry?.poultryName} (${item.process?.poultry?.poultryMobile})`,
|
||||
`${item.process?.poultry?.poultryProvince}/${item.process?.poultry?.poultryCity}`,
|
||||
formatJustDate(item.process?.poultryHatching?.date),
|
||||
item.process?.poultry?.age,
|
||||
item.IndexWeight,
|
||||
item.process?.poultry?.poultryQuantity.toLocaleString(),
|
||||
(
|
||||
item.IndexWeight * item.process?.poultry?.poultryQuantity
|
||||
).toLocaleString(),
|
||||
|
||||
<IconButton
|
||||
key={item?.orderCode}
|
||||
disabled={item?.directBuyingKillPlace}
|
||||
aria-label="delete"
|
||||
color="error"
|
||||
className="avicultureActiveRequestsBtn"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
archiveDeleteKillRequestService(
|
||||
item?.process?.poultry?.poultryRequestId
|
||||
)
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(avicultureGetRequests());
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>,
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
setDataTable(d);
|
||||
}, [avicultureRequests]);
|
||||
|
||||
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" }}
|
||||
width="100%"
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
alignItems={"start"}
|
||||
direction={"column"}
|
||||
width="100%"
|
||||
>
|
||||
<Grid container width="100%" gap={SPACING.SMALL}>
|
||||
<Button
|
||||
className="avicultureNewRequestBtn"
|
||||
variant={"contained"}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: "ثبت درخواست کشتار",
|
||||
content: <CityNewKillRequest isAviculture />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت درخواست کشتار
|
||||
</Button>
|
||||
|
||||
{/* <Button
|
||||
onClick={() => setIsTourOpen(!isTourOpen)}
|
||||
variant="outlined"
|
||||
endIcon={<HelpOutlineIcon />}
|
||||
>
|
||||
راهنما
|
||||
</Button> */}
|
||||
</Grid>
|
||||
<Grid width="100%" className="avicultureActiveRequestsView">
|
||||
<Grid container alignItems="center" 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>
|
||||
<ResponsiveTable
|
||||
title="درخواست های کشتار"
|
||||
columns={[
|
||||
"ردیف",
|
||||
"کد سفارش",
|
||||
"نوع فروش",
|
||||
"نوع کشتار",
|
||||
"اطلاعات خریدار",
|
||||
"محل کشتار",
|
||||
"تاریخ ثبت درخواست",
|
||||
"تاریخ کشتار",
|
||||
"مرغدار (تلفن)",
|
||||
"استان/شهر",
|
||||
"تاریخ جوجه ریزی",
|
||||
"سن مرغ",
|
||||
"میانگین وزنی",
|
||||
"تعداد",
|
||||
"وزن بار (کیلوگرم)",
|
||||
"حذف",
|
||||
]}
|
||||
data={dataTable}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
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 useAvicultureRequests from "../../hooks/useAvicultureRequests";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
|
||||
export const AvicultureArchivedRequests = () => {
|
||||
const navigate = useNavigate();
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const avicultureRequests = useAvicultureRequests("Poultry");
|
||||
const urlRole = window.location.pathname.split("/")[1];
|
||||
|
||||
useEffect(() => {
|
||||
const fileUrl = "/" + urlRole + "/file/";
|
||||
|
||||
const filteredData = avicultureRequests?.filter(
|
||||
(item, i) => item.finalState === "archive"
|
||||
);
|
||||
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={item?.orderCode}
|
||||
aria-label="delete"
|
||||
color="primary"
|
||||
onClick={() =>
|
||||
navigate(fileUrl + item?.process?.poultry?.poultryRequestId)
|
||||
}
|
||||
>
|
||||
<PlagiarismIcon />
|
||||
</IconButton>,
|
||||
];
|
||||
});
|
||||
|
||||
setDataTable(d);
|
||||
}, []);
|
||||
|
||||
const [tableDataCol] = useState([
|
||||
"ردیف",
|
||||
"کد سفارش",
|
||||
"تاریخ ثبت درخواست",
|
||||
"تاریخ درخواست",
|
||||
"مرغدار",
|
||||
"تلفن مرغدار",
|
||||
"شهر",
|
||||
"استان",
|
||||
"سن مرغ",
|
||||
"تعداد",
|
||||
"مشاهده",
|
||||
]);
|
||||
return (
|
||||
<Card>
|
||||
<AdvancedTable
|
||||
expandable
|
||||
name={"درخواست های پایان یافته"}
|
||||
columns={tableDataCol}
|
||||
data={dataTable}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,121 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
Grid,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { avicultureGetGivePermissionService } from "../../services/aviculture-get-give-permission";
|
||||
import { avicultureGivePermissionService } from "../../services/aviculture-give-permission";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
|
||||
const styles = {
|
||||
root: {
|
||||
padding: 20,
|
||||
textAlign: "left",
|
||||
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
|
||||
borderRadius: 8,
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
heading: {
|
||||
textAlign: "right",
|
||||
borderBottom: "2px solid #ccc",
|
||||
paddingBottom: SPACING.SMALL,
|
||||
marginBottom: SPACING.SMALL,
|
||||
},
|
||||
checkboxContainer: {
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
marginBottom: SPACING.SMALL,
|
||||
},
|
||||
checkbox: {
|
||||
marginLeft: SPACING.SMALL,
|
||||
},
|
||||
button: {
|
||||
marginTop: SPACING.SMALL,
|
||||
},
|
||||
};
|
||||
|
||||
export const AvicultureGivePermission = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [checkbox1, setCheckbox1] = useState(false);
|
||||
const [checkbox2, setCheckbox2] = useState(false);
|
||||
|
||||
const handleCheckbox1Change = (event) => {
|
||||
setCheckbox1(event.target.checked);
|
||||
};
|
||||
|
||||
const handleCheckbox2Change = (event) => {
|
||||
setCheckbox2(event.target.checked);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(avicultureGetGivePermissionService()).then((r) => {
|
||||
if (r?.payload?.data?.length) {
|
||||
setCheckbox1(r.payload.data[0]?.city);
|
||||
setCheckbox2(r.payload.data[0]?.province);
|
||||
} else {
|
||||
setCheckbox1(false);
|
||||
setCheckbox2(false);
|
||||
}
|
||||
});
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<Grid container style={styles.root} direction="column">
|
||||
<Typography variant="h6" gutterBottom style={styles.heading}>
|
||||
اجازه دسترسی
|
||||
</Typography>
|
||||
<Grid style={styles.checkboxContainer}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={checkbox1}
|
||||
onChange={handleCheckbox1Change}
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label={
|
||||
<Typography style={styles.checkbox}>
|
||||
دادن وکالت به شهرستان جهت ثبت درخواست کشتار
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid style={styles.checkboxContainer}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={checkbox2}
|
||||
onChange={handleCheckbox2Change}
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label={
|
||||
<Typography style={styles.checkbox}>
|
||||
دادن وکالت به استان جهت ثبت درخواست کشتار
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid style={styles.button}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
avicultureGivePermissionService({
|
||||
city: checkbox1,
|
||||
province: checkbox2,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,242 @@
|
||||
// import { IconButton, Tooltip } from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useFormik } from "formik";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import moment from "moment";
|
||||
import // DRAWER,
|
||||
|
||||
"../../../../lib/redux/slices/appSlice";
|
||||
// import { AvicultureNewHatching } from "../aviculture-new-hatching/AvicultureNewHatching";
|
||||
import { avicultureGetHatchings } from "../../services/aviculture-get-hatchings";
|
||||
import { useState } from "react";
|
||||
// import DeleteIcon from "@mui/icons-material/Delete";
|
||||
// import { avicultureDeleteHatching } from "../../services/aviculture-delete-hatching";
|
||||
// import { useContext } from "react";
|
||||
// import { AppContext } from "../../../../contexts/AppContext";
|
||||
// import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
|
||||
import Tour from "reactour";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
|
||||
const steps = [
|
||||
{
|
||||
selector: ".first-step",
|
||||
content: () => <div>برای ثبت جوجه ریزی اینجا کلیک کنید!</div>,
|
||||
},
|
||||
{
|
||||
selector: ".second",
|
||||
content: () => (
|
||||
<div>در این قسمت جوجه ریزی های ثبت شده توسط شما نمایش داده می شود.</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
export const AvicultureHatching = () => {
|
||||
const dispatch = useDispatch();
|
||||
// const [openNotif] = useContext(AppContext);
|
||||
const { avicultureHatchings } = useSelector((state) => state.avicultureSlice);
|
||||
const [isTourOpen, setIsTourOpen] = useState(false);
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(avicultureGetHatchings());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const d = avicultureHatchings?.map((item, i) => {
|
||||
const killedNumber = item.quantity - item.losses - item.leftOver;
|
||||
return [
|
||||
i + 1,
|
||||
item.allowHatching === "pending" ? "فعال" : "بایگانی شده",
|
||||
item.poultry.unitName,
|
||||
item.hall,
|
||||
item.period,
|
||||
formatJustDate(item?.createDate),
|
||||
formatJustDate(item?.date),
|
||||
item.breed.map((item) => {
|
||||
const title = `${item.breed} (${item.mainQuantity} قطعه)`;
|
||||
return <p key={item?.createDate}>{title}</p>;
|
||||
}),
|
||||
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
|
||||
)})`,
|
||||
// item.allowHatching === "pending" ? (
|
||||
// <Tooltip key={i} title={"حذف جوجه ریزی"} placement="left-start">
|
||||
// <IconButton
|
||||
// aria-label="delete"
|
||||
// color="error"
|
||||
// onClick={() => {
|
||||
// dispatch(LOADING_START());
|
||||
// dispatch(avicultureDeleteHatching(item.key)).then((r) => {
|
||||
// dispatch(LOADING_END());
|
||||
// if (r.error) {
|
||||
// if (r.error.message.includes("403")) {
|
||||
// openNotif({
|
||||
// vertical: "top",
|
||||
// horizontal: "center",
|
||||
// msg: "برای این جوجه ریزی درخواست کشتار ثبت شده است!",
|
||||
// severity: "error",
|
||||
// });
|
||||
// } else if (r.error.message.includes("400")) {
|
||||
// openNotif({
|
||||
// vertical: "top",
|
||||
// horizontal: "center",
|
||||
// msg: "برای این جوجه ریزی بازرسی ثبت شده است!",
|
||||
// severity: "error",
|
||||
// });
|
||||
// } else {
|
||||
// openNotif({
|
||||
// vertical: "top",
|
||||
// horizontal: "center",
|
||||
// msg: "مشکلی پیش آمده است!",
|
||||
// severity: "error",
|
||||
// });
|
||||
// }
|
||||
// } else {
|
||||
// dispatch(avicultureGetHatchings());
|
||||
// openNotif({
|
||||
// vertical: "top",
|
||||
// horizontal: "center",
|
||||
// msg: "عملیات با موفقیت انجام شد.",
|
||||
// severity: "success",
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// }}
|
||||
// >
|
||||
// <DeleteIcon />
|
||||
// </IconButton>
|
||||
// </Tooltip>
|
||||
// ) : (
|
||||
// "-"
|
||||
// ),
|
||||
];
|
||||
});
|
||||
|
||||
setDataTable(d);
|
||||
}, [avicultureHatchings]);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
noChicken: "",
|
||||
slaughterDate: moment(Date()).format("YYYY-MM-DD hh:mm:ss"),
|
||||
race: "آرین",
|
||||
weight: "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
noChicken: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا عدد وارد کنید!"),
|
||||
weight: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا وزن را وارد کنید!"),
|
||||
}),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
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}
|
||||
alignItems={"start"}
|
||||
gap={SPACING.SMALL}
|
||||
direction={"column"}
|
||||
>
|
||||
<Grid
|
||||
width="100%"
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
{/* <Grid>
|
||||
<Button
|
||||
className="first-step"
|
||||
variant={"contained"}
|
||||
disabled={true}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
title: "ثبت اطلاعات جوجه ریزی",
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: <AvicultureNewHatching />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت جوجه ریزی جدید
|
||||
</Button>
|
||||
</Grid> */}
|
||||
|
||||
<Grid>
|
||||
{/* <Button
|
||||
onClick={() => setIsTourOpen(!isTourOpen)}
|
||||
variant="outlined"
|
||||
endIcon={<HelpOutlineIcon />}
|
||||
>
|
||||
راهنما
|
||||
</Button> */}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Tour
|
||||
steps={steps}
|
||||
isOpen={isTourOpen}
|
||||
onRequestClose={() => setIsTourOpen(false)}
|
||||
styles={{
|
||||
popover: (base) => ({
|
||||
...base,
|
||||
borderRadius: "10px",
|
||||
"--reactor-accent": "red",
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
<Grid width="100%" className="second">
|
||||
<ResponsiveTable
|
||||
paginated
|
||||
title="دوره های جوجه ریزی"
|
||||
data={dataTable}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"وضعیت",
|
||||
"نام فارم",
|
||||
"سالن",
|
||||
"دوره جوجه ریزی",
|
||||
"تاریخ ثبت جوجه ریزی",
|
||||
"تاریخ جوجه ریزی",
|
||||
"نژاد",
|
||||
"سن",
|
||||
"تعداد جوجه ریزی",
|
||||
"تلفات دوره",
|
||||
"کشتار شده",
|
||||
"مانده برای کشتار",
|
||||
// "اقدام",
|
||||
]}
|
||||
customColors={[{ name: "وضعیت", color: "green" }]}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,254 @@
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import {
|
||||
Autocomplete,
|
||||
Button,
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
TextField,
|
||||
} 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 { avicultureGetPoultry } from "../../services/aviculture-get-poultry";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { avicultureNewHatching } from "../../services/aviculture-new-hatching";
|
||||
import { avicultureGetHatchings } from "../../services/aviculture-get-hatchings";
|
||||
import { useContext } from "react";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { NumberInput } from "../../../../components/number-format-custom/NumberFormatCustom";
|
||||
|
||||
export const AvicultureNewHatching = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [poultryKey, setPolutryKey] = useState("");
|
||||
const [polutryData, setpolutryData] = useState("");
|
||||
const [enableHall, setEnableHall] = useState(true);
|
||||
const [numberOfhalls, setNumberOfHalls] = useState(1);
|
||||
const [numberOfhallSelected, setNumberOfHallSelected] = useState(null);
|
||||
|
||||
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();
|
||||
dispatch(LOADING_START());
|
||||
dispatch(avicultureGetPoultry()).then((r) => {
|
||||
setpolutryData(r.payload.data);
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}, []);
|
||||
|
||||
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 (
|
||||
<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({
|
||||
key: poultryKey,
|
||||
quantity: formik.values.quantity,
|
||||
date: formik.values.hatchingDate,
|
||||
chicken_breed: formik.values.race,
|
||||
hall: numberOfhallSelected,
|
||||
})
|
||||
).then((r) => {
|
||||
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(avicultureGetHatchings());
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت اطلاعات
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
import { Box } from "@mui/system";
|
||||
import { format } from "date-fns-jalali";
|
||||
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 { avicultureGetProfile } from "../../services/aviculture-get-profile";
|
||||
|
||||
export const AvicultureProfile = () => {
|
||||
const { profile } = useSelector((state) => state.avicultureSlice);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(avicultureGetProfile()).then((r) => {
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}, []);
|
||||
|
||||
const avicultures = profile?.aviculture;
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Grid container gap={SPACING.LARGE}>
|
||||
<Grid container direction="column" xs={12}>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
justifyContent="space-between"
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
{avicultures?.map((item, i) => (
|
||||
<>
|
||||
<Grid>
|
||||
<SimpleTable
|
||||
key={"avicultures" + i}
|
||||
name={`اطلاعات مرغداری ${item.unitName}`}
|
||||
columns={[
|
||||
"شناسه پرورش دهنده",
|
||||
"آدرس",
|
||||
"تعداد سالن ها",
|
||||
"تعداد پارتی",
|
||||
"تاریخ آخرین پارتی",
|
||||
"کد سیستمی",
|
||||
"کد اپیدمیولوژیک",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
item.breedingUniqueId
|
||||
? item.breedingUniqueId
|
||||
: "نامشخص",
|
||||
`${item.address.province.name} - ${
|
||||
item.address.city.name
|
||||
} ${
|
||||
item.address.address
|
||||
? " - " + item.address.address
|
||||
: ""
|
||||
}`,
|
||||
item.numberOfHalls,
|
||||
item.numberOfParty,
|
||||
format(new Date(item?.lastPartyDate), "yyyy/MM/dd"),
|
||||
item.systemCode,
|
||||
item.epidemiologicalCode,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<ChangeCardInfo item={item} />
|
||||
</Grid>
|
||||
</>
|
||||
))}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
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_AVICULTURE_FILE } from "../../../../routes/routes";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { avicultureGetRequests } from "../../services/aviculture-requests";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
|
||||
export const AvicultureRejectedRequests = () => {
|
||||
const navigate = useNavigate();
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const { avicultureRequests } = useSelector((state) => state.avicultureSlice);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(avicultureGetRequests());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const filteredData = avicultureRequests?.filter(
|
||||
(item) =>
|
||||
item.stateProcess === "rejected" || item.provinceState === "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={item?.orderCode}
|
||||
aria-label="delete"
|
||||
color="primary"
|
||||
onClick={() =>
|
||||
navigate(
|
||||
ROUTE_AVICULTURE_FILE + item?.process?.poultry?.poultryRequestId
|
||||
)
|
||||
}
|
||||
>
|
||||
<PlagiarismIcon />
|
||||
</IconButton>,
|
||||
];
|
||||
});
|
||||
|
||||
setDataTable(d);
|
||||
}, [avicultureRequests]);
|
||||
|
||||
const [tableDataCol] = useState([
|
||||
"ردیف",
|
||||
"کد سفارش",
|
||||
"تاریخ ثبت درخواست",
|
||||
"تاریخ درخواست",
|
||||
"مرغدار",
|
||||
"تلفن مرغدار",
|
||||
"شهر",
|
||||
"استان",
|
||||
"سن مرغ",
|
||||
"تعداد",
|
||||
"مشاهده",
|
||||
]);
|
||||
return (
|
||||
<Card>
|
||||
<AdvancedTable
|
||||
name={"درخواست های رد شده"}
|
||||
columns={tableDataCol}
|
||||
data={dataTable}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Card, CardActionArea, CardContent, Typography } from "@mui/material";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import ChartBar from "../../../../components/chart-bar/ChartBar";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { PropTypes } from "prop-types";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import ChartLinear from "../../../../components/chart-linear/ChartLenear";
|
||||
|
||||
export const AvicultureReportsCharts = ({ data }) => {
|
||||
const [hatching, setHatching] = useState({ datasets: [] });
|
||||
const [hatchingWeight, setHatchingWeight] = useState({ datasets: [] });
|
||||
|
||||
useEffect(() => {
|
||||
setHatching({
|
||||
labels: data?.hatchingChart?.map((data) => formatJustDate(data?.date)),
|
||||
datasets: [
|
||||
{
|
||||
label: "تعداد",
|
||||
backgroundColor: ["rgba(33, 72, 214, 0.7)"],
|
||||
data: data?.hatchingChart?.map((data) => data?.quantity),
|
||||
borderRadius: 5,
|
||||
},
|
||||
{
|
||||
label: "تلفات",
|
||||
backgroundColor: ["rgba(100, 130, 160, 0.7)"],
|
||||
data: data.hatchingChart?.map((data) => data?.losses),
|
||||
borderRadius: 5,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
setHatchingWeight({
|
||||
labels: data?.weightChart?.map((data) => formatJustDate(data?.date)),
|
||||
datasets: [
|
||||
{
|
||||
label: "قیمت",
|
||||
backgroundColor: ["rgba(33, 72, 214, 0.7)"],
|
||||
data: data?.weightChart?.map((data) => data?.weight),
|
||||
borderRadius: 5,
|
||||
},
|
||||
],
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Grid mb={SPACING.LARGE}>
|
||||
<Grid
|
||||
container
|
||||
mt={SPACING.MEDIUM}
|
||||
gap={SPACING.SMALL}
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Card sx={{ width: "45%" }}>
|
||||
<CardActionArea>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="body1">
|
||||
نمودار حجم جوجه ریزی و تلفات دوره
|
||||
</Typography>
|
||||
|
||||
<ChartBar chartData={hatching} />
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
|
||||
<Card sx={{ width: "45%" }}>
|
||||
<CardActionArea>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="body1">
|
||||
نمودار پایش وزن و بهره وری وزن
|
||||
</Typography>
|
||||
|
||||
<ChartLinear chartData={hatchingWeight} />
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
AvicultureReportsCharts.propTypes = {
|
||||
data: PropTypes.any,
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
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 { Button } from "@mui/material";
|
||||
import {
|
||||
ROUTE_USER_CHANGE_BANK_ACCOUNT,
|
||||
ROUTE_USER_CHANGE_PASSWORD,
|
||||
ROUTE_USER_CHANGE_PROFILE_INFO,
|
||||
ROUTE_USER_CHANGE_PROFILE_PICTURE,
|
||||
ROUTE_USER_PROFILE,
|
||||
} from "../../../../routes/routes";
|
||||
|
||||
export const DashboardOperations = () => {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
p={SPACING.SMALL}
|
||||
direction={{ xs: "column", md: "row" }}
|
||||
>
|
||||
<NavLink
|
||||
to={ROUTE_USER_PROFILE}
|
||||
active={
|
||||
pathname === ROUTE_USER_PROFILE || pathname === "/" ? "true" : null
|
||||
}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
پروفایل کاربری
|
||||
</Button>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_USER_CHANGE_PASSWORD}
|
||||
active={pathname === ROUTE_USER_CHANGE_PASSWORD ? "true" : null}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
تغییر رمز عبور
|
||||
</Button>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_USER_CHANGE_PROFILE_PICTURE}
|
||||
active={pathname === ROUTE_USER_CHANGE_PROFILE_PICTURE ? "true" : null}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
تغییر عکس پروفایل
|
||||
</Button>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_USER_CHANGE_PROFILE_INFO}
|
||||
active={pathname === ROUTE_USER_CHANGE_PROFILE_INFO ? "true" : null}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
تغییر مشخصات پروفایل
|
||||
</Button>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_USER_CHANGE_BANK_ACCOUNT}
|
||||
active={pathname === ROUTE_USER_CHANGE_BANK_ACCOUNT ? "true" : null}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
تغییر اطلاعات حساب بانکی
|
||||
</Button>
|
||||
</NavLink>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,164 @@
|
||||
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_AVICULTURE_ARCHIVED_REQUESTS,
|
||||
ROUTE_AVICULTURE_AWAITING_INSPECTION_REQUESTS,
|
||||
ROUTE_AVICULTURE_AWAITING_PAYMENT_REQUESTS,
|
||||
ROUTE_AVICULTURE_GIVE_PERMISSION,
|
||||
ROUTE_AVICULTURE_HATCHING,
|
||||
ROUTE_AVICULTURE_REJECTED_REQUESTS,
|
||||
ROUTE_AVICULTURE_SUBMIT_REQUEST,
|
||||
} from "../../../../routes/routes";
|
||||
import LinkItem from "../../../../components/link-item/LinkItem";
|
||||
import {
|
||||
FaArchive,
|
||||
FaEgg,
|
||||
FaMoneyBillWave,
|
||||
FaRegFileAlt,
|
||||
} from "react-icons/fa";
|
||||
import { GrInspect } from "react-icons/gr";
|
||||
import { RiFolderWarningLine } from "react-icons/ri";
|
||||
|
||||
export const RequestsOperations = () => {
|
||||
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_AVICULTURE_HATCHING}
|
||||
active={pathname === ROUTE_AVICULTURE_HATCHING ? "true" : null}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<FaEgg size={30} color="#244CCC" />}
|
||||
title="جوجه ریزی"
|
||||
description="ثبت و مدیریت جوجه ریزی ها"
|
||||
/>
|
||||
</NavLink>
|
||||
{/* <NavLink
|
||||
to={ROUTE_AVICULTURE_CREATE_NEW_REQUEST}
|
||||
active={
|
||||
pathname === ROUTE_AVICULTURE_CREATE_NEW_REQUEST ? "true" : null
|
||||
}
|
||||
>
|
||||
<Button variant="text" color="inherit">
|
||||
ثبت درخواست جدید
|
||||
</Button>
|
||||
</NavLink> */}
|
||||
<NavLink
|
||||
to={ROUTE_AVICULTURE_SUBMIT_REQUEST}
|
||||
active={
|
||||
pathname === ROUTE_AVICULTURE_SUBMIT_REQUEST ? "true" : null
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<FaRegFileAlt size={30} color="#244CCC" />}
|
||||
title="درخواست های کشتار"
|
||||
description="مدیریت و ثبت درخواست های کشتار"
|
||||
/>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_AVICULTURE_AWAITING_PAYMENT_REQUESTS}
|
||||
active={
|
||||
pathname === ROUTE_AVICULTURE_AWAITING_PAYMENT_REQUESTS
|
||||
? "true"
|
||||
: null
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<FaMoneyBillWave size={30} color="#244CCC" />}
|
||||
title="در انتظار پرداخت"
|
||||
description="مشاهده درخواست های در انتظار پرداخت کشتارگاه"
|
||||
/>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_AVICULTURE_AWAITING_INSPECTION_REQUESTS}
|
||||
active={
|
||||
pathname === ROUTE_AVICULTURE_AWAITING_INSPECTION_REQUESTS
|
||||
? "true"
|
||||
: null
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={
|
||||
<GrInspect
|
||||
className="svg-icon-color"
|
||||
fill="#244CCC"
|
||||
stroke="#244CCC"
|
||||
style={{ color: "#4285F4" }}
|
||||
color="#244CCC"
|
||||
size={30}
|
||||
/>
|
||||
}
|
||||
title="در انتظار بازرسی"
|
||||
description="درخواست های در انتظار بررسی بازرس"
|
||||
/>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_AVICULTURE_REJECTED_REQUESTS}
|
||||
active={
|
||||
pathname === ROUTE_AVICULTURE_REJECTED_REQUESTS ? "true" : null
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={
|
||||
<RiFolderWarningLine
|
||||
className="svg-icon-color"
|
||||
color="#244CCC"
|
||||
size={30}
|
||||
/>
|
||||
}
|
||||
title="درخواست های رد شده"
|
||||
description="مشاهده درخواست هایی که به دلایل مختلف توسط اتحادیه رد شده است"
|
||||
/>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_AVICULTURE_ARCHIVED_REQUESTS}
|
||||
active={
|
||||
pathname === ROUTE_AVICULTURE_ARCHIVED_REQUESTS ? "true" : null
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={
|
||||
<FaArchive
|
||||
className="svg-icon-color"
|
||||
color="#244CCC"
|
||||
size={30}
|
||||
/>
|
||||
}
|
||||
title="بایگانی"
|
||||
description="درخواست های پایان یافته"
|
||||
/>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={ROUTE_AVICULTURE_GIVE_PERMISSION}
|
||||
active={
|
||||
pathname === ROUTE_AVICULTURE_GIVE_PERMISSION ? "true" : null
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={
|
||||
<FaArchive
|
||||
className="svg-icon-color"
|
||||
color="#244CCC"
|
||||
size={30}
|
||||
/>
|
||||
}
|
||||
title="وکالت"
|
||||
/>
|
||||
</NavLink>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,135 @@
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { PropTypes } from "prop-types";
|
||||
import { useContext } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { avicultureGetProfile } from "../../services/aviculture-get-profile";
|
||||
import { avicultureSetHallNumber } from "../../services/aviculture-set-hall-number";
|
||||
|
||||
export const StrictMissingHallNumber = ({
|
||||
name,
|
||||
id,
|
||||
avicultureKey,
|
||||
handleClose,
|
||||
}) => {
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const dispatch = useDispatch();
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
number_of_halls: 1,
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
number_of_halls: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا عدد وارد کنید!"),
|
||||
}),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Grid>
|
||||
<Typography variant="body2">
|
||||
تعداد سالن های {name} با شناسه جوجه ریزی {id} را وارد کنید.
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
xs={12}
|
||||
mt={SPACING.SMALL}
|
||||
>
|
||||
<FormControl sx={{ minWidth: "100%" }}>
|
||||
<InputLabel id="demo-simple-select-label">تعداد سالن</InputLabel>
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="type_car"
|
||||
label="تعداد سالن"
|
||||
value={formik.values.number_of_halls}
|
||||
onChange={(e) => {
|
||||
formik.setFieldValue("number_of_halls", e.target.value);
|
||||
}}
|
||||
error={
|
||||
formik.touched.number_of_halls
|
||||
? Boolean(formik.errors.number_of_halls)
|
||||
: null
|
||||
}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.number_of_halls &&
|
||||
Boolean(formik.errors.number_of_halls)
|
||||
? formik.errors.number_of_halls
|
||||
: null
|
||||
}
|
||||
>
|
||||
<MenuItem value={"1"}>1</MenuItem>
|
||||
<MenuItem value={"2"}>2</MenuItem>
|
||||
<MenuItem value={"3"}>3</MenuItem>
|
||||
<MenuItem value={"4"}>4</MenuItem>
|
||||
<MenuItem value={"5"}>5</MenuItem>
|
||||
<MenuItem value={"6"}>6</MenuItem>
|
||||
<MenuItem value={"7"}>7</MenuItem>
|
||||
<MenuItem value={"8"}>8</MenuItem>
|
||||
<MenuItem value={"9"}>9</MenuItem>
|
||||
<MenuItem value={"10"}>10</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
avicultureSetHallNumber({
|
||||
key: avicultureKey,
|
||||
number_of_halls: formik.values.number_of_halls,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
dispatch(avicultureGetProfile());
|
||||
handleClose();
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
StrictMissingHallNumber.propTypes = {
|
||||
name: PropTypes.any,
|
||||
id: PropTypes.any,
|
||||
avicultureKey: PropTypes.any,
|
||||
handleClose: PropTypes.any,
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Typography } from "@mui/material";
|
||||
import { Box } from "@mui/system";
|
||||
import { useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
|
||||
export const ViewBankAccount = () => {
|
||||
const { userProfile } = useSelector((state) => state.userSlice);
|
||||
const userData = [
|
||||
["نام بانک", userProfile.userBankInfo?.bankName],
|
||||
["شماره کارت", userProfile.userBankInfo?.card],
|
||||
["شماره حساب", userProfile.userBankInfo?.account],
|
||||
["شماره شبا", userProfile.userBankInfo?.shaba],
|
||||
];
|
||||
return (
|
||||
<Box>
|
||||
<Grid container p={SPACING.MEDIUM} direction="column">
|
||||
<Grid>
|
||||
<Typography variant="body1" fontWeight={"bold"}>
|
||||
اطلاعات حساب بانکی
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
justifyContent="space-between"
|
||||
gap={SPACING.SMALL}
|
||||
mt={SPACING.MEDIUM}
|
||||
>
|
||||
{userData.map((item, i) => (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
key={i}
|
||||
flexGrow="1"
|
||||
flexBasis="250px"
|
||||
>
|
||||
<Typography variant="body2" fontWeight={"bold"}>
|
||||
{item[0] + ":"}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{item[1] ? item[1] : "نامشخص"}
|
||||
</Typography>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
import { Chip, Divider, Typography } from "@mui/material";
|
||||
import { Box } from "@mui/system";
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { formatTime } from "../../../../utils/formatTime";
|
||||
import { avicultureGetProfile } from "../../services/aviculture-get-profile";
|
||||
|
||||
export const ViewProfile = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { profile } = useSelector((state) => state.avicultureSlice);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(avicultureGetProfile());
|
||||
}, []);
|
||||
const userProfile = profile?.profile;
|
||||
|
||||
const userData = [
|
||||
["نام", userProfile?.firstName],
|
||||
["نام خانوادگی", userProfile?.lastName],
|
||||
["موبایل", userProfile?.mobile],
|
||||
["استان", userProfile?.province?.name],
|
||||
["شهر", userProfile?.city.name],
|
||||
[
|
||||
"تاریخ تولد",
|
||||
userProfile?.birthday ? formatTime(userProfile?.birthday) : null,
|
||||
],
|
||||
];
|
||||
return (
|
||||
<Box>
|
||||
<Grid container direction="column">
|
||||
<Grid>
|
||||
<Divider textAlign="left">
|
||||
<Chip label="اطلاعات کاربر مرغدار" />
|
||||
</Divider>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
justifyContent="space-between"
|
||||
gap={SPACING.SMALL}
|
||||
mt={SPACING.MEDIUM}
|
||||
>
|
||||
{userData?.map((item, i) => (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
key={i}
|
||||
flexGrow="1"
|
||||
flexBasis="250px"
|
||||
>
|
||||
<Typography variant="body2" fontWeight={"bold"}>
|
||||
{item[0] + ":"}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{item[1] ? item[1] : "نامشخص"}
|
||||
</Typography>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
26
src/features/aviculture/hooks/useAvicultureRequests.js
Normal file
26
src/features/aviculture/hooks/useAvicultureRequests.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
import { avicultureGetRequests } from "../services/aviculture-requests";
|
||||
|
||||
const useAvicultureRequests = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { avicultureRequests } = useSelector((state) => state.avicultureSlice);
|
||||
|
||||
const [data, setData] = useState(avicultureRequests);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(avicultureGetRequests()).then(() => {
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setData(avicultureRequests);
|
||||
}, [avicultureRequests]);
|
||||
|
||||
return data ? data : [];
|
||||
};
|
||||
|
||||
export default useAvicultureRequests;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureDeleteHatching = createAsyncThunk(
|
||||
"AVICULTURE_DELETE_HATCHING",
|
||||
async (key) => {
|
||||
const { data, status } = await axios.delete(
|
||||
"poultry_hatching/0/?key=" + key
|
||||
);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const archiveDeleteKillRequestService = createAsyncThunk(
|
||||
"ARCHIVE_DELETE_KILL_REQUEST_SERVICE",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
try {
|
||||
const { data, status } = await axios.delete("Poultry_Request/" + d);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
} catch (e) {
|
||||
dispatch(LOADING_END());
|
||||
return { error: e.response.data.result };
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureGetChickenPrice = createAsyncThunk(
|
||||
"AVICULTURE_GET_CHICKEN_PRICE",
|
||||
async () => {
|
||||
const { data, status } = await axios.get("pricing/?role=Poultry");
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,15 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const avicultureGetDirectBuys = createAsyncThunk(
|
||||
"AVICULTURE_GET_DIRECT_BUYS",
|
||||
async (key, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get(
|
||||
"kill_request/?poultry_key=" + key
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,13 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const avicultureGetGivePermissionService = createAsyncThunk(
|
||||
"AVICULTURE_GET_GIVE_PERMISSION_SERVICE",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get("poultry_allow_city_province/");
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureGetHallInspects = createAsyncThunk(
|
||||
"AVICULTURE_GET_HALL)INSPECTS",
|
||||
async (key) => {
|
||||
const { data, status } = await axios.get(
|
||||
"vet_farm_inspection/?poultry_key=" + key
|
||||
);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureGetHallsInfo = createAsyncThunk(
|
||||
"AVICULTURE_GET_HALLS_INFO",
|
||||
async () => {
|
||||
const { data, status } = await axios.get("Poultry/?info");
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
10
src/features/aviculture/services/aviculture-get-halls.js
Normal file
10
src/features/aviculture/services/aviculture-get-halls.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureGetHalls = createAsyncThunk(
|
||||
"AVICULTURE_GET_HALLS",
|
||||
async () => {
|
||||
const { data, status } = await axios.get("poultry_hatching/");
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,24 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureGetHatchingData = createAsyncThunk(
|
||||
"VET_GET_HATCHING",
|
||||
async (d) => {
|
||||
const { data, status } = await axios.get("poultry_hatching/", {
|
||||
params: {
|
||||
key: d.key || "",
|
||||
},
|
||||
});
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
|
||||
export const avicultureGetHatchingDataForIncreaseHatching = createAsyncThunk(
|
||||
"VET_GET_HATCHING_FOR_INCREASE",
|
||||
async (key) => {
|
||||
const { data, status } = await axios.get(
|
||||
"poultry_hatching/?increase=true&key=" + key
|
||||
);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
10
src/features/aviculture/services/aviculture-get-hatchings.js
Normal file
10
src/features/aviculture/services/aviculture-get-hatchings.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureGetHatchings = createAsyncThunk(
|
||||
"AVICULTURE_GET_HATCHINGS",
|
||||
async () => {
|
||||
const { data, status } = await axios.get("poultry_hatching/");
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
13
src/features/aviculture/services/aviculture-get-poultry.js
Normal file
13
src/features/aviculture/services/aviculture-get-poultry.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { getRoleFromUrl } from "../../../utils/getRoleFromUrl";
|
||||
|
||||
export const avicultureGetPoultry = createAsyncThunk(
|
||||
"AVICULTURE_GET_POULTRY",
|
||||
async () => {
|
||||
const { data, status } = await axios.get("Poultry/", {
|
||||
params: { role: getRoleFromUrl() },
|
||||
});
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
10
src/features/aviculture/services/aviculture-get-profile.js
Normal file
10
src/features/aviculture/services/aviculture-get-profile.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureGetProfile = createAsyncThunk(
|
||||
"AVICULTURE_GET_PROFILE",
|
||||
async (d, { dispatch }) => {
|
||||
const { data, status } = await axios.get("Poultry/0/?profile", d);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
10
src/features/aviculture/services/aviculture-get-reports.js
Normal file
10
src/features/aviculture/services/aviculture-get-reports.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureGetReports = createAsyncThunk(
|
||||
"AVICULTURE_GET_REPORTS",
|
||||
async () => {
|
||||
const { data, status } = await axios.get("poultry_report/");
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureGetSlaughters = createAsyncThunk(
|
||||
"AVICULTURE_GET_SLAUGHTERS",
|
||||
async (d) => {
|
||||
const { data, status } = await axios.get("kill_house_list/?show_poultry", {
|
||||
params: { date: d.date },
|
||||
});
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
14
src/features/aviculture/services/aviculture-get-unions.js
Normal file
14
src/features/aviculture/services/aviculture-get-unions.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const avicultureGetUnions = createAsyncThunk(
|
||||
"AVICULTURE_GET_UNIONS",
|
||||
async (d, { dispatch }) => {
|
||||
const { data, status } = await axios.get("show_city_operator", {
|
||||
params: d,
|
||||
});
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
10
src/features/aviculture/services/aviculture-get-wage-type.js
Normal file
10
src/features/aviculture/services/aviculture-get-wage-type.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureGetWageType = createAsyncThunk(
|
||||
"AVICULTURE_GET_WAGE_TYPE",
|
||||
async () => {
|
||||
const { data, status } = await axios.get("poultry-out-province-wage-type");
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,16 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const avicultureGivePermissionService = createAsyncThunk(
|
||||
"AVICULTURE_GIVE_PERMISSION_SERVICE",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.post(
|
||||
"poultry_allow_city_province/",
|
||||
d
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,25 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import moment from "moment/moment";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../utils/getRoleFromUrl";
|
||||
|
||||
export const avicultureHatchingRequestsService = createAsyncThunk(
|
||||
"AVICULTURE_HATCHING_REQUESTS_SERVICE",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const today = "&today";
|
||||
d = d || moment(new Date()).format("YYYY-MM-DD");
|
||||
const { data, status } = await axios.get(
|
||||
"Poultry_Request/?role=" + getRoleFromUrl() + today,
|
||||
{
|
||||
params: {
|
||||
date1: d.selectedDate1,
|
||||
date2: d.selectedDate2,
|
||||
},
|
||||
}
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
10
src/features/aviculture/services/aviculture-new-hatching.js
Normal file
10
src/features/aviculture/services/aviculture-new-hatching.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureNewHatching = createAsyncThunk(
|
||||
"VET_FARM_NEW_FARM",
|
||||
async (d) => {
|
||||
const { data, status } = await axios.post("poultry_hatching/", d);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
14
src/features/aviculture/services/aviculture-new-request.js
Normal file
14
src/features/aviculture/services/aviculture-new-request.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const avicultureNewRequest = createAsyncThunk(
|
||||
"AVICULTURE_NEW_REQUEST",
|
||||
async (d) => {
|
||||
try {
|
||||
const { data, status } = await axios.post("Poultry_Request/", d);
|
||||
return { data, status };
|
||||
} catch (e) {
|
||||
return { error: e.response.data.result };
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,23 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../utils/getRoleFromUrl";
|
||||
|
||||
export const avicultureRequestsStateProcessService = createAsyncThunk(
|
||||
"AVICULTURE_REQUESTS_STATE_PROCESS",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get(
|
||||
"Poultry_Request/?role=" + getRoleFromUrl(),
|
||||
{
|
||||
params: {
|
||||
date1: d.selectedDate1,
|
||||
date2: d.selectedDate2,
|
||||
state_process: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
19
src/features/aviculture/services/aviculture-requests.js
Normal file
19
src/features/aviculture/services/aviculture-requests.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { getRoleFromUrl } from "../../../utils/getRoleFromUrl";
|
||||
|
||||
export const avicultureGetRequests = createAsyncThunk(
|
||||
"AVICULTURE_REQUESTS_SERVICE",
|
||||
async (d, { dispatch }) => {
|
||||
const { data, status } = await axios.get(
|
||||
"Poultry_Request/?role=" + getRoleFromUrl(),
|
||||
{
|
||||
params: {
|
||||
date1: d.selectedDate1,
|
||||
date2: d.selectedDate2,
|
||||
},
|
||||
}
|
||||
);
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,13 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const avicultureSetHallNumber = createAsyncThunk(
|
||||
"AVICULTURE_SET_HALL_NUMBER",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.put("Poultry/0/", d);
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
20
src/features/aviculture/services/province-get-poultry.js
Normal file
20
src/features/aviculture/services/province-get-poultry.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
import { getRoleFromUrl } from "../../../utils/getRoleFromUrl";
|
||||
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const provinceGetPoultry = createAsyncThunk(
|
||||
"PROVINCE_GET_POULTRY",
|
||||
async (d, { dispatch }) => {
|
||||
dispatch(LOADING_START());
|
||||
const { data, status } = await axios.get("get-all-poultry/", {
|
||||
params: {
|
||||
role: getRoleFromUrl(),
|
||||
active_hatching: true,
|
||||
...d,
|
||||
},
|
||||
});
|
||||
dispatch(LOADING_END());
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,714 @@
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import axios from "axios";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { formatTime } from "../../../../utils/formatTime";
|
||||
import { getFaUserRole } from "../../../../utils/getFaUserRole";
|
||||
import { PageTable } from "../../../../components/page-table/PageTable";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
|
||||
export const ChainCompanyActiveChains = () => {
|
||||
const [selectedAge1, setSelectedAge1] = useState(0);
|
||||
const [selectedAge2, setSelectedAge2] = useState(0);
|
||||
const [data, setData] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const userKey = useSelector((state) => state.userSlice.userProfile.key);
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, []);
|
||||
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const killedNumber = (item) => {
|
||||
let killedNumber = "";
|
||||
killedNumber = item.quantity - item.losses - item.leftOver;
|
||||
return killedNumber;
|
||||
};
|
||||
|
||||
const fetchApiData = async (page, textValue) => {
|
||||
setLoading(true);
|
||||
let response;
|
||||
if (textValue) {
|
||||
response = await axios.get(
|
||||
`poultry_hatching?search=filter&value=${textValue}&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&chain=true`
|
||||
);
|
||||
} else if (selectedAge1 && selectedAge2) {
|
||||
response = await axios.get(
|
||||
`poultry_hatching?role=${getRoleFromUrl()}&age1=${selectedAge1}&age2=${selectedAge2}&page=${page}&page_size=${perPage}&chain=true`
|
||||
);
|
||||
} else {
|
||||
response = await axios.get(
|
||||
`poultry_hatching/?role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&chain=true`
|
||||
);
|
||||
}
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page, textValue);
|
||||
};
|
||||
|
||||
// const updateTable = () => {
|
||||
// fetchApiData(1);
|
||||
// };
|
||||
|
||||
const handlePerRowsChange = async (newPerPage, page) => {
|
||||
setLoading(true);
|
||||
let response;
|
||||
if (textValue) {
|
||||
response = await axios.get(
|
||||
`poultry_hatching?search=filter&value=${textValue}&page=${page}&page_size=${newPerPage}&search=filter&value=${textValue}&chain=true`
|
||||
);
|
||||
} else if (selectedAge1 && selectedAge2) {
|
||||
response = await axios.get(
|
||||
`poultry_hatching?role=${getRoleFromUrl()}&age1=${selectedAge1}&age2=${selectedAge2}&page=${page}&page_size=${perPage}&chain=true`
|
||||
);
|
||||
} else {
|
||||
response = await axios.get(
|
||||
`poultry_hatching/?role=${getRoleFromUrl()}&page=${page}&page_size=${newPerPage}&chain=true`
|
||||
);
|
||||
}
|
||||
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
setPerPage(newPerPage);
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`poultry_hatching/?role=${getRoleFromUrl()}&search=filter&value=${textValue}&chain=true`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoveFilter = async (event) => {
|
||||
event.preventDefault();
|
||||
setSelectedAge1(null);
|
||||
setSelectedAge2(null);
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`poultry_hatching/?role=${getRoleFromUrl()}&chain=true&search=filter&value=`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmitSearchByAge = async (event) => {
|
||||
event.preventDefault();
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`poultry_hatching?role=${getRoleFromUrl()}&age1=${selectedAge1}&age2=${selectedAge2}&chain=true`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
let columns = [
|
||||
// {
|
||||
// name: "عملیات",
|
||||
// selector: (item) => (
|
||||
// <ChainsActiveChainsOperations item={item} updateTable={updateTable} />
|
||||
// ),
|
||||
// sortable: false,
|
||||
// wrap: true,
|
||||
// allowOverflow: true,
|
||||
// center: true,
|
||||
// width: "80px",
|
||||
// },
|
||||
{
|
||||
name: "ردیف",
|
||||
selector: (item, i) => {
|
||||
return i + 1;
|
||||
},
|
||||
sortable: false,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "30px",
|
||||
},
|
||||
{
|
||||
name: "شرکت زنجیره",
|
||||
selector: (item, i) => {
|
||||
return `${item?.chainCompany?.name} (${item?.chainCompany?.user.mobile})`;
|
||||
},
|
||||
sortable: false,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "وضعیت",
|
||||
selector: (item, i) => {
|
||||
return (
|
||||
<Typography
|
||||
variant="body2"
|
||||
color={item.violation ? "error" : "black"}
|
||||
>
|
||||
{item.violation ? "متخلف" : "عادی"}
|
||||
</Typography>
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "60px",
|
||||
},
|
||||
{
|
||||
name: "نام فارم",
|
||||
selector: (row) => row.poultry.unitName,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "90px",
|
||||
},
|
||||
{
|
||||
name: "مرغدار",
|
||||
selector: (item) =>
|
||||
`${item.poultry.userprofile.fullName} (${item.poultry.userprofile.mobile})`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "شهر/تعاونی",
|
||||
selector: (item) =>
|
||||
`${item?.poultry?.address.city.name}/${
|
||||
item?.poultry?.cityOperator
|
||||
? item?.poultry?.cityOperator
|
||||
: "بدون تعاونی"
|
||||
}`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "دامپزشک فارم",
|
||||
selector: (item) =>
|
||||
item?.vetFarm?.vetFarmMobile
|
||||
? `${item?.vetFarm?.vetFarmFullName} (${item?.vetFarm?.vetFarmMobile})`
|
||||
: "-",
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "سالن",
|
||||
selector: (item) => item.hall,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "60px",
|
||||
},
|
||||
{
|
||||
name: "دوره جوجه ریزی",
|
||||
selector: (item) => item.period,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "تاریخ ثبت جوجه ریزی",
|
||||
selector: (item) => formatTime(item?.createDate),
|
||||
sortable: false,
|
||||
wrap: false,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "100px",
|
||||
},
|
||||
{
|
||||
name: "تاریخ جوجه ریزی",
|
||||
selector: (item) => formatTime(item?.date),
|
||||
sortable: false,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "100px",
|
||||
},
|
||||
{
|
||||
name: "نژاد",
|
||||
selector: (item) => item.chickenBreed,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "سن",
|
||||
selector: (row) => row.age,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "60px",
|
||||
},
|
||||
{
|
||||
name: "تعداد جوجه ریزی",
|
||||
selector: (item) => item?.quantity?.toLocaleString(),
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "تلفات دوره (قطعه)",
|
||||
selector: (item) =>
|
||||
`${item.losses} (%${((item.losses * 100) / item.quantity).toFixed(0)})`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "تعداد کل تعهد دولتی (قطعه)",
|
||||
selector: (item) => `${item?.totalCommitmentQuantity?.toLocaleString()}`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "تعداد کشتار شده دولتی (قطعه)",
|
||||
selector: (item) => `${item?.governmentalQuantity?.toLocaleString()}`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "وزن کشتار شده دولتی",
|
||||
selector: (item) =>
|
||||
`${item?.governmentalKilledQuantity?.toLocaleString()}`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "تعداد کشتار شده آزاد (قطعه)",
|
||||
selector: (item) => `${item?.freeQuantity?.toLocaleString()}`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "وزن کشتار شده آزاد ",
|
||||
selector: (item) => `${item?.freeKilledQuantity?.toLocaleString()}`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "حجم خارج از استان",
|
||||
selector: (item) =>
|
||||
`${item?.outProvinceKilledQuantity?.toLocaleString()}`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "وزن خارج از استان",
|
||||
selector: (item) => `${item?.outProvinceKilledWeight?.toLocaleString()}`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "کشتار شده (قطعه)",
|
||||
selector: (item) => {
|
||||
return (
|
||||
killedNumber(item)?.toLocaleString() +
|
||||
` (%${((killedNumber(item) * 100) / item.quantity).toFixed(0)})`
|
||||
);
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "90px",
|
||||
},
|
||||
{
|
||||
name: "مانده در سالن (قطعه)",
|
||||
selector: (item) =>
|
||||
`${item?.leftOver?.toLocaleString()} (%${(
|
||||
(item.leftOver * 100) /
|
||||
item.quantity
|
||||
).toFixed(0)})`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "90px",
|
||||
},
|
||||
{
|
||||
name: "وزن تعهد دولتی",
|
||||
selector: (item) => item?.totalCommitment?.toLocaleString() + " کیلوگرم ",
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "وزن کشتار دولتی",
|
||||
selector: (item) =>
|
||||
item?.governmentalKilledQuantity?.toLocaleString() + " کیلوگرم ",
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "وزن کشتار آزاد",
|
||||
selector: (item) =>
|
||||
item?.freeKilledQuantity?.toLocaleString() + " کیلوگرم ",
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "میانگین وزن کشتار",
|
||||
selector: (item) =>
|
||||
item?.totalAverageKilledWeight?.toLocaleString() + " کیلوگرم ",
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "وزن کل کشتار شده",
|
||||
selector: (item) =>
|
||||
item?.totalKilledWeight?.toLocaleString() + " کیلوگرم ",
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "کشتار فعال",
|
||||
selector: (row) => (row?.activeKill?.activeKill ? "دارد" : "ندارد"),
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "تعداد درخواست کشتار",
|
||||
selector: (item) =>
|
||||
item?.activeKill?.countOfRequest ? item.activeKill.countOfRequest : "-",
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
width: "80px",
|
||||
},
|
||||
{
|
||||
name: "آخرین تغییر",
|
||||
selector: (item) => {
|
||||
const lastChange =
|
||||
item.lastChange &&
|
||||
item.lastChange.date &&
|
||||
`${item.lastChange.fullName} (${getFaUserRole(
|
||||
item.lastChange.role
|
||||
)}) در تاریخ ${formatTime(item.lastChange.date)}`;
|
||||
return item.lastChange ? lastChange : "-";
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
},
|
||||
{
|
||||
name: "سازنده جوجه ریزی",
|
||||
selector: (item) => {
|
||||
const lastChange =
|
||||
item.latestHatchingChange &&
|
||||
item.latestHatchingChange.date &&
|
||||
`${item.latestHatchingChange.fullName} (${getFaUserRole(
|
||||
item.latestHatchingChange.role
|
||||
)}) در تاریخ ${formatTime(item.latestHatchingChange.date)}`;
|
||||
return item.latestHatchingChange ? lastChange : "-";
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
},
|
||||
];
|
||||
|
||||
const selectAges = Array.from({ length: 75 }, (_, i) => i + 1);
|
||||
|
||||
const tableTitle = (
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
gap={2}
|
||||
paddingTop={2}
|
||||
mb={1}
|
||||
width="100%"
|
||||
mt={2}
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
gap={SPACING.SMALL}
|
||||
style={{
|
||||
padding: "10px",
|
||||
border: "1px solid #bbb",
|
||||
borderRadius: "10px",
|
||||
}}
|
||||
>
|
||||
<Typography>زنجیره های زیرمجموعه</Typography>
|
||||
<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>
|
||||
<Tooltip title="خروجی اکسل">
|
||||
{/* <a
|
||||
href={`${axios.defaults.baseURL}0/hatching_excel/`}
|
||||
rel="noreferrer"
|
||||
> */}
|
||||
<Button
|
||||
color="success"
|
||||
onClick={() => {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
|
||||
severity: "success",
|
||||
});
|
||||
const link = `${
|
||||
axios.defaults.baseURL
|
||||
}0/hatching_excel/?role=${getRoleFromUrl()}&key=${userKey}&chain=true`;
|
||||
window.location.href = link;
|
||||
}}
|
||||
>
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
{/* </a> */}
|
||||
</Tooltip>
|
||||
</form>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
gap={SPACING.SMALL}
|
||||
style={{
|
||||
padding: "10px",
|
||||
border: "1px solid #bbb",
|
||||
borderRadius: "10px",
|
||||
}}
|
||||
>
|
||||
<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="از سن"
|
||||
size="small"
|
||||
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="تا سن"
|
||||
size="small"
|
||||
onChange={(event) => setSelectedAge2(event.target.value)}
|
||||
>
|
||||
{selectAges.map((age) => (
|
||||
<MenuItem key={age} value={age}>
|
||||
{age}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
<Button onClick={handleSubmitSearchByAge}>جستجو</Button>
|
||||
<Tooltip title="خروجی اکسل">
|
||||
{/* <a
|
||||
href={`${axios.defaults.baseURL}hatching_report_from_age_excel/?age1=${selectedAge1}&age2=${selectedAge2}`}
|
||||
rel="noreferrer"
|
||||
> */}
|
||||
<Button
|
||||
color="success"
|
||||
onClick={() => {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
|
||||
severity: "success",
|
||||
});
|
||||
const link = `${axios.defaults.baseURL}hatching_report_from_age_excel/?age1=${selectedAge1}&age2=${selectedAge2}&chain=true`;
|
||||
window.location.href = link;
|
||||
}}
|
||||
>
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
{/* </a> */}
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
<Button onClick={handleRemoveFilter} color="error">
|
||||
حذف فیلتر
|
||||
</Button>
|
||||
</Grid>
|
||||
);
|
||||
return (
|
||||
<Grid container xs={12}>
|
||||
{/* <Button
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
title: "ثبت زنجیره فعال",
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: <ChainsSubmitActiveChain updateTable={updateTable} />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
ثبت زنجیره فعال
|
||||
</Button> */}
|
||||
|
||||
<Grid container xs={12} justifyContent="center" mt={2}>
|
||||
<PageTable
|
||||
title={tableTitle}
|
||||
columns={columns}
|
||||
data={data}
|
||||
progressPending={loading}
|
||||
pagination
|
||||
paginationServer
|
||||
paginationTotalRows={totalRows}
|
||||
onChangeRowsPerPage={handlePerRowsChange}
|
||||
onChangePage={handlePageChange}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
import { Box } from "@mui/system";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch } 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 { getChainCompanyProfile } from "../../services/get-chain-company-profile";
|
||||
|
||||
export const ChainCompanyProfile = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [data, setData] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(getChainCompanyProfile()).then((r) => {
|
||||
setData(r.payload.data);
|
||||
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={`اطلاعات شرکت زنجیره`}
|
||||
columns={[
|
||||
"نام",
|
||||
"نام خانوداگی",
|
||||
"استان",
|
||||
"شهر",
|
||||
"آدرس",
|
||||
"کدپستی",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
data?.user?.firstName,
|
||||
data?.user?.lastName,
|
||||
data?.address?.province.name,
|
||||
data?.address?.city.name,
|
||||
data?.address?.address,
|
||||
data?.address?.postalCode,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
</>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const getChainCompanyProfile = createAsyncThunk(
|
||||
"CHAIN_GET_PROFILE",
|
||||
async () => {
|
||||
const { data, status } = await axios.get("chain-company/0/?profile");
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { NavLink } from "../../../../components/nav-link/NavLink";
|
||||
import {
|
||||
ROUTE_CITY_JIHAD_ROUTE_GUILDS,
|
||||
ROUTE_CITY_JIHAD_ROUTE_STEWARDS,
|
||||
ROUTE_CITY_POULTRY_ROUTE_GUILDS,
|
||||
ROUTE_CITY_POULTRY_ROUTE_STEWARDS,
|
||||
} from "../../../../routes/routes";
|
||||
import LinkItem from "../../../../components/link-item/LinkItem";
|
||||
import { MdCorporateFare } from "react-icons/md";
|
||||
import { IoIosPeople } from "react-icons/io";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
|
||||
export const GuildsOperationsCityJihad = () => {
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
p={SPACING.SMALL}
|
||||
direction={{ xs: "column", md: "row" }}
|
||||
justifyContent="center"
|
||||
>
|
||||
<NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "CityJahad"
|
||||
? ROUTE_CITY_JIHAD_ROUTE_GUILDS
|
||||
: ROUTE_CITY_POULTRY_ROUTE_GUILDS
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title="اصناف"
|
||||
/>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "CityJahad"
|
||||
? ROUTE_CITY_JIHAD_ROUTE_STEWARDS
|
||||
: ROUTE_CITY_POULTRY_ROUTE_STEWARDS
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<IoIosPeople size={30} color="#244CCC" />}
|
||||
title="مباشرین"
|
||||
/>
|
||||
</NavLink>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
61
src/features/city-vet/components/CityVetProfile.js
Normal file
61
src/features/city-vet/components/CityVetProfile.js
Normal 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 { cityVetGetProfileService } from "../services/city-vet-profile";
|
||||
|
||||
export const CityVetProfile = () => {
|
||||
const { cityVetGetProfile } = useSelector((state) => state.generalSlice);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(cityVetGetProfileService()).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={`اطلاعات دامپزشک فارم`}
|
||||
columns={[
|
||||
"نام",
|
||||
"نام خانوداگی",
|
||||
"استان",
|
||||
"شهر",
|
||||
"آدرس",
|
||||
"کدپستی",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
cityVetGetProfile?.user?.firstName,
|
||||
cityVetGetProfile?.user?.lastName,
|
||||
cityVetGetProfile?.address?.province.name,
|
||||
cityVetGetProfile?.address?.city.name,
|
||||
cityVetGetProfile?.address?.address,
|
||||
cityVetGetProfile?.address?.postalCode,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
</>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
10
src/features/city-vet/services/city-vet-profile.js
Normal file
10
src/features/city-vet/services/city-vet-profile.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
export const cityVetGetProfileService = createAsyncThunk(
|
||||
"CITY_VET_GET_PROFILE",
|
||||
async () => {
|
||||
const { data, status } = await axios.get("city_vet/0/?profile");
|
||||
return { data, status };
|
||||
}
|
||||
);
|
||||
@@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
);
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user