push rasad front on new repo
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { MdCorporateFare } from "react-icons/md";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import LinkItem from "../../../../components/link-item/LinkItem";
|
||||
import { NavLink } from "../../../../components/nav-link/NavLink";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import {
|
||||
ROUTE_ADMINX_ROUTE_AGENT_SHARE,
|
||||
ROUTE_ADMINX_ROUTE_STEWARD_SHARE,
|
||||
ROUTE_PROVINCE_ROUTE_AGENT_SHARE,
|
||||
ROUTE_PROVINCE_ROUTE_STEWARD_SHARE,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_AGENT_SHARE,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_STEWARD_SHARE,
|
||||
} from "../../../../routes/routes";
|
||||
import { Typography } from "@mui/material";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
|
||||
const getRouteByRole = (isAgentRoute) => {
|
||||
const role = getRoleFromUrl();
|
||||
|
||||
if (role === "SuperAdmin") {
|
||||
if (isAgentRoute) {
|
||||
return ROUTE_SUPER_ADMIN_ROUTE_AGENT_SHARE;
|
||||
}
|
||||
return ROUTE_SUPER_ADMIN_ROUTE_STEWARD_SHARE;
|
||||
}
|
||||
|
||||
if (role === "AdminX") {
|
||||
if (isAgentRoute) {
|
||||
return ROUTE_ADMINX_ROUTE_AGENT_SHARE;
|
||||
}
|
||||
return ROUTE_ADMINX_ROUTE_STEWARD_SHARE;
|
||||
}
|
||||
|
||||
if (isAgentRoute) {
|
||||
return ROUTE_PROVINCE_ROUTE_AGENT_SHARE;
|
||||
}
|
||||
return ROUTE_PROVINCE_ROUTE_STEWARD_SHARE;
|
||||
};
|
||||
|
||||
export const BroadcastManagementOperations = () => {
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
p={SPACING.SMALL}
|
||||
direction={{ xs: "column", md: "row" }}
|
||||
justifyContent="center"
|
||||
>
|
||||
<NavLink to={getRouteByRole(true)}>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title={
|
||||
<>
|
||||
<Typography>گزارش پخش روزانه</Typography>
|
||||
<Typography variant="caption">کشتارگاه به مباشر/ صنف</Typography>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</NavLink>
|
||||
|
||||
<NavLink to={getRouteByRole(false)}>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title={
|
||||
<>
|
||||
<Typography>گزارش پخش روزانه</Typography>
|
||||
<Typography variant="caption">مباشر به صنف</Typography>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</NavLink>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,264 @@
|
||||
import { Button, TextField, Tooltip, Typography } from "@mui/material";
|
||||
import axios from "axios";
|
||||
import { useEffect, useState } from "react";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { CityHatchingsArchiveOperations } from "../../../city/components/city-hatchings-archive-operations/CityHatchingsArchiveOperations";
|
||||
import { formatTime } from "../../../../utils/formatTime";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { getFaUserRole } from "../../../../utils/getFaUserRole";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
const OperationsCell = ({ item, updateArchive, readOnly }) => (
|
||||
<CityHatchingsArchiveOperations
|
||||
item={item}
|
||||
updateArchive={updateArchive}
|
||||
readOnly={readOnly}
|
||||
/>
|
||||
);
|
||||
|
||||
export const ChainsArchiveChains = ({ readOnly }) => {
|
||||
readOnly = readOnly || false;
|
||||
const [data, setData] = useState([]);
|
||||
const [tableData, setTableData] = useState([]);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const userKey = useSelector((state) => state.userSlice.userProfile.key);
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const fetchApiData = async (page, textValue) => {
|
||||
let response;
|
||||
if (textValue) {
|
||||
response = await axios.get(
|
||||
`poultry_hatching/?archive=true&search=filter&value=${textValue}&role=${getRoleFromUrl()}&page=${page}&page_size=&chain=true`
|
||||
);
|
||||
} else {
|
||||
response = await axios.get(
|
||||
`poultry_hatching/?archive=true&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&chain=true`
|
||||
);
|
||||
}
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
};
|
||||
|
||||
const handlePageChange = (pageNum) => {
|
||||
setPage(pageNum);
|
||||
fetchApiData(pageNum, textValue);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (newPerPage) => {
|
||||
setPerPage(Number(newPerPage));
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (perPage) {
|
||||
fetchApiData(1, textValue);
|
||||
}
|
||||
}, [perPage]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1, "");
|
||||
}, []);
|
||||
|
||||
const columns = [
|
||||
"عملیات",
|
||||
"ردیف",
|
||||
"شرکت زنجیره",
|
||||
"وضعیت",
|
||||
"نام فارم",
|
||||
"مرغدار",
|
||||
"شهر/تعاونی",
|
||||
"دامپزشک فارم",
|
||||
"سالن",
|
||||
"دوره جوجه ریزی",
|
||||
"تاریخ ثبت جوجه ریزی",
|
||||
"تاریخ جوجه ریزی",
|
||||
"نژاد",
|
||||
"سن",
|
||||
"تعداد جوجه ریزی",
|
||||
"تلفات دوره",
|
||||
"حجم خارج از استان",
|
||||
"وزن کشتار شده دولتی",
|
||||
"وزن کشتار شده آزاد ",
|
||||
"وزن خارج از استان",
|
||||
"حخم کشتار زنجیره (قطعه)",
|
||||
"وزن کشتار زنجیره (کیلوگرم)",
|
||||
"کشتار شده",
|
||||
"مانده در سالن",
|
||||
"کشتار فعال",
|
||||
"تعداد درخواست کشتار",
|
||||
"آخرین تغییر",
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
if (!data || !Array.isArray(data)) {
|
||||
setTableData([]);
|
||||
return;
|
||||
}
|
||||
|
||||
const transformedData = data.map((item, i) => {
|
||||
const killedNumber = item?.quantity - item?.losses - item?.leftOver;
|
||||
const lastChange =
|
||||
item?.lastChange &&
|
||||
item?.lastChange?.date &&
|
||||
`${item?.lastChange?.fullName} (${getFaUserRole(
|
||||
item?.lastChange?.role
|
||||
)}) در تاریخ ${formatTime(item?.lastChange?.date)}`;
|
||||
|
||||
return [
|
||||
<OperationsCell
|
||||
key={`operations-${item?.key || i}`}
|
||||
item={item}
|
||||
updateArchive={(pageNum) => fetchApiData(pageNum || page, textValue)}
|
||||
readOnly={readOnly}
|
||||
/>,
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
item?.chainCompany?.name && item?.chainCompany?.user?.mobile
|
||||
? `${item.chainCompany.name} (${item.chainCompany.user.mobile})`
|
||||
: "-",
|
||||
<Typography
|
||||
key={`status-${item?.key || i}`}
|
||||
variant="body2"
|
||||
color={item?.violation ? "error" : "black"}
|
||||
>
|
||||
{item?.violation ? "متخلف" : "عادی"}
|
||||
</Typography>,
|
||||
item?.poultry?.unitName || "-",
|
||||
item?.poultry?.userprofile?.fullName &&
|
||||
item?.poultry?.userprofile?.mobile
|
||||
? `${item.poultry.userprofile.fullName} (${item.poultry.userprofile.mobile})`
|
||||
: "-",
|
||||
item?.poultry?.address?.city?.name
|
||||
? `${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?.chickenBreed || "-",
|
||||
item?.age || "-",
|
||||
item?.quantity ? item.quantity.toLocaleString() : "-",
|
||||
item?.losses && item?.quantity
|
||||
? `${item.losses} (%${((item.losses * 100) / item.quantity).toFixed(
|
||||
0
|
||||
)})`
|
||||
: "-",
|
||||
item?.outProvinceKilledQuantity
|
||||
? item.outProvinceKilledQuantity.toLocaleString()
|
||||
: "-",
|
||||
item?.governmentalKilledQuantity
|
||||
? item.governmentalKilledQuantity.toLocaleString()
|
||||
: "-",
|
||||
item?.freeKilledQuantity
|
||||
? item.freeKilledQuantity.toLocaleString()
|
||||
: "-",
|
||||
item?.outProvinceKilledWeight
|
||||
? item.outProvinceKilledWeight.toLocaleString()
|
||||
: "-",
|
||||
item?.chainKilledQuantity
|
||||
? item.chainKilledQuantity.toLocaleString()
|
||||
: "-",
|
||||
item?.chainKilledWeight ? item.chainKilledWeight.toLocaleString() : "-",
|
||||
item?.quantity && killedNumber !== undefined
|
||||
? `${killedNumber.toLocaleString()} (%${(
|
||||
(killedNumber * 100) /
|
||||
item.quantity
|
||||
).toFixed(0)})`
|
||||
: "-",
|
||||
item?.leftOver && item?.quantity
|
||||
? `${item.leftOver.toLocaleString()} (%${(
|
||||
(item.leftOver * 100) /
|
||||
item.quantity
|
||||
).toFixed(0)})`
|
||||
: "-",
|
||||
item?.activeKill?.activeKill ? "دارد" : "ندارد",
|
||||
item?.activeKill?.countOfRequest || "-",
|
||||
lastChange || "-",
|
||||
];
|
||||
});
|
||||
|
||||
setTableData(transformedData);
|
||||
}, [data, page, perPage, textValue, readOnly]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
setPage(1);
|
||||
fetchApiData(1, textValue);
|
||||
};
|
||||
|
||||
const tableTitle = (
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
gap={2}
|
||||
paddingTop={2}
|
||||
mb={1}
|
||||
>
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
<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
|
||||
}archive_hatching_excel/?chain=true&key=${userKey}&role=${getRoleFromUrl()}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
</form>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
return (
|
||||
<Grid alignItems="center" justifyContent="center" xs={12}>
|
||||
<ResponsiveTable
|
||||
title={tableTitle}
|
||||
columns={columns}
|
||||
data={tableData}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePageChange={handlePageChange}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,112 @@
|
||||
import { Button, IconButton, TextField, Typography } from "@mui/material";
|
||||
import { useContext, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import { provinceChainsEditAllocation } from "../../services/province-chains-edit-allocation";
|
||||
import { CLOSE_MODAL, OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const ChainBarManagementEditHealthCode = ({
|
||||
healthCode,
|
||||
item,
|
||||
updateTable,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const handleOpenModal = () => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ویرایش کد بهداشتی",
|
||||
size: "auto",
|
||||
content: (
|
||||
<EditHealthCodeModal
|
||||
initialValue={healthCode || ""}
|
||||
onSubmit={(newValue) => {
|
||||
dispatch(
|
||||
provinceChainsEditAllocation({
|
||||
chain_allcation_key: item?.key,
|
||||
health_code: newValue,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload?.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
updateTable();
|
||||
dispatch(CLOSE_MODAL());
|
||||
}
|
||||
});
|
||||
}}
|
||||
onCancel={() => dispatch(CLOSE_MODAL())}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
gap={0.5}
|
||||
sx={{ width: "120px" }}
|
||||
justifyContent="center"
|
||||
>
|
||||
<Typography variant="caption">{healthCode || "-"}</Typography>
|
||||
<IconButton
|
||||
aria-label="edit"
|
||||
size="small"
|
||||
color="primary"
|
||||
onClick={handleOpenModal}
|
||||
>
|
||||
<EditIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
const EditHealthCodeModal = ({ initialValue, onSubmit, onCancel }) => {
|
||||
const [value, setValue] = useState(initialValue);
|
||||
|
||||
return (
|
||||
<Grid container direction="column" gap={2} minWidth={260}>
|
||||
<TextField
|
||||
label="کد بهداشتی"
|
||||
value={value}
|
||||
onChange={(event) => setValue(event.target.value)}
|
||||
fullWidth
|
||||
size="small"
|
||||
/>
|
||||
<Grid container justifyContent="flex-end" xs={12} gap={1}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => onSubmit(value)}
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
<Button
|
||||
style={{ flex: 1 }}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={onCancel}
|
||||
>
|
||||
لغو
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,209 @@
|
||||
import {
|
||||
IconButton,
|
||||
Popover,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import React, { useContext, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import SettingsIcon from "@mui/icons-material/Settings";
|
||||
import TuneIcon from "@mui/icons-material/Tune";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { ChainsAllocation } from "../chains-allocation/ChainsAllocation";
|
||||
import { provinceChainsDeleteAllocation } from "../../services/province-chains-delete-allocation";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { ProvinceCheckChainAllocation } from "../province-check-chain-allocation/ProvinceCheckChainAllocation";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const ChainBarManagementOperations = ({ item, fetchApiData }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const id = open ? "popover" : undefined;
|
||||
const role = getRoleFromUrl();
|
||||
|
||||
const handleApprove = () => {
|
||||
handleClose();
|
||||
dispatch(
|
||||
DRAWER({
|
||||
title: "تایید/ رد درخواست",
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: (
|
||||
<ProvinceCheckChainAllocation
|
||||
item={item}
|
||||
fetchApiData={fetchApiData}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const handleEdit = () => {
|
||||
handleClose();
|
||||
dispatch(
|
||||
DRAWER({
|
||||
title: "ویرایش بار",
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: (
|
||||
<ChainsAllocation item={item} updateTable={fetchApiData} isEdit />
|
||||
),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
handleClose();
|
||||
dispatch(provinceChainsDeleteAllocation(item?.key)).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
|
||||
fetchApiData(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const canManage =
|
||||
role === "ProvinceOperator" || role === "SuperAdmin" || role === "AdminX";
|
||||
|
||||
const options = [
|
||||
{
|
||||
key: "approve",
|
||||
label: "تایید / رد درخواست",
|
||||
color: "primary.main",
|
||||
icon: <SettingsIcon sx={{ fontSize: { xs: 20, md: 18 } }} />,
|
||||
action: handleApprove,
|
||||
disabled: item?.state !== "pending",
|
||||
},
|
||||
{
|
||||
key: "edit",
|
||||
label: "ویرایش بار",
|
||||
color: "info.main",
|
||||
icon: <EditIcon sx={{ fontSize: { xs: 20, md: 18 } }} />,
|
||||
action: handleEdit,
|
||||
disabled:
|
||||
!canManage ||
|
||||
item?.state === "rejected" ||
|
||||
Boolean(item?.quarantineCode),
|
||||
},
|
||||
{
|
||||
key: "delete",
|
||||
label: "حذف بار",
|
||||
color: "error.main",
|
||||
icon: <DeleteIcon sx={{ fontSize: { xs: 20, md: 18 } }} />,
|
||||
action: handleDelete,
|
||||
disabled:
|
||||
!canManage ||
|
||||
item?.state === "rejected" ||
|
||||
Boolean(item?.quarantineCode),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<IconButton
|
||||
aria-describedby={id}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<TuneIcon />
|
||||
</IconButton>
|
||||
<Popover
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
slotProps={{
|
||||
paper: {
|
||||
sx: {
|
||||
mt: 1,
|
||||
},
|
||||
},
|
||||
}}
|
||||
id={id}
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
>
|
||||
<List sx={{ p: 1 }}>
|
||||
{options.map((option) => (
|
||||
<ListItemButton
|
||||
key={option.key}
|
||||
onClick={() => {
|
||||
if (option.disabled) {
|
||||
return;
|
||||
}
|
||||
option.action();
|
||||
}}
|
||||
disabled={Boolean(option.disabled)}
|
||||
sx={{
|
||||
borderRadius: 1,
|
||||
mb: 0.5,
|
||||
color: option.disabled ? "text.disabled" : option.color,
|
||||
"&:last-of-type": {
|
||||
mb: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
color: option.disabled ? "text.disabled" : option.color,
|
||||
minWidth: 36,
|
||||
}}
|
||||
>
|
||||
{option.icon}
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography
|
||||
sx={{
|
||||
color: option.disabled ? "text.disabled" : option.color,
|
||||
fontWeight: 600,
|
||||
fontSize: { xs: "13px", md: "14px" },
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
))}
|
||||
</List>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,506 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Button, Tab, Tabs, TextField, Tooltip } from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import {
|
||||
ROUTE_ADMINX_CHAINS,
|
||||
ROUTE_PARENT_COMPANY_ALLOCATIONS,
|
||||
ROUTE_PROVINCE_CHAINS,
|
||||
ROUTE_SUPER_ADMIN_CHAINS,
|
||||
} from "../../../../routes/routes";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { ChainBarManagementEditHealthCode } from "../chain-bar-management-edit-health-code/ChainBarManagementEditHealthCode";
|
||||
import { ChainBarManagementOperations } from "../chain-bar-management-operations/ChainBarManagementOperations";
|
||||
import { format } from "date-fns-jalali";
|
||||
import { ChainSubmitQuarantineCode } from "../chain-submit-quarantine-code/ChainSubmitQuarantineCode";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
|
||||
export const ChainBarManagement = ({ province }) => {
|
||||
const [
|
||||
openNotif,
|
||||
,
|
||||
selectedDate1,
|
||||
setSelectedDate1,
|
||||
selectedDate2,
|
||||
setSelectedDate2,
|
||||
] = useContext(AppContext);
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, []);
|
||||
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const userKey = useSelector((state) => state.userSlice?.userProfile?.key);
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const [value, setValue] = useState(0);
|
||||
|
||||
const handleChange = (event, newValue) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
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 [tableDataRejected, setTableDataRejected] = useState([]);
|
||||
const [has500Error, setHas500Error] = useState(false);
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
// Prevent request if there was a 500 error
|
||||
if (has500Error) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(LOADING_START());
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`${
|
||||
province ? province + "parent-company-" : ""
|
||||
}chain-allocation/?search=filter&value=${textValue}&page=${page}&page_size=${perPage}&role=${getRoleFromUrl()}&date1=${selectedDate1}&date2=${selectedDate2}${
|
||||
value === 1 ? "&state=rejected" : ""
|
||||
}`
|
||||
);
|
||||
// Reset error state on successful response
|
||||
setHas500Error(false);
|
||||
setData(response.data?.results || []);
|
||||
setTotalRows(response.data?.count || 0);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
const errorMessage = error?.message || "";
|
||||
const status = error?.response?.status;
|
||||
const is500Error = errorMessage.includes("500") || status === 500;
|
||||
|
||||
if (is500Error) {
|
||||
setHas500Error(true);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
setData([]);
|
||||
setTotalRows(0);
|
||||
} finally {
|
||||
dispatch(LOADING_END());
|
||||
}
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
const updateTable = () => {
|
||||
fetchApiData(page !== 0 ? page : 1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!data || !Array.isArray(data)) {
|
||||
setTableData([]);
|
||||
setTableDataRejected([]);
|
||||
return;
|
||||
}
|
||||
|
||||
const d = data.map((item, i) => {
|
||||
return [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
<ChainBarManagementOperations
|
||||
key={i}
|
||||
fetchApiData={updateTable}
|
||||
item={item}
|
||||
/>,
|
||||
item?.state === "accepted"
|
||||
? "تایید شده"
|
||||
: item?.state === "pending"
|
||||
? "در انتظار تایید"
|
||||
: "رد شده",
|
||||
item?.date ? formatJustDate(item.date) : "-",
|
||||
item?.outProvince ? "خارج استان" : "داخل استان",
|
||||
`${item?.registerer?.fullname || ""} (${
|
||||
item?.registerer?.mobile || ""
|
||||
})`,
|
||||
item?.killHouse?.killHouseOperator?.user?.fullname
|
||||
? `${item.killHouse.killHouseOperator.user.fullname} (${
|
||||
item?.killHouse?.killHouseOperator?.user?.mobile || ""
|
||||
})`
|
||||
: `${item?.buyerName || ""} (${item?.buyerMobile || ""})`,
|
||||
`${item?.poultryHatching?.poultry?.unitName || ""} (${
|
||||
item?.poultryHatching?.poultry?.user?.mobile || ""
|
||||
})`,
|
||||
`${item?.chainCompany?.name || ""} (${
|
||||
item?.chainCompany?.user?.mobile || ""
|
||||
})`,
|
||||
<>
|
||||
{" "}
|
||||
{getRoleFromUrl() === "ParentCompany" ? (
|
||||
item?.healthCode || ""
|
||||
) : (
|
||||
<ChainBarManagementEditHealthCode
|
||||
healthCode={item?.healthCode}
|
||||
item={item}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
)}
|
||||
</>,
|
||||
<>
|
||||
{getRoleFromUrl() === "VetFarm" ||
|
||||
getRoleFromUrl() === "ProvinceOperator" ||
|
||||
getRoleFromUrl() === "SuperAdmin" ||
|
||||
getRoleFromUrl() === "Supporter" ||
|
||||
getRoleFromUrl() === "AdminX" ||
|
||||
getRoleFromUrl() === "CityVet" ||
|
||||
getRoleFromUrl() === "VetSupervisor" ? (
|
||||
<>
|
||||
<ChainSubmitQuarantineCode
|
||||
isLocked={
|
||||
getRoleFromUrl() === "ProvinceOperator" ||
|
||||
getRoleFromUrl() === "VetSupervisor"
|
||||
? false
|
||||
: item?.trash === true ||
|
||||
// item.assignmentStateArchive === "True" ||
|
||||
// item.vetState === "accepted" ||
|
||||
item?.quarantineQuantity
|
||||
? true
|
||||
: false
|
||||
}
|
||||
item={item}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
{item?.quarantineCodeRegisterar?.date
|
||||
? (() => {
|
||||
try {
|
||||
const date = new Date(item?.registerar?.date);
|
||||
return isNaN(date.getTime())
|
||||
? ""
|
||||
: `${format(date, "yyyy/MM/dd")} ${
|
||||
item?.quarantineCodeRegisterar?.name || ""
|
||||
}`;
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"Error formatting quarantineCodeRegisterar date:",
|
||||
error
|
||||
);
|
||||
return "";
|
||||
}
|
||||
})()
|
||||
: ""}
|
||||
</>
|
||||
) : item?.quarantineCode ? (
|
||||
item.quarantineCode
|
||||
) : (
|
||||
"-"
|
||||
)}
|
||||
</>,
|
||||
item?.driverName
|
||||
? `${item.driverName} (${item?.driverMobile || ""})`
|
||||
: "-",
|
||||
item?.typeCar || "",
|
||||
item?.pelak || "",
|
||||
item?.quantity || 0,
|
||||
item?.indexWeight || 0,
|
||||
item?.weight || 0,
|
||||
];
|
||||
});
|
||||
setTableData(d);
|
||||
|
||||
const r = data.map((item, i) => {
|
||||
return [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
item?.state === "rejected"
|
||||
? "رد شده"
|
||||
: item?.state === "deleted"
|
||||
? "حذف شده"
|
||||
: "در انتظار تایید",
|
||||
item?.remover
|
||||
? `${item.remover?.fullname || ""} (${item.remover?.mobile || ""})`
|
||||
: `${item?.registerer?.fullname || ""} (${
|
||||
item?.registerer?.mobile || ""
|
||||
})`,
|
||||
item?.date ? formatJustDate(item.date) : "-",
|
||||
item?.outProvince ? "خارج استان" : "داخل استان",
|
||||
item?.registerer?.fullname
|
||||
? `${item.registerer.fullname} (${item?.registerer?.mobile || ""})`
|
||||
: "-",
|
||||
item?.killHouse?.killHouseOperator?.user?.fullname
|
||||
? `${item.killHouse.killHouseOperator.user.fullname} (${
|
||||
item?.killHouse?.killHouseOperator?.user?.mobile || ""
|
||||
})`
|
||||
: `${item?.buyerName || ""} (${item?.buyerMobile || ""})`,
|
||||
`${item?.poultryHatching?.poultry?.unitName || ""} (${
|
||||
item?.poultryHatching?.poultry?.user?.mobile || ""
|
||||
})`,
|
||||
`${item?.chainCompany?.name || ""} (${
|
||||
item?.chainCompany?.user?.mobile || ""
|
||||
})`,
|
||||
item?.healthCode || "",
|
||||
item?.quarantineCode || "",
|
||||
item?.driverName
|
||||
? `${item.driverName} (${item?.driverMobile || ""})`
|
||||
: "-",
|
||||
item?.typeCar || "",
|
||||
item?.pelak || "",
|
||||
item?.quantity || 0,
|
||||
item?.indexWeight || 0,
|
||||
item?.weight || 0,
|
||||
];
|
||||
});
|
||||
|
||||
setTableDataRejected(r);
|
||||
}, [data, page, perPage]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [dispatch, selectedDate1, selectedDate2, perPage, value]);
|
||||
|
||||
// Reset error state when dates, filters, or tab value changes
|
||||
useEffect(() => {
|
||||
setHas500Error(false);
|
||||
}, [selectedDate1, selectedDate2, textValue, value]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
// Reset error state on manual submit (user retry)
|
||||
setHas500Error(false);
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`${
|
||||
province ? province + "parent-company-" : ""
|
||||
}chain-allocation/?search=filter&value=${textValue}&page=${page}&page_size=${perPage}&role=${getRoleFromUrl()}&date1=${selectedDate1}&date2=${selectedDate2}${
|
||||
value === 1 ? "&state=rejected" : ""
|
||||
}`
|
||||
);
|
||||
// Reset error state on successful response
|
||||
setHas500Error(false);
|
||||
setData(response.data?.results || []);
|
||||
setTotalRows(response.data?.count || 0);
|
||||
dispatch(LOADING_END());
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
const errorMessage = error?.message || "";
|
||||
const status = error?.response?.status;
|
||||
const is500Error = errorMessage.includes("500") || status === 500;
|
||||
|
||||
if (is500Error) {
|
||||
setHas500Error(true);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
setData([]);
|
||||
setTotalRows(0);
|
||||
dispatch(LOADING_END());
|
||||
}
|
||||
};
|
||||
|
||||
const tableTitle = (
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
gap={2}
|
||||
paddingTop={2}
|
||||
mb={1}
|
||||
xs={12}
|
||||
>
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
<Grid style={{ width: "150px" }}>
|
||||
<DatePicker
|
||||
label="از تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid style={{ width: "150px" }}>
|
||||
<DatePicker
|
||||
label="تا تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</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>
|
||||
{value === 0 ? (
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<a
|
||||
href={`${
|
||||
province ? province : axios.defaults.baseURL
|
||||
}bar_chain_excel/?key=${
|
||||
userKey || ""
|
||||
}&role=${getRoleFromUrl()}&search=filter&value=${
|
||||
textValue || ""
|
||||
}&state=accepted&date1=${selectedDate1 || ""}&date2=${
|
||||
selectedDate2 || ""
|
||||
}&search=filter&value=${textValue || ""}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<a
|
||||
href={`${
|
||||
province ? province : axios.defaults.baseURL
|
||||
}bar_chain_excel/?key=${
|
||||
userKey || ""
|
||||
}&role=${getRoleFromUrl()}&search=filter&value=${
|
||||
textValue || ""
|
||||
}&state=rejected&date1=${selectedDate1 || ""}&date2=${
|
||||
selectedDate2 || ""
|
||||
}&search=filter&value=${textValue || ""}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
)}
|
||||
</form>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
|
||||
<Grid xs={12} container justifyContent="center" alignItems="center">
|
||||
{(pathname === ROUTE_PROVINCE_CHAINS ||
|
||||
pathname === ROUTE_SUPER_ADMIN_CHAINS ||
|
||||
pathname === ROUTE_ADMINX_CHAINS ||
|
||||
pathname === ROUTE_PARENT_COMPANY_ALLOCATIONS) && (
|
||||
<Tabs
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
aria-label="simple tabs example"
|
||||
>
|
||||
<Tab label="درخواست های تایید شده" />
|
||||
<Tab label="درخواست های رد شده" />
|
||||
</Tabs>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
{tableTitle}
|
||||
<ResponsiveTable
|
||||
data={value === 0 ? tableData : tableDataRejected}
|
||||
columns={
|
||||
value === 0
|
||||
? [
|
||||
"ردیف",
|
||||
"عملیات",
|
||||
"وضعیت",
|
||||
"تاریخ سفارش",
|
||||
"نوع فروش",
|
||||
"ثبت کننده سفارش",
|
||||
"خریدار",
|
||||
"مرغداری",
|
||||
"شرکت زنجیره",
|
||||
"کد بهداشتی",
|
||||
"کد قرنطینه",
|
||||
"راننده",
|
||||
"نوع خودرو",
|
||||
"پلاک",
|
||||
"حجم",
|
||||
"میانگین وزن",
|
||||
"وزن",
|
||||
]
|
||||
: [
|
||||
"ردیف",
|
||||
"وضعیت",
|
||||
"حذف/رد کننده",
|
||||
"تاریخ سفارش",
|
||||
"نوع فروش",
|
||||
"خریدار",
|
||||
"مرغداری",
|
||||
"شرکت زنجیره",
|
||||
"کد بهداشتی",
|
||||
"کد قرنطینه",
|
||||
"راننده",
|
||||
"نوع خودرو",
|
||||
"پلاک",
|
||||
"حجم",
|
||||
"میانگین وزن",
|
||||
"وزن",
|
||||
]
|
||||
}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title={value === 0 ? "بارهای تایید شده" : "بارهای رد شده"}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
108
src/features/province/components/chain-edit-bar/ChainEditBar.js
Normal file
108
src/features/province/components/chain-edit-bar/ChainEditBar.js
Normal file
@@ -0,0 +1,108 @@
|
||||
import React, { useContext, useEffect } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { Button, TextField } from "@mui/material";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { useFormik } from "formik";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { provinceChainsEditBar } from "../../services/province-chains-edit-bar";
|
||||
|
||||
export const ChainEditBar = ({ item, updateTable }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
weight: item?.weight ? item?.weight : "",
|
||||
quantity: item?.quantity ? item?.quantity : "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
weight: Yup.number().required("این فیلد اجباری است!"),
|
||||
quantity: Yup.number().required("این فیلد اجباری است!"),
|
||||
}),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Grid container xs={12} alignItems="center" justifyContent="center" gap={2}>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
id="quantity"
|
||||
fullWidth
|
||||
label="مقدار"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%" }}
|
||||
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
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
id="weight"
|
||||
fullWidth
|
||||
label="وزن"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%" }}
|
||||
value={formik.values.weight}
|
||||
error={formik.touched.weight ? Boolean(formik.errors.weight) : null}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.weight && Boolean(formik.errors.weight)
|
||||
? formik.errors.weight
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid xs={12}>
|
||||
<Button
|
||||
disabled={!formik.isValid}
|
||||
variant="contained"
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceChainsEditBar({
|
||||
chain_allcation_key: item?.key,
|
||||
quantity: formik.values.quantity,
|
||||
weight: formik.values.weight,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(CLOSE_MODAL());
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد!",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Autocomplete, Button, TextField } from "@mui/material";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { provinceChainsReplaceActiveChain } from "../../services/province-chains-replace-active-chain";
|
||||
import { provinceChainsGetCompanies } from "../../services/province-chains-get-companies";
|
||||
|
||||
export const ChainsReplaceActiveChain = ({ item, updateTable }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [dataCompany, setDataCompany] = useState([]);
|
||||
const [selectedCompany, setSelectedCompany] = useState("");
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceChainsGetCompanies()).then((r) => {
|
||||
setDataCompany(r.payload.data);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
direction="column"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Grid container direction="column" gap={SPACING.SMALL}>
|
||||
<Grid>
|
||||
<Autocomplete
|
||||
disablePortal
|
||||
id="province"
|
||||
options={
|
||||
dataCompany
|
||||
? dataCompany?.map((i) => ({
|
||||
id: i.key,
|
||||
label: `${i.name} (${i.user.mobile})`,
|
||||
}))
|
||||
: []
|
||||
}
|
||||
onChange={(e, value) => {
|
||||
setSelectedCompany(value.id);
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="شرکت زنجیره" />
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<Button
|
||||
disabled={!selectedCompany}
|
||||
variant="contained"
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceChainsReplaceActiveChain({
|
||||
type: "replace",
|
||||
hatching_key: item?.key,
|
||||
company_key: selectedCompany,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,220 @@
|
||||
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
Grid,
|
||||
IconButton,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useDispatch } from "react-redux";
|
||||
import PageviewIcon from "@mui/icons-material/Pageview";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline";
|
||||
import { PropTypes } from "prop-types";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { provinceChainsEditBar } from "../../services/province-chains-edit-bar";
|
||||
import { CLOSE_MODAL, OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const ChainSubmitQuarantineCode = ({ item, updateTable, isLocked }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const handleOpenModal = () => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ثبت کد قرنطینه",
|
||||
size: "auto",
|
||||
content: (
|
||||
<SubmitQuarantineModal
|
||||
code={item.quarantineCode || ""}
|
||||
isLocked={isLocked}
|
||||
onSubmit={(newCode) => {
|
||||
dispatch(
|
||||
provinceChainsEditBar({
|
||||
chain_allcation_key: item.key,
|
||||
quarantine_code: newCode,
|
||||
role: getRoleFromUrl(),
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
updateTable();
|
||||
dispatch(CLOSE_MODAL());
|
||||
}
|
||||
});
|
||||
}}
|
||||
onCancel={() => dispatch(CLOSE_MODAL())}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
gap={0.5}
|
||||
sx={{
|
||||
width: item.quarantineCode ? "160px" : "auto",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
{item.quarantineCode ? (
|
||||
<ViewCodeComponent clearanceCode={item.quarantineCode} />
|
||||
) : (
|
||||
<IconButton
|
||||
aria-label="add"
|
||||
size="small"
|
||||
color="primary"
|
||||
onClick={handleOpenModal}
|
||||
>
|
||||
<AddCircleOutlineIcon fontSize="small" />
|
||||
</IconButton>
|
||||
)}
|
||||
{!isLocked && (
|
||||
<IconButton
|
||||
aria-label="edit"
|
||||
size="small"
|
||||
color="primary"
|
||||
onClick={handleOpenModal}
|
||||
sx={{ display: item.quarantineCode ? "inline-flex" : "none" }}
|
||||
>
|
||||
<EditIcon fontSize="small" />
|
||||
</IconButton>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
const ViewCodeComponent = ({ clearanceCode }) => {
|
||||
const formRef = useRef(null);
|
||||
|
||||
const handleImageClick = () => {
|
||||
if (formRef.current) {
|
||||
formRef.current.submit();
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
gap={0.5}
|
||||
style={{ width: "auto" }}
|
||||
>
|
||||
<Tooltip title="مشاهده گواهینامه" arrow>
|
||||
<form
|
||||
action="https://e.ivo.ir/Rahgiri/Gidprnt.aspx"
|
||||
method="post"
|
||||
target="_blank"
|
||||
ref={formRef}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<input name="gid" type="hidden" value={clearanceCode} />
|
||||
|
||||
<PageviewIcon color="primary" onClick={handleImageClick} />
|
||||
</form>
|
||||
</Tooltip>
|
||||
<Typography variant="caption" color="primary">
|
||||
{clearanceCode}
|
||||
</Typography>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
const SubmitQuarantineModal = ({ code, isLocked, onSubmit, onCancel }) => {
|
||||
const [value, setValue] = useState(code);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
setValue(code);
|
||||
}, [code]);
|
||||
|
||||
const validate = (val) => {
|
||||
if (!val) {
|
||||
setError("این فیلد اجباری است");
|
||||
return false;
|
||||
}
|
||||
const pattern = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]+$/;
|
||||
if (!pattern.test(val)) {
|
||||
setError("باید شامل اعداد و حروف انگلیسی باشد");
|
||||
return false;
|
||||
}
|
||||
setError("");
|
||||
return true;
|
||||
};
|
||||
|
||||
const handleChange = (event) => {
|
||||
const newValue = event.target.value.toUpperCase();
|
||||
setValue(newValue);
|
||||
validate(newValue);
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (validate(value)) {
|
||||
onSubmit(value);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container direction="column" gap={2}>
|
||||
<TextField
|
||||
label="کد قرنطینه"
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
size="small"
|
||||
fullWidth
|
||||
error={Boolean(error)}
|
||||
helperText={error}
|
||||
InputProps={{
|
||||
readOnly: isLocked,
|
||||
}}
|
||||
/>
|
||||
<Grid container justifyContent="flex-end" gap={1} xs={12}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleSubmit}
|
||||
disabled={isLocked}
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
<Button
|
||||
style={{ flex: 1 }}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={onCancel}
|
||||
>
|
||||
لغو
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
ChainSubmitQuarantineCode.propTypes = {
|
||||
item: PropTypes.any,
|
||||
updateTable: PropTypes.any,
|
||||
isLocked: PropTypes.any,
|
||||
};
|
||||
@@ -0,0 +1,257 @@
|
||||
import {
|
||||
IconButton,
|
||||
Popover,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useContext, useState } from "react";
|
||||
import ArchiveIcon from "@mui/icons-material/Archive";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import TuneIcon from "@mui/icons-material/Tune";
|
||||
import FindReplaceIcon from "@mui/icons-material/FindReplace";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { provinceChainsDeleteChain } from "../../services/province-chains-delete-chain";
|
||||
import { ChainsReplaceActiveChain } from "../chain-replace-active-chain/ChainReplaceActiveChain";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { CityArchiveHatchingDrawer } from "../../../city/components/city-archive-hatching-drawer/CityArchiveHatchingDrawer";
|
||||
import AddTaskIcon from "@mui/icons-material/AddTask";
|
||||
import { ChainsAllocation } from "../chains-allocation/ChainsAllocation";
|
||||
|
||||
export const ChainsActiveChainsOperations = ({ item, updateTable }) => {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const id = open ? "popover" : undefined;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<IconButton
|
||||
aria-describedby={id}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<TuneIcon />
|
||||
</IconButton>
|
||||
<Popover
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
slotProps={{
|
||||
paper: {
|
||||
sx: {
|
||||
mt: 1,
|
||||
},
|
||||
},
|
||||
}}
|
||||
id={id}
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
>
|
||||
<List sx={{ p: 1 }}>
|
||||
<ListItemButton
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
dispatch(
|
||||
DRAWER({
|
||||
title: "تخصیص به زنجیره",
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: (
|
||||
<ChainsAllocation item={item} updateTable={updateTable} />
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
sx={{
|
||||
borderRadius: 1,
|
||||
mb: 0.5,
|
||||
color: "primary.main",
|
||||
"&:last-of-type": {
|
||||
mb: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ color: "primary.main", minWidth: 36 }}>
|
||||
<AddTaskIcon sx={{ fontSize: { xs: 20, md: 18 } }} />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography
|
||||
sx={{
|
||||
color: "primary.main",
|
||||
fontWeight: 600,
|
||||
fontSize: { xs: "13px", md: "14px" },
|
||||
}}
|
||||
>
|
||||
تخصیص به زنجیره
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
|
||||
<ListItemButton
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: "جایگزین کردن مرغداری ",
|
||||
content: (
|
||||
<ChainsReplaceActiveChain
|
||||
item={item}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
sx={{
|
||||
borderRadius: 1,
|
||||
mb: 0.5,
|
||||
color: "info.main",
|
||||
"&:last-of-type": {
|
||||
mb: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ color: "info.main", minWidth: 36 }}>
|
||||
<FindReplaceIcon sx={{ fontSize: { xs: 20, md: 18 } }} />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography
|
||||
sx={{
|
||||
color: "info.main",
|
||||
fontWeight: 600,
|
||||
fontSize: { xs: "13px", md: "14px" },
|
||||
}}
|
||||
>
|
||||
جایگزین کردن
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
|
||||
<ListItemButton
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
dispatch(
|
||||
DRAWER({
|
||||
title: "انتقال به آرشیو",
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: (
|
||||
<CityArchiveHatchingDrawer
|
||||
item={item}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
sx={{
|
||||
borderRadius: 1,
|
||||
mb: 0.5,
|
||||
color: "secondary.main",
|
||||
"&:last-of-type": {
|
||||
mb: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ color: "secondary.main", minWidth: 36 }}>
|
||||
<ArchiveIcon sx={{ fontSize: { xs: 20, md: 18 } }} />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography
|
||||
sx={{
|
||||
color: "secondary.main",
|
||||
fontWeight: 600,
|
||||
fontSize: { xs: "13px", md: "14px" },
|
||||
}}
|
||||
>
|
||||
انتقال به بایگانی
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
|
||||
<ListItemButton
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
dispatch(
|
||||
provinceChainsDeleteChain({
|
||||
type: "delete",
|
||||
hatching_key: item?.key,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
sx={{
|
||||
borderRadius: 1,
|
||||
mb: 0.5,
|
||||
color: "error.main",
|
||||
"&:last-of-type": {
|
||||
mb: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ color: "error.main", minWidth: 36 }}>
|
||||
<DeleteIcon sx={{ fontSize: { xs: 20, md: 18 } }} />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography
|
||||
sx={{
|
||||
color: "error.main",
|
||||
fontWeight: 600,
|
||||
fontSize: { xs: "13px", md: "14px" },
|
||||
}}
|
||||
>
|
||||
خروج از زنجیره
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,437 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { getFaUserRole } from "../../../../utils/getFaUserRole";
|
||||
import { ChainsActiveChainsOperations } from "../chains-active-chains-operations/ChainsActiveChainsOperations";
|
||||
import { ChainsSubmitActiveChain } from "../chains-submit-active-chain/ChainsSubmitActiveChain";
|
||||
import { convertToIranianTime } from "../../../../utils/formatTime";
|
||||
export const ChainsActiveChains = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [selectedAge1, setSelectedAge1] = useState(0);
|
||||
const [selectedAge2, setSelectedAge2] = useState(0);
|
||||
const userKey = useSelector((state) => state.userSlice.userProfile.key);
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const [data, setData] = useState([]);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const [page, setPage] = useState(1);
|
||||
const [tableData, setTableData] = useState([]);
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
let response;
|
||||
dispatch(LOADING_START());
|
||||
response = await axios.get(
|
||||
`poultry_hatching?search=filter&value=${textValue}&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&chain=true`
|
||||
);
|
||||
|
||||
dispatch(LOADING_END());
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
const updateTable = () => {
|
||||
fetchApiData(page !== 0 ? page : 1);
|
||||
};
|
||||
const killedNumber = (item) => {
|
||||
let killedNumber = "";
|
||||
killedNumber = item.quantity - item.losses - item.leftOver;
|
||||
return killedNumber;
|
||||
};
|
||||
useEffect(() => {
|
||||
const d = data?.map((item, i) => {
|
||||
let lastChange;
|
||||
return [
|
||||
<ChainsActiveChainsOperations
|
||||
key={i}
|
||||
item={item}
|
||||
updateTable={updateTable}
|
||||
/>,
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
`${item?.chainCompany?.name} (${item?.chainCompany?.user.mobile})`,
|
||||
item.violation ? "متخلف" : "عادی",
|
||||
item.poultry.unitName,
|
||||
`${item.poultry.userprofile.fullName} (${item.poultry.userprofile.mobile})`,
|
||||
|
||||
`${item?.poultry?.address.city.name}/${
|
||||
item?.poultry?.cityOperator
|
||||
? item?.poultry?.cityOperator
|
||||
: "بدون تعاونی"
|
||||
}`,
|
||||
item?.vetFarm?.vetFarmMobile
|
||||
? `${item?.vetFarm?.vetFarmFullName} (${item?.vetFarm?.vetFarmMobile})`
|
||||
: "-",
|
||||
item.hall,
|
||||
item.period,
|
||||
convertToIranianTime(item?.createDate),
|
||||
convertToIranianTime(item?.date),
|
||||
item.chickenBreed,
|
||||
item.age,
|
||||
item?.quantity?.toLocaleString(),
|
||||
`${item.losses} (%${((item.losses * 100) / item.quantity).toFixed(0)})`,
|
||||
`${item?.totalCommitmentQuantity?.toLocaleString()}`,
|
||||
`${item?.governmentalQuantity?.toLocaleString()}`,
|
||||
`${item?.governmentalKilledQuantity?.toLocaleString()}`,
|
||||
`${item?.freeQuantity?.toLocaleString()}`,
|
||||
`${item?.freeKilledQuantity?.toLocaleString()}`,
|
||||
`${item?.outProvinceKilledQuantity?.toLocaleString()}`,
|
||||
`${item?.outProvinceKilledWeight?.toLocaleString()}`,
|
||||
item?.chainKilledQuantity?.toLocaleString(),
|
||||
item?.chainKilledWeight?.toLocaleString(),
|
||||
killedNumber(item)?.toLocaleString() +
|
||||
` (%${((killedNumber(item) * 100) / item.quantity).toFixed(0)})`,
|
||||
`${item?.leftOver?.toLocaleString()} (%${(
|
||||
(item.leftOver * 100) /
|
||||
item.quantity
|
||||
).toFixed(0)})`,
|
||||
|
||||
item?.totalCommitment?.toLocaleString() + " کیلوگرم ",
|
||||
item?.governmentalKilledQuantity?.toLocaleString() + " کیلوگرم ",
|
||||
item?.freeKilledQuantity?.toLocaleString() + " کیلوگرم ",
|
||||
item?.totalAverageKilledWeight?.toLocaleString() + " کیلوگرم ",
|
||||
item?.totalKilledWeight?.toLocaleString() + " کیلوگرم ",
|
||||
item?.activeKill?.activeKill ? "دارد" : "ندارد",
|
||||
item?.activeKill?.countOfRequest ? item.activeKill.countOfRequest : "-",
|
||||
(lastChange = item.lastChange
|
||||
? `${item.lastChange.fullName} (${getFaUserRole(
|
||||
item.lastChange.role
|
||||
)}) در تاریخ ${item.lastChange.date}`
|
||||
: "-"),
|
||||
(lastChange =
|
||||
item.latestHatchingChange &&
|
||||
item.latestHatchingChange.date &&
|
||||
`${item.latestHatchingChange.fullName} (${getFaUserRole(
|
||||
item.latestHatchingChange.role
|
||||
)}) در تاریخ ${item.latestHatchingChange.date}`),
|
||||
item.latestHatchingChange ? lastChange : "-",
|
||||
];
|
||||
});
|
||||
|
||||
setTableData(d);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, [dispatch, perPage]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`poultry_hatching/?role=${getRoleFromUrl()}&search=filter&value=${textValue}&chain=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(null);
|
||||
setSelectedAge2(null);
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmitSearchByAge = async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`poultry_hatching?role=${getRoleFromUrl()}&age1=${selectedAge1}&age2=${selectedAge2}&chain=true`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
dispatch(LOADING_END());
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const selectAges = Array.from({ length: 75 }, (_, i) => i + 1);
|
||||
|
||||
const tableTitle = (
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
gap={2}
|
||||
paddingTop={2}
|
||||
mb={1}
|
||||
>
|
||||
<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} endIcon={<RiSearchLine />}>
|
||||
جستجو
|
||||
</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} justifyContent="center" alignItems="center" gap={2}>
|
||||
<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>
|
||||
{tableTitle}
|
||||
<ResponsiveTable
|
||||
data={tableData}
|
||||
columns={[
|
||||
"عملیات",
|
||||
"ردیف",
|
||||
"شرکت زنجیره",
|
||||
"وضعیت",
|
||||
"نام فارم",
|
||||
"مرغدار",
|
||||
"شهر/تعاونی",
|
||||
"دامپزشک فارم",
|
||||
"سالن",
|
||||
"دوره جوجه ریزی",
|
||||
"تاریخ ثبت جوجه ریزی",
|
||||
"تاریخ جوجه ریزی",
|
||||
"نژاد",
|
||||
"سن",
|
||||
"تعداد جوجه ریزی",
|
||||
"تلفات دوره (قطعه)",
|
||||
"تعداد کل تعهد دولتی (قطعه)",
|
||||
"تعداد کشتار شده دولتی (قطعه)",
|
||||
"وزن کشتار شده دولتی",
|
||||
"تعداد کشتار شده آزاد (قطعه)",
|
||||
"وزن کشتار شده آزاد ",
|
||||
"حجم خارج از استان",
|
||||
"وزن خارج از استان",
|
||||
"حخم کشتار زنجیره (قطعه)",
|
||||
"وزن کشتار زنجیره (کیلوگرم)",
|
||||
"کشتار شده (قطعه)",
|
||||
"مانده در سالن (قطعه)",
|
||||
"وزن تعهد دولتی",
|
||||
"وزن کشتار دولتی",
|
||||
"وزن کشتار آزاد",
|
||||
"میانگین وزن کشتار",
|
||||
"وزن کل کشتار شده",
|
||||
"کشتار فعال",
|
||||
"تعداد درخواست کشتار",
|
||||
"آخرین تغییر",
|
||||
"سازنده جوجه ریزی",
|
||||
]}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title="زنجیره"
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,720 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import moment from "moment";
|
||||
import {
|
||||
Button,
|
||||
Divider,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { useFormik } from "formik";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { provinceChainsSubmitAllocation } from "../../services/province-chains-submut-allocation";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import Radio from "@mui/material/Radio";
|
||||
import RadioGroup from "@mui/material/RadioGroup";
|
||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||
import FormControl from "@mui/material/FormControl";
|
||||
import FormLabel from "@mui/material/FormLabel";
|
||||
import { CarPelak } from "../../../../components/car-pelak/CarPelak";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { provinceGetKillHousesForAllocation } from "../../services/province-get-killhouses-for-allocation";
|
||||
import { provinceChainsEditAllocation } from "../../services/province-chains-edit-allocation";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
|
||||
export const ChainsAllocation = ({ item, updateTable, isEdit }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [value, setValue] = React.useState(
|
||||
isEdit ? (item?.outProvince ? "out" : "native") : "out"
|
||||
);
|
||||
const [selectedKillhouse, setSelectedKillHouse] = React.useState();
|
||||
|
||||
useEffect(() => {
|
||||
if (value === "native") {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(provinceGetKillHousesForAllocation()).then((r) => {
|
||||
dispatch(LOADING_END());
|
||||
const d = r?.payload.data.map((item) => {
|
||||
return { name: item.name, key: item.key };
|
||||
});
|
||||
setKillhouses(d);
|
||||
setSelectedKillHouse("");
|
||||
});
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
const [killhouses, setKillhouses] = useState([]);
|
||||
|
||||
const handleChange = (event) => {
|
||||
setValue(event.target.value);
|
||||
};
|
||||
|
||||
const [driverPelak, setDriverPelak] = useState([]);
|
||||
|
||||
const carPelakHandleChange = (pelak1, pelak2, pelak3, pelak4) => {
|
||||
setDriverPelak([pelak1, pelak2, pelak3, pelak4]);
|
||||
};
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
weight: isEdit ? item?.indexWeight : "",
|
||||
quantity: isEdit ? item?.quantity : "",
|
||||
driverName: isEdit ? item?.driverName : "",
|
||||
driverMobile: isEdit ? item?.driverMobile : "",
|
||||
driverCar: isEdit ? item?.typeCar : "",
|
||||
healthCode: isEdit ? item?.healthCode : "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
weight: Yup.number().required("این فیلد اجباری است!"),
|
||||
quantity: Yup.number().required("این فیلد اجباری است!"),
|
||||
driverName: Yup.string().required("این فیلد اجباری است!"),
|
||||
healthCode: Yup.string().required("این فیلد اجباری است!"),
|
||||
driverMobile: Yup.string()
|
||||
.required("شماره موبایل کشتارگاه الزامی است")
|
||||
.min(11, "شماره موبایل باید 11 رقم باشد")
|
||||
.max(11, "شماره موبایل باید 11 رقم باشد")
|
||||
.matches(/^09\d{9}$/, "شماره موبایل باید با 09 شروع شود و 11 رقم باشد"),
|
||||
driverCar: Yup.string().required("این فیلد اجباری است!"),
|
||||
// driverhealthCode: Yup.string().required("این فیلد اجباری است!"),
|
||||
}),
|
||||
});
|
||||
|
||||
const [, , selectedDate1, setSelectedDate1, ,] = useContext(AppContext);
|
||||
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
}, []);
|
||||
|
||||
const formikbuyer = useFormik({
|
||||
initialValues: {
|
||||
name: isEdit ? item?.buyerName : "",
|
||||
mobile: isEdit ? item?.buyerMobile : "",
|
||||
province: isEdit ? item?.province : "",
|
||||
city: isEdit ? item?.city : "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
name: Yup.string().required("نام اجباری است"),
|
||||
mobile: Yup.string()
|
||||
.required("شماره موبایل کشتارگاه الزامی است")
|
||||
.min(11, "شماره موبایل باید 11 رقم باشد")
|
||||
.max(11, "شماره موبایل باید 11 رقم باشد")
|
||||
.matches(/^09\d{9}$/, "شماره موبایل باید با 09 شروع شود و 11 رقم باشد"),
|
||||
province: Yup.string().required("استان اجباری است"),
|
||||
city: Yup.string().required("شهرستان اجباری است"),
|
||||
}),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
formikbuyer.validateForm();
|
||||
}, []);
|
||||
|
||||
const isFormValid = () => {
|
||||
if (value === "native") {
|
||||
return formik.isValid && selectedKillhouse && driverPelak[1];
|
||||
} else {
|
||||
return formik.isValid && formikbuyer.isValid && driverPelak[1];
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let newVal = formik.values.weight;
|
||||
const mystring = formik.values.weight.toString().split(".").join("");
|
||||
if (formik.values.weight) {
|
||||
if (mystring.length <= 3) {
|
||||
if (mystring.length === 2) {
|
||||
newVal = mystring[0] + "." + mystring[1];
|
||||
}
|
||||
if (mystring.length === 3) {
|
||||
newVal = mystring[0] + "." + mystring[1] + mystring[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isNaN(Number.parseFloat(newVal))) {
|
||||
formik.setFieldValue("weight", "");
|
||||
} else {
|
||||
formik.setFieldValue("weight", Number.parseFloat(newVal));
|
||||
}
|
||||
}, [formik.values.weight]);
|
||||
|
||||
return (
|
||||
<Grid container xs={12} alignItems="center" justifyContent="center" gap={2}>
|
||||
{!isEdit && (
|
||||
<>
|
||||
<Grid container xs={12}>
|
||||
<Typography variant="body2">شرکت زنجیره:{" "}</Typography>
|
||||
<Typography variant="body2" style={{ color: "gray" }}>
|
||||
{item?.companyName}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container xs={12}>
|
||||
<Typography variant="body2">مرغدار:{" "}</Typography>
|
||||
<Typography variant="body2" style={{ color: "gray" }}>
|
||||
{item.poultry.userprofile.fullName} (
|
||||
{item.poultry.userprofile.mobile})
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container xs={12}>
|
||||
<Typography variant="body2">نژاد:{" "}</Typography>
|
||||
<Typography variant="body2" style={{ color: "gray" }}>
|
||||
{item.chickenBreed}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container xs={12}>
|
||||
<Typography variant="body2">سن جوجه:{" "}</Typography>
|
||||
<Typography variant="body2" style={{ color: "gray" }}>
|
||||
{item.age}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
{isEdit && (
|
||||
<>
|
||||
<Grid container xs={12}>
|
||||
<Typography variant="body2">مرغدار:{" "}</Typography>
|
||||
<Typography variant="body2" style={{ color: "gray" }}>
|
||||
{item?.poultryHatching?.poultry?.unitName} (
|
||||
{item?.poultryHatching?.poultry?.user?.mobile})
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container xs={12}>
|
||||
<Typography variant="body2">شرکت زنجیره:{" "}</Typography>
|
||||
<Typography variant="body2" style={{ color: "gray" }}>
|
||||
{item?.chainCompany?.name}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
<Divider style={{ width: "100%" }} />
|
||||
|
||||
<Grid xs={12}>
|
||||
<DatePicker
|
||||
label=" تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
id="quantity"
|
||||
fullWidth
|
||||
label="حجم (قطعه)"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%" }}
|
||||
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
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
id="weight"
|
||||
fullWidth
|
||||
label="میانگین وزن"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%" }}
|
||||
value={formik.values.weight}
|
||||
error={formik.touched.weight ? Boolean(formik.errors.weight) : null}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.weight && Boolean(formik.errors.weight)
|
||||
? formik.errors.weight
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
{formik.values.weight && formik.values.quantity && (
|
||||
<Grid
|
||||
container
|
||||
style={{
|
||||
borderStyle: "solid",
|
||||
borderWidth: "2px",
|
||||
borderColor: "gray",
|
||||
borderRadius: "6px",
|
||||
}}
|
||||
xs={12}
|
||||
p={1}
|
||||
>
|
||||
<Typography variant="body2" color="primary">
|
||||
وزن کل: {" "}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{parseInt(formik.values.quantity * formik.values.weight)} کیلوگرم
|
||||
</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
<FormControl>
|
||||
<FormLabel id="demo-controlled-radio-buttons-group">نوع فروش</FormLabel>
|
||||
<RadioGroup
|
||||
row
|
||||
aria-labelledby="demo-controlled-radio-buttons-group"
|
||||
name="controlled-radio-buttons-group"
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
>
|
||||
<FormControlLabel
|
||||
value="out"
|
||||
control={<Radio disabled={isEdit} />}
|
||||
label="خارج استان"
|
||||
/>
|
||||
<FormControlLabel
|
||||
value="native"
|
||||
control={<Radio disabled={isEdit} />}
|
||||
label="درون استان"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
|
||||
{value === "out" ? (
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
<Typography variant="body1">اطلاعات خریدار</Typography>
|
||||
<TextField
|
||||
label="نام و نام خانوادگی"
|
||||
name="name"
|
||||
value={formikbuyer.values.name}
|
||||
onChange={formikbuyer.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={formikbuyer.touched.name && Boolean(formikbuyer.errors.name)}
|
||||
helperText={formikbuyer.touched.name && formikbuyer.errors.name}
|
||||
required
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="mobile"
|
||||
value={formikbuyer.values.mobile}
|
||||
error={
|
||||
formikbuyer.touched.mobile
|
||||
? Boolean(formikbuyer.errors.mobile)
|
||||
: null
|
||||
}
|
||||
onChange={formikbuyer.handleChange}
|
||||
onBlur={formikbuyer.handleBlur}
|
||||
helperText={
|
||||
formikbuyer.touched.mobile && Boolean(formikbuyer.errors.mobile)
|
||||
? formikbuyer.errors.mobile
|
||||
: null
|
||||
}
|
||||
label="موبایل"
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
/>
|
||||
<TextField
|
||||
label="استان"
|
||||
name="province"
|
||||
value={formikbuyer.values.province}
|
||||
onChange={formikbuyer.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formikbuyer.touched.province &&
|
||||
Boolean(formikbuyer.errors.province)
|
||||
}
|
||||
helperText={
|
||||
formikbuyer.touched.province && formikbuyer.errors.province
|
||||
}
|
||||
required
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
label="شهرستان"
|
||||
name="city"
|
||||
value={formikbuyer.values.city}
|
||||
onBlur={formik.handleBlur}
|
||||
onChange={formikbuyer.handleChange}
|
||||
error={formikbuyer.touched.city && Boolean(formikbuyer.errors.city)}
|
||||
helperText={formikbuyer.touched.city && formikbuyer.errors.city}
|
||||
required
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
) : (
|
||||
<Grid xs={12}>
|
||||
<FormControl
|
||||
fullWidth
|
||||
error={
|
||||
formik.errors.selectedOption && formik.touched.selectedOption
|
||||
}
|
||||
>
|
||||
<InputLabel>کشتارگاه را انتخاب کنید</InputLabel>
|
||||
<Select
|
||||
fullWidth
|
||||
label="کشتارگاه را انتخاب کنید"
|
||||
id="selectedKillhouse"
|
||||
name="selectedKillhouse"
|
||||
onChange={(e) => {
|
||||
const [key] = e.target.value.split("#");
|
||||
setSelectedKillHouse(key);
|
||||
}}
|
||||
onBlur={formik.handleBlur}
|
||||
>
|
||||
{killhouses?.map((option) => (
|
||||
<MenuItem
|
||||
key={option}
|
||||
value={`${option.key + "#" + option.killer}`}
|
||||
>
|
||||
{`کشتارگاه ${option.name}`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{formik.errors.selectedKillhouse &&
|
||||
formik.touched.selectedKillhouse && (
|
||||
<div>{formik.errors.selectedKillhouse}</div>
|
||||
)}
|
||||
</FormControl>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
<Typography variant="body1">اطلاعات خودرو حمل</Typography>
|
||||
<TextField
|
||||
label="نام و نام خانوادگی راننده"
|
||||
name="driverName"
|
||||
value={formik.values.driverName}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={formik.touched.driverName && Boolean(formik.errors.driverName)}
|
||||
helperText={
|
||||
formik.touched.driverName && Boolean(formik.errors.driverName)
|
||||
? formik.errors.driverName
|
||||
: null
|
||||
}
|
||||
required
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="driverMobile"
|
||||
value={formik.values.driverMobile}
|
||||
error={
|
||||
formik.touched.driverMobile
|
||||
? Boolean(formik.errors.driverMobile)
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.driverMobile && Boolean(formik.errors.driverMobile)
|
||||
? formik.errors.driverMobile
|
||||
: null
|
||||
}
|
||||
label="موبایل راننده"
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
/>
|
||||
<TextField
|
||||
label="کد بهداشتی "
|
||||
name="healthCode"
|
||||
value={formik.values.healthCode}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={formik.touched.healthCode && Boolean(formik.errors.healthCode)}
|
||||
helperText={formik.touched.healthCode && formik.errors.healthCode}
|
||||
type="tel"
|
||||
required
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
<TextField
|
||||
label="مدل خودرو"
|
||||
name="driverCar"
|
||||
value={formik.values.driverCar}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={formik.touched.driverCar && Boolean(formik.errors.driverCar)}
|
||||
helperText={formik.touched.driverCar && formik.errors.driverCar}
|
||||
type="tel"
|
||||
required
|
||||
fullWidth
|
||||
/>
|
||||
<CarPelak
|
||||
width="100%"
|
||||
handleChange={carPelakHandleChange}
|
||||
pelakInitial={isEdit ? item?.pelak : ""}
|
||||
/>
|
||||
{/* <TextField
|
||||
label="کد بهداشتی حمل"
|
||||
name="driverhealthCode"
|
||||
value={formik.values.driverhealthCode}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.driverhealthCode &&
|
||||
Boolean(formik.errors.driverhealthCode)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.driverhealthCode && formik.errors.driverhealthCode
|
||||
}
|
||||
required
|
||||
fullWidth
|
||||
/> */}
|
||||
</Grid>
|
||||
<Button
|
||||
disabled={!isFormValid()}
|
||||
variant="contained"
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
if (
|
||||
getRoleFromUrl() !== "SuperAdmin" &&
|
||||
getRoleFromUrl() !== "AdminX" &&
|
||||
((item.age > 40 && formik.values.weight < 1.9) ||
|
||||
(item.age > 40 && formik.values.weight > 4) ||
|
||||
(item.age < 40 && formik.values.weight < 1.5) ||
|
||||
(item.age < 40 && formik.values.weight > 4) ||
|
||||
(item.age > 56 && formik.values.weight < 2.8) ||
|
||||
(item.age > 56 && formik.values.weight > 4))
|
||||
) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg:
|
||||
item?.age > 56
|
||||
? "میانگین وزنی باید عددی بین 2.8 تا 4 کیلوگرم باشد!"
|
||||
: item?.age > 40
|
||||
? "میانگین وزنی باید عددی بین 1.9 تا 4 کیلوگرم باشد!"
|
||||
: "میانگین وزنی باید عددی بین 1.5 تا 4 باشد!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
if (isEdit) {
|
||||
if (value === "native") {
|
||||
dispatch(
|
||||
provinceChainsEditAllocation({
|
||||
chain_allcation_key: item?.key,
|
||||
quantity: formik.values.quantity,
|
||||
weight: parseInt(
|
||||
formik.values.quantity * formik.values.weight
|
||||
),
|
||||
index_weight: formik.values.weight,
|
||||
date: selectedDate1,
|
||||
out_province: false,
|
||||
driver_name: formik.values.driverName,
|
||||
driver_mobile: formik.values.driverMobile,
|
||||
health_code: formik.values.healthCode,
|
||||
type_car: formik.values.driverCar,
|
||||
pelak:
|
||||
driverPelak[0] +
|
||||
" " +
|
||||
driverPelak[1] +
|
||||
" " +
|
||||
driverPelak[2] +
|
||||
" " +
|
||||
driverPelak[3],
|
||||
kill_house_key: selectedKillhouse,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable(1);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "بار با موفقیت ثبت شد؛ جهت مشاهده به بخش مدیریت بارها در همین صفحه مراجعه کنید",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
dispatch(
|
||||
provinceChainsEditAllocation({
|
||||
chain_allcation_key: item?.key,
|
||||
quantity: formik.values.quantity,
|
||||
weight: parseInt(
|
||||
formik.values.quantity * formik.values.weight
|
||||
),
|
||||
index_weight: formik.values.weight,
|
||||
date: selectedDate1,
|
||||
out_province: true,
|
||||
driver_name: formik.values.driverName,
|
||||
driver_mobile: formik.values.driverMobile,
|
||||
health_code: formik.values.healthCode,
|
||||
type_car: formik.values.driverCar,
|
||||
pelak:
|
||||
driverPelak[0] +
|
||||
" " +
|
||||
driverPelak[1] +
|
||||
" " +
|
||||
driverPelak[2] +
|
||||
" " +
|
||||
driverPelak[3],
|
||||
buyer_name: formikbuyer.values.name,
|
||||
buyer_mobile: formikbuyer.values.mobile,
|
||||
city: formikbuyer.values.city,
|
||||
province: formikbuyer.values.name,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable(1);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "بار با موفقیت ثبت شد؛ جهت مشاهده به بخش مدیریت بارها در همین صفحه مراجعه کنید",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (value === "native") {
|
||||
dispatch(
|
||||
provinceChainsSubmitAllocation({
|
||||
hatching_key: item?.key,
|
||||
quantity: formik.values.quantity,
|
||||
weight: parseInt(
|
||||
formik.values.quantity * formik.values.weight
|
||||
),
|
||||
index_weight: formik.values.weight,
|
||||
date: selectedDate1,
|
||||
out_province: false,
|
||||
driver_name: formik.values.driverName,
|
||||
driver_mobile: formik.values.driverMobile,
|
||||
health_code: formik.values.healthCode,
|
||||
type_car: formik.values.driverCar,
|
||||
pelak:
|
||||
driverPelak[0] +
|
||||
" " +
|
||||
driverPelak[1] +
|
||||
" " +
|
||||
driverPelak[2] +
|
||||
" " +
|
||||
driverPelak[3],
|
||||
kill_house_key: selectedKillhouse,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "بار با موفقیت ثبت شد؛ جهت مشاهده به بخش مدیریت بارها در همین صفحه مراجعه کنید",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
dispatch(
|
||||
provinceChainsSubmitAllocation({
|
||||
hatching_key: item?.key,
|
||||
quantity: formik.values.quantity,
|
||||
weight: parseInt(
|
||||
formik.values.quantity * formik.values.weight
|
||||
),
|
||||
index_weight: formik.values.weight,
|
||||
date: selectedDate1,
|
||||
out_province: true,
|
||||
driver_name: formik.values.driverName,
|
||||
driver_mobile: formik.values.driverMobile,
|
||||
health_code: formik.values.healthCode,
|
||||
type_car: formik.values.driverCar,
|
||||
pelak:
|
||||
driverPelak[0] +
|
||||
" " +
|
||||
driverPelak[1] +
|
||||
" " +
|
||||
driverPelak[2] +
|
||||
" " +
|
||||
driverPelak[3],
|
||||
buyer_name: formikbuyer.values.name,
|
||||
buyer_mobile: formikbuyer.values.mobile,
|
||||
city: formikbuyer.values.city,
|
||||
province: formikbuyer.values.name,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "بار با موفقیت ثبت شد؛ جهت مشاهده به بخش مدیریت بارها در همین صفحه مراجعه کنید",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,373 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { useFormik } from "formik";
|
||||
import { Button, TextField, Autocomplete, Typography } from "@mui/material";
|
||||
import { provinceChainsSubmitCompany } from "../../services/province-chains-submit-company";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { provinceChainsEditCompany } from "../../services/province-chains-edit-company";
|
||||
import { provinceChainsGetCompanies } from "../../services/province-chains-get-companies";
|
||||
import {
|
||||
slaughterGetCitiesService,
|
||||
slaughterGetProvinceService,
|
||||
} from "../../../slaughter-house/services/slaughter-get-provinces";
|
||||
|
||||
export const ChainsCompaniesSubmit = ({ item }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [provinceData, setProvinceData] = useState([]);
|
||||
const [cityData, setCityData] = useState([]);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
mobile: item?.user?.mobile ? item?.user?.mobile : "",
|
||||
name: item?.name ? item?.name : "",
|
||||
firstname: item?.user?.firstName ? item?.user?.firstName : "",
|
||||
lastname: item?.user?.lastName ? item?.user?.lastName : "",
|
||||
natioanlId: item?.user?.nationalId ? item?.user?.nationalId : "",
|
||||
postal: item?.postalCode ? item?.postalCode : "",
|
||||
province: item?.province ? item?.province : "",
|
||||
city: item?.city ? item?.city : "",
|
||||
address: item?.address ? item?.address : "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
mobile: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را به صورت عددی وارد کنید!")
|
||||
.test("len", "شماره تلفن باید با 0 شروع شود", (val, context) => {
|
||||
return context.originalValue && context.originalValue.startsWith("0");
|
||||
})
|
||||
.test("len", "شماره تماس 11 رقم باید باشد", (val, context) => {
|
||||
if (context.originalValue) {
|
||||
return context.originalValue.length === 11;
|
||||
}
|
||||
}),
|
||||
name: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را پر کنید!"),
|
||||
firstname: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را پر کنید!"),
|
||||
lastname: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را پر کنید!"),
|
||||
province: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را به درستی وارد کنید!"),
|
||||
city: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را به درستی وارد کنید!"),
|
||||
address: Yup.string()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را پر کنید!"),
|
||||
natioanlId: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را پر کنید!"),
|
||||
postal: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا فیلد را پر کنید!"),
|
||||
}),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
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]);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
direction="column"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Grid container direction="column" gap={SPACING.SMALL}>
|
||||
<Grid>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="name"
|
||||
label="نام شرکت"
|
||||
variant="outlined"
|
||||
value={formik.values.name}
|
||||
error={formik.touched.name ? Boolean(formik.errors.name) : null}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.name && Boolean(formik.errors.name)
|
||||
? formik.errors.name
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="firstname"
|
||||
label="نام مدیرعامل"
|
||||
variant="outlined"
|
||||
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
|
||||
fullWidth
|
||||
id="lastname"
|
||||
label="نام خانوادگی مدیرعامل"
|
||||
variant="outlined"
|
||||
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
|
||||
fullWidth
|
||||
id="mobile"
|
||||
label="موبایل"
|
||||
variant="outlined"
|
||||
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>
|
||||
<Autocomplete
|
||||
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="استان را انتخاب کنید" />
|
||||
)}
|
||||
/>
|
||||
{item && (
|
||||
<Typography variant="caption" color="error">
|
||||
استان: {formik.values.province}
|
||||
</Typography>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Autocomplete
|
||||
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="شهر را انتخاب کنید" />
|
||||
)}
|
||||
/>
|
||||
{item && (
|
||||
<Typography variant="caption" color="error">
|
||||
شهر: {formik.values.city}
|
||||
</Typography>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="natioanlId"
|
||||
label="کد ملی"
|
||||
variant="outlined"
|
||||
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
|
||||
fullWidth
|
||||
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
|
||||
fullWidth
|
||||
id="postal"
|
||||
label="کد پستی"
|
||||
variant="outlined"
|
||||
value={formik.values.postal}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={formik.touched.postal ? Boolean(formik.errors.postal) : null}
|
||||
helperText={
|
||||
formik.touched.postal && Boolean(formik.errors.postal)
|
||||
? formik.errors.postal
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
if (item) {
|
||||
dispatch(
|
||||
provinceChainsEditCompany({
|
||||
city: formik.values.city,
|
||||
province: formik.values.province,
|
||||
mobile: formik.values.mobile,
|
||||
first_name: formik.values.firstname,
|
||||
last_name: formik.values.lastname,
|
||||
national_id: formik.values.natioanlId,
|
||||
address: formik.values.address,
|
||||
postal_code: formik.values.postal,
|
||||
name: formik.values.name,
|
||||
company_key: item?.key,
|
||||
})
|
||||
).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 })
|
||||
);
|
||||
dispatch(provinceChainsGetCompanies());
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
dispatch(
|
||||
provinceChainsSubmitCompany({
|
||||
city: formik.values.city,
|
||||
province: formik.values.province,
|
||||
mobile: formik.values.mobile,
|
||||
first_name: formik.values.firstname,
|
||||
last_name: formik.values.lastname,
|
||||
national_id: formik.values.natioanlId,
|
||||
address: formik.values.address,
|
||||
postal_code: formik.values.postal,
|
||||
name: formik.values.name,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(provinceChainsGetCompanies());
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,231 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import moment from "moment";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { ChainsCompaniesSubmit } from "../chains-companies-submit/ChainsCompaniesSubmit";
|
||||
|
||||
export const ProvinceChainsCompanies = () => {
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
const userKey = useSelector((state) => state.userSlice.userProfile.key);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, [setSelectedDate1, setSelectedDate2]);
|
||||
|
||||
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 handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const isAvalableEdit = () => {
|
||||
if (
|
||||
getRoleFromUrl() === "AdminX" ||
|
||||
getRoleFromUrl() === "SuperAdmin" ||
|
||||
getRoleFromUrl() === "ProvinceOperator"
|
||||
) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const fetchApiData = async (page = 1) => {
|
||||
try {
|
||||
dispatch(LOADING_START());
|
||||
const response = await axios.get(
|
||||
`chain-company/?search=filter&value=${textValue}&page=${page}&page_size=${perPage}&role=${getRoleFromUrl()}&state=total_companies`
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
} catch (error) {
|
||||
dispatch(LOADING_END());
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePageChange = (newPage) => {
|
||||
setPage(newPage);
|
||||
fetchApiData(newPage);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (newPerPage) => {
|
||||
setPerPage(newPerPage);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData();
|
||||
}, [selectedDate1, selectedDate2, perPage]);
|
||||
|
||||
useEffect(() => {
|
||||
const formattedData = data?.map((item, i) => [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
item.name,
|
||||
item.user.firstName,
|
||||
item.user.lastName,
|
||||
item.user.mobile,
|
||||
item.province,
|
||||
item.city,
|
||||
item.address,
|
||||
item.postalCode,
|
||||
item.requestsInfo?.numberOfRequests?.toLocaleString(),
|
||||
item.requestsInfo?.totalQuantity?.toLocaleString(),
|
||||
item.requestsInfo?.totalWeight?.toLocaleString(),
|
||||
<Tooltip title="ویرایش اطلاعات" placement="left" key={i}>
|
||||
<IconButton
|
||||
disabled={isAvalableEdit()}
|
||||
color="primary"
|
||||
onClick={() =>
|
||||
dispatch(
|
||||
DRAWER({
|
||||
title: "ویرایش شرکت زنجیره",
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: <ChainsCompaniesSubmit item={item} />,
|
||||
})
|
||||
)
|
||||
}
|
||||
>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
</Tooltip>,
|
||||
]);
|
||||
setTableData(formattedData);
|
||||
}, [data, page, perPage]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
fetchApiData(1);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
|
||||
<Grid container xs={12}>
|
||||
{(getRoleFromUrl() === "ProvinceOperator" ||
|
||||
getRoleFromUrl() === "SuperAdmin") && (
|
||||
<Button
|
||||
onClick={() =>
|
||||
dispatch(
|
||||
DRAWER({
|
||||
title: "ثبت شرکت زنجیره",
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: <ChainsCompaniesSubmit />,
|
||||
})
|
||||
)
|
||||
}
|
||||
variant="contained"
|
||||
>
|
||||
ثبت شرکت زنجیره
|
||||
</Button>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
gap={2}
|
||||
paddingTop={2}
|
||||
mb={1}
|
||||
width="100%"
|
||||
>
|
||||
<Typography>خریداران</Typography>
|
||||
<Grid container alignItems="center" gap={2}>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
id="outlined-basic"
|
||||
size="small"
|
||||
autoComplete="off"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button type="submit" endIcon={<RiSearchLine />}>
|
||||
جستجو
|
||||
</Button>
|
||||
</form>
|
||||
<Grid>
|
||||
<Tooltip title="خروجی اکسل شرکت های زنجیره">
|
||||
<a
|
||||
href={`${
|
||||
axios.defaults.baseURL
|
||||
}chain_company_buyers_excel/?role=${getRoleFromUrl()}&key=${userKey}&search=filter&value=${textValue}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<ResponsiveTable
|
||||
data={tableData}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"نام شرکت",
|
||||
"نام مدیرعامل",
|
||||
"نام خانوادگی مدیرعامل",
|
||||
"موبایل",
|
||||
"استان",
|
||||
"شهر",
|
||||
"آدرس",
|
||||
"کد پستی",
|
||||
"تعداد سفارشات",
|
||||
"حجم سفارشات (قطعه)",
|
||||
"وزن سفارشات (کیلوگرم)",
|
||||
"عملیات",
|
||||
]}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title="مدیریت بارها"
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,132 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { provinceGetPoultry } from "../../../aviculture/services/province-get-poultry";
|
||||
import { Autocomplete, Button, TextField } from "@mui/material";
|
||||
import { provinceChainsGetCompanies } from "../../services/province-chains-get-companies";
|
||||
import { provinceChainsSubmitActiveChain } from "../../services/province-chains-submit-active-chain";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const ChainsSubmitActiveChain = ({ updateTable }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [poultries, setPoultries] = useState([]);
|
||||
const [data, setData] = useState([]);
|
||||
const [dataCompany, setDataCompany] = useState([]);
|
||||
const [selectedPoultries, setSelectedPoultries] = useState([]);
|
||||
const [selectedCompany, setSelectedCompany] = useState("");
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
provinceGetPoultry({
|
||||
chain: true,
|
||||
})
|
||||
).then((r) => {
|
||||
setData(r.payload.data);
|
||||
});
|
||||
dispatch(provinceChainsGetCompanies()).then((r) => {
|
||||
setDataCompany(r.payload.data);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setPoultries(
|
||||
data?.map((item) => {
|
||||
return {
|
||||
label: `${item.unitName} (${item?.user.mobile})`,
|
||||
value: `${item.chainCompany?.hatchingKey}`,
|
||||
};
|
||||
})
|
||||
);
|
||||
}, [data]);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
direction="column"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Grid container direction="column" gap={SPACING.SMALL}>
|
||||
<Grid>
|
||||
<Autocomplete
|
||||
disablePortal
|
||||
id="province"
|
||||
multiple
|
||||
options={poultries}
|
||||
getOptionLabel={(option) => option.label}
|
||||
onChange={(e, value) => {
|
||||
setSelectedPoultries(value);
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="انتخاب مرغداران" />
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<Autocomplete
|
||||
disablePortal
|
||||
id="province"
|
||||
options={
|
||||
dataCompany
|
||||
? dataCompany?.map((i) => ({
|
||||
id: i.key,
|
||||
label: `${i.name} (${i.user.mobile})`,
|
||||
}))
|
||||
: []
|
||||
}
|
||||
onChange={(e, value) => {
|
||||
setSelectedCompany(value.id);
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="شرکت زنجیره" />
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<Button
|
||||
disabled={!selectedPoultries.length || !selectedCompany}
|
||||
variant="contained"
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceChainsSubmitActiveChain({
|
||||
poultry_hitchings: selectedPoultries?.map((item) => {
|
||||
return item?.value;
|
||||
}),
|
||||
chain_company: selectedCompany,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد!",
|
||||
severity: "success",
|
||||
});
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
54
src/features/province/components/chains/ProvinceChains.js
Normal file
54
src/features/province/components/chains/ProvinceChains.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import React from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { Tab, Tabs } from "@mui/material";
|
||||
import { ProvinceChainsCompanies } from "../chains-companies/ProvinceChainsCompanies";
|
||||
import { ChainsActiveChains } from "../chains-active-chains/ChainsActiveChains";
|
||||
import { ChainsArchiveChains } from "../chain-archive-chains/ChainsArchiveChains";
|
||||
import { ChainBarManagement } from "../chain-bar-management/ChainBarManagement";
|
||||
|
||||
export const ProvinceChains = () => {
|
||||
const [value, setValue] = React.useState("0");
|
||||
|
||||
const handleChange = (event, newValue) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
return (
|
||||
<Grid container justifyContent="center" xs={12}>
|
||||
<Tabs
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
textColor="secondary"
|
||||
indicatorColor="secondary"
|
||||
aria-label="secondary tabs example"
|
||||
scrollButtons="auto"
|
||||
variant="scrollable"
|
||||
allowScrollButtonsMobile
|
||||
>
|
||||
<Tab value="0" label="زنجیره های فعال" />
|
||||
<Tab value="1" label="مدیریت بارها" />
|
||||
<Tab value="2" label="شرکت ها" />
|
||||
<Tab value="3" label="بایگانی" />
|
||||
</Tabs>
|
||||
<Grid
|
||||
container
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
px={2}
|
||||
xs={12}
|
||||
>
|
||||
<Grid container justifyContent="center" mt={2} xs={12}>
|
||||
{value === "0" && <ChainsActiveChains />}
|
||||
</Grid>
|
||||
<Grid container justifyContent="center" mt={2} xs={12}>
|
||||
{value === "1" && <ChainBarManagement />}
|
||||
</Grid>
|
||||
<Grid container justifyContent="center" mt={2} xs={12}>
|
||||
{value === "2" && <ProvinceChainsCompanies />}
|
||||
</Grid>
|
||||
<Grid container justifyContent="center" xs={12}>
|
||||
{value === "3" && <ChainsArchiveChains />}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
574
src/features/province/components/create-guilds/CreateGuilds.js
Normal file
574
src/features/province/components/create-guilds/CreateGuilds.js
Normal file
@@ -0,0 +1,574 @@
|
||||
import React, { useContext, useEffect, useState, useCallback } from "react";
|
||||
import { useFormik } from "formik";
|
||||
import { useDispatch } from "react-redux";
|
||||
import {
|
||||
Button,
|
||||
Box,
|
||||
Typography,
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
} from "@mui/material";
|
||||
import { Add as AddIcon } from "@mui/icons-material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { updateGuildByNationalIdNewService } from "../../services/update-guild-by-national-id-new";
|
||||
import { deactivateGuildService } from "../../services/deactivate-guild";
|
||||
import { provinceGetCitiesService } from "../../services/province-get-cities";
|
||||
import { provinceGetFieldOfWorks } from "../../services/ProvinceGetFieldOfWorks";
|
||||
import { provinceGetTypeActivity } from "../../services/provinceGetTypeActivity";
|
||||
import { provinceGetRegisterCodeStateService } from "../../services/province-get-register-code-state";
|
||||
import { mainGetGuildsForUpdateOrCreateService } from "../../services/main-get-guilds-for-update-or-create";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { PersonalInfoSection } from "./components/PersonalInfoSection";
|
||||
import { InquiryForm } from "./components/InquiryForm";
|
||||
import { UpdateFromExternalButton } from "./components/UpdateFromExternalButton";
|
||||
import { ConfirmationDialog } from "./components/ConfirmationDialog";
|
||||
import { FormActions } from "./components/FormActions";
|
||||
import { GuildInfoAccordionItem } from "./components/GuildInfoAccordionItem";
|
||||
import { getValidationSchema, getInitialValues } from "./utils/formUtils";
|
||||
import {
|
||||
mapResponseDataToFormFields,
|
||||
prepareSubmitData,
|
||||
} from "./utils/dataMapping";
|
||||
import { handleSubmitSuccess, handleSubmitError } from "./utils/submitHandlers";
|
||||
|
||||
const DeleteConfirmationDialog = ({ open, onClose, onConfirm, isDeleting }) => {
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>آیا مطمئن هستید؟</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant="body2">
|
||||
آیا از حذف این صنف مطمئن هستید؟ این عمل قابل بازگشت نیست.
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ gap: 2, p: 2 }}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={onClose}
|
||||
disabled={isDeleting}
|
||||
sx={{ flex: 1 }}
|
||||
>
|
||||
انصراف
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={onConfirm}
|
||||
disabled={isDeleting}
|
||||
sx={{ flex: 1 }}
|
||||
>
|
||||
{isDeleting ? "در حال حذف..." : "حذف"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export const CreateGuilds = ({ guild, updateTable }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [hasRegisterCode, setHasRegisterCode] = useState();
|
||||
const [inquiryNationalCode, setInquiryNationalCode] = useState("");
|
||||
const [isInquiryDone, setIsInquiryDone] = useState(false);
|
||||
const [dbRegister, setDbRegister] = useState(null);
|
||||
const [hasInquiry, setHasInquiry] = useState(null);
|
||||
const [guildActive, setGuildActive] = useState(null);
|
||||
const [guildsList, setGuildsList] = useState(() => (guild ? [guild] : []));
|
||||
const [expandedAccordion, setExpandedAccordion] = useState(0);
|
||||
const [guildsFormValues, setGuildsFormValues] = useState(() => {
|
||||
// Initialize with guild data if editing
|
||||
if (guild) {
|
||||
return [getInitialValues(guild)];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
const [cities, setCities] = useState([]);
|
||||
const [typeActivities, setTypeActivities] = useState([]);
|
||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||
const [deleteDialogIndex, setDeleteDialogIndex] = useState(null);
|
||||
const [isDeletingGuild, setIsDeletingGuild] = useState(false);
|
||||
|
||||
const originalPhoneNumber = guild?.phoneNumber || null;
|
||||
|
||||
const currentRole = getRoleFromUrl();
|
||||
const isAdmin = currentRole === "AdminX";
|
||||
const isSuperAdmin = currentRole === "SuperAdmin";
|
||||
const isKillHouse = currentRole === "KillHouse";
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: getInitialValues(guild),
|
||||
validationSchema: getValidationSchema(!!guild),
|
||||
validateOnMount: true,
|
||||
onSubmit: (values) => {
|
||||
const guildsDataArray = guildsList.map((guildItem, index) => {
|
||||
const guildValues = guildsFormValues[index] || values;
|
||||
const combinedValues = {
|
||||
...values, // Personal info (shared)
|
||||
...guildValues, // Guild-specific info (overrides if same keys exist)
|
||||
};
|
||||
return prepareSubmitData(
|
||||
combinedValues,
|
||||
guildItem,
|
||||
originalPhoneNumber,
|
||||
hasInquiry
|
||||
);
|
||||
});
|
||||
|
||||
dispatch(updateGuildByNationalIdNewService(guildsDataArray)).then(
|
||||
(result) => {
|
||||
if (result.payload.error) {
|
||||
handleSubmitError(openNotif, result.payload.error);
|
||||
} else {
|
||||
handleSubmitSuccess(
|
||||
dispatch,
|
||||
openNotif,
|
||||
updateTable,
|
||||
values,
|
||||
result.payload?.data
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetRegisterCodeStateService()).then((r) => {
|
||||
const isActive = r.payload.data?.[0]?.active;
|
||||
setHasRegisterCode(isActive);
|
||||
if (isActive === false) {
|
||||
formik.setFieldValue("isAccepted", true);
|
||||
}
|
||||
});
|
||||
dispatch(provinceGetCitiesService()).then((r) => {
|
||||
setCities(r.payload.data || []);
|
||||
});
|
||||
dispatch(provinceGetFieldOfWorks());
|
||||
dispatch(provinceGetTypeActivity()).then((r) => {
|
||||
setTypeActivities(r.payload.data || []);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
const mapResponseToFormFields = useCallback(
|
||||
(responseData) => {
|
||||
const guildsData = Array.isArray(responseData.guilds)
|
||||
? responseData.guilds
|
||||
: [];
|
||||
|
||||
mapResponseDataToFormFields(responseData, inquiryNationalCode, formik);
|
||||
|
||||
if (responseData.dbRegister === false) {
|
||||
setDbRegister(false);
|
||||
setHasInquiry(null);
|
||||
} else {
|
||||
setHasInquiry(responseData.hasInquiry ?? null);
|
||||
const firstGuild = guildsData.length > 0 ? guildsData[0] : null;
|
||||
const activeStatus = firstGuild?.active ?? responseData.active ?? null;
|
||||
setGuildActive(activeStatus);
|
||||
formik.setFieldValue("active", activeStatus);
|
||||
setDbRegister(true);
|
||||
}
|
||||
|
||||
if (guildsData.length > 0) {
|
||||
setGuildsList(guildsData);
|
||||
const initialGuildValues = guildsData.map((guildItem) => {
|
||||
const combinedGuild = {
|
||||
...guildItem,
|
||||
user: responseData.user || {},
|
||||
};
|
||||
return getInitialValues(combinedGuild);
|
||||
});
|
||||
setGuildsFormValues(initialGuildValues);
|
||||
setExpandedAccordion(0);
|
||||
} else {
|
||||
setGuildsList([]);
|
||||
setGuildsFormValues([]);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
formik.validateField("mobile");
|
||||
formik.validateField("national_id");
|
||||
}, 0);
|
||||
},
|
||||
[formik, inquiryNationalCode]
|
||||
);
|
||||
|
||||
const handleInquiry = useCallback(() => {
|
||||
if (!inquiryNationalCode) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "لطفا کد ملی را وارد کنید",
|
||||
severity: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAdmin && inquiryNationalCode.length !== 10) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "لطفا کد ملی 10 رقمی معتبر وارد کنید",
|
||||
severity: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
mainGetGuildsForUpdateOrCreateService({
|
||||
national_code: inquiryNationalCode,
|
||||
update: false,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
setHasInquiry(false);
|
||||
if (isAdmin) {
|
||||
setIsInquiryDone(true);
|
||||
formik.setFieldValue("national_id", inquiryNationalCode);
|
||||
}
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
if (!isAdmin) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (r.payload.data) {
|
||||
mapResponseToFormFields(r.payload.data);
|
||||
setIsInquiryDone(true);
|
||||
|
||||
if (r.payload.data.dbRegister === false) {
|
||||
setHasInquiry(true);
|
||||
}
|
||||
|
||||
const successMsg =
|
||||
r.payload.data.dbRegister === false
|
||||
? "اطلاعات از سامانه خارجی دریافت شد"
|
||||
: "اطلاعات از پایگاه داده دریافت شد";
|
||||
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: successMsg,
|
||||
severity: "success",
|
||||
});
|
||||
} else {
|
||||
setHasInquiry(false);
|
||||
setIsInquiryDone(true);
|
||||
if (isAdmin) {
|
||||
formik.setFieldValue("national_id", inquiryNationalCode);
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [
|
||||
dispatch,
|
||||
inquiryNationalCode,
|
||||
openNotif,
|
||||
mapResponseToFormFields,
|
||||
isAdmin,
|
||||
formik,
|
||||
]);
|
||||
|
||||
const handleUpdateFromExternal = useCallback(() => {
|
||||
if (!formik.values.national_id || formik.values.national_id.length !== 10) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "لطفا کد ملی 10 رقمی معتبر وارد کنید",
|
||||
severity: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
mainGetGuildsForUpdateOrCreateService({
|
||||
national_code: formik.values.national_id,
|
||||
update: true,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
setHasInquiry(false);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (r.payload.data) {
|
||||
const updateResponse = {
|
||||
...r.payload.data,
|
||||
dbRegister: false,
|
||||
};
|
||||
mapResponseToFormFields(updateResponse);
|
||||
setHasInquiry(true);
|
||||
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "اطلاعات از سامانه خارجی بروزرسانی شد",
|
||||
severity: "success",
|
||||
});
|
||||
} else {
|
||||
setHasInquiry(false);
|
||||
}
|
||||
});
|
||||
}, [dispatch, formik.values.national_id, openNotif, mapResponseToFormFields]);
|
||||
|
||||
const handleAddGuild = () => {
|
||||
const newIndex = guildsList.length;
|
||||
setGuildsList([...guildsList, null]);
|
||||
setGuildsFormValues([...guildsFormValues, getInitialValues(null)]);
|
||||
setExpandedAccordion(newIndex);
|
||||
};
|
||||
|
||||
const handleDeleteGuild = (index) => {
|
||||
const guildToDelete = guildsList[index];
|
||||
if (guildToDelete?.key) {
|
||||
setDeleteDialogIndex(index);
|
||||
setDeleteDialogOpen(true);
|
||||
return;
|
||||
}
|
||||
if (guildsList.length > 1) {
|
||||
setGuildsList(guildsList.filter((_, i) => i !== index));
|
||||
setGuildsFormValues(guildsFormValues.filter((_, i) => i !== index));
|
||||
if (expandedAccordion === index) {
|
||||
setExpandedAccordion(0);
|
||||
} else if (expandedAccordion > index) {
|
||||
setExpandedAccordion(expandedAccordion - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirmDelete = () => {
|
||||
if (deleteDialogIndex === null) return;
|
||||
|
||||
const guildToDelete = guildsList[deleteDialogIndex];
|
||||
if (!guildToDelete?.key) return;
|
||||
|
||||
setIsDeletingGuild(true);
|
||||
dispatch(deactivateGuildService(guildToDelete.key)).then((r) => {
|
||||
setIsDeletingGuild(false);
|
||||
setDeleteDialogOpen(false);
|
||||
setDeleteDialogIndex(null);
|
||||
|
||||
if (r.payload?.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "صنف با موفقیت حذف شد",
|
||||
severity: "success",
|
||||
});
|
||||
// Remove from list after successful deletion
|
||||
if (guildsList.length > 1) {
|
||||
setGuildsList(guildsList.filter((_, i) => i !== deleteDialogIndex));
|
||||
setGuildsFormValues(
|
||||
guildsFormValues.filter((_, i) => i !== deleteDialogIndex)
|
||||
);
|
||||
// If deleted accordion was expanded, expand the first one
|
||||
if (expandedAccordion === deleteDialogIndex) {
|
||||
setExpandedAccordion(0);
|
||||
} else if (expandedAccordion > deleteDialogIndex) {
|
||||
// Adjust expanded index if deleted item was before it
|
||||
setExpandedAccordion(expandedAccordion - 1);
|
||||
}
|
||||
}
|
||||
if (updateTable) {
|
||||
updateTable();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleCloseDeleteDialog = () => {
|
||||
if (!isDeletingGuild) {
|
||||
setDeleteDialogOpen(false);
|
||||
setDeleteDialogIndex(null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleGuildValuesChange = useCallback((index, fieldName, value) => {
|
||||
setGuildsFormValues((prev) => {
|
||||
const newValues = [...prev];
|
||||
if (!newValues[index]) {
|
||||
newValues[index] = getInitialValues(null);
|
||||
}
|
||||
newValues[index] = {
|
||||
...newValues[index],
|
||||
[fieldName]: value,
|
||||
};
|
||||
return newValues;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleAccordionChange = (index) => (event, isExpanded) => {
|
||||
setExpandedAccordion(isExpanded ? index : false);
|
||||
};
|
||||
|
||||
const shouldShowUpdateButton =
|
||||
formik?.values?.national_id &&
|
||||
(isAdmin ||
|
||||
(dbRegister !== false &&
|
||||
(guild ||
|
||||
(!guild &&
|
||||
((dbRegister === true && hasInquiry === false) ||
|
||||
(isAdmin && isInquiryDone))))));
|
||||
|
||||
const shouldShowInquiryForm = !guild && !isInquiryDone;
|
||||
const shouldShowFormContent = guild || isInquiryDone;
|
||||
|
||||
return (
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.TINY}
|
||||
maxHeight="80vh"
|
||||
minWidth={
|
||||
!guild && !isInquiryDone
|
||||
? "auto"
|
||||
: { xs: "96vw", md: "90vw", nlg: "1280px" }
|
||||
}
|
||||
overflow="auto"
|
||||
p={2}
|
||||
>
|
||||
{shouldShowUpdateButton && (
|
||||
<UpdateFromExternalButton
|
||||
onUpdate={handleUpdateFromExternal}
|
||||
disabled={!!formik.errors.national_id}
|
||||
/>
|
||||
)}
|
||||
|
||||
{shouldShowInquiryForm && (
|
||||
<InquiryForm
|
||||
inquiryNationalCode={inquiryNationalCode}
|
||||
setInquiryNationalCode={setInquiryNationalCode}
|
||||
onInquiry={handleInquiry}
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
)}
|
||||
|
||||
{shouldShowFormContent && (
|
||||
<>
|
||||
<Grid container xs={12}>
|
||||
<PersonalInfoSection
|
||||
formik={formik}
|
||||
guild={guild}
|
||||
hasInquiry={hasInquiry}
|
||||
isAdmin={isAdmin}
|
||||
isSuperAdmin={isSuperAdmin}
|
||||
isKillHouse={isKillHouse}
|
||||
/>
|
||||
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
lg={6}
|
||||
pr={{ xs: 0, md: 2 }}
|
||||
pl={{ xs: 0, md: 3 }}
|
||||
>
|
||||
<Grid container gap={SPACING.TINY} direction="column">
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
اطلاعات صنفی
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
{guildsList.map((guildItem, index) => (
|
||||
<Box key={index} sx={{ mb: 2 }}>
|
||||
<GuildInfoAccordionItem
|
||||
guildIndex={index}
|
||||
guildData={guildItem}
|
||||
guildActive={guildActive}
|
||||
isAdmin={isAdmin}
|
||||
cities={cities}
|
||||
typeActivities={typeActivities}
|
||||
onDelete={() => handleDeleteGuild(index)}
|
||||
canDelete={
|
||||
(guildsList.length > 1 || !guild) && isAdmin
|
||||
}
|
||||
guildFormValues={guildsFormValues[index]}
|
||||
onGuildValuesChange={handleGuildValuesChange}
|
||||
expanded={expandedAccordion === index}
|
||||
onChange={handleAccordionChange(index)}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
</Grid>
|
||||
{isAdmin && (
|
||||
<Grid item xs={12} xl={4}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<AddIcon />}
|
||||
onClick={handleAddGuild}
|
||||
fullWidth
|
||||
sx={{ mb: 2 }}
|
||||
>
|
||||
افزودن واحد صنفی
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container item xs={12}>
|
||||
{hasRegisterCode &&
|
||||
(!(!guild && hasInquiry === true) ||
|
||||
isAdmin ||
|
||||
isSuperAdmin ||
|
||||
isKillHouse) && (
|
||||
<ConfirmationDialog
|
||||
isAccepted={formik.values.isAccepted}
|
||||
onAccept={() => formik.setFieldValue("isAccepted", true)}
|
||||
onReject={() => formik.setFieldValue("isAccepted", false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<FormActions
|
||||
formik={formik}
|
||||
onClose={() => dispatch(CLOSE_MODAL())}
|
||||
showCloseButton={
|
||||
!guild &&
|
||||
hasInquiry === true &&
|
||||
!isAdmin &&
|
||||
!isSuperAdmin &&
|
||||
!isKillHouse
|
||||
}
|
||||
isKillHouse={isKillHouse}
|
||||
onSubmit={formik.handleSubmit}
|
||||
/>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
<DeleteConfirmationDialog
|
||||
open={deleteDialogOpen}
|
||||
onClose={handleCloseDeleteDialog}
|
||||
onConfirm={handleConfirmDelete}
|
||||
isDeleting={isDeletingGuild}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Button,
|
||||
Typography,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
} from "@mui/material";
|
||||
import { Grid } from "../../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../../data/spacing";
|
||||
import { DialogAlert } from "../../../../../components/dialog-alert/DialogAlert";
|
||||
import { Done } from "@mui/icons-material";
|
||||
|
||||
export const ConfirmationDialog = ({ isAccepted, onAccept, onReject }) => {
|
||||
return (
|
||||
<Grid item pb={2} mt={2}>
|
||||
<DialogAlert
|
||||
title="تعهد نامه"
|
||||
content={
|
||||
<>
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<Done />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="لطفا صحت اطلاعات وارد شده را بررسی نمایید. پس از تکمیل و ثبت درخواست، یک کد احراز هویت از طریق پیامک برای صنف یا مباشر به شماره تلفن اعلامی ارسال میگردد." />
|
||||
</ListItem>
|
||||
<Typography></Typography>
|
||||
</>
|
||||
}
|
||||
actions={
|
||||
<Grid container gap={SPACING.TINY}>
|
||||
<Button variant="outlined" color="error" onClick={onReject}>
|
||||
رد
|
||||
</Button>
|
||||
<Button variant="contained" color="success" onClick={onAccept}>
|
||||
موافقم
|
||||
</Button>
|
||||
</Grid>
|
||||
}
|
||||
btnTitle="تایید صحت اطلاعات"
|
||||
isAccepted={isAccepted}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
import React from "react";
|
||||
import { Button, Typography, Checkbox, FormControlLabel } from "@mui/material";
|
||||
import { Grid } from "../../../../../components/grid/Grid";
|
||||
|
||||
export const FormActions = ({
|
||||
formik,
|
||||
onClose,
|
||||
showCloseButton,
|
||||
isKillHouse,
|
||||
onSubmit,
|
||||
}) => {
|
||||
if (showCloseButton) {
|
||||
return (
|
||||
<Grid item xs={12} mt={4}>
|
||||
<Button color="primary" fullWidth variant="contained" onClick={onClose}>
|
||||
متوجه شدم
|
||||
</Button>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
// For KillHouse: check if area_activity contains "مرغ"
|
||||
const isAreaActivityValid = isKillHouse
|
||||
? formik.values.area_activity && formik.values.area_activity.includes("مرغ")
|
||||
: true;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid item xs={12}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={formik.values.verify_mobile}
|
||||
onChange={formik.handleChange}
|
||||
name="verify_mobile"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label="احراز شماره موبایل"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Button
|
||||
disabled={
|
||||
formik.errors.isAccepted ||
|
||||
Boolean(formik.errors.national_id) ||
|
||||
!isAreaActivityValid
|
||||
}
|
||||
color="primary"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={onSubmit}
|
||||
type="button"
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
{isKillHouse && !isAreaActivityValid && (
|
||||
<Typography
|
||||
variant="caption"
|
||||
color="error"
|
||||
sx={{ mt: 1, display: "block" }}
|
||||
>
|
||||
رسته واحد صنفی باید شامل کلمه "مرغ" باشد
|
||||
</Typography>
|
||||
)}
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionSummary,
|
||||
AccordionDetails,
|
||||
Typography,
|
||||
IconButton,
|
||||
} from "@mui/material";
|
||||
import {
|
||||
ExpandMore as ExpandMoreIcon,
|
||||
Delete as DeleteIcon,
|
||||
} from "@mui/icons-material";
|
||||
import { GuildInfoSection } from "./GuildInfoSection";
|
||||
|
||||
export const GuildInfoAccordionItem = ({
|
||||
guildIndex,
|
||||
guildData,
|
||||
guildActive,
|
||||
isAdmin,
|
||||
cities,
|
||||
typeActivities,
|
||||
onDelete,
|
||||
canDelete,
|
||||
guildFormValues,
|
||||
onGuildValuesChange,
|
||||
expanded,
|
||||
onChange,
|
||||
}) => {
|
||||
// Create a formik-like object for this guild's values
|
||||
const guildFormik = {
|
||||
values: guildFormValues || {},
|
||||
setFieldValue: (fieldName, value) => {
|
||||
onGuildValuesChange(guildIndex, fieldName, value);
|
||||
},
|
||||
handleChange: (e) => {
|
||||
onGuildValuesChange(guildIndex, e.target.name, e.target.value);
|
||||
},
|
||||
handleBlur: () => {},
|
||||
errors: {},
|
||||
touched: {},
|
||||
};
|
||||
const getGuildTitle = () => {
|
||||
if (guildData?.guildsName) {
|
||||
return guildData.guildsName;
|
||||
}
|
||||
if (guildData?.title) {
|
||||
return guildData.title;
|
||||
}
|
||||
if (guildFormik.values.guild_name) {
|
||||
return guildFormik.values.guild_name;
|
||||
}
|
||||
return `واحد صنفی ${guildIndex + 1}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<Accordion expanded={expanded} onChange={onChange}>
|
||||
<AccordionSummary
|
||||
expandIcon={<ExpandMoreIcon />}
|
||||
sx={{
|
||||
"& .MuiAccordionSummary-content": {
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" sx={{ flexGrow: 1, fontSize: 18 }}>
|
||||
{getGuildTitle()}
|
||||
</Typography>
|
||||
{canDelete && (
|
||||
<IconButton
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onDelete();
|
||||
}}
|
||||
color="error"
|
||||
size="small"
|
||||
sx={{ mr: 1 }}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<GuildInfoSection
|
||||
formik={guildFormik}
|
||||
guild={guildData}
|
||||
guildActive={guildActive}
|
||||
isAdmin={isAdmin}
|
||||
cities={cities}
|
||||
typeActivities={typeActivities}
|
||||
hideTitle={true}
|
||||
noGridWrapper={true}
|
||||
/>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,566 @@
|
||||
import React from "react";
|
||||
import {
|
||||
TextField,
|
||||
Typography,
|
||||
RadioGroup,
|
||||
FormControl,
|
||||
Radio,
|
||||
FormControlLabel,
|
||||
Select,
|
||||
MenuItem,
|
||||
InputLabel,
|
||||
Checkbox,
|
||||
} from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment";
|
||||
import BusinessIcon from "@mui/icons-material/Business";
|
||||
import PublicIcon from "@mui/icons-material/Public";
|
||||
import LocationCityIcon from "@mui/icons-material/LocationCity";
|
||||
import DateRangeIcon from "@mui/icons-material/DateRange";
|
||||
import ConfirmationNumberIcon from "@mui/icons-material/ConfirmationNumber";
|
||||
import AccountBalanceIcon from "@mui/icons-material/AccountBalance";
|
||||
import LocalPostOfficeIcon from "@mui/icons-material/LocalPostOffice";
|
||||
import PhoneIcon from "@mui/icons-material/Phone";
|
||||
import BadgeIcon from "@mui/icons-material/Badge";
|
||||
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
|
||||
import HomeIcon from "@mui/icons-material/Home";
|
||||
import CorporateFareIcon from "@mui/icons-material/CorporateFare";
|
||||
import { Grid } from "../../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../../data/spacing";
|
||||
import { LabelField } from "../../../../../components/label-field/LabelField";
|
||||
import { InfoBox } from "./InfoBox";
|
||||
import { STATUS_VALUES } from "../constants";
|
||||
import {
|
||||
convertPersianToGregorian,
|
||||
convertGregorianToPersian,
|
||||
} from "../utils/dateUtils";
|
||||
|
||||
export const GuildInfoSection = ({
|
||||
formik,
|
||||
guild,
|
||||
guildActive,
|
||||
isAdmin,
|
||||
cities,
|
||||
typeActivities,
|
||||
hideTitle = false,
|
||||
noGridWrapper = false,
|
||||
}) => {
|
||||
const getForeignerDisplay = (isForeigner) => {
|
||||
if (isForeigner === STATUS_VALUES.NO || isForeigner === false)
|
||||
return STATUS_VALUES.NO;
|
||||
if (isForeigner === STATUS_VALUES.YES || isForeigner === true)
|
||||
return STATUS_VALUES.YES;
|
||||
return "-";
|
||||
};
|
||||
|
||||
const getLicenseExpireDateDisplay = () => {
|
||||
return formik.values.license_expire_date || "-";
|
||||
};
|
||||
|
||||
const getActiveStatusDisplay = () => {
|
||||
const activeValue =
|
||||
formik.values.active !== null
|
||||
? formik.values.active
|
||||
: guild?.active === true || guildActive === true;
|
||||
return activeValue === true ? "فعال" : "غیر فعال";
|
||||
};
|
||||
|
||||
const content = (
|
||||
<Grid container gap={SPACING.TINY} direction="column">
|
||||
{!hideTitle && (
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
اطلاعات صنفی
|
||||
</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid container xs={12}>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
xs={12}
|
||||
md={6}
|
||||
px={SPACING.TINY}
|
||||
gap={SPACING.TINY}
|
||||
>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="نام واحد"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="guild_name"
|
||||
name="guild_name"
|
||||
value={formik.values.guild_name}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={BusinessIcon}
|
||||
label="نام واحد"
|
||||
value={formik.values.guild_name}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<FormControl fullWidth>
|
||||
<InputLabel id="area-activity-select-label">
|
||||
رسته واحد صنفی
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="area-activity-select-label"
|
||||
id="area_activity"
|
||||
name="area_activity"
|
||||
value={formik.values.area_activity || ""}
|
||||
label="رسته واحد صنفی"
|
||||
onChange={(e) => {
|
||||
formik.setFieldValue("area_activity", e.target.value);
|
||||
}}
|
||||
onBlur={formik.handleBlur}
|
||||
>
|
||||
{typeActivities.map((activity) => (
|
||||
<MenuItem key={activity.key} value={activity.title}>
|
||||
{activity.title}
|
||||
</MenuItem>
|
||||
))}
|
||||
{/* Show current value if it doesn't exist in options */}
|
||||
{formik.values.area_activity &&
|
||||
!typeActivities.some(
|
||||
(activity) =>
|
||||
activity.title === formik.values.area_activity
|
||||
) && (
|
||||
<MenuItem
|
||||
key="current-value"
|
||||
value={formik.values.area_activity}
|
||||
>
|
||||
{formik.values.area_activity}
|
||||
</MenuItem>
|
||||
)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={BusinessIcon}
|
||||
label="رسته واحد صنفی"
|
||||
value={formik.values.area_activity}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="استان"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="state"
|
||||
name="state"
|
||||
value={formik.values.state}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={PublicIcon}
|
||||
label="استان"
|
||||
value={formik.values.state}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<FormControl fullWidth>
|
||||
<InputLabel id="city-select-label">شهرستان</InputLabel>
|
||||
<Select
|
||||
labelId="city-select-label"
|
||||
id="city"
|
||||
name="city"
|
||||
value={formik.values.city || ""}
|
||||
label="شهرستان"
|
||||
onChange={(e) => {
|
||||
formik.setFieldValue("city", e.target.value);
|
||||
}}
|
||||
onBlur={formik.handleBlur}
|
||||
>
|
||||
{cities.map((city) => (
|
||||
<MenuItem key={city.key} value={city.name}>
|
||||
{city.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
{/* Show current value if it doesn't exist in options */}
|
||||
{formik.values.city &&
|
||||
!cities.some(
|
||||
(city) => city.name === formik.values.city
|
||||
) && (
|
||||
<MenuItem key="current-value" value={formik.values.city}>
|
||||
{formik.values.city}
|
||||
</MenuItem>
|
||||
)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={LocationCityIcon}
|
||||
label="شهرستان"
|
||||
value={formik.values.city}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<DatePicker
|
||||
label="تاریخ انقضا مجوز"
|
||||
value={
|
||||
formik.values.license_expire_date
|
||||
? moment(
|
||||
convertPersianToGregorian(
|
||||
formik.values.license_expire_date
|
||||
)
|
||||
)
|
||||
: null
|
||||
}
|
||||
onChange={(newValue) => {
|
||||
if (newValue) {
|
||||
const gregorianDate = moment(newValue).format("YYYY-MM-DD");
|
||||
const persianDate =
|
||||
convertGregorianToPersian(gregorianDate);
|
||||
formik.setFieldValue("license_expire_date", persianDate);
|
||||
} else {
|
||||
formik.setFieldValue("license_expire_date", "");
|
||||
}
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} fullWidth variant="outlined" />
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={DateRangeIcon}
|
||||
label="تاریخ انقضا مجوز"
|
||||
value={getLicenseExpireDateDisplay()}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="شماره مجوز"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="license_number"
|
||||
name="license_number"
|
||||
value={formik.values.license_number}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={ConfirmationNumberIcon}
|
||||
label="شماره مجوز"
|
||||
value={formik.values.license_number}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="نام اتحادیه"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="union_name"
|
||||
name="union_name"
|
||||
value={formik.values.union_name}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={AccountBalanceIcon}
|
||||
label="نام اتحادیه"
|
||||
value={formik.values.union_name}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<LabelField label="وضعیت">
|
||||
<FormControl fullWidth>
|
||||
<RadioGroup
|
||||
row
|
||||
name="active"
|
||||
value={
|
||||
formik.values.active === true
|
||||
? "true"
|
||||
: formik.values.active === false
|
||||
? "false"
|
||||
: ""
|
||||
}
|
||||
onChange={(e) => {
|
||||
formik.setFieldValue(
|
||||
"active",
|
||||
e.target.value === "true" ? true : false
|
||||
);
|
||||
}}
|
||||
sx={{ justifyContent: "space-around" }}
|
||||
>
|
||||
<FormControlLabel
|
||||
value="true"
|
||||
control={<Radio />}
|
||||
label="فعال"
|
||||
/>
|
||||
<FormControlLabel
|
||||
value="false"
|
||||
control={<Radio />}
|
||||
label="غیر فعال"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</LabelField>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={CheckCircleIcon}
|
||||
label="وضعیت"
|
||||
value={getActiveStatusDisplay()}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
md={6}
|
||||
px={SPACING.TINY}
|
||||
direction="column"
|
||||
gap={SPACING.TINY}
|
||||
>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="کد پستی"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="postal_code"
|
||||
name="postal_code"
|
||||
value={formik.values.postal_code}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={LocalPostOfficeIcon}
|
||||
label="کد پستی"
|
||||
value={formik.values.postal_code}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="شماره تلفن"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="phone_number"
|
||||
name="phone_number"
|
||||
value={formik.values.phone_number}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={PhoneIcon}
|
||||
label="شماره تلفن"
|
||||
value={formik.values.phone_number}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<LabelField label="آیا اتباع است؟">
|
||||
<FormControl fullWidth>
|
||||
<RadioGroup
|
||||
row
|
||||
name="is_foreigner"
|
||||
value={
|
||||
formik.values.is_foreigner === "بلی" ||
|
||||
formik.values.is_foreigner === true
|
||||
? "بلی"
|
||||
: formik.values.is_foreigner === "خیر" ||
|
||||
formik.values.is_foreigner === false
|
||||
? "خیر"
|
||||
: ""
|
||||
}
|
||||
onChange={(e) => {
|
||||
formik.setFieldValue(
|
||||
"is_foreigner",
|
||||
e.target.value === "بلی" ? "بلی" : "خیر"
|
||||
);
|
||||
}}
|
||||
sx={{ justifyContent: "space-around" }}
|
||||
>
|
||||
<FormControlLabel
|
||||
value="بلی"
|
||||
control={<Radio />}
|
||||
label="بلی"
|
||||
/>
|
||||
<FormControlLabel
|
||||
value="خیر"
|
||||
control={<Radio />}
|
||||
label="خیر"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</LabelField>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={PublicIcon}
|
||||
label="آیا اتباع است؟"
|
||||
value={getForeignerDisplay(formik.values.is_foreigner)}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="نام شرکت"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="corporation_name"
|
||||
name="corporation_name"
|
||||
value={formik.values.corporation_name}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={CorporateFareIcon}
|
||||
label="نام شرکت"
|
||||
value={formik.values.corporation_name}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="شناسه ملی شرکت"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="guild_national_id"
|
||||
name="guild_national_id"
|
||||
value={formik.values.guild_national_id}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={BadgeIcon}
|
||||
label="شناسه ملی شرکت"
|
||||
value={formik.values.guild_national_id}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="وضعیت مجوز"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="license_status"
|
||||
name="license_status"
|
||||
value={formik.values.license_status}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={CheckCircleIcon}
|
||||
label="وضعیت مجوز"
|
||||
value={formik.values.license_status}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="آدرس"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
multiline
|
||||
rows={3}
|
||||
id="address"
|
||||
name="address"
|
||||
value={formik.values.address}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={HomeIcon}
|
||||
label="آدرس"
|
||||
value={formik.values.address}
|
||||
iconSx={{ mt: 0.5 }}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} sx={{ display: "flex", mt: 2, pl: 2, mb: 2 }}>
|
||||
{isAdmin ? (
|
||||
<>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={formik.values.steward || false}
|
||||
onChange={(e) =>
|
||||
formik.setFieldValue("steward", e.target.checked)
|
||||
}
|
||||
name="steward"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label="مباشر"
|
||||
/>
|
||||
<FormControlLabel
|
||||
sx={{ ml: 3 }}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={formik.values.guild || false}
|
||||
onChange={(e) =>
|
||||
formik.setFieldValue("guild", e.target.checked)
|
||||
}
|
||||
name="guild"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label="صنف"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<InfoBox
|
||||
icon={CheckCircleIcon}
|
||||
label="مباشر"
|
||||
value={formik.values.steward ? "بلی" : "خیر"}
|
||||
/>
|
||||
<InfoBox
|
||||
icon={CheckCircleIcon}
|
||||
label="صنف"
|
||||
value={formik.values.guild ? "بلی" : "خیر"}
|
||||
sx={{ ml: 3 }}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
if (noGridWrapper) {
|
||||
return <>{content}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid item xs={12} lg={6} pr={{ xs: 0, md: 2 }} pl={{ xs: 0, md: 3 }}>
|
||||
{content}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from "react";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
|
||||
export const InfoBox = ({ icon: Icon, label, value, iconSx }) => (
|
||||
<Box
|
||||
display="flex"
|
||||
alignItems={iconSx ? "flex-start" : "center"}
|
||||
gap={1}
|
||||
px={1.5}
|
||||
py={0.5}
|
||||
bgcolor="#f5f5f5"
|
||||
borderRadius={1}
|
||||
>
|
||||
<Icon color="action" sx={iconSx} />
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{label}
|
||||
</Typography>
|
||||
<Typography variant="body1">{value || "-"}</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import React from "react";
|
||||
import { TextField, Button } from "@mui/material";
|
||||
|
||||
export const InquiryForm = ({
|
||||
inquiryNationalCode,
|
||||
setInquiryNationalCode,
|
||||
onInquiry,
|
||||
isAdmin,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<TextField
|
||||
label="کد ملی برای استعلام"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
value={inquiryNationalCode}
|
||||
onChange={(e) => setInquiryNationalCode(e.target.value)}
|
||||
placeholder={
|
||||
isAdmin ? "کد ملی را وارد کنید" : "کد ملی 10 رقمی را وارد کنید"
|
||||
}
|
||||
inputProps={isAdmin ? {} : { maxLength: 10 }}
|
||||
/>
|
||||
<Button
|
||||
color="primary"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={onInquiry}
|
||||
disabled={!isAdmin && inquiryNationalCode.length !== 10}
|
||||
>
|
||||
استعلام
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,369 @@
|
||||
import React from "react";
|
||||
import {
|
||||
TextField,
|
||||
Typography,
|
||||
RadioGroup,
|
||||
FormControl,
|
||||
Radio,
|
||||
FormControlLabel,
|
||||
} from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment";
|
||||
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 FaceIcon from "@mui/icons-material/Face";
|
||||
import LocationCityIcon from "@mui/icons-material/LocationCity";
|
||||
import FavoriteIcon from "@mui/icons-material/Favorite";
|
||||
import { Grid } from "../../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../../data/spacing";
|
||||
import { LabelField } from "../../../../../components/label-field/LabelField";
|
||||
import { InfoBox } from "./InfoBox";
|
||||
import { GENDER_VALUES, ALIVE_STATUS } from "../constants";
|
||||
import {
|
||||
convertPersianToGregorian,
|
||||
convertGregorianToPersian,
|
||||
} from "../utils/dateUtils";
|
||||
|
||||
export const PersonalInfoSection = ({
|
||||
formik,
|
||||
guild,
|
||||
hasInquiry,
|
||||
isAdmin,
|
||||
isSuperAdmin,
|
||||
isKillHouse,
|
||||
}) => {
|
||||
const getGenderDisplay = (gender) => {
|
||||
if (gender === "True" || gender === true) return GENDER_VALUES.MALE;
|
||||
if (gender === "False" || gender === false) return GENDER_VALUES.FEMALE;
|
||||
return "-";
|
||||
};
|
||||
|
||||
const getAliveStatusDisplay = (isAlive) => {
|
||||
if (isAlive === ALIVE_STATUS.YES || isAlive === true)
|
||||
return ALIVE_STATUS.YES;
|
||||
if (isAlive === ALIVE_STATUS.NO || isAlive === false)
|
||||
return ALIVE_STATUS.NO;
|
||||
return "-";
|
||||
};
|
||||
|
||||
const getBirthDateDisplay = () => {
|
||||
return formik.values.birth_date || "-";
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
lg={6}
|
||||
pl={{ xs: 0, md: 2 }}
|
||||
pr={{ xs: 0, md: 3 }}
|
||||
mb={2}
|
||||
>
|
||||
<Grid container direction="column" gap={SPACING.SMALL}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
اطلاعات شخصی
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container xs={12}>
|
||||
<Grid container xs={12} md={6} gap={SPACING.TINY} px={SPACING.TINY}>
|
||||
<Grid item xs={12}>
|
||||
{guild || isAdmin ? (
|
||||
<TextField
|
||||
label="کد ملی"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="national_id"
|
||||
name="national_id"
|
||||
value={formik.values.national_id}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={Boolean(formik.errors.national_id)}
|
||||
helperText={formik.errors.national_id}
|
||||
inputProps={{ maxLength: 10 }}
|
||||
disabled={!isAdmin || isKillHouse}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={BadgeIcon}
|
||||
label="کد ملی"
|
||||
value={formik.values.national_id}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="نام"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="first_name"
|
||||
name="first_name"
|
||||
value={formik.values.first_name}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={PersonIcon}
|
||||
label="نام"
|
||||
value={formik.values.first_name}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="نام خانوادگی"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="last_name"
|
||||
name="last_name"
|
||||
value={formik.values.last_name}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={PersonIcon}
|
||||
label="نام خانوادگی"
|
||||
value={formik.values.last_name}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="شماره شناسنامه"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="national_code"
|
||||
name="national_code"
|
||||
value={formik.values.national_code}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={BadgeIcon}
|
||||
label="شماره شناسنامه"
|
||||
value={formik.values.national_code}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<LabelField label="در قید حیات">
|
||||
<FormControl fullWidth>
|
||||
<RadioGroup
|
||||
row
|
||||
name="is_alive"
|
||||
value={
|
||||
formik.values.is_alive === "بلی" ||
|
||||
formik.values.is_alive === true
|
||||
? "بلی"
|
||||
: formik.values.is_alive === "خیر" ||
|
||||
formik.values.is_alive === false
|
||||
? "خیر"
|
||||
: ""
|
||||
}
|
||||
onChange={(e) => {
|
||||
formik.setFieldValue(
|
||||
"is_alive",
|
||||
e.target.value === "بلی" ? "بلی" : "خیر"
|
||||
);
|
||||
}}
|
||||
sx={{ justifyContent: "space-around" }}
|
||||
>
|
||||
<FormControlLabel
|
||||
value="بلی"
|
||||
control={<Radio />}
|
||||
label="بلی"
|
||||
/>
|
||||
<FormControlLabel
|
||||
value="خیر"
|
||||
control={<Radio />}
|
||||
label="خیر"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</LabelField>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={FavoriteIcon}
|
||||
label="در قید حیات"
|
||||
value={getAliveStatusDisplay(formik.values.is_alive)}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
md={6}
|
||||
gap={SPACING.TINY}
|
||||
px={SPACING.TINY}
|
||||
mt={{ xs: 1, md: 0 }}
|
||||
>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<DatePicker
|
||||
label="تاریخ تولد"
|
||||
value={
|
||||
formik.values.birth_date
|
||||
? moment(
|
||||
convertPersianToGregorian(formik.values.birth_date)
|
||||
)
|
||||
: null
|
||||
}
|
||||
onChange={(newValue) => {
|
||||
if (newValue) {
|
||||
const gregorianDate =
|
||||
moment(newValue).format("YYYY-MM-DD");
|
||||
const persianDate =
|
||||
convertGregorianToPersian(gregorianDate);
|
||||
formik.setFieldValue("birth_date", persianDate);
|
||||
} else {
|
||||
formik.setFieldValue("birth_date", "");
|
||||
}
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} fullWidth variant="outlined" />
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={CakeIcon}
|
||||
label="تاریخ تولد"
|
||||
value={getBirthDateDisplay()}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="نام پدر"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="father_name"
|
||||
name="father_name"
|
||||
value={formik.values.father_name}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={PersonIcon}
|
||||
label="نام پدر"
|
||||
value={formik.values.father_name}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<LabelField label="جنسیت">
|
||||
<FormControl fullWidth>
|
||||
<RadioGroup
|
||||
row
|
||||
name="gender"
|
||||
value={
|
||||
formik.values.gender === "True" ||
|
||||
formik.values.gender === true
|
||||
? "True"
|
||||
: formik.values.gender === "False" ||
|
||||
formik.values.gender === false
|
||||
? "False"
|
||||
: ""
|
||||
}
|
||||
onChange={(e) => {
|
||||
formik.setFieldValue("gender", e.target.value);
|
||||
}}
|
||||
sx={{ justifyContent: "space-around" }}
|
||||
>
|
||||
<FormControlLabel
|
||||
value="True"
|
||||
control={<Radio />}
|
||||
label="مرد"
|
||||
/>
|
||||
<FormControlLabel
|
||||
value="False"
|
||||
control={<Radio />}
|
||||
label="زن"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</LabelField>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={FaceIcon}
|
||||
label="جنسیت"
|
||||
value={getGenderDisplay(formik.values.gender)}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{isAdmin ? (
|
||||
<TextField
|
||||
label="شهر"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="person_city"
|
||||
name="person_city"
|
||||
value={formik.values.person_city}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<InfoBox
|
||||
icon={LocationCityIcon}
|
||||
label="شهر"
|
||||
value={formik.values.person_city}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12} mt={{ xs: 1, md: 0 }}>
|
||||
{!guild &&
|
||||
hasInquiry &&
|
||||
!isAdmin &&
|
||||
!isSuperAdmin &&
|
||||
!isKillHouse ? (
|
||||
<InfoBox
|
||||
icon={PhoneIcon}
|
||||
label="شماره همراه"
|
||||
value={formik.values.mobile}
|
||||
/>
|
||||
) : isKillHouse &&
|
||||
formik.values.mobile &&
|
||||
/^[0-9]{11}$/.test(formik.values.mobile) ? (
|
||||
<InfoBox
|
||||
icon={PhoneIcon}
|
||||
label="شماره همراه"
|
||||
value={formik.values.mobile}
|
||||
/>
|
||||
) : (
|
||||
<TextField
|
||||
label="شماره همراه"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="mobile"
|
||||
name="mobile"
|
||||
value={formik.values.mobile}
|
||||
onChange={formik.handleChange}
|
||||
error={formik.touched.mobile && Boolean(formik.errors.mobile)}
|
||||
helperText={formik.touched.mobile && formik.errors.mobile}
|
||||
disabled={
|
||||
isKillHouse &&
|
||||
formik.values.mobile &&
|
||||
/^[0-9]{11}$/.test(formik.values.mobile)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
import { Button } from "@mui/material";
|
||||
import { Refresh } from "@mui/icons-material";
|
||||
import { Grid } from "../../../../../components/grid/Grid";
|
||||
|
||||
export const UpdateFromExternalButton = ({ onUpdate, disabled }) => {
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="flex-end">
|
||||
<Button
|
||||
onClick={onUpdate}
|
||||
disabled={disabled}
|
||||
color="primary"
|
||||
size="small"
|
||||
>
|
||||
بروزرسانی از سامانه واحد <Refresh />
|
||||
</Button>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
17
src/features/province/components/create-guilds/constants.js
Normal file
17
src/features/province/components/create-guilds/constants.js
Normal file
@@ -0,0 +1,17 @@
|
||||
export const STATUS_VALUES = {
|
||||
YES: "بلی",
|
||||
NO: "خیر",
|
||||
TRUE: "True",
|
||||
FALSE: "False",
|
||||
};
|
||||
|
||||
export const GENDER_VALUES = {
|
||||
MALE: "مرد",
|
||||
FEMALE: "زن",
|
||||
};
|
||||
|
||||
export const ALIVE_STATUS = {
|
||||
YES: "بلی",
|
||||
NO: "خیر",
|
||||
};
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
import { getRoleFromUrl } from "../../../../../utils/getRoleFromUrl";
|
||||
import { normalizeExternalApiDate, normalizeDatabaseDate } from "./dateUtils";
|
||||
import { formatDateForSubmit } from "./dateUtils";
|
||||
|
||||
export const prepareSubmitData = (
|
||||
values,
|
||||
guild,
|
||||
originalPhoneNumber,
|
||||
hasInquiry
|
||||
) => {
|
||||
const baseData = {
|
||||
national_id: values.national_id,
|
||||
mobile: values.mobile,
|
||||
mobilenumber: values.mobile,
|
||||
steward: !!values.steward,
|
||||
guild: !!values.guild,
|
||||
active_register_code: !!values.verify_mobile,
|
||||
firstName: values.first_name || "",
|
||||
lastName: values.last_name || "",
|
||||
fatherName: values.father_name || "",
|
||||
gender: values.gender || "",
|
||||
identityNo: values.national_code || "",
|
||||
isLive: values.is_alive === "بلی" || values.is_alive === true,
|
||||
birthDate: formatDateForSubmit(
|
||||
values.birth_date || "",
|
||||
hasInquiry === true
|
||||
),
|
||||
city: values.city || "",
|
||||
address: values.address || "",
|
||||
postalcode: values.postal_code || "",
|
||||
licenseNumber: values.license_number || "",
|
||||
licenseExpireDate: formatDateForSubmit(
|
||||
values.license_expire_date || "",
|
||||
hasInquiry === true
|
||||
),
|
||||
licenseIssueDate: formatDateForSubmit(
|
||||
values.license_issue_date || "",
|
||||
hasInquiry === true
|
||||
),
|
||||
licenseType: values.license_type || "",
|
||||
licenseStatus: values.license_status || "",
|
||||
isicname: values.area_activity || "",
|
||||
corporationName: values.corporation_name || "",
|
||||
nationalId: values.guild_national_id || "",
|
||||
unionName: values.union_name || "",
|
||||
phonenumber: values.phone_number || "",
|
||||
hasPartner: values.has_partner === true || values.has_partner === "بلی",
|
||||
isForeigner: values.is_foreigner === true || values.is_foreigner === "بلی",
|
||||
title: values.guild_name || "",
|
||||
role: getRoleFromUrl(),
|
||||
has_inquiry: hasInquiry !== null ? hasInquiry : false,
|
||||
...(values.active !== null && { active: values.active }),
|
||||
};
|
||||
|
||||
if (guild) {
|
||||
baseData.guilds_key = guild.key;
|
||||
if (values.mobile !== originalPhoneNumber) {
|
||||
baseData.mobile = values.mobile;
|
||||
baseData.mobilenumber = values.mobile;
|
||||
}
|
||||
}
|
||||
|
||||
return baseData;
|
||||
};
|
||||
|
||||
export const mapResponseDataToFormFields = (
|
||||
responseData,
|
||||
inquiryNationalCode,
|
||||
formik
|
||||
) => {
|
||||
const isExternalApi = responseData.dbRegister === false;
|
||||
|
||||
// New structure: user is at top level, guilds is an array
|
||||
const userData = responseData.user || {};
|
||||
// For personal info, we use the first guild's data if available, or empty
|
||||
const firstGuild =
|
||||
Array.isArray(responseData.guilds) && responseData.guilds.length > 0
|
||||
? responseData.guilds[0]
|
||||
: {};
|
||||
const guildData = firstGuild || {};
|
||||
const layerTwo = guildData.layerTwo || {};
|
||||
const addressData = firstGuild?.address || guildData.address || {};
|
||||
const provinceData = addressData.province || {};
|
||||
const cityData = addressData.city || {};
|
||||
|
||||
const nationalIdValue = isExternalApi
|
||||
? String(
|
||||
layerTwo.nationalcode || userData.nationalCode || inquiryNationalCode
|
||||
).trim()
|
||||
: String(userData.nationalId || inquiryNationalCode).trim();
|
||||
|
||||
const birthDatePersian = isExternalApi
|
||||
? normalizeExternalApiDate(userData.birthDate || "")
|
||||
: normalizeDatabaseDate(userData.birthday || "");
|
||||
|
||||
const licenseExpireDatePersian = isExternalApi
|
||||
? normalizeExternalApiDate(guildData.licenseExpireDate || "")
|
||||
: normalizeDatabaseDate(firstGuild.licenseExpireDate || "");
|
||||
|
||||
const licenseIssueDatePersian = isExternalApi
|
||||
? normalizeExternalApiDate(layerTwo.licenseIssueDate || "")
|
||||
: normalizeDatabaseDate(responseData.licenseIssueDate || "");
|
||||
|
||||
const genderValue = isExternalApi
|
||||
? userData.gender === true
|
||||
? "True"
|
||||
: userData.gender === false
|
||||
? "False"
|
||||
: ""
|
||||
: userData.gender || "";
|
||||
|
||||
const isAliveValue = isExternalApi
|
||||
? userData.isLive === true
|
||||
? "بلی"
|
||||
: userData.isLive === false
|
||||
? "خیر"
|
||||
: ""
|
||||
: userData.isAlive === false
|
||||
? "خیر"
|
||||
: userData.isAlive === true
|
||||
? "بلی"
|
||||
: "";
|
||||
|
||||
const isForeignerValue = isExternalApi
|
||||
? layerTwo.isForeigner === "خیر"
|
||||
? false
|
||||
: layerTwo.isForeigner === "بلی"
|
||||
? true
|
||||
: ""
|
||||
: responseData.isForeignNational === false
|
||||
? false
|
||||
: responseData.isForeignNational === true
|
||||
? true
|
||||
: "";
|
||||
|
||||
const hasStewardValue = isExternalApi
|
||||
? layerTwo.hasSteward === "خیر"
|
||||
? false
|
||||
: layerTwo.hasSteward === "بلی"
|
||||
? true
|
||||
: ""
|
||||
: responseData.steward === false
|
||||
? false
|
||||
: responseData.steward === true
|
||||
? true
|
||||
: "";
|
||||
|
||||
const hasPartnerValue = isExternalApi
|
||||
? layerTwo.hasPartner === "خیر"
|
||||
? false
|
||||
: layerTwo.hasPartner === "بلی"
|
||||
? true
|
||||
: ""
|
||||
: responseData.hasPartner === false
|
||||
? false
|
||||
: responseData.hasPartner === true
|
||||
? true
|
||||
: "";
|
||||
|
||||
const values = {
|
||||
first_name: userData.firstName || "",
|
||||
last_name: userData.lastName || "",
|
||||
national_id: nationalIdValue,
|
||||
national_code: isExternalApi
|
||||
? userData.identityNo || ""
|
||||
: userData.nationalCode || "",
|
||||
birth_date: birthDatePersian,
|
||||
father_name: userData.fatherName || "",
|
||||
gender: genderValue,
|
||||
person_city: userData.city || "",
|
||||
is_alive: isAliveValue,
|
||||
// Guild fields - will be set per guild in accordion, so we set empty or first guild's data
|
||||
guild_name: isExternalApi
|
||||
? guildData.title || ""
|
||||
: firstGuild.guildsName || "",
|
||||
area_activity: isExternalApi
|
||||
? guildData.isicname || ""
|
||||
: firstGuild.areaActivity || "",
|
||||
state: isExternalApi ? guildData.state || "" : provinceData.name || "",
|
||||
city: isExternalApi ? guildData.city || "" : cityData.name || "",
|
||||
address: isExternalApi
|
||||
? guildData.address || ""
|
||||
: addressData.address || "",
|
||||
license_expire_date: licenseExpireDatePersian,
|
||||
license_status: isExternalApi
|
||||
? guildData.licenseStatus || ""
|
||||
: firstGuild.licenseStatus || "",
|
||||
license_type: isExternalApi
|
||||
? guildData.licenseType || ""
|
||||
: firstGuild.licenseType || "",
|
||||
license_number: isExternalApi
|
||||
? guildData.licenseNumber || ""
|
||||
: firstGuild.licenseNumber || "",
|
||||
union_name: isExternalApi
|
||||
? layerTwo.unionName || ""
|
||||
: firstGuild.unionName || "",
|
||||
postal_code: isExternalApi
|
||||
? layerTwo.postalcode || ""
|
||||
: addressData.postalCode || "",
|
||||
phone_number: isExternalApi
|
||||
? layerTwo.phonenumber || ""
|
||||
: firstGuild.phoneNumber || "",
|
||||
mobile: isExternalApi ? layerTwo.mobilenumber || "" : userData.mobile || "",
|
||||
guild_national_id: isExternalApi
|
||||
? layerTwo.nationalId || ""
|
||||
: firstGuild.nationalCode || "",
|
||||
is_foreigner: isForeignerValue,
|
||||
corporation_name: isExternalApi
|
||||
? layerTwo.corporationName || ""
|
||||
: firstGuild.companyName || "",
|
||||
has_steward: hasStewardValue,
|
||||
has_partner: hasPartnerValue,
|
||||
steward: isExternalApi ? false : firstGuild.isSteward || false,
|
||||
guild: isExternalApi
|
||||
? typeof guildData.guild === "boolean"
|
||||
? guildData.guild
|
||||
: false
|
||||
: typeof firstGuild.guild === "boolean"
|
||||
? firstGuild.guild
|
||||
: false,
|
||||
license_issue_date: licenseIssueDatePersian,
|
||||
...(isExternalApi
|
||||
? {}
|
||||
: {
|
||||
company_name: firstGuild.companyName || "",
|
||||
company_identifier: firstGuild.companyIdentifier || "",
|
||||
type_activity_name: firstGuild.typeActivity || "",
|
||||
}),
|
||||
};
|
||||
|
||||
formik.setValues({ ...formik.values, ...values });
|
||||
};
|
||||
@@ -0,0 +1,158 @@
|
||||
import {
|
||||
convertToIranianTime,
|
||||
convertPersianToEnglishNumerals,
|
||||
} from "../../../../../utils/formatTime";
|
||||
import { fromJalali } from "../../../../../utils/jalali";
|
||||
|
||||
export const convertGregorianToPersian = (gregorianDateString) => {
|
||||
if (!gregorianDateString || typeof gregorianDateString !== "string") {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Check if the date is already in Persian format (YYYY/MM/DD with year < 1500)
|
||||
const persianPattern = /^\d{4}\/\d{2}\/\d{2}$/;
|
||||
if (persianPattern.test(gregorianDateString)) {
|
||||
const year = parseInt(gregorianDateString.split("/")[0]);
|
||||
// If year is < 1500, it's likely Persian, return as is
|
||||
if (year < 1500) {
|
||||
return gregorianDateString;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to convert using convertToIranianTime
|
||||
try {
|
||||
return convertToIranianTime(gregorianDateString);
|
||||
} catch (error) {
|
||||
console.error("Error converting Gregorian date to Persian:", error);
|
||||
return gregorianDateString; // Return original on error
|
||||
}
|
||||
};
|
||||
|
||||
export const convertPersianToGregorian = (persianDateString) => {
|
||||
if (!persianDateString || typeof persianDateString !== "string") {
|
||||
return "";
|
||||
}
|
||||
|
||||
const normalizedDateString =
|
||||
convertPersianToEnglishNumerals(persianDateString);
|
||||
|
||||
const gregorianPattern = /^\d{4}[-/]\d{2}[-/]\d{2}$/;
|
||||
if (gregorianPattern.test(normalizedDateString)) {
|
||||
const year = parseInt(normalizedDateString.split(/[-/]/)[0]);
|
||||
if (year > 1500) {
|
||||
return normalizedDateString.replace(/\//g, "-");
|
||||
}
|
||||
}
|
||||
|
||||
const parts = normalizedDateString.split("/");
|
||||
if (parts.length !== 3) {
|
||||
return persianDateString;
|
||||
}
|
||||
|
||||
const py = parseInt(parts[0]);
|
||||
const pm = parseInt(parts[1]);
|
||||
const pd = parseInt(parts[2]);
|
||||
|
||||
if (isNaN(py) || isNaN(pm) || isNaN(pd)) {
|
||||
return persianDateString;
|
||||
}
|
||||
|
||||
try {
|
||||
const gregorianDate = fromJalali(py, pm, pd);
|
||||
const year = gregorianDate.getFullYear();
|
||||
const month = String(gregorianDate.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(gregorianDate.getDate()).padStart(2, "0");
|
||||
return `${year}-${month}-${day}`;
|
||||
} catch (error) {
|
||||
console.error("Error converting Persian date to Gregorian:", error);
|
||||
return persianDateString;
|
||||
}
|
||||
};
|
||||
|
||||
export const normalizeExternalApiDate = (dateString) => {
|
||||
if (!dateString || typeof dateString !== "string") {
|
||||
return "";
|
||||
}
|
||||
return convertPersianToEnglishNumerals(dateString);
|
||||
};
|
||||
|
||||
export const normalizeDatabaseDate = (dateString) => {
|
||||
if (!dateString || typeof dateString !== "string") {
|
||||
return "";
|
||||
}
|
||||
const first10Chars = dateString.substring(0, 10);
|
||||
const normalizedDate = first10Chars.replace(/-/g, "/");
|
||||
return convertToIranianTime(normalizedDate);
|
||||
};
|
||||
|
||||
export const formatDateForSubmitExternal = (dateString) => {
|
||||
if (!dateString || typeof dateString !== "string") {
|
||||
return "";
|
||||
}
|
||||
return convertPersianToEnglishNumerals(dateString);
|
||||
};
|
||||
|
||||
export const formatDateForSubmitDatabase = (dateString) => {
|
||||
if (!dateString || typeof dateString !== "string") {
|
||||
return "";
|
||||
}
|
||||
|
||||
const normalizedDate = convertPersianToEnglishNumerals(dateString);
|
||||
const persianPattern = /^\d{4}\/\d{2}\/\d{2}$/;
|
||||
|
||||
if (persianPattern.test(normalizedDate)) {
|
||||
const year = parseInt(normalizedDate.split("/")[0]);
|
||||
if (year < 1500) {
|
||||
const parts = normalizedDate.split("/");
|
||||
const py = parseInt(parts[0]);
|
||||
const pm = parseInt(parts[1]);
|
||||
const pd = parseInt(parts[2]);
|
||||
|
||||
if (!isNaN(py) && !isNaN(pm) && !isNaN(pd)) {
|
||||
try {
|
||||
const gregorianDate = fromJalali(py, pm, pd);
|
||||
const gy = gregorianDate.getFullYear();
|
||||
const gm = String(gregorianDate.getMonth() + 1).padStart(2, "0");
|
||||
const gd = String(gregorianDate.getDate()).padStart(2, "0");
|
||||
return `${gy}/${gm}/${gd}`;
|
||||
} catch (error) {
|
||||
console.error("Error converting Persian to Gregorian:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const gregorianPattern = /^\d{4}[-/]\d{2}[-/]\d{2}$/;
|
||||
if (gregorianPattern.test(normalizedDate)) {
|
||||
const year = parseInt(normalizedDate.split(/[-/]/)[0]);
|
||||
if (year > 1900) {
|
||||
return normalizedDate.replace(/-/g, "/");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const date = new Date(normalizedDate);
|
||||
if (!isNaN(date.getTime())) {
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
return `${year}/${month}/${day}`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error formatting database date:", error);
|
||||
}
|
||||
|
||||
return normalizedDate.replace(/-/g, "/");
|
||||
};
|
||||
|
||||
export const formatDateForSubmit = (dateString, isExternalApi = false) => {
|
||||
if (!dateString || typeof dateString !== "string") {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (isExternalApi) {
|
||||
return formatDateForSubmitExternal(dateString);
|
||||
} else {
|
||||
return formatDateForSubmitDatabase(dateString);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
import * as yup from "yup";
|
||||
import { normalizeDatabaseDate } from "./dateUtils";
|
||||
|
||||
export const getValidationSchema = (isEditMode) =>
|
||||
yup.object({
|
||||
national_id: yup
|
||||
.string()
|
||||
.required("کد ملی الزامی است")
|
||||
.matches(/^[0-9]{10}$/, "کد ملی باید 10 رقم باشد"),
|
||||
mobile: isEditMode
|
||||
? yup
|
||||
.string()
|
||||
.nullable()
|
||||
.test(
|
||||
"mobile-format",
|
||||
"شماره تلفن باید 11 رقم باشد",
|
||||
(value) => !value || /^[0-9]{11}$/.test(value)
|
||||
)
|
||||
: yup
|
||||
.string()
|
||||
.required("شماره تلفن الزامی است")
|
||||
.matches(/^[0-9]{11}$/, "شماره تلفن باید 11 رقم باشد"),
|
||||
first_name: yup.string(),
|
||||
last_name: yup.string(),
|
||||
guild_name: yup.string(),
|
||||
guild_category: yup.string(),
|
||||
state: yup.string(),
|
||||
city: yup.string(),
|
||||
address: yup.string(),
|
||||
license_expire_date: yup.string(),
|
||||
license_status: yup.string(),
|
||||
union_name: yup.string(),
|
||||
postal_code: yup.string(),
|
||||
guild_national_id: yup.string(),
|
||||
is_foreigner: yup.string(),
|
||||
national_code: yup.string(),
|
||||
has_steward: yup.string(),
|
||||
has_partner: yup.string(),
|
||||
license_number: yup.string(),
|
||||
isAccepted: yup
|
||||
.boolean()
|
||||
.test("req", "باید تعهد نامه را بپذیرید!", (val) => {
|
||||
return val === true;
|
||||
})
|
||||
.required("این فیلد اجباری است!"),
|
||||
});
|
||||
|
||||
export const getInitialValues = (guild) => ({
|
||||
first_name: guild?.user?.firstName || "",
|
||||
last_name: guild?.user?.lastName || "",
|
||||
corporation_name: guild?.companyName || "",
|
||||
national_id: guild?.user?.nationalId || "",
|
||||
national_code: guild?.user?.nationalCode || "",
|
||||
birth_date: normalizeDatabaseDate(guild?.user?.birthday || ""),
|
||||
father_name: guild?.user?.fatherName || "",
|
||||
gender: guild?.user?.gender || "",
|
||||
person_city: guild?.user?.city || "",
|
||||
is_alive: guild?.user?.isAlive || "",
|
||||
guild_name: guild?.guildsName || "",
|
||||
area_activity: guild?.areaActivity || "",
|
||||
state: guild?.address?.province?.name || "",
|
||||
city: guild?.address?.city?.name || "",
|
||||
address: guild?.address?.address || "",
|
||||
license_expire_date: normalizeDatabaseDate(guild?.licenseExpireDate || ""),
|
||||
license_status: guild?.licenseStatus || "",
|
||||
license_type: guild?.licenseType || "",
|
||||
union_name: guild?.unionName || "",
|
||||
postal_code: guild?.address?.postalCode || "",
|
||||
phone_number: guild?.phoneNumber || "",
|
||||
mobile: guild?.user?.mobile || "",
|
||||
is_foreigner: guild?.is_foreign_national || "",
|
||||
has_steward: guild?.hasSteward || "",
|
||||
has_partner: guild?.hasPartner || "",
|
||||
license_number: guild?.licenseNumber || "",
|
||||
isAccepted: guild?.provinceAcceptState === "accepted" || false,
|
||||
steward:
|
||||
typeof guild?.steward === "boolean"
|
||||
? guild.steward
|
||||
: typeof guild?.isSteward === "boolean"
|
||||
? guild.isSteward
|
||||
: false,
|
||||
guild:
|
||||
typeof guild?.guild === "boolean"
|
||||
? guild.guild
|
||||
: typeof guild?.isGuild === "boolean"
|
||||
? guild.isGuild
|
||||
: false,
|
||||
verify_mobile: guild?.verifyMobile || false,
|
||||
guild_national_id: guild?.nationalId || "",
|
||||
license_issue_date: normalizeDatabaseDate(guild?.licenseIssueDate || ""),
|
||||
company_name: guild?.companyName || "",
|
||||
company_identifier: guild?.companyIdentifier || "",
|
||||
type_activity_name: guild?.typeActivityName || "",
|
||||
active: guild?.active ?? null,
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
import {
|
||||
CLOSE_MODAL,
|
||||
OPEN_MODAL,
|
||||
} from "../../../../../lib/redux/slices/appSlice";
|
||||
import { ProvinceManageGuildsSubmitRegisterCode } from "../../province-manage-guilds-submit-register-code/ProvinceManageGuildsSubmitRegisterCode";
|
||||
|
||||
export const handleSubmitSuccess = (
|
||||
dispatch,
|
||||
openNotif,
|
||||
updateTable,
|
||||
values,
|
||||
responseData
|
||||
) => {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
dispatch(CLOSE_MODAL());
|
||||
|
||||
if (values.verify_mobile && responseData) {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ثبت کد احراز",
|
||||
content: (
|
||||
<ProvinceManageGuildsSubmitRegisterCode
|
||||
item={responseData}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const handleSubmitError = (openNotif, error) => {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: error,
|
||||
severity: "error",
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
import { Autocomplete, Button, TextField } from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { useContext, useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import * as yup from "yup";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { provinceCreateStewardService } from "../../services/province-create-steward";
|
||||
import { provinceGetGuildsService } from "../../services/province-get-guilds";
|
||||
|
||||
const validationSchema = yup.object({
|
||||
// guild: yup.string().required(""),
|
||||
});
|
||||
|
||||
export const CreateStewards = ({ guild }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const { provinceGetGuildsOptions } = useSelector(
|
||||
(state) => state.provinceSlice
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetGuildsService());
|
||||
}, []);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
guild: null,
|
||||
},
|
||||
validationSchema,
|
||||
onSubmit: (values) => {
|
||||
// Handle form submission here
|
||||
dispatch(
|
||||
provinceCreateStewardService({ guilds_key: values.guild.value })
|
||||
).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 }));
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
<Grid container gap={SPACING.TINY}>
|
||||
<Autocomplete
|
||||
style={{ width: "100%" }}
|
||||
options={provinceGetGuildsOptions}
|
||||
value={formik.values.guild}
|
||||
onChange={(e, v) => {
|
||||
formik.setFieldValue("guild", v);
|
||||
}}
|
||||
error={formik.touched.guild && Boolean(formik.errors.guild)}
|
||||
helperText={formik.touched.guild && formik.errors.guild}
|
||||
getOptionLabel={(option) => option.label}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="انتخاب صنف" variant="outlined" />
|
||||
)}
|
||||
/>
|
||||
<Button color="primary" fullWidth variant="contained" type="submit">
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Autocomplete, Button, TextField } from "@mui/material";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { getCitiesService } from "../../services/get-cities";
|
||||
import { provinceEditPoultryCityService } from "../../services/province-edit-poultry-city";
|
||||
|
||||
export const EditPoultryCity = ({ item, updateTable }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [sellected, setSellected] = useState();
|
||||
const { getCitiesOptions } = useSelector((state) => state.provinceSlice);
|
||||
const getOptionLabel = (option) => option.label; // Customize how the label is displayed
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getCitiesService());
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Grid container gap={1} width="100%">
|
||||
<Autocomplete
|
||||
options={getCitiesOptions}
|
||||
getOptionLabel={getOptionLabel}
|
||||
sx={{ width: "100%" }}
|
||||
onChange={(event, value) => setSellected(value)}
|
||||
value={sellected}
|
||||
renderInput={(params) => <TextField {...params} label="تعاونی" />}
|
||||
/>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
if (sellected) {
|
||||
dispatch(
|
||||
provinceEditPoultryCityService({
|
||||
key: item.key,
|
||||
city_operator: sellected.value,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(CLOSE_MODAL());
|
||||
updateTable();
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
167
src/features/province/components/edit-stewards/EditStewards.js
Normal file
167
src/features/province/components/edit-stewards/EditStewards.js
Normal file
@@ -0,0 +1,167 @@
|
||||
import {
|
||||
Autocomplete,
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
InputAdornment,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { provinceEditStewardService } from "../../services/province-edit-steward";
|
||||
import { provinceGetBuyersService } from "../../services/province-get-buyers";
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
// agreed: Yup.boolean().oneOf([true], 'You must agree to the terms and conditions'),
|
||||
});
|
||||
|
||||
export const EditStewards = ({ guild }) => {
|
||||
const { provinceGetBuyersOptions } = useSelector(
|
||||
(state) => state.provinceSlice
|
||||
);
|
||||
const [warehouses, setWarehouses] = useState(
|
||||
guild.centersAllocation ? guild.centersAllocation : []
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
allocation_limit: guild.allocationLimit,
|
||||
centers_allocation: "",
|
||||
limitation_allocation: guild.limitationAllocation,
|
||||
},
|
||||
validationSchema,
|
||||
onSubmit: (values) => {
|
||||
dispatch(
|
||||
provinceEditStewardService({
|
||||
allocation_limit: values.allocation_limit,
|
||||
limitation_allocation: values.limitation_allocation,
|
||||
centers_allocation: warehouses,
|
||||
steward_key: guild.key,
|
||||
})
|
||||
).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 }));
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetBuyersService());
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<form onSubmit={formik.handleSubmit} style={{ width: "100%" }}>
|
||||
<Grid container direction="column" width="100%" gap={SPACING.SMALL}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
name="limitation_allocation"
|
||||
checked={formik.values.limitation_allocation}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
}
|
||||
label="محدودیت تخصیص"
|
||||
/>
|
||||
{formik.errors.limitation_allocation && (
|
||||
<div>{formik.errors.limitation_allocation}</div>
|
||||
)}
|
||||
{formik.values.limitation_allocation && (
|
||||
<>
|
||||
<TextField
|
||||
label="حداکثر تخصیص"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="allocation_limit"
|
||||
name="allocation_limit"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="start">کیلوگرم</InputAdornment>
|
||||
),
|
||||
}}
|
||||
value={formik.values.allocation_limit}
|
||||
onChange={formik.handleChange}
|
||||
error={
|
||||
formik.touched.allocation_limit &&
|
||||
Boolean(formik.errors.allocation_limit)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.allocation_limit &&
|
||||
formik.errors.allocation_limit
|
||||
}
|
||||
/>
|
||||
<Autocomplete
|
||||
style={{ width: "100%" }}
|
||||
options={provinceGetBuyersOptions}
|
||||
value={formik.values.guild}
|
||||
onChange={(e, item) => {
|
||||
setWarehouses([...warehouses, item]);
|
||||
}}
|
||||
error={formik.touched.guild && Boolean(formik.errors.guild)}
|
||||
helperText={formik.touched.guild && formik.errors.guild}
|
||||
getOptionLabel={(option) => option.label}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label="انتخاب انبار"
|
||||
variant="outlined"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Typography>محدودیت انبار های انتخاب شده</Typography>
|
||||
{!warehouses.length && (
|
||||
<Typography variant="caption">محدودیتی وجود ندارد</Typography>
|
||||
)}
|
||||
{warehouses?.map((item, i) => {
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
key={item.value}
|
||||
alignItems="center"
|
||||
>
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={() => {
|
||||
setWarehouses(
|
||||
warehouses.filter((it) => it.value !== item.value)
|
||||
);
|
||||
}}
|
||||
>
|
||||
حذف
|
||||
</Button>
|
||||
<Typography key={item.label}>{item.label}</Typography>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
|
||||
<Button color="primary" fullWidth variant="contained" type="submit">
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,311 @@
|
||||
import {
|
||||
Button,
|
||||
Pagination,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import axios from "axios";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { PageTable } from "../../../../components/page-table/PageTable";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment/moment";
|
||||
import { format } from "date-fns-jalali";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const FailedTransactions = () => {
|
||||
const authToken = useSelector((state) => state.userSlice.authToken);
|
||||
console.log(authToken);
|
||||
const userInfo = useSelector((state) => state.userSlice);
|
||||
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
const [dataTableM, setDataTableM] = useState([]);
|
||||
const dispatch = useDispatch();
|
||||
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);
|
||||
const response = await axios.get(
|
||||
`transactions/?search=filter&value=${textValue}&page=${page}&page_size=${perPage}&date1=${selectedDate1}&date2=${selectedDate2}&state=failed&role=${getRoleFromUrl()}`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page, textValue);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = async (newPerPage, page) => {
|
||||
setLoading(true);
|
||||
const response = await axios.get(
|
||||
`transactions/?search=filter&value=${textValue}&page=${page}&page_size=${newPerPage}&date1=${selectedDate1}&date2=${selectedDate2}&state=failed&role=${getRoleFromUrl()}`
|
||||
);
|
||||
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
setPerPage(newPerPage);
|
||||
|
||||
setLoading(false);
|
||||
dispatch(LOADING_END());
|
||||
};
|
||||
|
||||
const [page, setPage] = useState(0);
|
||||
const handleChangePageM = (event, newPage) => {
|
||||
dispatch(LOADING_START());
|
||||
setPage(newPage);
|
||||
fetchApiData(newPage + 1, textValue);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, [selectedDate1, selectedDate2, perPage]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`transactions/?search=filter&value=${textValue}&date1=${selectedDate1}&date2=${selectedDate2}&state=failed&role=${getRoleFromUrl()}`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: "تاریخ و زمان",
|
||||
selector: (item) => {
|
||||
return format(new Date(item.createDate), "yyyy/MM/dd hh:mm:ss");
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "پرداخت کننده",
|
||||
selector: (item) => {
|
||||
return item.payer;
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "شماره درخواست",
|
||||
selector: (item) => {
|
||||
return item.orderId;
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "شماره پیگیری",
|
||||
selector: (item) => {
|
||||
return item.saleReferenceId;
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "کدسفارش",
|
||||
selector: (item) => {
|
||||
return item.orderId;
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "شماره کارت",
|
||||
selector: (item) => {
|
||||
return item.cardHolderPan;
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "قیمت",
|
||||
selector: (item) => {
|
||||
return item?.amount?.toLocaleString() + " ﷼";
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "متن خطا",
|
||||
selector: (item) => {
|
||||
return item.message?.split("_")?.join(" ");
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
];
|
||||
|
||||
const tableTitle = (
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
gap={2}
|
||||
paddingTop={2}
|
||||
mb={1}
|
||||
width="100%"
|
||||
>
|
||||
<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"
|
||||
autoComplete="off"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button
|
||||
// disabled={!textValue}
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
endIcon={<RiSearchLine />}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
</form>
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<a
|
||||
href={`${axios.defaults.baseURL}unsuccessful_transactions_excel/?date1=${selectedDate1}&date2=${selectedDate2}&key=${userInfo?.userProfile?.key}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
const columnNames = columns.map((column) => column.name);
|
||||
const isMobile = window.innerWidth <= 600;
|
||||
|
||||
useEffect(() => {
|
||||
const d = data?.map((item) => {
|
||||
return [
|
||||
format(new Date(item.createDate), "yyyy/MM/dd hh:mm:ss"),
|
||||
item.payerInfo,
|
||||
item.refId,
|
||||
item.message?.split("_")?.join(" "),
|
||||
];
|
||||
});
|
||||
|
||||
setDataTableM(d);
|
||||
}, [data]);
|
||||
|
||||
return (
|
||||
<Grid container justifyContent="center" gap={SPACING.SMALL}>
|
||||
{isMobile ? (
|
||||
<>
|
||||
{tableTitle}
|
||||
<SimpleTable columns={columnNames} data={dataTableM} />
|
||||
<Pagination
|
||||
count={Math.ceil(totalRows / 10)}
|
||||
page={page + 1}
|
||||
variant="outlined"
|
||||
onChange={(event, newPage) => {
|
||||
handleChangePageM(event, newPage - 1);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<PageTable
|
||||
title={tableTitle}
|
||||
columns={columns}
|
||||
data={data}
|
||||
progressPending={loading}
|
||||
pagination
|
||||
paginationServer
|
||||
paginationTotalRows={totalRows}
|
||||
onChangeRowsPerPage={handlePerRowsChange}
|
||||
onChangePage={handlePageChange}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,257 @@
|
||||
import {
|
||||
Autocomplete,
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
InputAdornment,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { provinceChangeActiveGuildService } from "../../services/province-change-active-guild";
|
||||
import { provinceGetBuyersService } from "../../services/province-get-buyers";
|
||||
import { provinceGetStewardsService } from "../../services/province-get-stewards";
|
||||
import { checkPathStartsWith } from "../../../../utils/checkPathStartsWith";
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
// agreed: Yup.boolean().oneOf([true], 'You must agree to the terms and conditions'),
|
||||
});
|
||||
|
||||
export const GuildLimitaion = ({ guild, updateTable }) => {
|
||||
const { provinceGetStewardsOptions, provinceGetBuyersOptions } = useSelector(
|
||||
(state) => state.provinceSlice
|
||||
);
|
||||
const selectedSubUser = useSelector(
|
||||
(state) => state.userSlice.selectedSubUser
|
||||
);
|
||||
const [warehouses, setWarehouses] = useState(
|
||||
guild.centersAllocation ? guild.centersAllocation : []
|
||||
);
|
||||
const [buyers, setBuyers] = useState(
|
||||
guild.killHouseCentersAllocation ? guild.killHouseCentersAllocation : []
|
||||
);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
allocation_limit: guild.allocationLimit,
|
||||
centers_allocation: "",
|
||||
limitation_allocation: guild.limitationAllocation,
|
||||
currentBuyer: "",
|
||||
},
|
||||
validationSchema,
|
||||
onSubmit: (values) => {
|
||||
dispatch(
|
||||
provinceChangeActiveGuildService({
|
||||
kill_house_centers_allocation: buyers,
|
||||
allocation_limit: values.allocation_limit,
|
||||
limitation_allocation: values.limitation_allocation,
|
||||
centers_allocation: warehouses,
|
||||
guilds_key: guild.key,
|
||||
})
|
||||
).then((r) => {
|
||||
updateTable();
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(DRAWER({ right: false, bottom: false, content: null }));
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
provinceGetStewardsService({
|
||||
role_key: checkPathStartsWith("province")
|
||||
? selectedSubUser?.key || ""
|
||||
: "",
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
provinceGetBuyersService({
|
||||
role_key: checkPathStartsWith("province")
|
||||
? selectedSubUser?.key || ""
|
||||
: "",
|
||||
})
|
||||
);
|
||||
}, [selectedSubUser?.key]);
|
||||
|
||||
return (
|
||||
<form onSubmit={formik.handleSubmit} style={{ width: "100%" }}>
|
||||
<Grid container direction="column" width="100%" gap={SPACING.SMALL}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
name="limitation_allocation"
|
||||
checked={formik.values.limitation_allocation}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
}
|
||||
label="محدودیت تخصیص"
|
||||
/>
|
||||
{formik.errors.limitation_allocation && (
|
||||
<div>{formik.errors.limitation_allocation}</div>
|
||||
)}
|
||||
{formik.values.limitation_allocation && (
|
||||
<>
|
||||
<TextField
|
||||
label="حداکثر تخصیص"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
id="allocation_limit"
|
||||
name="allocation_limit"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="start">کیلوگرم</InputAdornment>
|
||||
),
|
||||
}}
|
||||
value={formik.values.allocation_limit}
|
||||
onChange={formik.handleChange}
|
||||
error={
|
||||
formik.touched.allocation_limit &&
|
||||
Boolean(formik.errors.allocation_limit)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.allocation_limit &&
|
||||
formik.errors.allocation_limit
|
||||
}
|
||||
/>
|
||||
{!guild?.steward && getRoleFromUrl() !== "Guilds" && (
|
||||
<>
|
||||
<Autocomplete
|
||||
style={{ width: "100%" }}
|
||||
options={provinceGetStewardsOptions}
|
||||
value={formik.values.guild}
|
||||
onChange={(e, item) => {
|
||||
setWarehouses([...warehouses, item]);
|
||||
}}
|
||||
error={formik.touched.guild && Boolean(formik.errors.guild)}
|
||||
helperText={formik.touched.guild && formik.errors.guild}
|
||||
getOptionLabel={(option) => option.label}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label="انتخاب مباشر"
|
||||
variant="outlined"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Typography>محدودیت مباشرین انتخاب شده</Typography>
|
||||
{!warehouses.length && (
|
||||
<Typography variant="caption">محدودیتی وجود ندارد</Typography>
|
||||
)}
|
||||
{warehouses?.map((item) => {
|
||||
return (
|
||||
<>
|
||||
{item !== null && (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
key={item.value}
|
||||
alignItems="center"
|
||||
>
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={() => {
|
||||
setWarehouses(
|
||||
warehouses.filter(
|
||||
(it) => it.value !== item.value
|
||||
)
|
||||
);
|
||||
}}
|
||||
>
|
||||
حذف
|
||||
</Button>
|
||||
<Typography key={item.label}>{item.label}</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{formik.values.limitation_allocation &&
|
||||
getRoleFromUrl() !== "KillHouse" &&
|
||||
getRoleFromUrl() !== "Guilds" && (
|
||||
<>
|
||||
<Autocomplete
|
||||
style={{ width: "100%" }}
|
||||
options={provinceGetBuyersOptions}
|
||||
value={formik.values.guild}
|
||||
onChange={(e, item) => {
|
||||
setBuyers([...buyers, item]);
|
||||
}}
|
||||
error={formik.touched.guild && Boolean(formik.errors.guild)}
|
||||
helperText={formik.touched.guild && formik.errors.guild}
|
||||
getOptionLabel={(option) => option.label}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label="انتخاب انبار"
|
||||
variant="outlined"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Typography>محدودیت انبار های انتخاب شده</Typography>
|
||||
{!buyers.length && (
|
||||
<Typography variant="caption">محدودیتی وجود ندارد</Typography>
|
||||
)}
|
||||
{buyers?.map((item) => {
|
||||
return (
|
||||
<>
|
||||
{item !== null && (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
key={item.value}
|
||||
alignItems="center"
|
||||
>
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={() => {
|
||||
setBuyers(
|
||||
buyers.filter((it) => it.value !== item.value)
|
||||
);
|
||||
}}
|
||||
>
|
||||
حذف
|
||||
</Button>
|
||||
<Typography key={item.label}>{item.label}</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
<Button color="primary" fullWidth variant="contained" type="submit">
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,237 @@
|
||||
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_ADMINX_ROUTE_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_IN_PROVINCE_GUILDS_REQUESTS,
|
||||
ROUTE_ADMINX_ROUTE_IN_PROVINCE_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_MANAGE_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_OUT_PROVINCE_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_IN_PROVINCE_GUILDS_REQUESTS,
|
||||
ROUTE_PROVINCE_ROUTE_IN_PROVINCE_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_MANAGE_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_OUT_PROVINCE_GUILDS,
|
||||
// ROUTE_SUPER_ADMIN_ROUTE_GUILDS,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_GUILDS_REQUESTS,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_GUILDS,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_MANAGE_GUILDS,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_OUT_PROVINCE_GUILDS,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_OUT_PROVINCE_TRUE_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_OUT_PROVINCE_TRUE_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_OUT_PROVINCE_TRUE_GUILDS,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_OUT_PROVINCE_LEGAL_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_OUT_PROVINCE_LEGAL_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_OUT_PROVINCE_LEGAL_GUILDS,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_TRUE_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_IN_PROVINCE_TRUE_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_IN_PROVINCE_TRUE_GUILDS,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_LEGAL_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_IN_PROVINCE_LEGAL_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_IN_PROVINCE_LEGAL_GUILDS,
|
||||
} from "../../../../routes/routes";
|
||||
import LinkItem from "../../../../components/link-item/LinkItem";
|
||||
import { MdCorporateFare } from "react-icons/md";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { BackButton } from "../../../../components/back-button/BackButton";
|
||||
|
||||
export const GuildsOperations = () => {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
return (
|
||||
<>
|
||||
{[
|
||||
ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_IN_PROVINCE_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_IN_PROVINCE_GUILDS,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_OUT_PROVINCE_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_OUT_PROVINCE_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_OUT_PROVINCE_GUILDS,
|
||||
].includes(pathname) && <BackButton />}
|
||||
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
p={SPACING.SMALL}
|
||||
direction={"row"}
|
||||
justifyContent="center"
|
||||
xs={12}
|
||||
>
|
||||
{[
|
||||
ROUTE_SUPER_ADMIN_ROUTE_MANAGE_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_MANAGE_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_MANAGE_GUILDS,
|
||||
].includes(pathname) && (
|
||||
<>
|
||||
<NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "SuperAdmin"
|
||||
? ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_GUILDS
|
||||
: getRoleFromUrl() === "AdminX"
|
||||
? ROUTE_ADMINX_ROUTE_IN_PROVINCE_GUILDS
|
||||
: ROUTE_PROVINCE_ROUTE_IN_PROVINCE_GUILDS
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title="اصناف داخل استان"
|
||||
/>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "SuperAdmin"
|
||||
? ROUTE_SUPER_ADMIN_ROUTE_OUT_PROVINCE_GUILDS
|
||||
: getRoleFromUrl() === "AdminX"
|
||||
? ROUTE_ADMINX_ROUTE_OUT_PROVINCE_GUILDS
|
||||
: ROUTE_PROVINCE_ROUTE_OUT_PROVINCE_GUILDS
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title="اصناف خارج استان"
|
||||
/>
|
||||
</NavLink>
|
||||
</>
|
||||
)}
|
||||
{[
|
||||
ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_IN_PROVINCE_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_IN_PROVINCE_GUILDS,
|
||||
].includes(pathname) && (
|
||||
<>
|
||||
<NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "SuperAdmin"
|
||||
? ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_GUILDS_REQUESTS
|
||||
: getRoleFromUrl() === "AdminX"
|
||||
? ROUTE_ADMINX_ROUTE_IN_PROVINCE_GUILDS_REQUESTS
|
||||
: ROUTE_PROVINCE_ROUTE_IN_PROVINCE_GUILDS_REQUESTS
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title="درخواست های ثبت صنف"
|
||||
/>
|
||||
</NavLink>
|
||||
{/* <NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "SuperAdmin"
|
||||
? ROUTE_SUPER_ADMIN_ROUTE_GUILDS
|
||||
: getRoleFromUrl() === "AdminX"
|
||||
? ROUTE_ADMINX_ROUTE_GUILDS
|
||||
: ROUTE_PROVINCE_ROUTE_GUILDS
|
||||
}
|
||||
active={pathname === ROUTE_PROVINCE_ROUTE_GUILDS ? "true" : null}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title="اصناف"
|
||||
/>
|
||||
</NavLink> */}
|
||||
<NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "SuperAdmin"
|
||||
? ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_TRUE_GUILDS
|
||||
: getRoleFromUrl() === "AdminX"
|
||||
? ROUTE_ADMINX_ROUTE_IN_PROVINCE_TRUE_GUILDS
|
||||
: ROUTE_PROVINCE_ROUTE_IN_PROVINCE_TRUE_GUILDS
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title="اصناف حقیقی"
|
||||
/>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "SuperAdmin"
|
||||
? ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_LEGAL_GUILDS
|
||||
: getRoleFromUrl() === "AdminX"
|
||||
? ROUTE_ADMINX_ROUTE_IN_PROVINCE_LEGAL_GUILDS
|
||||
: ROUTE_PROVINCE_ROUTE_IN_PROVINCE_LEGAL_GUILDS
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title="اصناف حقوقی"
|
||||
/>
|
||||
</NavLink>
|
||||
{/* <NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "SuperAdmin"
|
||||
? ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_STEWARDS
|
||||
: getRoleFromUrl() === "AdminX"
|
||||
? ROUTE_ADMINX_ROUTE_IN_PROVINCE_STEWARDS
|
||||
: ROUTE_PROVINCE_ROUTE_IN_PROVINCE_STEWARDS
|
||||
}
|
||||
active={pathname === ROUTE_PROVINCE_ROUTE_GUILDS ? "true" : null}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<IoIosPeople size={30} color="#244CCC" />}
|
||||
title="مباشرین"
|
||||
/>
|
||||
</NavLink>
|
||||
{(getRoleFromUrl() === "AdminX" ||
|
||||
getRoleFromUrl() === "SuperAdmin") && (
|
||||
<NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "SuperAdmin"
|
||||
? ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_GUILDS_DISTRIBUTIONS
|
||||
: ROUTE_ADMINX_ROUTE_IN_PROVINCE_GUILDS_DISTRIBUTIONS
|
||||
}
|
||||
active={
|
||||
pathname ===
|
||||
ROUTE_SUPER_ADMIN_ROUTE_IN_PROVINCE_GUILDS_DISTRIBUTIONS
|
||||
? "true"
|
||||
: null
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<VscLiveShare size={30} color="#244CCC" />}
|
||||
title="مدیریت مباشرین"
|
||||
/>
|
||||
</NavLink>
|
||||
)} */}
|
||||
</>
|
||||
)}
|
||||
|
||||
{[
|
||||
ROUTE_SUPER_ADMIN_ROUTE_OUT_PROVINCE_GUILDS,
|
||||
ROUTE_ADMINX_ROUTE_OUT_PROVINCE_GUILDS,
|
||||
ROUTE_PROVINCE_ROUTE_OUT_PROVINCE_GUILDS,
|
||||
].includes(pathname) && (
|
||||
<>
|
||||
<NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "SuperAdmin"
|
||||
? ROUTE_SUPER_ADMIN_ROUTE_OUT_PROVINCE_TRUE_GUILDS
|
||||
: getRoleFromUrl() === "AdminX"
|
||||
? ROUTE_ADMINX_ROUTE_OUT_PROVINCE_TRUE_GUILDS
|
||||
: ROUTE_PROVINCE_ROUTE_OUT_PROVINCE_TRUE_GUILDS
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title="اصناف حقیقی"
|
||||
/>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={
|
||||
getRoleFromUrl() === "SuperAdmin"
|
||||
? ROUTE_SUPER_ADMIN_ROUTE_OUT_PROVINCE_LEGAL_GUILDS
|
||||
: getRoleFromUrl() === "AdminX"
|
||||
? ROUTE_ADMINX_ROUTE_OUT_PROVINCE_LEGAL_GUILDS
|
||||
: ROUTE_PROVINCE_ROUTE_OUT_PROVINCE_LEGAL_GUILDS
|
||||
}
|
||||
>
|
||||
<LinkItem
|
||||
icon={<MdCorporateFare size={30} color="#244CCC" />}
|
||||
title="اصناف حقوقی"
|
||||
/>
|
||||
</NavLink>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { getGuildsSettingsService } from "../../services/get-guilds-settings";
|
||||
import { ManageGuildsState } from "../manage-guilds-state/ManageGuildsState";
|
||||
import { ManageStewardsState } from "../manage-stewards-state/ManageStewardsState";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
|
||||
export const GuildsSettings = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const { getGuildsSettings } = useSelector((state) => state.provinceSlice);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(LOADING_START());
|
||||
dispatch(getGuildsSettingsService({ kill_house_key: null })).then(() => {
|
||||
dispatch(LOADING_END());
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (Array.isArray(getGuildsSettings)) {
|
||||
const d = getGuildsSettings?.map((item, i) => {
|
||||
return [
|
||||
i + 1,
|
||||
item.killHouse.name,
|
||||
<ManageGuildsState
|
||||
key={i}
|
||||
guildState={item.guilds}
|
||||
choose_steward_guilds_key={item.key}
|
||||
/>,
|
||||
<ManageStewardsState
|
||||
key={i}
|
||||
stewardState={item.steward}
|
||||
choose_steward_guilds_key={item.key}
|
||||
/>,
|
||||
];
|
||||
});
|
||||
setDataTable(d);
|
||||
}
|
||||
}, [getGuildsSettings]);
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<ResponsiveTable
|
||||
paginated
|
||||
title="مجوزهای توزیع"
|
||||
columns={[
|
||||
"ردیف",
|
||||
"نام کشتارگاه",
|
||||
"اجازه فروش آزاد به صنف",
|
||||
"اجازه فروش آزاد به مباشرین",
|
||||
]}
|
||||
data={dataTable}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Button, TextField, Typography } from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment/moment";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
|
||||
export const KillProcessStats = ({ province }) => {
|
||||
const [selectedDate1, setSelectedDate1] = useState(
|
||||
moment(new Date()).format("YYYY-MM-DD")
|
||||
);
|
||||
const [selectedDate2, setSelectedDate2] = useState(
|
||||
moment(new Date()).format("YYYY-MM-DD")
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
var currentDate = moment(selectedDate1);
|
||||
var newDate = currentDate.add(7, "days").format("YYYY-MM-DD");
|
||||
setSelectedDate2(newDate);
|
||||
}, [selectedDate1]);
|
||||
|
||||
return (
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
<Grid container alignItems="center" gap={SPACING.TINY}>
|
||||
<Typography>روند کشتار بر اساس بازه</Typography>
|
||||
<DatePicker
|
||||
label="از تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField style={{ width: "160px" }} {...params} />
|
||||
)}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>{" "}
|
||||
<DatePicker
|
||||
label="تا تاریخ"
|
||||
id="date"
|
||||
disabled={true}
|
||||
renderInput={(params) => (
|
||||
<TextField style={{ width: "160px" }} {...params} />
|
||||
)}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<a
|
||||
href={`${province}killing_process_from_date_excel/?start=${selectedDate1}&end=${selectedDate2}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button variant="outlined" size="large">
|
||||
دانلود
|
||||
</Button>
|
||||
</a>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
import { Switch } from "@mui/material";
|
||||
import { useContext, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { provinceGetCars } from "../../services/province-get-cars";
|
||||
import { updateCarStateService } from "../../services/update-car-state";
|
||||
|
||||
export const ManageCarState = ({ item }) => {
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const dispatch = useDispatch();
|
||||
const [checked, setChecked] = useState(
|
||||
getRoleFromUrl() === "KillHouse"
|
||||
? item.addCarActiveState
|
||||
: item.driverActiveState
|
||||
);
|
||||
|
||||
const handleChange = (event) => {
|
||||
let reqObj;
|
||||
if (getRoleFromUrl() === "KillHouse") {
|
||||
reqObj = {
|
||||
add_car_key: item.addCarKey,
|
||||
add_car_change_activation: event.target.checked,
|
||||
};
|
||||
} else {
|
||||
reqObj = {
|
||||
driver_key: item.key,
|
||||
change_activation: event.target.checked,
|
||||
};
|
||||
}
|
||||
dispatch(updateCarStateService(reqObj)).then((r) => {
|
||||
if (r?.payload?.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r?.payload?.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(provinceGetCars());
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
setChecked(event.target.checked);
|
||||
};
|
||||
|
||||
let disabled = false;
|
||||
if (item.driverType === "rental") {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Switch
|
||||
checked={checked}
|
||||
onChange={handleChange}
|
||||
name="mySwitch"
|
||||
color="primary"
|
||||
disabled={disabled}
|
||||
/>
|
||||
{checked ? (
|
||||
<label htmlFor="mySwitch">فعال</label>
|
||||
) : (
|
||||
<label htmlFor="mySwitch">غیرفعال</label>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,184 @@
|
||||
import {
|
||||
Grid,
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
CircularProgress,
|
||||
FormControlLabel,
|
||||
FormGroup,
|
||||
Stack,
|
||||
} from "@mui/material";
|
||||
import axios from "axios";
|
||||
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
|
||||
const LOSS_FIELDS = [
|
||||
{
|
||||
key: "includeTotalDiseaseLosses",
|
||||
apiKey: "include_total_disease_losses",
|
||||
label: "مجموع تلفات ناشی از بیماری",
|
||||
},
|
||||
{
|
||||
key: "includeTotalFlockDestruction",
|
||||
apiKey: "include_total_flock_destruction",
|
||||
label: "مجموع معدومسازی گله",
|
||||
},
|
||||
{
|
||||
key: "includeTotalNormalFlockLosses",
|
||||
apiKey: "include_total_normal_flock_losses",
|
||||
label: "مجموع تلفات عادی گله",
|
||||
},
|
||||
{
|
||||
key: "includeTotalForceMajeureLosses",
|
||||
apiKey: "include_total_force_majeure_losses",
|
||||
label: "مجموع تلفات ناشی از عوامل قهری و طبیعی",
|
||||
},
|
||||
{
|
||||
key: "includeTotalFireLosses",
|
||||
apiKey: "include_total_fire_losses",
|
||||
label: "مجموع تلفات ناشی از آتشسوزی",
|
||||
},
|
||||
];
|
||||
|
||||
const DEFAULT_FORM_STATE = LOSS_FIELDS.reduce(
|
||||
(acc, { key }) => ({ ...acc, [key]: false }),
|
||||
{}
|
||||
);
|
||||
|
||||
export const ManageEvacuations = () => {
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const notify = useCallback(
|
||||
({ severity, msg, vertical = "top", horizontal = "center" }) =>
|
||||
openNotif({
|
||||
severity,
|
||||
msg,
|
||||
vertical,
|
||||
horizontal,
|
||||
}),
|
||||
[openNotif]
|
||||
);
|
||||
const [formState, setFormState] = useState(DEFAULT_FORM_STATE);
|
||||
const [recordId, setRecordId] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchLossManagement = async () => {
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const { data } = await axios.get("hatching-loss-management/");
|
||||
|
||||
setRecordId(data?.id ?? null);
|
||||
|
||||
setFormState((prev) =>
|
||||
LOSS_FIELDS.reduce(
|
||||
(acc, { key }) => ({
|
||||
...acc,
|
||||
[key]: Boolean(data?.[key]),
|
||||
}),
|
||||
{ ...prev }
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
const errorText =
|
||||
error?.response?.data?.detail ??
|
||||
error?.response?.data?.message ??
|
||||
error?.message ??
|
||||
"خطایی در دریافت اطلاعات رخ داده است.";
|
||||
notify({ severity: "error", msg: errorText });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchLossManagement();
|
||||
}, []);
|
||||
|
||||
const handleChange = (fieldKey) => (event) => {
|
||||
const { checked } = event.target;
|
||||
setFormState((prev) => ({
|
||||
...prev,
|
||||
[fieldKey]: checked,
|
||||
}));
|
||||
};
|
||||
|
||||
const requestBody = useMemo(
|
||||
() =>
|
||||
LOSS_FIELDS.reduce((acc, { key, apiKey }) => {
|
||||
acc[apiKey] = Boolean(formState[key]);
|
||||
return acc;
|
||||
}, {}),
|
||||
[formState]
|
||||
);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
setIsSaving(true);
|
||||
|
||||
const targetId = recordId ?? 1;
|
||||
|
||||
try {
|
||||
await axios.patch(`hatching-loss-management/${targetId}/`, requestBody);
|
||||
|
||||
notify({
|
||||
severity: "success",
|
||||
msg: "اطلاعات با موفقیت بهروزرسانی شد.",
|
||||
});
|
||||
} catch (error) {
|
||||
const errorText =
|
||||
error?.response?.data?.detail ??
|
||||
error?.response?.data?.message ??
|
||||
error?.message ??
|
||||
"خطایی در بهروزرسانی اطلاعات رخ داده است.";
|
||||
notify({ severity: "error", msg: errorText });
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid
|
||||
component="section"
|
||||
xs={12}
|
||||
style={{ padding: "20px", width: "100%" }}
|
||||
>
|
||||
{isLoading ? (
|
||||
<Stack direction="row" justifyContent="center">
|
||||
<CircularProgress />
|
||||
</Stack>
|
||||
) : (
|
||||
<Grid component="form" onSubmit={handleSubmit} xs={12}>
|
||||
<FormGroup>
|
||||
{LOSS_FIELDS.map(({ key, label }) => (
|
||||
<FormControlLabel
|
||||
key={key}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={Boolean(formState[key])}
|
||||
onChange={handleChange(key)}
|
||||
name={key}
|
||||
disabled={isSaving}
|
||||
/>
|
||||
}
|
||||
label={label}
|
||||
/>
|
||||
))}
|
||||
</FormGroup>
|
||||
|
||||
<Box>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
disabled={isSaving}
|
||||
color="primary"
|
||||
>
|
||||
{isSaving ? "در حال ذخیره..." : "بهروزرسانی"}
|
||||
</Button>
|
||||
</Box>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,576 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Button, Checkbox, IconButton, TextField } from "@mui/material";
|
||||
import axios from "axios";
|
||||
import { RiSearchLine } from "react-icons/ri";
|
||||
import { useDispatch } from "react-redux";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
OPEN_MODAL,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { ProvinceManageDistributionsSubmitCommitmentPercent } from "../province-manage-distributions-submit-commitment-percentet/ProvinceManageDistributionsSubmitCommitmentPercent";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { ProvinceManageGuildDistributionsSubmitPercents } from "../province-manage-guild-distributions-submit-percents/ProvinceManageGuildDistributionsSubmitPercents";
|
||||
import {
|
||||
provinceManageGuildTradesEditAllPercents,
|
||||
provinceManageGuildTradesEditPercents,
|
||||
provinceManageGuildTradesGetPercents,
|
||||
} from "../../services/province-manage-guilds-trades-edit-percents";
|
||||
|
||||
export const ManageGuildDistributions = () => {
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
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 [dashboardData, setDashboardData] = useState([]);
|
||||
|
||||
const getDashboardData = () => {
|
||||
dispatch(provinceManageGuildTradesGetPercents()).then((r) => {
|
||||
setDashboardData(r.payload.data);
|
||||
});
|
||||
};
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
let response;
|
||||
dispatch(LOADING_START());
|
||||
response = await axios.get(
|
||||
`guilds-for-configs/?search=filter&value=${textValue}&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}`
|
||||
);
|
||||
getDashboardData();
|
||||
dispatch(LOADING_END());
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
const updateTable = () => {
|
||||
fetchApiData(page !== 0 ? page : 1);
|
||||
};
|
||||
|
||||
const openGovModal = (item, isAll) => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "فروش دولتی",
|
||||
content: (
|
||||
<ProvinceManageGuildDistributionsSubmitPercents
|
||||
item={item}
|
||||
updateTable={updateTable}
|
||||
type="gov"
|
||||
isDashboard={isAll}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const openFreeModal = (item, isAll) => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "فروش آزاد",
|
||||
content: (
|
||||
<ProvinceManageGuildDistributionsSubmitPercents
|
||||
item={item}
|
||||
updateTable={updateTable}
|
||||
type="free"
|
||||
isDashboard={isAll}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const d = data?.map((item, i) => {
|
||||
return [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
`${item?.user?.fullname} (${item?.user?.mobile})`,
|
||||
<ProvinceManageDistributionsSubmitCommitmentPercent
|
||||
key={i}
|
||||
amount={item?.outProvinceFreeBuyingCommitmentPercent}
|
||||
updateTable={updateTable}
|
||||
item={item}
|
||||
isGuild
|
||||
/>,
|
||||
<Checkbox
|
||||
key={i}
|
||||
checked={item?.freeSaleFromFreeQuotaInProvince}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceManageGuildTradesEditPercents({
|
||||
key: item?.key,
|
||||
free_sale_from_free_quota_in_province:
|
||||
!item?.freeSaleFromFreeQuotaInProvince,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>,
|
||||
<Checkbox
|
||||
key={i}
|
||||
checked={item?.freeSaleFormGovernmentalQuota}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceManageGuildTradesEditPercents({
|
||||
key: item?.key,
|
||||
free_sale_form_governmental_quota:
|
||||
!item?.freeSaleFormGovernmentalQuota,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>,
|
||||
|
||||
<Grid
|
||||
key={i}
|
||||
container
|
||||
alignItems="center"
|
||||
xs={12}
|
||||
justifyContent="start"
|
||||
direction="row"
|
||||
>
|
||||
<Grid xs={6}>
|
||||
<Checkbox
|
||||
checked={item?.governmentalSellingPermission}
|
||||
onChange={() => {
|
||||
const newValue = !item?.governmentalSellingPermission;
|
||||
dispatch(
|
||||
provinceManageGuildTradesEditPercents({
|
||||
key: item?.key,
|
||||
governmental_selling_permission: newValue,
|
||||
...(newValue === false
|
||||
? {
|
||||
in_province_governmental_selling_percent: 0,
|
||||
segmentation_governmental_percent: 0,
|
||||
out_province_governmental_selling_percent: 0,
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
).then(() => {
|
||||
if (newValue === true) {
|
||||
openGovModal(item);
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
updateTable();
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
{item?.governmentalSellingPermission && (
|
||||
<Grid xs={6}>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => openGovModal(item)}
|
||||
color="primary"
|
||||
>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>,
|
||||
<Grid
|
||||
key={i}
|
||||
container
|
||||
alignItems="center"
|
||||
xs={12}
|
||||
justifyContent="center"
|
||||
direction="row"
|
||||
>
|
||||
<Grid xs={6}>
|
||||
<Checkbox
|
||||
checked={item?.freeSellingPermission}
|
||||
onChange={() => {
|
||||
const newValue = !item?.freeSellingPermission;
|
||||
dispatch(
|
||||
provinceManageGuildTradesEditPercents({
|
||||
key: item?.key,
|
||||
free_selling_permission: newValue,
|
||||
...(newValue === false
|
||||
? {
|
||||
in_province_free_selling_percent: 0,
|
||||
out_province_free_selling_percent: 0,
|
||||
segmentation_free_selling_percent: 0,
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
).then(() => {
|
||||
if (newValue === true) {
|
||||
openFreeModal(item);
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
updateTable();
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid xs={6}>
|
||||
{item?.freeSellingPermission && (
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => openFreeModal(item)}
|
||||
color="primary"
|
||||
>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
)}{" "}
|
||||
</Grid>
|
||||
</Grid>,
|
||||
item?.inProvinceGovernmentalSellingPercent,
|
||||
item?.outProvinceGovernmentalSellingPercent,
|
||||
item?.segmentationGovernmentalPercent,
|
||||
item?.inProvinceFreeSellingPercent,
|
||||
item?.outProvinceFreeSellingPercent,
|
||||
item?.segmentationFreeSellingPercent,
|
||||
];
|
||||
});
|
||||
|
||||
setTableData(d);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, [dispatch, perPage]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`guilds-for-configs/?role=${getRoleFromUrl()}&search=filter&value=${textValue}&page=${1}&page_size=${perPage}`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
dispatch(LOADING_END());
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
|
||||
<Grid container mt={2} mb={4} isDashboard xs={12}>
|
||||
<ResponsiveTable
|
||||
noPagination
|
||||
isDashboard
|
||||
columns={[
|
||||
"درصد تحویل خرید خارج استان",
|
||||
"فروش آزاد به داخل استان",
|
||||
"فروش آزاد از سهمیه دولتی",
|
||||
"فروش دولتی",
|
||||
"فروش آزاد",
|
||||
"درصد فروش دولتی داخل استان",
|
||||
"درصد فروش دولتی خارج استان",
|
||||
"درصد فروش دولتی قطعه بندی",
|
||||
"درصد فروش آزاد داخل استان",
|
||||
"درصد فروش آزاد خارج استان",
|
||||
"درصد فروش آزاد قطعه بندی",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
<ProvinceManageDistributionsSubmitCommitmentPercent
|
||||
key={dashboardData}
|
||||
amount={dashboardData?.outProvinceFreeBuyingCommitmentPercent}
|
||||
updateTable={updateTable}
|
||||
item={dashboardData}
|
||||
isGuild
|
||||
isDashboard
|
||||
/>,
|
||||
<Checkbox
|
||||
key={dashboardData}
|
||||
checked={dashboardData?.freeSaleFromFreeQuotaInProvince}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceManageGuildTradesEditAllPercents({
|
||||
free_sale_from_free_quota_in_province:
|
||||
!dashboardData?.freeSaleFromFreeQuotaInProvince,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>,
|
||||
<Checkbox
|
||||
key={dashboardData}
|
||||
checked={dashboardData?.freeSaleFormGovernmentalQuota}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceManageGuildTradesEditAllPercents({
|
||||
free_sale_form_governmental_quota:
|
||||
!dashboardData?.freeSaleFormGovernmentalQuota,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>,
|
||||
|
||||
<Grid
|
||||
key={dashboardData}
|
||||
container
|
||||
alignItems="center"
|
||||
xs={12}
|
||||
justifyContent="start"
|
||||
direction="row"
|
||||
>
|
||||
<Grid xs={6}>
|
||||
<Checkbox
|
||||
checked={dashboardData?.governmentalSellingPermission}
|
||||
onChange={() => {
|
||||
const newValue =
|
||||
!dashboardData?.governmentalSellingPermission;
|
||||
dispatch(
|
||||
provinceManageGuildTradesEditAllPercents({
|
||||
governmental_selling_permission: newValue,
|
||||
...(newValue === false
|
||||
? {
|
||||
in_province_governmental_selling_percent: 0,
|
||||
segmentation_governmental_percent: 0,
|
||||
out_province_governmental_selling_percent: 0,
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
).then(() => {
|
||||
if (newValue === true) {
|
||||
openGovModal(dashboardData, true);
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
updateTable();
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
{dashboardData?.governmentalSellingPermission && (
|
||||
<Grid xs={6}>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => openGovModal(dashboardData, true)}
|
||||
color="primary"
|
||||
>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>,
|
||||
<Grid
|
||||
key={dashboardData}
|
||||
container
|
||||
alignItems="center"
|
||||
xs={12}
|
||||
justifyContent="center"
|
||||
direction="row"
|
||||
>
|
||||
<Grid xs={6}>
|
||||
<Checkbox
|
||||
checked={dashboardData?.freeSellingPermission}
|
||||
onChange={() => {
|
||||
const newValue = !dashboardData?.freeSellingPermission;
|
||||
dispatch(
|
||||
provinceManageGuildTradesEditAllPercents({
|
||||
free_selling_permission: newValue,
|
||||
...(newValue === false
|
||||
? {
|
||||
in_province_free_selling_percent: 0,
|
||||
out_province_free_selling_percent: 0,
|
||||
segmentation_free_selling_percent: 0,
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
).then(() => {
|
||||
if (newValue === true) {
|
||||
openFreeModal(dashboardData, true);
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
updateTable();
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid xs={6}>
|
||||
{dashboardData?.freeSellingPermission && (
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => openFreeModal(dashboardData, true)}
|
||||
color="primary"
|
||||
>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
)}{" "}
|
||||
</Grid>
|
||||
</Grid>,
|
||||
dashboardData?.inProvinceGovernmentalSellingPercent,
|
||||
dashboardData?.outProvinceGovernmentalSellingPercent,
|
||||
dashboardData?.segmentationGovernmentalPercent,
|
||||
dashboardData?.inProvinceFreeSellingPercent,
|
||||
dashboardData?.outProvinceFreeSellingPercent,
|
||||
dashboardData?.segmentationFreeSellingPercent,
|
||||
],
|
||||
]}
|
||||
title={"تنظیمات کلی"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
>
|
||||
<Grid>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
id="outlined-basic"
|
||||
size="small"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
endIcon={<RiSearchLine />}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
</form>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<ResponsiveTable
|
||||
data={tableData}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"نام مباشر",
|
||||
"درصد تحویل خرید خارج استان",
|
||||
"فروش آزاد به داخل استان",
|
||||
"فروش آزاد از سهمیه دولتی",
|
||||
"فروش دولتی",
|
||||
"فروش آزاد",
|
||||
"درصد فروش دولتی داخل استان",
|
||||
"درصد فروش دولتی خارج استان",
|
||||
"درصد فروش دولتی قطعه بندی",
|
||||
"درصد فروش آزاد داخل استان",
|
||||
"درصد فروش آزاد خارج استان",
|
||||
"درصد فروش آزاد قطعه بندی",
|
||||
]}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title="مباشرین"
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,285 @@
|
||||
import {
|
||||
Button,
|
||||
FormControlLabel,
|
||||
IconButton,
|
||||
Popover,
|
||||
Switch,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import { useContext, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import {
|
||||
DRAWER,
|
||||
OPEN_MODAL,
|
||||
LOADING_START,
|
||||
LOADING_END,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { CreateGuilds } from "../create-guilds/CreateGuilds";
|
||||
import { GuildLimitaion } from "../guild-limitaion/GuildLimitaion";
|
||||
import ManageHistoryIcon from "@mui/icons-material/ManageHistory";
|
||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
|
||||
import SendIcon from "@mui/icons-material/Send";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { ProvinceManageGuildsSubmitRegisterCode } from "../province-manage-guilds-submit-register-code/ProvinceManageGuildsSubmitRegisterCode";
|
||||
import { provinceResendRegisterCodeStateService } from "../../services/province-get-register-code-state";
|
||||
import { ViewGuildDetails } from "../view-guild-details/ViewGuildDetails";
|
||||
import TuneIcon from "@mui/icons-material/Tune";
|
||||
|
||||
export const ManageGuildsOperations = ({ guild, updateTable }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [checked, setChecked] = useState(guild.active);
|
||||
const [popoverOpen, setPopoverOpen] = useState(false);
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const openPopover = (event) => {
|
||||
setPopoverOpen(true);
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const closePopover = () => {
|
||||
setPopoverOpen(false);
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const handleChange = async (event) => {
|
||||
const newChecked = event.target.checked;
|
||||
setChecked(newChecked);
|
||||
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.put("guilds/0/", {
|
||||
guilds_key: guild?.key,
|
||||
active: newChecked,
|
||||
role: getRoleFromUrl(),
|
||||
});
|
||||
|
||||
dispatch(LOADING_END());
|
||||
|
||||
if (response.status === 200) {
|
||||
updateTable();
|
||||
dispatch(DRAWER({ right: false, bottom: false, content: null }));
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
dispatch(LOADING_END());
|
||||
const errorMessage =
|
||||
error.response?.data?.result ||
|
||||
error.response?.data?.error ||
|
||||
"خطا در انجام عملیات";
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: errorMessage,
|
||||
severity: "error",
|
||||
});
|
||||
// Revert the checkbox state on error
|
||||
setChecked(!newChecked);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<Tooltip title="مدیریت صنف" placement="left">
|
||||
<IconButton color="primary" onClick={openPopover}>
|
||||
<TuneIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<Popover
|
||||
open={popoverOpen}
|
||||
anchorEl={anchorEl}
|
||||
onClose={closePopover}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
>
|
||||
<div style={{ padding: 10 }}>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
alignItems="flex-start"
|
||||
justifyContent="center"
|
||||
gap={1}
|
||||
>
|
||||
<Button
|
||||
size="small"
|
||||
color="info"
|
||||
startIcon={<VisibilityIcon />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "مشاهده جزییات صنف",
|
||||
content: <ViewGuildDetails guild={guild} />,
|
||||
size: window.innerWidth <= 600 ? "small" : "auto",
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
جزییات
|
||||
</Button>
|
||||
|
||||
{["AdminX", "SuperAdmin", "GuildRoom"].includes(
|
||||
getRoleFromUrl()
|
||||
) && (
|
||||
<>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={checked}
|
||||
onChange={handleChange}
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label={checked ? "فعال" : "غیرفعال"}
|
||||
style={{
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
display: "flex",
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
color="primary"
|
||||
size="small"
|
||||
startIcon={<EditIcon />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
// disabled={guild?.provinceAcceptState !== "pending"}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: "ویرایش واحد",
|
||||
size: window.innerWidth <= 600 ? "small" : "auto",
|
||||
content: (
|
||||
<CreateGuilds
|
||||
guild={guild}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ویرایش
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
color="warning"
|
||||
startIcon={<ManageHistoryIcon />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: "اعمال محدودیت",
|
||||
content: (
|
||||
<GuildLimitaion
|
||||
guild={guild}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
محدودیت
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!guild?.isRegistered && (
|
||||
<Grid
|
||||
container
|
||||
alignItems="flex-start"
|
||||
justifyContent="flex-start"
|
||||
gap={SPACING.TINY}
|
||||
direction="column"
|
||||
>
|
||||
<Button
|
||||
size="small"
|
||||
color="success"
|
||||
startIcon={<CheckCircleIcon size={30} />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ثبت کد احراز",
|
||||
content: (
|
||||
<ProvinceManageGuildsSubmitRegisterCode
|
||||
item={guild}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت کد احراز
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
size="small"
|
||||
color="secondary"
|
||||
startIcon={<SendIcon />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
|
||||
dispatch(
|
||||
provinceResendRegisterCodeStateService({
|
||||
key: guild.key,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "کد با موفقیت ارسال شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ارسال مجدد کد
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</div>
|
||||
</Popover>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,314 @@
|
||||
import { Button, IconButton, Popover, TextField } from "@mui/material";
|
||||
import { useContext, useState } from "react";
|
||||
import TuneIcon from "@mui/icons-material/Tune";
|
||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||
import CheckIcon from "@mui/icons-material/Check";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
|
||||
import SendIcon from "@mui/icons-material/Send";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { checkKillhouseRequestGuildService } from "../../services/check-killhouse-request-guild";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { CLOSE_MODAL, OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { ProvinceManageGuildsSubmitRegisterCode } from "../province-manage-guilds-submit-register-code/ProvinceManageGuildsSubmitRegisterCode";
|
||||
import { provinceResendRegisterCodeStateService } from "../../services/province-get-register-code-state";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { ViewGuildDetails } from "../view-guild-details/ViewGuildDetails";
|
||||
|
||||
export const ManageGuildsRequestsOperations = ({ guild, updateTable }) => {
|
||||
const [popoverOpen, setPopoverOpen] = useState(false);
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const openPopover = (event) => {
|
||||
setPopoverOpen(true);
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const closePopover = () => {
|
||||
setPopoverOpen(false);
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<IconButton variant="contained" color="primary" onClick={openPopover}>
|
||||
<TuneIcon />
|
||||
</IconButton>
|
||||
<Popover
|
||||
open={popoverOpen}
|
||||
anchorEl={anchorEl}
|
||||
onClose={closePopover}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
>
|
||||
<div style={{ padding: 10 }}>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
alignItems="flex-start"
|
||||
justifyContent="center"
|
||||
gap={1}
|
||||
>
|
||||
{/* {!readOnly && (
|
||||
<Tooltip placement="left" title="بازگشت جوجه ریزی">
|
||||
<IconButton
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
hatchingUndoArchiveService({
|
||||
key: item.key,
|
||||
type: "return_archive",
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateArchive(1);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
<KeyboardReturnIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)} */}
|
||||
|
||||
{["SuperAdmin", "AdminX", "GuildRoom"].includes(
|
||||
getRoleFromUrl()
|
||||
) && (
|
||||
<Button
|
||||
size="small"
|
||||
color="info"
|
||||
startIcon={<VisibilityIcon />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "مشاهده جزییات صنف",
|
||||
content: <ViewGuildDetails guild={guild} />,
|
||||
size: window.innerWidth <= 600 ? "small" : "auto",
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
جزییات
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{(guild?.activeRegisterCode && guild?.loggedRegisterCode) ||
|
||||
!guild?.activeRegisterCode ? (
|
||||
<Grid
|
||||
container
|
||||
alignItems="flex-start"
|
||||
justifyContent="flex-start"
|
||||
gap={SPACING.TINY}
|
||||
direction="column"
|
||||
>
|
||||
<Button
|
||||
size="small"
|
||||
color="success"
|
||||
startIcon={<CheckIcon />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
|
||||
dispatch(
|
||||
checkKillhouseRequestGuildService({
|
||||
guilds_key: guild.key,
|
||||
state: "accepted",
|
||||
role: getRoleFromUrl(),
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
تایید
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
color="error"
|
||||
startIcon={<CloseIcon />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "رد درخواست ثبت صنف",
|
||||
content: (
|
||||
<RejectModal
|
||||
guild={guild}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
رد
|
||||
</Button>
|
||||
</Grid>
|
||||
) : (
|
||||
<Grid
|
||||
container
|
||||
alignItems="flex-start"
|
||||
justifyContent="flex-start"
|
||||
gap={SPACING.TINY}
|
||||
direction="column"
|
||||
>
|
||||
<Button
|
||||
size="small"
|
||||
color="success"
|
||||
startIcon={<CheckCircleIcon />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ثبت کد احراز",
|
||||
content: (
|
||||
<ProvinceManageGuildsSubmitRegisterCode
|
||||
item={guild}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت کد احراز
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
size="small"
|
||||
color="secondary"
|
||||
startIcon={<SendIcon />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
|
||||
dispatch(
|
||||
provinceResendRegisterCodeStateService({
|
||||
key: guild.key,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "کد با موفقیت ارسال شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ارسال مجدد کد
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</div>
|
||||
</Popover>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
const RejectModal = ({ guild, updateTable }) => {
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [text, setText] = useState("");
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<Grid container gap={SPACING.TINY}>
|
||||
<TextField
|
||||
placeholder="دلیل رد درخواست..."
|
||||
value={text}
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={!text}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
checkKillhouseRequestGuildService({
|
||||
guilds_key: guild.key,
|
||||
state: "rejected",
|
||||
message: text,
|
||||
role: getRoleFromUrl(),
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
updateTable();
|
||||
dispatch(CLOSE_MODAL());
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,191 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Button, TextField } from "@mui/material";
|
||||
import { useDispatch } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { RiSearchLine } from "react-icons/ri";
|
||||
import {
|
||||
// DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
OPEN_MODAL,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { ManageGuildsRequestsOperations } from "../manage-guilds-requests-operations/ManageGuildsRequestsOperations";
|
||||
import { CreateGuilds } from "../create-guilds/CreateGuilds";
|
||||
|
||||
export const ManageGuildsRequests = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const [data, setData] = useState([]);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const [page, setPage] = useState(1);
|
||||
const [tableData, setTableData] = useState([]);
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
dispatch(LOADING_START());
|
||||
const response = await axios.get(
|
||||
`total_guilds/?search=filter&value=${textValue}&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&check=true&state=pending`
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
setData(response.data?.results || []);
|
||||
setTotalRows(response.data?.count || 0);
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
const updateTable = () => {
|
||||
fetchApiData(page !== 0 ? page : 1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const d = data?.map((item, i) => {
|
||||
return [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
// item?.killHouseInfo?.length
|
||||
// ? item?.killHouseInfo
|
||||
// ?.map((item) => {
|
||||
// const type = item?.killer ? "کشتارکن" : "کشتارگاه";
|
||||
// return `${type} ${item?.name} (${item?.mobile})`;
|
||||
// })
|
||||
// .join(" - ")
|
||||
// :
|
||||
`${item?.registerarFullname || ""} ${
|
||||
item?.registerarMobile ? "(" + item?.registerarMobile + " )" : " "
|
||||
}`,
|
||||
item?.licenseNumber || "-",
|
||||
item?.guildsName || "-",
|
||||
`${item?.user?.fullname || "-"} (${item?.user?.mobile || "-"})`,
|
||||
item?.user?.nationalId || "-",
|
||||
item?.typeActivity || "-",
|
||||
item?.areaActivity || "-",
|
||||
item?.address?.postalCode || "-",
|
||||
`${item?.address?.province?.name || "-"}/${
|
||||
item?.address?.city?.name || "-"
|
||||
}/${item?.address?.address || "-"}`,
|
||||
item?.steward ? "می باشد" : "نمی باشد",
|
||||
item?.hasInquiry ? "استعلامی" : "دستی",
|
||||
item?.activeRegisterCode ? "انجام شده" : "انجام نشده",
|
||||
<ManageGuildsRequestsOperations
|
||||
updateTable={updateTable}
|
||||
key={item?.guildsName}
|
||||
guild={item}
|
||||
/>,
|
||||
];
|
||||
});
|
||||
|
||||
setTableData(d);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, [dispatch, perPage]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`total_guilds/?role=${getRoleFromUrl()}&search=filter&value=${textValue}&page=${1}&page_size=${perPage}&check=true&state=pending`
|
||||
);
|
||||
setData(response.data?.results || []);
|
||||
setTotalRows(response.data?.count || 0);
|
||||
dispatch(LOADING_END());
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
dispatch(LOADING_END());
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
>
|
||||
{["AdminX", "SuperAdmin"].includes(getRoleFromUrl()) && (
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ثبت واحد جدید",
|
||||
size: window.innerWidth <= 600 ? "small" : "auto",
|
||||
content: <CreateGuilds updateTable={updateTable} />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت واحد جدید
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Grid>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
id="outlined-basic"
|
||||
size="small"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button
|
||||
// disabled={!textValue}
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
endIcon={<RiSearchLine />}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
</form>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<ResponsiveTable
|
||||
data={tableData}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"ثبت کننده",
|
||||
"شناسه صنف",
|
||||
"نام واحد صنفی",
|
||||
"نام شخص/شرکت",
|
||||
"کدملی",
|
||||
"نوع فعالیت",
|
||||
"حوزه فعالیت",
|
||||
"کدپستی",
|
||||
"استان/شهر/آدرس",
|
||||
"مباشر",
|
||||
"نوع ثبت",
|
||||
"احراز شماره موبایل",
|
||||
"عملیات",
|
||||
]}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title="درخواست های ثبت صنف"
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
import { FormControlLabel, Switch } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { updateGuildsSettingsService } from "../../services/update-guilds-settings";
|
||||
|
||||
export const ManageGuildsState = ({
|
||||
guildState,
|
||||
choose_steward_guilds_key,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const [switchState, setSwitchState] = useState(guildState);
|
||||
|
||||
const handleSwitchChange = () => {
|
||||
setSwitchState((prevState) => {
|
||||
dispatch(
|
||||
updateGuildsSettingsService({
|
||||
choose_steward_guilds_key,
|
||||
guilds: !prevState,
|
||||
})
|
||||
);
|
||||
return !prevState;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container alignItems="center" justifyContent="center">
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={switchState}
|
||||
onChange={handleSwitchChange}
|
||||
name="switchState"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
// label="Toggle Switch"
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
417
src/features/province/components/manage-guilds/ManageGuilds.js
Normal file
417
src/features/province/components/manage-guilds/ManageGuilds.js
Normal file
@@ -0,0 +1,417 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Button, TextField, Tooltip, MenuItem } from "@mui/material";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { provinceGetTotalGuildsService } from "../../services/province-get-total-guilds";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { ManageGuildsOperations } from "../manage-guilds-operations/ManageGuildsOperations";
|
||||
import { OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
|
||||
import { CreateGuilds } from "../create-guilds/CreateGuilds";
|
||||
import { checkPathStartsWith } from "../../../../utils/checkPathStartsWith";
|
||||
|
||||
export const MaangeGuilds = () => {
|
||||
const userKey = useSelector((state) => state.userSlice?.userProfile?.key);
|
||||
const dispatch = useDispatch();
|
||||
const selectedSubUser = useSelector(
|
||||
(state) => state.userSlice.selectedSubUser
|
||||
);
|
||||
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 [activeState, setActiveState] = useState("active");
|
||||
|
||||
const handleTextChange = (e) => setTextValue(e.target.value);
|
||||
// const handleCheckboxChange = () => setIsSteward(!isSteward);
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
const response = await dispatch(
|
||||
provinceGetTotalGuildsService({
|
||||
search: "filter",
|
||||
value: textValue,
|
||||
page: page,
|
||||
page_size: perPage,
|
||||
steward: false,
|
||||
active_state: activeState,
|
||||
is_real_person: true,
|
||||
role_key: checkPathStartsWith("province")
|
||||
? selectedSubUser?.key || ""
|
||||
: "",
|
||||
})
|
||||
);
|
||||
|
||||
if (response.payload.error) {
|
||||
console.error("Error fetching data:", response.payload.error);
|
||||
setData([]);
|
||||
setTotalRows(0);
|
||||
} else {
|
||||
setData(response.payload.data?.results || []);
|
||||
setTotalRows(response.payload.data?.count || 0);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
const updateTable = () => {
|
||||
fetchApiData(page !== 0 ? page : 1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, [perPage, selectedSubUser?.key, activeState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!data || !Array.isArray(data)) {
|
||||
setTableData([]);
|
||||
return;
|
||||
}
|
||||
const d = data.map((item, i) => {
|
||||
const commonData = [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
item?.licenseNumber || "-",
|
||||
item?.guildsName || "-",
|
||||
`${item?.user?.fullname || "-"} (${item?.user?.mobile || "-"})`,
|
||||
item?.user?.nationalId ? item?.user?.nationalId : "-",
|
||||
item?.typeActivity || "-",
|
||||
item?.areaActivity || "-",
|
||||
item?.address?.postalCode || "-",
|
||||
`${item?.address?.province?.name || "-"}/${
|
||||
item?.address?.city?.name || "-"
|
||||
}/${item?.address?.address || "-"}`,
|
||||
item?.steward ? "می باشد" : "نمی باشد",
|
||||
item?.limitationAllocation ? "دارد" : "ندارد",
|
||||
item?.allocationLimit ? item?.allocationLimit : "-",
|
||||
item?.getPosStatus?.hasActivePons ? "دارد" : "ندارد",
|
||||
item?.getPosStatus?.lenActiveSessions || "-",
|
||||
];
|
||||
|
||||
if (getRoleFromUrl() !== "KillHouse") {
|
||||
commonData.push(
|
||||
<Button
|
||||
key={`stewards-${i}`}
|
||||
onClick={() => {
|
||||
const tableData = item?.stewards?.map((option, index) => [
|
||||
index + 1,
|
||||
option?.guildsName || "-",
|
||||
option?.user?.mobile || "-",
|
||||
]);
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "مباشرین",
|
||||
content: (
|
||||
<SimpleTable
|
||||
paginated
|
||||
title={"مباشرین"}
|
||||
columns={["ردیف", "نام و نام خانوادگی", "تلفن"]}
|
||||
data={tableData}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
نمایش ({item?.stewards?.length || 0})
|
||||
</Button>
|
||||
);
|
||||
|
||||
commonData.push(
|
||||
<Button
|
||||
key={`killHouse-${i}`}
|
||||
onClick={() => {
|
||||
const tableData = item?.killHouse?.map((option, index) => [
|
||||
index + 1,
|
||||
option?.name || "-",
|
||||
option?.killHouseOperator?.user?.mobile || "-",
|
||||
]);
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "کشتارگاه ها",
|
||||
content: (
|
||||
<SimpleTable
|
||||
paginated
|
||||
title={"کشتارگاه ها"}
|
||||
columns={["ردیف", "نام و نام خانوادگی", "تلفن"]}
|
||||
data={tableData}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
نمایش ({item?.killHouse?.length || 0})
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!["CityJahad", "CityPoultry", "KillHouse"].includes(getRoleFromUrl())
|
||||
) {
|
||||
commonData.splice(
|
||||
14,
|
||||
0,
|
||||
item?.productInfo?.totalCarcassesWeight
|
||||
? item.productInfo.totalCarcassesWeight.toLocaleString()
|
||||
: "-"
|
||||
);
|
||||
commonData.splice(10, 0, item?.hasInquiry ? "استعلامی" : "دستی");
|
||||
commonData.splice(
|
||||
11,
|
||||
0,
|
||||
item?.activeRegisterCode ? "انجام شده" : "انجام نشده"
|
||||
);
|
||||
}
|
||||
|
||||
commonData?.push(item?.active ? "فعال" : "غیر فعال");
|
||||
|
||||
commonData.push(
|
||||
!item?.isRegistered &&
|
||||
item?.registerCode &&
|
||||
!item?.loggedRegistrationCode
|
||||
? "در انتظار ورود کد احراز"
|
||||
: item?.isRegistered && item?.provinceAcceptState === "pending"
|
||||
? "در انتظار تایید استان"
|
||||
: item?.isRegistered
|
||||
? "احراز شده"
|
||||
: "احراز نشده"
|
||||
);
|
||||
if (getRoleFromUrl() !== "KillHouse") {
|
||||
commonData.push(
|
||||
<ManageGuildsOperations
|
||||
guild={item}
|
||||
updateTable={updateTable}
|
||||
isModal={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return commonData;
|
||||
});
|
||||
|
||||
setTableData(d);
|
||||
}, [data]);
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
const response = await dispatch(
|
||||
provinceGetTotalGuildsService({
|
||||
search: "filter",
|
||||
value: textValue,
|
||||
page: page,
|
||||
page_size: perPage,
|
||||
steward: false,
|
||||
active_state: activeState,
|
||||
is_real_person: true,
|
||||
role_key: checkPathStartsWith("province")
|
||||
? selectedSubUser?.key || ""
|
||||
: "",
|
||||
})
|
||||
);
|
||||
|
||||
if (response.payload.error) {
|
||||
console.error("Error fetching data:", response.payload.error);
|
||||
setData([]);
|
||||
setTotalRows(0);
|
||||
} else {
|
||||
setData(response.payload.data?.results || []);
|
||||
setTotalRows(response.payload.data?.count || 0);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
mt={2}
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
{["KillHouse", "GuildRoom"].includes(getRoleFromUrl()) && (
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
size: window.innerWidth <= 600 ? "small" : "auto",
|
||||
title: "ثبت واحد جدید",
|
||||
content: <CreateGuilds updateTable={updateTable} />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت واحد جدید
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<TextField
|
||||
size="small"
|
||||
autoComplete="off"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 200 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
|
||||
{/* <FormControlLabel
|
||||
style={{ marginRight: 4 }}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={isSteward}
|
||||
onChange={handleCheckboxChange}
|
||||
name="checkboxName"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label="نمایش مباشرین"
|
||||
/> */}
|
||||
{getRoleFromUrl() !== "KillHouse" && (
|
||||
<TextField
|
||||
select
|
||||
size="small"
|
||||
label="وضعیت"
|
||||
value={activeState}
|
||||
onChange={(e) => setActiveState(e.target.value)}
|
||||
sx={{ width: 150 }}
|
||||
>
|
||||
<MenuItem value="all">همه</MenuItem>
|
||||
<MenuItem value="active">فعال</MenuItem>
|
||||
<MenuItem value="deactive">غیرفعال</MenuItem>
|
||||
</TextField>
|
||||
)}
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
endIcon={<RiSearchLine />}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
</Grid>
|
||||
</form>
|
||||
{getRoleFromUrl() !== "KillHouse" && (
|
||||
<Grid>
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<a
|
||||
href={`${
|
||||
axios.defaults.baseURL
|
||||
}guilds_excel/?key=${userKey}&search=filter&value=${textValue}&role=${getRoleFromUrl()}${
|
||||
checkPathStartsWith("province")
|
||||
? `&role_key=${selectedSubUser?.key}`
|
||||
: ""
|
||||
}&active_state=${activeState}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
<ResponsiveTable
|
||||
data={tableData}
|
||||
columns={
|
||||
getRoleFromUrl() === "CityJahad" || getRoleFromUrl() === "CityPoultry"
|
||||
? [
|
||||
"ردیف",
|
||||
"شناسه صنف",
|
||||
"نام واحد صنفی",
|
||||
"نام شخص/شرکت",
|
||||
"کدملی",
|
||||
"نوع فعالیت",
|
||||
"حوزه فعالیت",
|
||||
"کدپستی",
|
||||
"استان/شهر/آدرس",
|
||||
"مباشر",
|
||||
"محدودیت تخصیص",
|
||||
"حداکثر تخصیص",
|
||||
"وضعیت کارتخوان",
|
||||
"تعداد کارتخوان ",
|
||||
"مباشرین",
|
||||
"وضعیت فعالیت",
|
||||
"وضعیت",
|
||||
"کشتارگاه ها",
|
||||
]
|
||||
: getRoleFromUrl() === "KillHouse"
|
||||
? [
|
||||
"ردیف",
|
||||
"شناسه صنف",
|
||||
"نام واحد صنفی",
|
||||
"نام شخص/شرکت",
|
||||
"کدملی",
|
||||
"نوع فعالیت",
|
||||
"حوزه فعالیت",
|
||||
"کدپستی",
|
||||
"استان/شهر/آدرس",
|
||||
"مباشر",
|
||||
"محدودیت تخصیص",
|
||||
"حداکثر تخصیص",
|
||||
"وضعیت کارتخوان",
|
||||
"تعداد کارتخوان ",
|
||||
"وضعیت فعالیت",
|
||||
"وضعیت",
|
||||
// "عملیات",
|
||||
]
|
||||
: [
|
||||
"ردیف",
|
||||
"شناسه صنف",
|
||||
"نام واحد صنفی",
|
||||
"نام شخص/شرکت",
|
||||
"کدملی",
|
||||
"نوع فعالیت",
|
||||
"حوزه فعالیت",
|
||||
"کدپستی",
|
||||
"استان/شهر/آدرس",
|
||||
"مباشر",
|
||||
"نوع ثبت",
|
||||
"احراز شماره موبایل",
|
||||
"محدودیت تخصیص",
|
||||
"حداکثر تخصیص",
|
||||
"وضعیت کارتخوان",
|
||||
"تعداد کارتخوان ",
|
||||
"وزن خرید (کیلوگرم)",
|
||||
"مباشرین",
|
||||
"کشتارگاه ها",
|
||||
"وضعیت فعالیت",
|
||||
"وضعیت",
|
||||
"عملیات",
|
||||
]
|
||||
}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title="مدیریت اصناف"
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,663 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Popover,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import axios from "axios";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
OPEN_MODAL,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { EditPoultryCity } from "../edit-poultry-city/EditPoultryCity";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { RiFileExcel2Fill } from "react-icons/ri";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { provinceGetDashboardPoultriesService } from "../../services/getDashboardOfManagePoultries";
|
||||
import { getPoultryActiveLimitedService } from "../../services/province-get-poultry-active-limited";
|
||||
import Chip from "@mui/material/Chip";
|
||||
import TuneIcon from "@mui/icons-material/Tune";
|
||||
import ManageAccountsIcon from "@mui/icons-material/ManageAccounts";
|
||||
import FileDownloadIcon from "@mui/icons-material/FileDownload";
|
||||
import ToggleOnIcon from "@mui/icons-material/ToggleOn";
|
||||
import ToggleOffIcon from "@mui/icons-material/ToggleOff";
|
||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||
|
||||
export const ManagePoultries = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
const userKey = useSelector((state) => state.userSlice?.userProfile?.key);
|
||||
const [dashboardData, setDashboardData] = useState([]);
|
||||
const [data, setData] = useState([]);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const [page, setPage] = useState(1);
|
||||
const [tableData, setTableData] = useState([]);
|
||||
const [has500Error, setHas500Error] = useState(false);
|
||||
|
||||
const PoultryActions = ({ poultryItem, onToggleLimit }) => {
|
||||
const navigate = useNavigate();
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const open = Boolean(anchorEl);
|
||||
|
||||
const handleOpen = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const handleEdit = () => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ویرایش تعاونی",
|
||||
content: (
|
||||
<EditPoultryCity updateTable={updateTable} item={poultryItem} />
|
||||
),
|
||||
})
|
||||
);
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handleDownload = () => {
|
||||
if (poultryItem?.key) {
|
||||
window.open(
|
||||
`${axios.defaults.baseURL}poultry_monitoring_excel/?key=${poultryItem.key}`,
|
||||
"_blank"
|
||||
);
|
||||
}
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handleViewDetails = () => {
|
||||
if (poultryItem?.breedingUniqueId) {
|
||||
navigate(
|
||||
window.location.pathname +
|
||||
`${poultryItem.breedingUniqueId}?from=Poultry`
|
||||
);
|
||||
}
|
||||
handleClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<Tooltip title={"تنظیمات"} placement="right-start">
|
||||
<IconButton
|
||||
color="primary"
|
||||
className="avicultureActiveRequestsBtn"
|
||||
onClick={handleOpen}
|
||||
>
|
||||
<TuneIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Popover
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
>
|
||||
<List sx={{ minWidth: 220, p: 1 }}>
|
||||
<ListItemButton
|
||||
sx={{ py: 1 }}
|
||||
onClick={() => onToggleLimit(!poultryItem?.orderLimit)}
|
||||
>
|
||||
<ListItemIcon>
|
||||
{poultryItem?.orderLimit ? (
|
||||
<ToggleOnIcon color="success" />
|
||||
) : (
|
||||
<ToggleOffIcon color="disabled" />
|
||||
)}
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="body2" color="textPrimary">
|
||||
محدودیت ثبت سفارش
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
<ListItemButton onClick={handleViewDetails} sx={{ py: 1 }}>
|
||||
<ListItemIcon>
|
||||
<VisibilityIcon color="primary" />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="body2" color="textPrimary">
|
||||
مشاهده جزییات
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
<ListItemButton
|
||||
disabled={getRoleFromUrl() === "VetSupervisor"}
|
||||
onClick={handleEdit}
|
||||
sx={{ py: 1 }}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<ManageAccountsIcon color="secondary" />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="body2" color="textPrimary">
|
||||
ویرایش تعاونی
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
<ListItemButton onClick={handleDownload} sx={{ py: 1 }}>
|
||||
<ListItemIcon>
|
||||
<FileDownloadIcon color="success" />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="body2" color="textPrimary">
|
||||
خروجی اکسل
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</Popover>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
// Prevent request if there was a 500 error
|
||||
if (has500Error) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(LOADING_START());
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`total_poultry/?search=filter&value=${textValue}&role=${getRoleFromUrl()}&page=${page}&page_size=${perPage}&search=filter&value=${textValue}`
|
||||
);
|
||||
// Reset error state on successful response
|
||||
setHas500Error(false);
|
||||
setData(response.data?.results || []);
|
||||
setTotalRows(response.data?.count || 0);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
const errorMessage = error?.message || "";
|
||||
const status = error?.response?.status;
|
||||
const is500Error = errorMessage.includes("500") || status === 500;
|
||||
|
||||
if (is500Error) {
|
||||
setHas500Error(true);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
setData([]);
|
||||
setTotalRows(0);
|
||||
} finally {
|
||||
dispatch(LOADING_END());
|
||||
}
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
const updateTable = () => {
|
||||
fetchApiData(page !== 0 ? page : 1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Prevent request if there was a 500 error
|
||||
if (has500Error) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(provinceGetDashboardPoultriesService({ textValue }))
|
||||
.then((r) => {
|
||||
if (r?.error) {
|
||||
const errorMessage = r.error?.message || "";
|
||||
const is500Error =
|
||||
errorMessage.includes("500") ||
|
||||
r.error?.status === 500 ||
|
||||
r.error?.statusCode === 500;
|
||||
|
||||
if (is500Error) {
|
||||
setHas500Error(true);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
setDashboardData([]);
|
||||
} else if (r?.payload?.data) {
|
||||
// Reset error state on successful response
|
||||
setHas500Error(false);
|
||||
setDashboardData(r.payload.data);
|
||||
} else {
|
||||
setDashboardData([]);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error fetching dashboard data:", error);
|
||||
const errorMessage = error?.message || "";
|
||||
const status = error?.response?.status;
|
||||
const is500Error = errorMessage.includes("500") || status === 500;
|
||||
|
||||
if (is500Error) {
|
||||
setHas500Error(true);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
setDashboardData([]);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
// Reset error state when textValue changes
|
||||
useEffect(() => {
|
||||
setHas500Error(false);
|
||||
}, [textValue]);
|
||||
|
||||
const handleOrderLimitChange = (poultryKey, newChecked) => {
|
||||
dispatch(
|
||||
getPoultryActiveLimitedService({
|
||||
key: poultryKey,
|
||||
order_limit: newChecked,
|
||||
})
|
||||
)
|
||||
.then((r) => {
|
||||
if (r?.error) {
|
||||
const errorMessage = r.error?.message || "";
|
||||
const is500Error =
|
||||
errorMessage.includes("500") ||
|
||||
r.error?.status === 500 ||
|
||||
r.error?.statusCode === 500;
|
||||
|
||||
if (is500Error) {
|
||||
setHas500Error(true);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در تغییر وضعیت محدودیت پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Reset error state on successful response
|
||||
setHas500Error(false);
|
||||
updateTable();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error updating order limit:", error);
|
||||
const errorMessage = error?.message || "";
|
||||
const status = error?.response?.status;
|
||||
const is500Error = errorMessage.includes("500") || status === 500;
|
||||
|
||||
if (is500Error) {
|
||||
setHas500Error(true);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در تغییر وضعیت محدودیت پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!data || !Array.isArray(data)) {
|
||||
setTableData([]);
|
||||
return;
|
||||
}
|
||||
|
||||
const d = data.map((item, i) => {
|
||||
return [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
item?.unitName || "",
|
||||
`${item?.user?.fullname || ""} (${item?.user?.mobile || ""})`,
|
||||
item?.breedingUniqueId || "",
|
||||
item?.epidemiologicalCode || "",
|
||||
item?.healthCertificateNumber || "",
|
||||
item?.numberOfHalls || 0,
|
||||
item?.totalCapacity ? item.totalCapacity.toLocaleString() : "0",
|
||||
`${item?.address?.province?.name || ""}/${
|
||||
item?.address?.city?.name || ""
|
||||
}`,
|
||||
item?.cityOperator || "ندارد",
|
||||
item?.vetFarm?.vetFarmName
|
||||
? `${item.vetFarm.vetFarmName} (${item.vetFarm?.vetFarmMobile || ""})`
|
||||
: "ندارد",
|
||||
`${item?.hatchingInfo?.activeHatching ? "دارد" : "ندارد"} (${
|
||||
item?.hatchingInfo?.period || "0"
|
||||
})`,
|
||||
<Chip
|
||||
key={`orderLimitStatus-${i}`}
|
||||
label={item?.orderLimit ? "فعال" : "غیرفعال"}
|
||||
color={item?.orderLimit ? "success" : "default"}
|
||||
variant={item?.orderLimit ? "filled" : "outlined"}
|
||||
size="small"
|
||||
sx={{
|
||||
width: 80,
|
||||
justifyContent: "center",
|
||||
}}
|
||||
/>,
|
||||
<PoultryActions
|
||||
key={`actions-${i}`}
|
||||
poultryItem={item}
|
||||
onToggleLimit={(checked) =>
|
||||
handleOrderLimitChange(item?.key, checked)
|
||||
}
|
||||
/>,
|
||||
];
|
||||
});
|
||||
|
||||
setTableData(d);
|
||||
}, [data, page, perPage]);
|
||||
|
||||
useEffect(() => {
|
||||
// Reset error state when perPage changes
|
||||
setHas500Error(false);
|
||||
fetchApiData(1);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [perPage]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
// Reset error state on manual submit (user retry)
|
||||
setHas500Error(false);
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`total_poultry/?role=${getRoleFromUrl()}&search=filter&value=${textValue}&page=${1}&page_size=${perPage}&search=filter&value=${textValue}`
|
||||
);
|
||||
// Reset error state on successful response
|
||||
setHas500Error(false);
|
||||
setData(response.data?.results || []);
|
||||
setTotalRows(response.data?.count || 0);
|
||||
dispatch(LOADING_END());
|
||||
|
||||
dispatch(provinceGetDashboardPoultriesService({ textValue }))
|
||||
.then((r) => {
|
||||
if (r?.error) {
|
||||
const errorMessage = r.error?.message || "";
|
||||
const is500Error =
|
||||
errorMessage.includes("500") ||
|
||||
r.error?.status === 500 ||
|
||||
r.error?.statusCode === 500;
|
||||
|
||||
if (is500Error) {
|
||||
setHas500Error(true);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
setDashboardData([]);
|
||||
} else if (r?.payload?.data) {
|
||||
setHas500Error(false);
|
||||
setDashboardData(r.payload.data);
|
||||
} else {
|
||||
setDashboardData([]);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error fetching dashboard data:", error);
|
||||
const errorMessage = error?.message || "";
|
||||
const status = error?.response?.status;
|
||||
const is500Error = errorMessage.includes("500") || status === 500;
|
||||
|
||||
if (is500Error) {
|
||||
setHas500Error(true);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
setDashboardData([]);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
const errorMessage = error?.message || "";
|
||||
const status = error?.response?.status;
|
||||
const is500Error = errorMessage.includes("500") || status === 500;
|
||||
|
||||
if (is500Error) {
|
||||
setHas500Error(true);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "مشکلی در دریافت اطلاعات پیش آمده است!",
|
||||
severity: "error",
|
||||
});
|
||||
}
|
||||
setData([]);
|
||||
setTotalRows(0);
|
||||
dispatch(LOADING_END());
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container xs={10} alignItems="center" justifyContent="center" mt={2}>
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
paddingTop={2}
|
||||
paddingRight={2}
|
||||
mx={4}
|
||||
mb={1}
|
||||
>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
id="outlined-basic"
|
||||
size="small"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button
|
||||
// disabled={!textValue}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
</form>
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<a
|
||||
href={`${axios.defaults.baseURL}management_poultry/?key=${
|
||||
userKey || ""
|
||||
}&role=${getRoleFromUrl()}&search=filter&value=${textValue || ""}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
|
||||
<Grid container mt={2} mb={4} isDashboard xs={12}>
|
||||
<ResponsiveTable
|
||||
noPagination
|
||||
isDashboard
|
||||
columns={[
|
||||
"تعداد مرغداران",
|
||||
"تعداد کل دوره جوجه ریزی",
|
||||
"حجم کل جوجه ریزی",
|
||||
"جوجه ریزی های فعال",
|
||||
" حجم جوجه ریزی فعال",
|
||||
"حجم مانده در سالن فعال",
|
||||
"تعداد کل بار",
|
||||
"حجم کل بار",
|
||||
"میانگین درصد افت",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
dashboardData?.poultryCounts
|
||||
? dashboardData.poultryCounts.toLocaleString()
|
||||
: "0",
|
||||
dashboardData?.allPeriod
|
||||
? dashboardData.allPeriod.toLocaleString()
|
||||
: "0",
|
||||
dashboardData?.allTotalQuantity
|
||||
? dashboardData.allTotalQuantity.toLocaleString()
|
||||
: "0",
|
||||
dashboardData?.hatchingPending
|
||||
? dashboardData.hatchingPending.toLocaleString()
|
||||
: "0",
|
||||
dashboardData?.totalQuantityPoultryHatchingPending
|
||||
? dashboardData.totalQuantityPoultryHatchingPending.toLocaleString()
|
||||
: "0",
|
||||
dashboardData?.totalLeftOverPoultryHatchingPending
|
||||
? dashboardData.totalLeftOverPoultryHatchingPending.toLocaleString()
|
||||
: "0",
|
||||
dashboardData?.allKillRequest
|
||||
? dashboardData.allKillRequest.toLocaleString()
|
||||
: "0",
|
||||
dashboardData?.allKillRequestQuantity
|
||||
? dashboardData.allKillRequestQuantity.toLocaleString()
|
||||
: "0",
|
||||
dashboardData?.percentLoss
|
||||
? dashboardData.percentLoss.toLocaleString()
|
||||
: "0",
|
||||
],
|
||||
]}
|
||||
title={"خلاصه اطلاعات"}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<ResponsiveTable
|
||||
data={tableData}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"نام واحد",
|
||||
"مالک (تلفن)",
|
||||
"شناسه یکتا",
|
||||
"کداپیدمیولوژیک",
|
||||
"کد بهداشتی",
|
||||
"تعداد سالن",
|
||||
"ظرفیت فارم (قطعه)",
|
||||
"استان/شهر",
|
||||
"تعاونی",
|
||||
"دامپزشک فارم (تلفن)",
|
||||
"جوجه ریزی فعال (تعداد دوره)",
|
||||
"محدودیت ثبت سفارش",
|
||||
"عملیات",
|
||||
]}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title="مدیریت مرغداران"
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,112 @@
|
||||
import {
|
||||
Button,
|
||||
FormControlLabel,
|
||||
IconButton,
|
||||
Popover,
|
||||
Switch,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { provinceChangeActiveStewardService } from "../../services/province-change-active-steward";
|
||||
import { EditStewards } from "../edit-stewards/EditStewards";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import TuneIcon from "@mui/icons-material/Tune";
|
||||
|
||||
export const ManageStewardsOperations = ({ guild }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [checked, setChecked] = useState(guild.active);
|
||||
const [popoverOpen, setPopoverOpen] = useState(false);
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
||||
const openPopover = (event) => {
|
||||
setPopoverOpen(true);
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const closePopover = () => {
|
||||
setPopoverOpen(false);
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const handleChange = (event) => {
|
||||
setChecked(event.target.checked);
|
||||
dispatch(
|
||||
provinceChangeActiveStewardService({
|
||||
steward_key: guild?.key,
|
||||
active: event.target.checked,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<Tooltip title="مدیریت متصدی" placement="left">
|
||||
<IconButton color="primary" onClick={openPopover}>
|
||||
<TuneIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<Popover
|
||||
open={popoverOpen}
|
||||
anchorEl={anchorEl}
|
||||
onClose={closePopover}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
>
|
||||
<div style={{ padding: 10 }}>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
alignItems="flex-start"
|
||||
justifyContent="center"
|
||||
gap={1}
|
||||
>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={checked}
|
||||
onChange={handleChange}
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label={checked ? "فعال" : "غیرفعال"}
|
||||
style={{
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
display: "flex",
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
size="small"
|
||||
color="primary"
|
||||
startIcon={<EditIcon />}
|
||||
sx={{ fontSize: { xs: 12, md: 15 } }}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: "اعمال محدودیت",
|
||||
content: <EditStewards guild={guild} />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
اعمال محدودیت
|
||||
</Button>
|
||||
</Grid>
|
||||
</div>
|
||||
</Popover>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
import { FormControlLabel, Switch } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { updateGuildsSettingsService } from "../../services/update-guilds-settings";
|
||||
|
||||
export const ManageStewardsState = ({
|
||||
stewardState,
|
||||
choose_steward_guilds_key,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const [switchState, setSwitchState] = useState(stewardState);
|
||||
|
||||
const handleSwitchChange = () => {
|
||||
setSwitchState((prevState) => {
|
||||
dispatch(
|
||||
updateGuildsSettingsService({
|
||||
choose_steward_guilds_key,
|
||||
steward: !prevState,
|
||||
})
|
||||
);
|
||||
return !prevState;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container alignItems="center" justifyContent="center">
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={switchState}
|
||||
onChange={handleSwitchChange}
|
||||
name="switchState"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
// label="Toggle Switch"
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,122 @@
|
||||
import { Button, Tooltip, MenuItem, TextField } from "@mui/material";
|
||||
import axios from "axios";
|
||||
import { useEffect, useState } from "react";
|
||||
import { RiFileExcel2Fill } from "react-icons/ri";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { provinceGetStewardsService } from "../../services/province-get-stewards";
|
||||
import { ManageStewardsOperations } from "../manage-stewards-operations/ManageStewardsOperations";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
|
||||
export const ManageStewards = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const [statusFilter, setStatusFilter] = useState("همه");
|
||||
const { provinceGetStewards } = useSelector((state) => state.provinceSlice);
|
||||
const userKey = useSelector((state) => state.userSlice.userProfile.key);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetStewardsService());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const filtered =
|
||||
statusFilter === "همه"
|
||||
? provinceGetStewards
|
||||
: provinceGetStewards?.filter((item) =>
|
||||
statusFilter === "فعال" ? item?.active : !item?.active
|
||||
);
|
||||
|
||||
const d = filtered?.map((item, i) => {
|
||||
const dataRow = [
|
||||
i + 1,
|
||||
item?.guilds?.guildsId,
|
||||
item?.guilds?.guildsName,
|
||||
`${item?.guilds?.user?.fullname} (${item?.guilds?.user?.mobile})`,
|
||||
item?.guilds?.user?.nationalId,
|
||||
item?.guilds?.typeActivity,
|
||||
item?.guilds?.areaActivity,
|
||||
item?.guilds?.licenseNumber,
|
||||
`${item?.guilds?.address?.province.name}/${item?.guilds?.address?.city.name}`,
|
||||
item?.guilds?.address?.address,
|
||||
item?.limitationAllocation ? "دارد" : "ندارد",
|
||||
item?.allocationLimit?.toLocaleString(),
|
||||
item?.centersAllocation?.map((item) => item.label).join(" - "),
|
||||
item?.productInfo?.totalCarcassesWeight?.toLocaleString(),
|
||||
item?.productInfo?.realAllocatedWeight?.toLocaleString(),
|
||||
<ManageStewardsOperations guild={item} key={i} />,
|
||||
];
|
||||
|
||||
if (getRoleFromUrl() === "CityJahad") {
|
||||
dataRow.pop();
|
||||
}
|
||||
return dataRow;
|
||||
});
|
||||
|
||||
setDataTable(d);
|
||||
}, [provinceGetStewards, statusFilter]);
|
||||
|
||||
const columns = [
|
||||
"ردیف",
|
||||
"شناسه صنف",
|
||||
"نام واحد صنفی",
|
||||
"نام شخص/شرکت",
|
||||
"کدملی",
|
||||
"نوع فعالیت",
|
||||
"حوزه فعالیت",
|
||||
"شماره مجوز",
|
||||
"استان/شهرستان",
|
||||
"آدرس واحد صنفی",
|
||||
"محدودیت تخصیص",
|
||||
"حداکثر تخصیص",
|
||||
"مراکز تخصیص",
|
||||
"وزن خرید (کیلوگرم)",
|
||||
"وزن فروش (کیلوگرم)",
|
||||
"عملیات",
|
||||
];
|
||||
|
||||
if (getRoleFromUrl() === "CityJahad") {
|
||||
columns.pop();
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid container>
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<a
|
||||
href={`${
|
||||
axios.defaults.baseURL
|
||||
}stewards_excel/?role=${getRoleFromUrl()}&key=${userKey}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
|
||||
<TextField
|
||||
select
|
||||
label="وضعیت"
|
||||
value={statusFilter}
|
||||
onChange={(e) => setStatusFilter(e.target.value)}
|
||||
size="small"
|
||||
sx={{ width: 150 }}
|
||||
>
|
||||
<MenuItem value="همه">همه</MenuItem>
|
||||
<MenuItem value="فعال">فعال</MenuItem>
|
||||
<MenuItem value="غیرفعال">غیرفعال</MenuItem>
|
||||
</TextField>
|
||||
</Grid>
|
||||
|
||||
<ResponsiveTable
|
||||
title="مباشرین"
|
||||
paginated
|
||||
columns={columns}
|
||||
data={dataTable}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
36
src/features/province/components/manage-tab/ManageTab.js
Normal file
36
src/features/province/components/manage-tab/ManageTab.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { useState } from "react";
|
||||
import { Tab, Tabs } from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { MaangeGuilds } from "../manage-guilds/ManageGuilds";
|
||||
import { PspActiveSession } from "../../../psp-company/components/psp-active-session/PspActiveSession";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
|
||||
export const ManageTab = () => {
|
||||
const [value, setValue] = useState(0);
|
||||
|
||||
const handleChange = (event, newValue) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
return (
|
||||
<Grid container alignItems="center" justifyContent="center">
|
||||
<Grid xs={12} container alignItems="center" justifyContent="center">
|
||||
<Tabs
|
||||
scrollButtons="auto"
|
||||
variant="scrollable"
|
||||
allowScrollButtonsMobile
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
mt={2}
|
||||
>
|
||||
<Tab label="اصناف" value={0} />
|
||||
{getRoleFromUrl() !== "KillHouse" && (
|
||||
<Tab label="نشست ها" value={1} />
|
||||
)}
|
||||
</Tabs>
|
||||
</Grid>
|
||||
|
||||
{value === 0 && <MaangeGuilds readOnly={true} />}
|
||||
{value === 1 && <PspActiveSession readOnly={true} />}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,88 @@
|
||||
import { IconButton, Tooltip, Typography } from "@mui/material";
|
||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { slaughterGetKillerKillhousesService } from "../../../slaughter-house/services/slaughter-get-killers-killhouses";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
|
||||
export function MonitoringBuyers() {
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const { pathname } = useLocation();
|
||||
const [dataTable, setDataTable] = useState();
|
||||
const { slaughterGetKillerKillhouses } = useSelector(
|
||||
(state) => state.slaughterSlice
|
||||
);
|
||||
|
||||
// Get the first segment from pathname (adminx - could be superadmin or province)
|
||||
const getPathPrefix = () => {
|
||||
const segments = pathname.split("/").filter(Boolean);
|
||||
return segments[0] || "";
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(slaughterGetKillerKillhousesService());
|
||||
}, [dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
const d = slaughterGetKillerKillhouses?.map((item, i) => {
|
||||
const pathPrefix = getPathPrefix();
|
||||
|
||||
return [
|
||||
i + 1,
|
||||
item?.killer ? "کشتارکن" : "کشتارگاه",
|
||||
<Grid key={item.key} alignItems="center" justifyContent="center">
|
||||
<Typography variant="caption">{item?.name}</Typography>
|
||||
</Grid>,
|
||||
<Grid
|
||||
container
|
||||
key={item.key}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Typography variant="caption">
|
||||
{item?.killHouseOperator?.user?.fullname} (
|
||||
{item?.killHouseOperator?.user?.mobile})
|
||||
</Typography>
|
||||
</Grid>,
|
||||
item?.uniqueIdentifier && (
|
||||
<Tooltip title="مشاهده جزییات" key={item.key}>
|
||||
<IconButton
|
||||
size="small"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
navigate(
|
||||
`/${pathPrefix}/poultries/${item.uniqueIdentifier}?from=KillHouse`
|
||||
);
|
||||
}}
|
||||
>
|
||||
<VisibilityIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
),
|
||||
];
|
||||
});
|
||||
|
||||
setDataTable(d);
|
||||
}, [slaughterGetKillerKillhouses, navigate, pathname]);
|
||||
|
||||
return (
|
||||
<Grid mt={SPACING.SMALL}>
|
||||
<ResponsiveTable
|
||||
paginated
|
||||
title="خریداران"
|
||||
columns={[
|
||||
"ردیف",
|
||||
"ماهیت",
|
||||
"نام واحد",
|
||||
"نام و نام خانوادگی (تلفن)",
|
||||
"مشاهده جزییات",
|
||||
]}
|
||||
data={dataTable}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
import { Button } from "@mui/material";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { ProvincePaymentPayDept } from "../province-payment-pay-dept/ProvincePaymentPayDept";
|
||||
import { OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { parentCompanyGetWagesOfKillhousesService } from "../../services/province-get-wages-of-killhouses";
|
||||
import { parentConpanyGetPaymentByWeightOverview } from "../../services/province-get-payment-by-weight-overview";
|
||||
import { ProvinceWagePaymentTransactions } from "../province-wage-payment-transactions/ProvinceWagePaymentTransactions";
|
||||
|
||||
export const ParentCompanyPaymentByWeightOverviewTable = ({ province }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [tableDataOfWages, setTableDataOfWages] = useState();
|
||||
|
||||
const { parentCompanyPaymentByWeightOverview } = useSelector(
|
||||
(item) => item.provinceSlice
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(parentConpanyGetPaymentByWeightOverview(province));
|
||||
|
||||
if (getRoleFromUrl() !== "KillHouse") {
|
||||
dispatch(parentCompanyGetWagesOfKillhousesService(province)).then((r) => {
|
||||
const d = r.payload.data?.map((item, i) => {
|
||||
return [
|
||||
i + 1,
|
||||
item?.name,
|
||||
Math.ceil(item?.wageInfo?.totalWage)?.toLocaleString(),
|
||||
Math.ceil(item?.wageInfo?.totalPaidWage)?.toLocaleString(),
|
||||
Math.ceil(item?.wageInfo?.off)?.toLocaleString(),
|
||||
Math.ceil(item?.wageInfo?.totalUnpaidWage)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
item?.wageInfo?.totalProvinceLiveWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
item?.wageInfo?.totalProvinceCarcassesWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
item?.wageInfo?.provinceKillRequestsTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
item?.wageInfo?.provinceKillRequestsTotalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
item?.wageInfo?.freeBarsOutProvinceCarcasesTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
item?.wageInfo?.freeBarsOutProvinceCarcasesTotalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
item?.wageInfo?.freeBarsCarcasesTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
item?.wageInfo?.freeBarsCarcasesTotalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
item?.wageInfo?.freeBarsLiveTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(item?.wageInfo?.freeBarsLiveTotalWage)?.toLocaleString(),
|
||||
];
|
||||
});
|
||||
|
||||
setTableDataOfWages(d);
|
||||
});
|
||||
}
|
||||
}, [dispatch, province]);
|
||||
|
||||
return (
|
||||
<Grid container justifyContent="center" xs={12} mt={1}>
|
||||
<Grid isDashboard container justifyContent="center" xs={12} p={2}>
|
||||
<Grid container xs={12} justifyContent="space-between">
|
||||
{(getRoleFromUrl() === "KillHouse" ||
|
||||
getRoleFromUrl() === "ChainCompany") && (
|
||||
<Grid>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "پرداخت تعرفه",
|
||||
content: <ProvincePaymentPayDept />,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
پرداخت تعرفه
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
{/* {(getRoleFromUrl() === "KillHouse" ||
|
||||
getRoleFromUrl() === "ChainCompany") && (
|
||||
<Grid>
|
||||
<Button variant="contained" href="https://zarinp.al/ravandno">
|
||||
پرداخت تعرفه
|
||||
</Button>
|
||||
</Grid>
|
||||
)} */}
|
||||
</Grid>
|
||||
<ResponsiveTable
|
||||
isDashboard
|
||||
noPagination
|
||||
title="اطلاعات کلی تعرفه"
|
||||
columns={[
|
||||
"کل تعرفه (ریال)",
|
||||
"کل تعرفه پرداخت شده (ریال)",
|
||||
"تخفیف (ریال)",
|
||||
"کل تعرفه پرداخت نشده (ریال)",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
// Math.ceil(
|
||||
// parentCompanyPaymentByWeightOverview?.wageInfo?.totalWeight
|
||||
// )?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo?.totalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo?.totalPaidWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo?.off
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo?.totalUnpaidWage
|
||||
)?.toLocaleString(),
|
||||
],
|
||||
]}
|
||||
/>
|
||||
|
||||
{getRoleFromUrl() !== "KillHouse" && (
|
||||
<ResponsiveTable
|
||||
noPagination
|
||||
title="جزئیات کلی تعرفه"
|
||||
columns={[
|
||||
"کل وزن زنده کشتار داخل استان (کیلوگرم)",
|
||||
"وزن لاشه کشتار داخل استان (کیلوگرم)",
|
||||
"وزن توزیع لاشه داخل استان (کیلوگرم)",
|
||||
"تعرفه توزیع لاشه داخل استان (ریال)",
|
||||
"وزن توزیع لاشه به خارج استان (کیلوگرم)",
|
||||
"تعرفه توزیع لاشه خارج استان (ریال)",
|
||||
"وزن لاشه ورودی به استان (کیلوگرم)",
|
||||
"تعرفه لاشه ورودی به استان (ریال)",
|
||||
"وزن مرغ زنده ورودی به استان (کیلوگرم)",
|
||||
"تعرفه مرغ زنده ورودی به استان (ریال)",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.totalProvinceLiveWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.totalProvinceCarcassesWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.provinceKillRequestsTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.provinceKillRequestsTotalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsOutProvinceCarcasesTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsOutProvinceCarcasesTotalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsCarcasesTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsCarcasesTotalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsLiveTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsLiveTotalWage
|
||||
)?.toLocaleString(),
|
||||
],
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
<Grid container justifyContent="center" xs={12} mt={2} mb={2}>
|
||||
<ResponsiveTable
|
||||
noPagination
|
||||
title="مبنای تعرفه به ازای هر کیلوگرم (ریال)"
|
||||
columns={[
|
||||
"تعرفه پایه توزیع لاشه درون استان",
|
||||
"تعرفه پایه توزیع لاشه خارج استان",
|
||||
"تعرفه پایه خرید مرغ زنده خارج از استان",
|
||||
"تعرفه پایه لاشه خارج از استان",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo?.provinceLiveWageAmount?.toLocaleString(),
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo?.freeSellCarcessesWeightAmount?.toLocaleString(),
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo?.freeBuyingLiveWeightAmount?.toLocaleString(),
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo?.freeBuyingCarcessesWeightAmount?.toLocaleString(),
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid container justifyContent="center" xs={12} mt={1}>
|
||||
<ResponsiveTable
|
||||
noPagination={getRoleFromUrl() === "KillHouse"}
|
||||
paginated={getRoleFromUrl() !== "KillHouse"}
|
||||
title="جزئیات"
|
||||
columns={
|
||||
getRoleFromUrl() === "KillHouse"
|
||||
? [
|
||||
"کل تعرفه (ریال)",
|
||||
"کل تعرفه پرداخت شده (ریال)",
|
||||
"تخفیف (ریال)",
|
||||
"کل تعرفه پرداخت نشده (ریال)",
|
||||
"کل وزن زنده کشتار داخل استان (کیلوگرم)",
|
||||
"وزن لاشه کشتار داخل استان (کیلوگرم)",
|
||||
"وزن توزیع لاشه داخل استان (کیلوگرم)",
|
||||
"تعرفه توزیع لاشه داخل استان (ریال)",
|
||||
"وزن توزیع لاشه به خارج استان (کیلوگرم)",
|
||||
"تعرفه توزیع لاشه خارج استان (ریال)",
|
||||
"وزن لاشه ورودی به استان (کیلوگرم)",
|
||||
"تعرفه لاشه ورودی به استان (ریال)",
|
||||
"وزن مرغ زنده ورودی به استان (کیلوگرم)",
|
||||
"تعرفه مرغ زنده ورودی به استان (ریال)",
|
||||
]
|
||||
: [
|
||||
"ردیف",
|
||||
"کشتارگاه",
|
||||
"کل تعرفه (ریال)",
|
||||
"کل تعرفه پرداخت شده (ریال)",
|
||||
"تخفیف (ریال)",
|
||||
"کل تعرفه پرداخت نشده (ریال)",
|
||||
"کل وزن زنده کشتار داخل استان (کیلوگرم)",
|
||||
"وزن لاشه کشتار داخل استان (کیلوگرم)",
|
||||
"وزن توزیع لاشه داخل استان (کیلوگرم)",
|
||||
"تعرفه توزیع لاشه داخل استان (ریال)",
|
||||
"وزن توزیع لاشه به خارج استان (کیلوگرم)",
|
||||
"تعرفه توزیع لاشه خارج استان (ریال)",
|
||||
"وزن لاشه ورودی به استان (کیلوگرم)",
|
||||
"تعرفه لاشه ورودی به استان (ریال)",
|
||||
"وزن مرغ زنده ورودی به استان (کیلوگرم)",
|
||||
"تعرفه مرغ زنده ورودی به استان (ریال)",
|
||||
]
|
||||
}
|
||||
data={
|
||||
getRoleFromUrl() === "KillHouse"
|
||||
? [
|
||||
[
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo?.totalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.totalPaidWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo?.off
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.totalUnpaidWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.totalProvinceLiveWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.totalProvinceCarcassesWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.provinceKillRequestsTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.provinceKillRequestsTotalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsOutProvinceCarcasesTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsOutProvinceCarcasesTotalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsCarcasesTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsCarcasesTotalWage
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsLiveTotalWeight
|
||||
)?.toLocaleString(),
|
||||
Math.ceil(
|
||||
parentCompanyPaymentByWeightOverview?.wageInfo
|
||||
?.freeBarsLiveTotalWage
|
||||
)?.toLocaleString(),
|
||||
],
|
||||
]
|
||||
: tableDataOfWages
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<ProvinceWagePaymentTransactions province={province} />
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Switch } from "@mui/material";
|
||||
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 { policyChangeKillhouseDirectBuyService } from "../../services/policy-change-killhouse-direct-buy";
|
||||
import { provinceGetKillhousesService } from "../../services/province-get-killhouses";
|
||||
import { BackButton } from "../../../../components/back-button/BackButton";
|
||||
|
||||
export const PolicyKillhouseDirectBuy = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { provinceGetKillhouses } = useSelector((state) => state.provinceSlice);
|
||||
const [data, setData] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetKillhousesService());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const d = provinceGetKillhouses?.map((item) => {
|
||||
return [
|
||||
item.killHouse.name,
|
||||
<Switch
|
||||
key="kkk"
|
||||
checked={item.allow}
|
||||
onChange={(event) => {
|
||||
dispatch(
|
||||
policyChangeKillhouseDirectBuyService({
|
||||
direct_buying_key: item.key,
|
||||
allow: event.target.checked,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(provinceGetKillhousesService());
|
||||
});
|
||||
// setChecked(event.target.checked);
|
||||
}}
|
||||
name="checked"
|
||||
color="primary"
|
||||
/>,
|
||||
<Switch
|
||||
key="kkk"
|
||||
checked={item.exportStatus}
|
||||
onChange={(event) => {
|
||||
dispatch(
|
||||
policyChangeKillhouseDirectBuyService({
|
||||
direct_buying_key: item.key,
|
||||
export_status: event.target.checked,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(provinceGetKillhousesService());
|
||||
});
|
||||
// setChecked(event.target.checked);
|
||||
}}
|
||||
name="checked"
|
||||
color="primary"
|
||||
/>,
|
||||
];
|
||||
});
|
||||
setData(d);
|
||||
}, [provinceGetKillhouses]);
|
||||
|
||||
return (
|
||||
<Grid container>
|
||||
<BackButton />
|
||||
<AdvancedTable
|
||||
name="اجازه خرید مستقیم"
|
||||
columns={["کشتارگاه/کشتارکن", "خرید مستقیم", "صادرات"]}
|
||||
data={data}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Switch } from "@mui/material";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { BackButton } from "../../../../components/back-button/BackButton";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { policyChangeKillhouseGuildsService } from "../../services/policy-change-killhouse-guilds";
|
||||
import { provinceGetKillhousesGuildsService } from "../../services/province-get-killhouses-guilds";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
|
||||
export const PolicyKillhouseGuilds = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { provinceGetKillhousesGuilds } = useSelector(
|
||||
(state) => state.provinceSlice
|
||||
);
|
||||
const [data, setData] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetKillhousesGuildsService());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const d = provinceGetKillhousesGuilds?.map((item, i) => {
|
||||
return [
|
||||
item.killHouse?.name,
|
||||
item.killHouse?.killer ? "کشتارکن" : "کشتارگاه",
|
||||
<Switch
|
||||
key={i}
|
||||
checked={item.allow}
|
||||
onChange={(event) => {
|
||||
dispatch(
|
||||
policyChangeKillhouseGuildsService({
|
||||
register_guilds_key: item.key,
|
||||
allow: event.target.checked,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(provinceGetKillhousesGuildsService());
|
||||
});
|
||||
// setChecked(event.target.checked);
|
||||
}}
|
||||
name="checked"
|
||||
color="primary"
|
||||
/>,
|
||||
];
|
||||
});
|
||||
setData(d);
|
||||
}, [provinceGetKillhousesGuilds]);
|
||||
|
||||
return (
|
||||
<Grid container>
|
||||
<BackButton />
|
||||
<ResponsiveTable
|
||||
paginated
|
||||
title="دسترسی به اصناف"
|
||||
columns={["کشتارگاه/کشتارکن", "ماهیت", "دسترسی"]}
|
||||
data={data}
|
||||
customColors={[{ name: "ماهیت", color: "green" }]}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
import { Switch } from "@mui/material";
|
||||
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 { policyChangePoultryChooseSlaughterService } from "../../services/policy-change-poultry-choose-slaughter";
|
||||
import { provinceGetPoultriesService } from "../../services/province-get-poultries";
|
||||
|
||||
export const PolicyPoultryChooseSlaughter = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { provinceGetPoultries } = useSelector((state) => state.provinceSlice);
|
||||
const [data, setData] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetPoultriesService());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const d = provinceGetPoultries?.map((item) => {
|
||||
return [
|
||||
item.name,
|
||||
<Switch
|
||||
key="kkk"
|
||||
checked={item.allowState}
|
||||
onChange={(event) => {
|
||||
dispatch(
|
||||
policyChangePoultryChooseSlaughterService({
|
||||
poultry_key: item.key,
|
||||
allow: event.target.checked,
|
||||
})
|
||||
).then(() => {
|
||||
dispatch(provinceGetPoultriesService());
|
||||
});
|
||||
// setChecked(event.target.checked);
|
||||
}}
|
||||
name="checked"
|
||||
color="primary"
|
||||
/>,
|
||||
];
|
||||
});
|
||||
setData(d);
|
||||
}, [provinceGetPoultries]);
|
||||
|
||||
return (
|
||||
<Grid container>
|
||||
<AdvancedTable
|
||||
name="دسترسی مرغداران جهت انتخاب کشتارگاه"
|
||||
columns={["مرغدار", "دسترسی"]}
|
||||
data={data}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Switch } from "@mui/material";
|
||||
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 { policyChangePoultryFreeSalesService } from "../../services/policy-change-poultry-free-sales";
|
||||
import { provinceGetPoultriesService } from "../../services/province-get-poultries";
|
||||
import { BackButton } from "../../../../components/back-button/BackButton";
|
||||
|
||||
export const PolicyPoultryFreeSale = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { provinceGetPoultries } = useSelector((state) => state.provinceSlice);
|
||||
const [data, setData] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetPoultriesService());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const d = provinceGetPoultries?.map((item) => {
|
||||
return [
|
||||
item.name,
|
||||
<Switch
|
||||
key="kkk"
|
||||
checked={item.allowSellState}
|
||||
onChange={(event) => {
|
||||
dispatch(
|
||||
policyChangePoultryFreeSalesService({
|
||||
poultry_key: item.key,
|
||||
allow: event.target.checked,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(provinceGetPoultriesService());
|
||||
});
|
||||
// setChecked(event.target.checked);
|
||||
}}
|
||||
name="checked"
|
||||
color="primary"
|
||||
/>,
|
||||
];
|
||||
});
|
||||
setData(d);
|
||||
}, [provinceGetPoultries]);
|
||||
|
||||
return (
|
||||
<Grid container>
|
||||
<BackButton />
|
||||
<AdvancedTable
|
||||
name="دسترسی مرغداران جهت فروش آزاد"
|
||||
columns={["مرغدار", "دسترسی"]}
|
||||
data={data}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,647 @@
|
||||
import { Fragment, useContext, useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { useParams, useSearchParams } from "react-router-dom";
|
||||
import {
|
||||
Autocomplete,
|
||||
Checkbox,
|
||||
CircularProgress,
|
||||
Tab,
|
||||
Tabs,
|
||||
TextField,
|
||||
Typography,
|
||||
IconButton,
|
||||
} from "@mui/material";
|
||||
import { useDispatch } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment";
|
||||
import ToggleOffOutlinedIcon from "@mui/icons-material/ToggleOffOutlined";
|
||||
import ToggleOnIcon from "@mui/icons-material/ToggleOn";
|
||||
import SearchIcon from "@mui/icons-material/Search";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import { CheckCleanceCode } from "../../../../components/check-clearance-code/ChechClearanceCode";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { getPoultryTransportByCodeService } from "../../services/get-poultry-transport-by-code";
|
||||
import { getPoultryTransportProductsByCodeService } from "../../services/get-poultry-transport-products-by-code";
|
||||
import { getPoultryTransportDashboardByCodeService } from "../../services/get-poultry-transport-dashboard-by-code";
|
||||
|
||||
export const PoultriesDetails = () => {
|
||||
const { key } = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
const from = searchParams.get("from");
|
||||
const dispatch = useDispatch();
|
||||
const [tabValue, setTabValue] = useState("1");
|
||||
const [tableData, setTableData] = useState([]);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [page, setPage] = useState(1);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [isLoading, setIsLoading] = useState(false); // eslint-disable-line no-unused-vars
|
||||
const [error, setError] = useState(null);
|
||||
const [withDate, setWithDate] = useState(true);
|
||||
const [productOptions, setProductOptions] = useState([]);
|
||||
const [selectedProduct, setSelectedProduct] = useState("");
|
||||
const [isProductLoading, setIsProductLoading] = useState(false);
|
||||
const [searchValue, setSearchValue] = useState("");
|
||||
const [searchInput, setSearchInput] = useState("");
|
||||
const [dashboardData, setDashboardData] = useState(null);
|
||||
const [provinceOptions, setProvinceOptions] = useState([]);
|
||||
const [selectedProvince, setSelectedProvince] = useState("");
|
||||
const [isProvinceLoading, setIsProvinceLoading] = useState(false);
|
||||
console.log(from);
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
|
||||
const columns = [
|
||||
"ردیف",
|
||||
"کد رهگیری",
|
||||
"محصول",
|
||||
"اقلام",
|
||||
"مقدار",
|
||||
"واحد",
|
||||
"تاریخ",
|
||||
"مقصد",
|
||||
"شناسه مقصد",
|
||||
"استان مقصد",
|
||||
"شهرستان مقصد",
|
||||
"مبدا",
|
||||
"شناسه مبدا",
|
||||
"استان مبدا",
|
||||
"شهرستان مبدا",
|
||||
"نوع حمل",
|
||||
"مقصد قبلی",
|
||||
"تغییر مقصد",
|
||||
"کد رهگیری خودرو",
|
||||
"تاریخ تخلیه",
|
||||
"تخلیه",
|
||||
];
|
||||
|
||||
const formatNumber = (value) => {
|
||||
if (value === null || value === undefined) {
|
||||
return "-";
|
||||
}
|
||||
if (typeof value === "number") {
|
||||
return value.toLocaleString("fa-IR");
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
const safeValue = (value) => {
|
||||
if (value === null || value === undefined || value === "") {
|
||||
return "-";
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
const formatPercent = (value) => {
|
||||
if (value === null || value === undefined) {
|
||||
return "-";
|
||||
}
|
||||
const numericValue = Number(value);
|
||||
if (Number.isNaN(numericValue)) {
|
||||
return "-";
|
||||
}
|
||||
return `${numericValue.toFixed(1)}%`;
|
||||
};
|
||||
|
||||
const formatDateTimeFromIso = (value) => {
|
||||
if (!value) return "-";
|
||||
const dateObj = new Date(value);
|
||||
if (Number.isNaN(dateObj.getTime())) return "-";
|
||||
const date = dateObj.toLocaleDateString("fa-IR");
|
||||
const time = dateObj.toLocaleTimeString("fa-IR", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
});
|
||||
return `${date} ${time}`;
|
||||
};
|
||||
|
||||
const dashboardColumns = [
|
||||
"محصول",
|
||||
"تعداد بار",
|
||||
"حجم بار (کیلوگرم)",
|
||||
"تعداد بار داخل استان",
|
||||
"حجم بار داخل استان (کیلوگرم)",
|
||||
"درصد داخل استان",
|
||||
"تعداد بار خارج استان",
|
||||
"حجم بار خارج استان (کیلوگرم)",
|
||||
"درصد خارج استان",
|
||||
"آخرین بروزرسانی",
|
||||
];
|
||||
|
||||
const handleTabChange = (event, newValue) => {
|
||||
setTabValue(newValue);
|
||||
setSelectedProduct("");
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
const normalizedSearch = searchInput.trim();
|
||||
setSearchValue(normalizedSearch);
|
||||
setSearchInput(normalizedSearch);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setPage(1);
|
||||
}, [
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
withDate,
|
||||
selectedProduct,
|
||||
searchValue,
|
||||
tabValue,
|
||||
selectedProvince,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const isMounted = { current: true };
|
||||
|
||||
const fetchProvinces = async () => {
|
||||
try {
|
||||
setIsProvinceLoading(true);
|
||||
const { data } = await axios.get("iran_province/");
|
||||
if (!isMounted.current) {
|
||||
return;
|
||||
}
|
||||
const names =
|
||||
data?.map?.((item) => item?.name).filter((name) => !!name) ?? [];
|
||||
setProvinceOptions(names);
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch provinces:", err);
|
||||
} finally {
|
||||
if (isMounted.current) {
|
||||
setIsProvinceLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchProvinces();
|
||||
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!key) return;
|
||||
|
||||
const isMounted = { current: true };
|
||||
|
||||
const fetchProducts = async () => {
|
||||
try {
|
||||
setIsProductLoading(true);
|
||||
const type = tabValue === "1" ? "in" : "out";
|
||||
const response = await dispatch(
|
||||
getPoultryTransportProductsByCodeService({
|
||||
code: key,
|
||||
type: type,
|
||||
date1: withDate && selectedDate1 ? selectedDate1 : "",
|
||||
date2: withDate && selectedDate2 ? selectedDate2 : "",
|
||||
search: searchValue || "",
|
||||
from: from,
|
||||
})
|
||||
);
|
||||
|
||||
if (!isMounted.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.error) {
|
||||
console.error("Failed to fetch products:", response.error);
|
||||
return;
|
||||
}
|
||||
|
||||
const products = Array.isArray(response.payload?.data?.products)
|
||||
? response.payload.data.products
|
||||
: [];
|
||||
setProductOptions(products);
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch product types:", err);
|
||||
} finally {
|
||||
if (isMounted.current) {
|
||||
setIsProductLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchProducts();
|
||||
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
};
|
||||
}, [
|
||||
key,
|
||||
tabValue,
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
withDate,
|
||||
searchValue,
|
||||
dispatch,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!key) return;
|
||||
|
||||
const isMounted = { current: true };
|
||||
|
||||
const fetchDashboardData = async () => {
|
||||
try {
|
||||
const type = tabValue === "1" ? "in" : "out";
|
||||
const response = await dispatch(
|
||||
getPoultryTransportDashboardByCodeService({
|
||||
code: key,
|
||||
type: type,
|
||||
date1: withDate && selectedDate1 ? selectedDate1 : "",
|
||||
date2: withDate && selectedDate2 ? selectedDate2 : "",
|
||||
search: searchValue || "",
|
||||
product: selectedProduct || "",
|
||||
province: selectedProvince || "",
|
||||
from: from,
|
||||
})
|
||||
);
|
||||
|
||||
if (!isMounted.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response.error && response.payload?.data) {
|
||||
setDashboardData(response.payload.data);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch dashboard data:", err);
|
||||
}
|
||||
};
|
||||
|
||||
fetchDashboardData();
|
||||
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
};
|
||||
}, [
|
||||
key,
|
||||
tabValue,
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
withDate,
|
||||
selectedProduct,
|
||||
searchValue,
|
||||
selectedProvince,
|
||||
dispatch,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!key) return;
|
||||
|
||||
const isMounted = { current: true };
|
||||
|
||||
const fetchTransportData = async () => {
|
||||
try {
|
||||
setError(null);
|
||||
setIsLoading(true);
|
||||
|
||||
const type = tabValue === "1" ? "in" : "out";
|
||||
|
||||
const response = await dispatch(
|
||||
getPoultryTransportByCodeService({
|
||||
code: key,
|
||||
type: type,
|
||||
page: page,
|
||||
page_size: perPage,
|
||||
date1: withDate && selectedDate1 ? selectedDate1 : "",
|
||||
date2: withDate && selectedDate2 ? selectedDate2 : "",
|
||||
search: searchValue || "",
|
||||
product: selectedProduct || "",
|
||||
province: selectedProvince || "",
|
||||
from: from,
|
||||
})
|
||||
);
|
||||
|
||||
if (!isMounted.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.error) {
|
||||
setError(response.error);
|
||||
return;
|
||||
}
|
||||
|
||||
const responseData = response.payload?.data ?? { results: [] };
|
||||
const results = responseData?.results ?? [];
|
||||
|
||||
const mappedTableData = results.map((item, index) => [
|
||||
safeValue(formatNumber(index + 1 + (page - 1) * perPage)),
|
||||
<CheckCleanceCode
|
||||
key={item?.tracking || index}
|
||||
clearanceCode={item?.tracking}
|
||||
/>,
|
||||
safeValue(item?.product),
|
||||
safeValue(item?.items),
|
||||
safeValue(formatNumber(item?.quantity)),
|
||||
safeValue(item?.unit),
|
||||
safeValue(formatJustDate(item?.date)),
|
||||
safeValue(item?.destination),
|
||||
safeValue(item?.jihadiDestination),
|
||||
safeValue(item?.destinationProvince),
|
||||
safeValue(item?.destinationCity),
|
||||
safeValue(item?.origin),
|
||||
safeValue(item?.jihadiOrigin),
|
||||
safeValue(item?.originProvince),
|
||||
safeValue(item?.originCity),
|
||||
safeValue(
|
||||
item?.originProvince === item?.destinationProvince
|
||||
? "داخل استان"
|
||||
: "خارج استان"
|
||||
),
|
||||
safeValue(item?.destinationPrev),
|
||||
safeValue(item?.destinationChanged),
|
||||
safeValue(item?.carTrackingCode),
|
||||
safeValue(formatJustDate(item?.unloadingDate)),
|
||||
safeValue(item?.unloading),
|
||||
]);
|
||||
|
||||
setTableData(mappedTableData);
|
||||
setTotalRows(responseData?.count ?? 0);
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch transport data:", err);
|
||||
if (!isMounted.current) {
|
||||
return;
|
||||
}
|
||||
setError(err);
|
||||
} finally {
|
||||
if (isMounted.current) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchTransportData();
|
||||
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
};
|
||||
}, [
|
||||
key,
|
||||
tabValue,
|
||||
page,
|
||||
perPage,
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
withDate,
|
||||
selectedProduct,
|
||||
searchValue,
|
||||
selectedProvince,
|
||||
dispatch,
|
||||
]);
|
||||
|
||||
const handlePageChange = (newPage) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (newPerPage) => {
|
||||
setPerPage(newPerPage);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid container justifyContent="center" xs={12} mt={2}>
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
xs={12}
|
||||
mt={2}
|
||||
>
|
||||
<Tabs
|
||||
scrollButtons="auto"
|
||||
variant="scrollable"
|
||||
allowScrollButtonsMobile
|
||||
value={tabValue}
|
||||
onChange={handleTabChange}
|
||||
>
|
||||
<Tab label="بارهای ورودی" value="1" />
|
||||
<Tab label="بارهای خروجی" value="2" />
|
||||
</Tabs>
|
||||
</Grid>
|
||||
{dashboardData && (
|
||||
<Grid container mt={2} mb={4} isDashboard xs={12}>
|
||||
<ResponsiveTable
|
||||
noPagination
|
||||
isDashboard
|
||||
columns={dashboardColumns}
|
||||
data={[
|
||||
[
|
||||
safeValue(dashboardData?.product),
|
||||
safeValue(formatNumber(dashboardData?.bars)),
|
||||
safeValue(formatNumber(dashboardData?.totalBarsWight)),
|
||||
safeValue(formatNumber(dashboardData?.inputBars)),
|
||||
safeValue(formatNumber(dashboardData?.totalInputBarsWight)),
|
||||
formatPercent(dashboardData?.totalInputBarsPercent),
|
||||
safeValue(formatNumber(dashboardData?.outputBars)),
|
||||
safeValue(formatNumber(dashboardData?.totalOutputBarsWight)),
|
||||
formatPercent(dashboardData?.totalOutputBarsPercent),
|
||||
formatDateTimeFromIso(dashboardData?.lastUpdate),
|
||||
],
|
||||
]}
|
||||
title="داشبورد"
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
gap={2}
|
||||
xs={12}
|
||||
mt={2}
|
||||
px={2}
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
gap={1}
|
||||
style={{
|
||||
borderStyle: "solid",
|
||||
borderWidth: "1px",
|
||||
padding: "5px",
|
||||
borderRadius: "15px",
|
||||
borderColor: "gray",
|
||||
justifyContent: "left",
|
||||
maxWidth: "fit-content",
|
||||
}}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Checkbox
|
||||
icon={<ToggleOffOutlinedIcon />}
|
||||
checkedIcon={<ToggleOnIcon />}
|
||||
checked={withDate}
|
||||
onChange={() => setWithDate(!withDate)}
|
||||
color="primary"
|
||||
size="large"
|
||||
/>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
disabled={!withDate}
|
||||
label="از تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
size="small"
|
||||
sx={{ width: { xs: "126px", md: "160px" } }}
|
||||
{...params}
|
||||
/>
|
||||
)}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
if (!e) return;
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
disabled={!withDate}
|
||||
label="تا تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
size="small"
|
||||
sx={{ width: { xs: "126px", md: "160px" } }}
|
||||
{...params}
|
||||
/>
|
||||
)}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
if (!e) return;
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
gap={1}
|
||||
sx={{ maxWidth: "fit-content" }}
|
||||
>
|
||||
<Autocomplete
|
||||
options={provinceOptions}
|
||||
loading={isProvinceLoading}
|
||||
value={selectedProvince || null}
|
||||
onChange={(_, value) => {
|
||||
setSelectedProvince(value || "");
|
||||
}}
|
||||
noOptionsText="استانی یافت نشد"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label={tabValue === "2" ? "استان مقصد" : "استان مبدا"}
|
||||
size="small"
|
||||
sx={{ width: { xs: 200, md: 240 } }}
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
endAdornment: (
|
||||
<>
|
||||
{isProvinceLoading ? (
|
||||
<CircularProgress color="inherit" size={16} />
|
||||
) : null}
|
||||
{params.InputProps.endAdornment}
|
||||
</>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
clearOnEscape
|
||||
/>
|
||||
<Autocomplete
|
||||
options={productOptions}
|
||||
loading={isProductLoading}
|
||||
value={selectedProduct || null}
|
||||
onChange={(_, value) => {
|
||||
setSelectedProduct(value || "");
|
||||
}}
|
||||
noOptionsText="محصولی یافت نشد"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label="نوع محصول"
|
||||
size="small"
|
||||
sx={{ width: { xs: 200, md: 240 } }}
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
endAdornment: (
|
||||
<>
|
||||
{isProductLoading ? (
|
||||
<CircularProgress color="inherit" size={16} />
|
||||
) : null}
|
||||
{params.InputProps.endAdornment}
|
||||
</>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
clearOnEscape
|
||||
/>
|
||||
|
||||
<Grid
|
||||
item
|
||||
component="form"
|
||||
onSubmit={handleSubmit}
|
||||
sx={{ width: { xs: 220, md: 260 }, display: "flex" }}
|
||||
>
|
||||
<TextField
|
||||
value={searchInput}
|
||||
onChange={(event) => setSearchInput(event.target.value)}
|
||||
label="جستجو"
|
||||
size="small"
|
||||
variant="outlined"
|
||||
sx={{ flexGrow: 1 }}
|
||||
/>
|
||||
<IconButton
|
||||
type="submit"
|
||||
color="primary"
|
||||
aria-label="جستجو"
|
||||
sx={{ ml: 1 }}
|
||||
>
|
||||
<SearchIcon />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
px={2}
|
||||
xs={12}
|
||||
mt={2}
|
||||
>
|
||||
{error && (
|
||||
<Grid container justifyContent="center" xs={12}>
|
||||
<Typography variant="body1" color="error">
|
||||
خطا در دریافت اطلاعات
|
||||
</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
{!error && (
|
||||
<ResponsiveTable
|
||||
columns={columns}
|
||||
data={tableData}
|
||||
title={tabValue === "1" ? "بارهای ورودی" : "بارهای خروجی"}
|
||||
paginated={false}
|
||||
handlePageChange={handlePageChange}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Button, TextField, Typography } from "@mui/material";
|
||||
import { useContext, useState } 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 { provinceAcceptSlaughterFreeBuyService } from "../../../slaughter-house/services/province-accept-slaughter-free-buy";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
|
||||
export const ProvinceAcceptDirectBuy = ({ item, updateTable }) => {
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const dispatch = useDispatch();
|
||||
const [text, setText] = useState(item.killCapacity);
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setText(event.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container direction="column" gap={SPACING.TINY} width="100%">
|
||||
<Typography variant="body1" color="error">
|
||||
مانده در سالن مرغدار:{" "}
|
||||
{item?.poultry?.leftOverOwnHatching?.toLocaleString()}
|
||||
</Typography>
|
||||
<TextField
|
||||
label="تعداد تایید شده"
|
||||
variant="outlined"
|
||||
type="number"
|
||||
fullWidth
|
||||
value={text}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={parseInt(text) > item?.poultry?.leftOverOwnHatching || !text}
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceAcceptSlaughterFreeBuyService({
|
||||
state: "accepted",
|
||||
kill_request_key: item.key,
|
||||
quantity: text,
|
||||
role: getRoleFromUrl(),
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
dispatch(CLOSE_MODAL());
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import { Card, IconButton } from "@mui/material";
|
||||
import { useEffect, useState } from "react";
|
||||
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { provinceGetActiveRequestsService } from "../../services/province-get-active-requests";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { ROUTE_PROVINCE_FILE } from "../../../../routes/routes";
|
||||
import PlagiarismIcon from "@mui/icons-material/Plagiarism";
|
||||
import { format } from "date-fns-jalali";
|
||||
|
||||
export const ProvinceActiveRequests = () => {
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const { provinceGetActiveRequests } = useSelector(
|
||||
(state) => state.provinceSlice
|
||||
);
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetActiveRequestsService());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const d = provinceGetActiveRequests?.map((item, i) => {
|
||||
return [
|
||||
i + 1,
|
||||
item?.poultryRequest?.orderCode,
|
||||
format(new Date(item?.poultryRequest?.createDate), "yyyy/MM/dd"),
|
||||
format(new Date(item?.poultryRequest?.sendDate), "yyyy/MM/dd"),
|
||||
item?.poultryRequest?.process?.poultry?.poultryName,
|
||||
item?.poultryRequest?.process?.poultry?.poultryMobile,
|
||||
item?.poultryRequest?.process?.poultry?.poultryCity,
|
||||
item?.poultryRequest?.process?.poultry?.poultryProvince,
|
||||
item?.poultryRequest?.process?.poultry?.age,
|
||||
item?.poultryRequest?.process?.poultry?.poultryQuantity,
|
||||
<IconButton
|
||||
key={i}
|
||||
aria-label="delete"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
navigate(
|
||||
ROUTE_PROVINCE_FILE +
|
||||
item?.poultryRequest?.process?.poultry?.poultryRequestId
|
||||
);
|
||||
}}
|
||||
>
|
||||
<PlagiarismIcon />
|
||||
</IconButton>,
|
||||
];
|
||||
});
|
||||
setDataTable(d);
|
||||
}, [provinceGetActiveRequests]);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<AdvancedTable
|
||||
name={"درخواست های فعال"}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"کد سفارش",
|
||||
"تاریخ ثبت درخواست",
|
||||
"تاریخ کشتار",
|
||||
"مرغدار",
|
||||
"تلفن مرغدار",
|
||||
"شهر",
|
||||
"استان",
|
||||
"سن مرغ",
|
||||
"تعداد",
|
||||
"مشاهده",
|
||||
]}
|
||||
data={dataTable}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,128 @@
|
||||
import { Autocomplete, Button, TextField } from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { NumberInput } from "../../../../components/number-format-custom/NumberFormatCustom";
|
||||
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { provinceGetBuyersService } from "../../services/province-get-buyers";
|
||||
|
||||
export const ProvinceAddBuyerAutoAllocation = ({
|
||||
dataTable,
|
||||
setDataTable,
|
||||
setAddedRows,
|
||||
poultryIndex,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const [selectedCountry, setSelectedCountry] = useState(null);
|
||||
const { provinceGetBuyers } = useSelector((state) => state.provinceSlice);
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
num: "",
|
||||
},
|
||||
onSubmit: (values) => {
|
||||
// console.log(values);
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetBuyersService());
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Grid contianer width="70%">
|
||||
<Autocomplete
|
||||
id="country-select"
|
||||
options={provinceGetBuyers?.map((item) => {
|
||||
return {
|
||||
// disabled: item.debt,
|
||||
name: item.debt ? `${item.name} (بدهکار)` : item.name,
|
||||
obj: item,
|
||||
};
|
||||
})}
|
||||
getOptionLabel={(option) => option.name}
|
||||
getOptionDisabled={(option) => option.disabled}
|
||||
value={selectedCountry}
|
||||
onChange={(event, newValue) => {
|
||||
setSelectedCountry(newValue);
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="انتخاب خریدار" variant="outlined" />
|
||||
)}
|
||||
/>
|
||||
<div style={{ marginTop: "10px" }}></div>
|
||||
<NumberInput
|
||||
allowLeadingZeros
|
||||
thousandSeparator=","
|
||||
fullWidth
|
||||
id="num"
|
||||
label="تعداد مرغ"
|
||||
variant="outlined"
|
||||
value={formik.values.num}
|
||||
error={formik.touched.num ? Boolean(formik.errors.num) : null}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.num && Boolean(formik.errors.num)
|
||||
? formik.errors.num
|
||||
: null
|
||||
}
|
||||
/>
|
||||
<div style={{ marginTop: "10px" }}></div>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
setAddedRows((prevState) => {
|
||||
return [
|
||||
...prevState,
|
||||
{
|
||||
kill_house_key: selectedCountry?.obj?.key,
|
||||
poultry_request_key: dataTable[poultryIndex].poultryRequestKey,
|
||||
quantity: Number(formik.values.num),
|
||||
},
|
||||
];
|
||||
});
|
||||
setDataTable((prevState) => {
|
||||
// let edited = Array.from(prevState);
|
||||
let edited = deepCopy(prevState);
|
||||
edited[poultryIndex].allocations.push({
|
||||
allocationKey: null,
|
||||
type: selectedCountry?.obj?.killer,
|
||||
buyerName: selectedCountry?.name,
|
||||
buyerMobile: selectedCountry?.obj?.phone,
|
||||
buyerAddress: selectedCountry?.obj?.systemAddress?.city?.name,
|
||||
allocationQuantity: Number(formik.values.num),
|
||||
allocationPercent: 0,
|
||||
KillingPlace: selectedCountry?.obj?.killPlace,
|
||||
});
|
||||
|
||||
edited[poultryIndex].allocationsSum = edited[
|
||||
poultryIndex
|
||||
].allocations?.reduce((total, item) => {
|
||||
return total + item.allocationQuantity;
|
||||
}, 0);
|
||||
|
||||
return edited;
|
||||
});
|
||||
dispatch(CLOSE_MODAL());
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
function deepCopy(obj) {
|
||||
let newObj = Array.isArray(obj) ? [] : {};
|
||||
for (let key in obj) {
|
||||
if (typeof obj[key] === "object" && obj[key] !== null) {
|
||||
newObj[key] = deepCopy(obj[key]);
|
||||
} else {
|
||||
newObj[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return newObj;
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
TextField,
|
||||
Button,
|
||||
Grid,
|
||||
IconButton,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Popover,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { useDispatch } from "react-redux";
|
||||
import {
|
||||
provinceDeleteAgeMessagesService,
|
||||
provinceGetAgeMessagesService,
|
||||
provinceSubmitAgeMessagesService,
|
||||
} from "../../services/province-age-message";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import TuneIcon from "@mui/icons-material/Tune";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { ProvinceEditAgeMessage } from "../province-edit-age-message/ProvinceEditAgeMessage";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
|
||||
export const ProvinceAgeMessage = () => {
|
||||
const [tableData, setTableData] = useState([]);
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const validationSchema = Yup.object({
|
||||
ageRange: Yup.number()
|
||||
.required("بازه سنی ضروری است")
|
||||
.max(99, "عدد دورقمی وارد کنید!"),
|
||||
lossPercent: Yup.number()
|
||||
.required("درصد افت ضروری است")
|
||||
.max(99, "عدد دورقمی وارد کنید!"),
|
||||
message: Yup.string()
|
||||
.required("پیغام ضروری است")
|
||||
.max(500, "حداکثر 500 کاراکتر"),
|
||||
});
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
ageRange: "",
|
||||
message: "",
|
||||
lossPercent: "",
|
||||
},
|
||||
validationSchema,
|
||||
onSubmit: (values, { resetForm }) => {
|
||||
dispatch(
|
||||
provinceSubmitAgeMessagesService({
|
||||
message: values.message,
|
||||
poultry_age: values.ageRange,
|
||||
losses_percent: values.lossPercent,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
fetchData();
|
||||
resetForm();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const fetchData = () => {
|
||||
dispatch(provinceGetAgeMessagesService()).then((r) => {
|
||||
const d = r.payload.data?.map((item, i) => {
|
||||
return [
|
||||
i + 1,
|
||||
formatJustDate(item?.createDate),
|
||||
item?.lossesPercent,
|
||||
item?.poultryAge,
|
||||
item?.message,
|
||||
<Grid justifyContent="center" alignItems="center" key={i}>
|
||||
<ProvinceAgeMessageActions
|
||||
item={item}
|
||||
onDelete={() => {
|
||||
dispatch(provinceDeleteAgeMessagesService(item?.key)).then(
|
||||
(r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
fetchData();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}}
|
||||
onEdit={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
title: "ویرایش خریدار",
|
||||
content: (
|
||||
<ProvinceEditAgeMessage
|
||||
isEdit
|
||||
item={item}
|
||||
fetchData={fetchData}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Grid>,
|
||||
];
|
||||
});
|
||||
setTableData(d);
|
||||
});
|
||||
};
|
||||
|
||||
const ProvinceAgeMessageActions = ({ onDelete, onEdit }) => {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const open = Boolean(anchorEl);
|
||||
|
||||
const handleOpen = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
onDelete();
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handleEdit = () => {
|
||||
onEdit();
|
||||
handleClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<Tooltip title="تنظیمات">
|
||||
<IconButton
|
||||
color="primary"
|
||||
className="avicultureActiveRequestsBtn"
|
||||
onClick={handleOpen}
|
||||
>
|
||||
<TuneIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Popover
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
>
|
||||
<List sx={{ minWidth: 140, p: 1 }}>
|
||||
<ListItemButton onClick={handleEdit} sx={{ py: 1 }}>
|
||||
<ListItemIcon>
|
||||
<EditIcon color="primary" />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="body2" color="textPrimary">
|
||||
ویرایش
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
<ListItemButton onClick={handleDelete} sx={{ py: 1 }}>
|
||||
<ListItemIcon>
|
||||
<DeleteIcon color="error" />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="body2" color="textPrimary">
|
||||
حذف
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</Popover>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [dispatch]);
|
||||
return (
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
<Grid container justifyContent="space-between" xs={12} spacing={2}>
|
||||
<Grid container spacing={2} xs={12} sm={6}>
|
||||
<Grid item xs={6}>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="ageRange"
|
||||
name="ageRange"
|
||||
label="بازه سنی"
|
||||
variant="outlined"
|
||||
value={formik.values.ageRange}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={formik.touched.ageRange && Boolean(formik.errors.ageRange)}
|
||||
helperText={formik.touched.ageRange && formik.errors.ageRange}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="lossPercent"
|
||||
name="lossPercent"
|
||||
label="درصد افت"
|
||||
variant="outlined"
|
||||
value={formik.values.lossPercent}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={
|
||||
formik.touched.lossPercent && Boolean(formik.errors.lossPercent)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.lossPercent && formik.errors.lossPercent
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
fullWidth
|
||||
multiline
|
||||
rows={5}
|
||||
id="message"
|
||||
name="message"
|
||||
label="پیغام"
|
||||
variant="outlined"
|
||||
value={formik.values.message}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={formik.touched.message && Boolean(formik.errors.message)}
|
||||
helperText={formik.touched.message && formik.errors.message}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Button type="submit" variant="contained" color="primary" fullWidth>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={2} xs={12} sm={6}>
|
||||
<ResponsiveTable
|
||||
title="پیغام بازه سنی"
|
||||
paginated
|
||||
columns={[
|
||||
"ردیف",
|
||||
"تاریخ ثبت",
|
||||
"درصد افت",
|
||||
"بازه سنی",
|
||||
"متن پیام",
|
||||
"عملیات",
|
||||
]}
|
||||
data={tableData}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,210 @@
|
||||
import { Autocomplete, Button, TextField, Typography } from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { provinceAddCarToKillhouseService } from "../../services/province-add-car-to-killhouse";
|
||||
import { provinceGetCars } from "../../services/province-get-cars";
|
||||
import { provinceGetOnlyKillHousesService } from "../../services/province-get-only-kill-houses";
|
||||
import { provinceRemoveCarFromKillhouseService } from "../../services/province-remove-car-from-killhouse";
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
// add any other validation rules that you need
|
||||
autocompleteField: Yup.string().required("This field is required"),
|
||||
});
|
||||
|
||||
export const ProvinceAllocateCarsForm = ({ killHouseList, driverKey }) => {
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
autocompleteField: "",
|
||||
},
|
||||
validationSchema,
|
||||
onSubmit: (values) => {
|
||||
if (!values?.autocompleteField || !driverKey) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "لطفا تمام فیلدها را پر کنید",
|
||||
severity: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
dispatch(
|
||||
provinceAddCarToKillhouseService({
|
||||
kill_house_key: values.autocompleteField,
|
||||
driver_key: driverKey,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r?.payload?.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(provinceGetCars());
|
||||
dispatch(DRAWER({ right: false, bottom: false, content: null }));
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
const dispatch = useDispatch();
|
||||
const [killhouses, setKillhouses] = useState([]);
|
||||
const { provinceGetOnlyKillHouses } = useSelector(
|
||||
(state) => state.provinceSlice
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (getRoleFromUrl() === "KillHouse") {
|
||||
dispatch(provinceGetOnlyKillHousesService("self_kill_houses"));
|
||||
} else {
|
||||
dispatch(provinceGetOnlyKillHousesService("role=ProvinceOperator"));
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!provinceGetOnlyKillHouses ||
|
||||
!Array.isArray(provinceGetOnlyKillHouses)
|
||||
) {
|
||||
setKillhouses([]);
|
||||
return;
|
||||
}
|
||||
const d = provinceGetOnlyKillHouses
|
||||
.map((item) => {
|
||||
if (!item) return null;
|
||||
let prefix;
|
||||
if (item.killer) {
|
||||
prefix = "کشتارکن";
|
||||
} else {
|
||||
prefix = "کشتارگاه";
|
||||
}
|
||||
const name = `${prefix} ${item?.name || ""}`;
|
||||
return { title: name, value: item?.key || "" };
|
||||
})
|
||||
.filter((item) => item !== null && item.value);
|
||||
setKillhouses(d || []);
|
||||
}, [provinceGetOnlyKillHouses]);
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
gap={SPACING.TINY}
|
||||
mb={SPACING.SMALL}
|
||||
>
|
||||
<Autocomplete
|
||||
id="autocompleteField"
|
||||
options={killhouses || []}
|
||||
getOptionLabel={(option) => option?.title || ""}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label="انتخاب کشتارگاه"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
error={
|
||||
formik.touched.autocompleteField &&
|
||||
Boolean(formik.errors.autocompleteField)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.autocompleteField &&
|
||||
formik.errors.autocompleteField
|
||||
}
|
||||
/>
|
||||
)}
|
||||
onChange={(e, value) =>
|
||||
formik.setFieldValue("autocompleteField", value?.value || "")
|
||||
}
|
||||
value={killhouses?.find(
|
||||
(o) => o.value === formik.values.autocompleteField
|
||||
)}
|
||||
/>
|
||||
<Button fullWidth variant="contained" type="submit">
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</form>
|
||||
<Typography variant="body1" fontWeight={"bold"}>
|
||||
کشتارگاه های خودرو
|
||||
</Typography>
|
||||
{killHouseList && Array.isArray(killHouseList) && killHouseList.length > 0
|
||||
? killHouseList.map((item, i) => {
|
||||
if (!item) return null;
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.TINY}
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
style={{ borderBottom: "1px solid #DDD" }}
|
||||
key={item.killHouseKey || i}
|
||||
>
|
||||
<Typography>
|
||||
{i + 1}. {item?.killHouseName || ""}
|
||||
</Typography>
|
||||
<Button
|
||||
color="error"
|
||||
onClick={() => {
|
||||
if (!item?.killHouseKey || !driverKey) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "اطلاعات ناقص است",
|
||||
severity: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
dispatch(
|
||||
provinceRemoveCarFromKillhouseService({
|
||||
kill_house_key: item.killHouseKey,
|
||||
driver_key: driverKey,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r?.payload?.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(provinceGetCars());
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
حذف
|
||||
</Button>
|
||||
</Grid>
|
||||
);
|
||||
})
|
||||
: null}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,239 @@
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
Popover,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useContext, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import {
|
||||
CLOSE_MODAL,
|
||||
DRAWER,
|
||||
OPEN_MODAL,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { provinceCloseAllocationService } from "../../services/province-close-allocation";
|
||||
import { provinceGetAllRequests } from "../../services/province-get-all-requests";
|
||||
import ArchiveIcon from "@mui/icons-material/Archive";
|
||||
import ConstructionIcon from "@mui/icons-material/Construction";
|
||||
import { ProvinceAllocation } from "../../../file/components/province-allocation/ProvinceAllocation";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import TuneIcon from "@mui/icons-material/Tune";
|
||||
import { ProvincePoultryRequestEnterConfirmationCode } from "../province-poultry-request-enter-confirmation-code/ProvincePoultryRequestEnterConfirmationCode";
|
||||
|
||||
export const ProvinceAllocateOperations = ({
|
||||
item,
|
||||
remainQuantity,
|
||||
getItemFreeSaleInProvince,
|
||||
updateTable,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif, , selectedDate1] = useContext(AppContext);
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const id = open ? "ProvinceAllocateRequests" : undefined;
|
||||
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<IconButton
|
||||
aria-describedby={id}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<TuneIcon />
|
||||
</IconButton>
|
||||
|
||||
<Popover
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
id={id}
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
>
|
||||
<div
|
||||
style={{ padding: "20px", display: "flex", flexDirection: "column" }}
|
||||
>
|
||||
<Tooltip title="تخصیص" placement="right">
|
||||
<IconButton
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
if (
|
||||
item?.poultryRequest?.priceConfirmation === true &&
|
||||
!item?.poultryRequest?.inputPriceConfirmationCode
|
||||
) {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ورود کد احراز",
|
||||
content: (
|
||||
<ProvincePoultryRequestEnterConfirmationCode
|
||||
updateTable={updateTable}
|
||||
item={item?.poultryRequest}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
} else if (item?.provinceState === "pending") {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "اطلاعیه سیستم",
|
||||
content: (
|
||||
<Grid>
|
||||
<Typography variant="body1" color="secondary">
|
||||
درخواست ابتدا باید توسط استان تایید شود!
|
||||
</Typography>
|
||||
<Grid container justifyContent="center">
|
||||
<Grid
|
||||
item
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="center"
|
||||
mt={2}
|
||||
>
|
||||
<Button
|
||||
size="small"
|
||||
color="success"
|
||||
variant="contained"
|
||||
onClick={() => dispatch(CLOSE_MODAL())}
|
||||
>
|
||||
متوجه شدم
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
title: "انجام عملیات تخصیص",
|
||||
// right: !(window.innerWidth <= 600),
|
||||
top: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
size: 1000,
|
||||
content: (
|
||||
<ProvinceAllocation
|
||||
remainQuantity={remainQuantity}
|
||||
item={item}
|
||||
id={
|
||||
item?.poultryRequest?.process?.poultry
|
||||
?.poultryRequestId
|
||||
}
|
||||
orginalQuantity={
|
||||
item?.poultryRequest?.process?.poultry
|
||||
?.poultryQuantity
|
||||
}
|
||||
file={item?.poultryRequest?.process}
|
||||
getItemFreeSaleInProvince={getItemFreeSaleInProvince}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ConstructionIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="اتمام" placement="right">
|
||||
<IconButton
|
||||
aria-label="delete"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "آیا مطمئن هستید؟",
|
||||
content: (
|
||||
<Grid container>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceCloseAllocationService({
|
||||
allocated_number:
|
||||
item?.quantity?.allocatedNumber,
|
||||
final_state: "archive",
|
||||
key: item?.poultryRequest?.key,
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(provinceGetAllRequests(selectedDate1));
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(CLOSE_MODAL());
|
||||
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
تایید
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
dispatch(CLOSE_MODAL());
|
||||
}}
|
||||
>
|
||||
لغو
|
||||
</Button>
|
||||
</Grid>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ArchiveIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
{/* <Tooltip title="مشاهده" placement="right">
|
||||
<IconButton
|
||||
aria-label="delete"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
navigate(
|
||||
ROUTE_PROVINCE_FILE +
|
||||
item?.poultryRequest?.process?.poultry?.poultryRequestId
|
||||
);
|
||||
}}
|
||||
>
|
||||
<PlagiarismIcon />
|
||||
</IconButton>
|
||||
</Tooltip> */}
|
||||
</div>
|
||||
</Popover>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,342 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
CardContent,
|
||||
IconButton,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
OPEN_MODAL,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { ProvinceAllocateOperations } from "../province-allocate-operations/ProvinceAllocateOperations";
|
||||
import { ProvinceEditSendDate } from "../province-edit-send-date/ProvinceEditSendDate";
|
||||
import { formatJustDate, formatTime } from "../../../../utils/formatTime";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import { getPoultryRequestsTotalQuantityService } from "../../../city/services/get-poultry-requests-total-quantity";
|
||||
import { motion } from "framer-motion";
|
||||
import { RiSearchLine } from "react-icons/ri";
|
||||
|
||||
const cardVariants = {
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
visible: { opacity: 1, y: 0 },
|
||||
};
|
||||
|
||||
export const ProvinceAllocateRequests = () => {
|
||||
const [, , selectedDate1, setSelectedDate1] = useContext(AppContext);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
}, []);
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const [data, setData] = useState([]);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const [page, setPage] = useState(1);
|
||||
const [tableData, setTableData] = useState([]);
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
dispatch(getPoultryRequestsTotalQuantityService(selectedDate1)).then(
|
||||
async () => {
|
||||
dispatch(LOADING_START());
|
||||
const response = await axios.get(
|
||||
`city_operator_check_request_new/?state=waiting&date=${selectedDate1}&page=${page}&page_size=${perPage}&search=filter&value=${
|
||||
textValue ? textValue : ""
|
||||
}`
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
const getItemFreeSaleInProvince = (item) => {
|
||||
let sellType = "";
|
||||
if (item?.poultryRequest?.freeSaleInProvince) {
|
||||
sellType = "آزاد";
|
||||
} else {
|
||||
sellType = "دولتی";
|
||||
}
|
||||
return sellType;
|
||||
};
|
||||
|
||||
const updateTable = () => {
|
||||
fetchApiData(page !== 0 ? page : 1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const d = data?.map((item, i) => {
|
||||
return [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
item?.poultryRequest?.orderCode,
|
||||
getItemFreeSaleInProvince(item),
|
||||
formatTime(item?.poultryRequest?.createDate),
|
||||
<Grid
|
||||
key={item?.poultryRequest?.orderCode}
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
width="100px"
|
||||
>
|
||||
<Typography variant="caption">
|
||||
{formatJustDate(item?.poultryRequest?.sendDate)}
|
||||
</Typography>
|
||||
<IconButton
|
||||
size={"small"}
|
||||
color="primary"
|
||||
disabled={Number(item?.quantity?.allocatedNumber) > 0}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ویرایش تاریخ درخواست کشتار",
|
||||
content: (
|
||||
<ProvinceEditSendDate
|
||||
poultryRequestKey={item?.poultryRequest?.key}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
<EditIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Grid>,
|
||||
item?.poultryRequest?.freezing
|
||||
? "انجماد"
|
||||
: item?.poultryRequest?.export
|
||||
? "صادرات"
|
||||
: "عادی",
|
||||
`${item?.poultryRequest?.process?.poultry?.poultryName}/${item?.poultryRequest?.process?.poultry?.poultryMobile}`,
|
||||
item?.poultryRequest?.killHouseList.length
|
||||
? item?.poultryRequest?.killHouseList?.join(" - ")
|
||||
: "-",
|
||||
`${item?.poultryRequest?.process?.poultry?.poultryProvince}/${item?.poultryRequest?.process?.poultry?.poultryCity}`,
|
||||
item?.poultryRequest?.poultry?.cityOperator,
|
||||
item?.poultryRequest?.killingAge,
|
||||
item?.poultryRequest?.process?.poultry?.IndexWeight,
|
||||
item?.poultryRequest?.process?.poultry?.totalWeight?.toLocaleString(),
|
||||
item?.poultryRequest?.process?.poultry?.poultryQuantity?.toLocaleString(),
|
||||
item?.poultryRequest?.amount?.toLocaleString() + " ﷼",
|
||||
<Typography color="green" variant="caption" fontWeight="bold" key="sss">
|
||||
{item?.quantity?.allocatedNumber?.toLocaleString()}
|
||||
</Typography>,
|
||||
item?.quantity?.returnedNumber?.toLocaleString(),
|
||||
item?.quantity?.assignableNumber?.toLocaleString(),
|
||||
<ProvinceAllocateOperations
|
||||
key={i}
|
||||
remainQuantity={
|
||||
item?.poultryRequest?.process?.poultry?.poultryRemainQuantity
|
||||
}
|
||||
item={item}
|
||||
getItemFreeSaleInProvince={getItemFreeSaleInProvince}
|
||||
updateTable={updateTable}
|
||||
/>,
|
||||
];
|
||||
});
|
||||
|
||||
setTableData(d);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, [dispatch, selectedDate1, perPage]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`city_operator_check_request_new/?state=waiting&date=${selectedDate1}&page=${1}&page_size=${perPage}&search=filter&value=${
|
||||
textValue ? textValue : ""
|
||||
}`
|
||||
);
|
||||
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
dispatch(LOADING_END());
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const { poultryRequestsTotalQuantity } = useSelector(
|
||||
(state) => state.citySlice
|
||||
);
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
px={{
|
||||
xs: 2,
|
||||
sm: 0,
|
||||
}}
|
||||
>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
label="تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField style={{ width: "160px" }} {...params} size="small" />
|
||||
)}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(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>
|
||||
|
||||
<Grid
|
||||
container
|
||||
sx={{
|
||||
gap: {
|
||||
xs: "8px 0px",
|
||||
sm: "8px",
|
||||
},
|
||||
}}
|
||||
mt={2}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
{[
|
||||
{
|
||||
label: "تعداد درخواست کشتار",
|
||||
value: poultryRequestsTotalQuantity?.acceptedQuantity || 0,
|
||||
},
|
||||
{
|
||||
label: "اعلام نیاز کشتارگاه ها",
|
||||
value: poultryRequestsTotalQuantity?.killRequestsQuantity || 0,
|
||||
},
|
||||
{
|
||||
label: "تخصیص داده شده",
|
||||
value: poultryRequestsTotalQuantity?.allocatedQuantity || 0,
|
||||
},
|
||||
{
|
||||
label: "قابل تخصیص",
|
||||
value: poultryRequestsTotalQuantity?.assignableQuantity || 0,
|
||||
},
|
||||
{
|
||||
label: "برگشت داده شده",
|
||||
value: poultryRequestsTotalQuantity?.returnedQuantity || 0,
|
||||
},
|
||||
].map((item, index) => (
|
||||
<Grid item sx={{ width: "250px" }} key={index}>
|
||||
<motion.div
|
||||
variants={cardVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
transition={{ duration: 0.5, delay: index * 0.2 }}
|
||||
>
|
||||
<Card elevation={3} sx={{ borderRadius: 2 }}>
|
||||
<CardContent>
|
||||
<Typography color="red" variant="subtitle2" gutterBottom>
|
||||
{item.label}
|
||||
</Typography>
|
||||
<Typography variant="h6" sx={{ fontSize: 18 }}>
|
||||
{item.value?.toLocaleString()} قطعه
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
px={{
|
||||
xs: 1,
|
||||
sm: 0,
|
||||
}}
|
||||
>
|
||||
<ResponsiveTable
|
||||
data={tableData}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"کد سفارش",
|
||||
"نوع فروش",
|
||||
"تاریخ ثبت درخواست",
|
||||
"تاریخ کشتار",
|
||||
"نوع کشتار",
|
||||
"مرغدار/تلفن",
|
||||
"کشتارگاه انتخابی",
|
||||
"استان/شهر",
|
||||
"تعاونی",
|
||||
"سن مرغ",
|
||||
"میانگین وزنی",
|
||||
"وزن تقریبی",
|
||||
"تعداد",
|
||||
"قیمت مرغدار",
|
||||
"تخصیص داده شده",
|
||||
"برگشت داده شده",
|
||||
"قابل تخصیص",
|
||||
"عملیات",
|
||||
]}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title="مدیریت تخصیصات"
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,218 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { useFormik } from "formik";
|
||||
import {
|
||||
provinceDispensersAddSteward,
|
||||
provinceDispensersGetAllStewards,
|
||||
} from "../../services/province-dispensers-services";
|
||||
import {
|
||||
Autocomplete,
|
||||
Button,
|
||||
FormControl,
|
||||
FormControlLabel,
|
||||
FormLabel,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
|
||||
export const ProvinceAllocateStewardGuild = ({
|
||||
killHousekey,
|
||||
updateTable,
|
||||
type,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [stewardsOptions, setStewardsOptions] = useState([]);
|
||||
|
||||
const [value, setValue] = useState("forced");
|
||||
const [userType, setUserType] = useState("steward");
|
||||
|
||||
const handleChangeRadioButton = (event) => {
|
||||
setValue(event.target.value);
|
||||
};
|
||||
const handleChangeRadioButtonUserType = (event) => {
|
||||
setUserType(event.target.value);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
provinceDispensersGetAllStewards({
|
||||
role_type: "KillHouse",
|
||||
key: killHousekey,
|
||||
type: userType,
|
||||
})
|
||||
).then((r) => {
|
||||
setStewardsOptions(r.payload.data);
|
||||
});
|
||||
}, [dispatch, userType]);
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
steward_key: Yup.string(),
|
||||
allocation_limit: Yup.number()
|
||||
.required("این فیلد اجباری است!")
|
||||
.typeError("لطفا عدد وارد کنید!"),
|
||||
});
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
steward_key: "",
|
||||
allocation_limit: "",
|
||||
},
|
||||
validationSchema,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
|
||||
<Grid>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
aria-labelledby="demo-controlled-radio-buttons-group"
|
||||
name="controlled-radio-buttons-group"
|
||||
value={userType}
|
||||
onChange={handleChangeRadioButtonUserType}
|
||||
row
|
||||
sx={{ alignItems: "center" }}
|
||||
>
|
||||
<FormControlLabel
|
||||
value="steward"
|
||||
control={<Radio />}
|
||||
label="مباشرین"
|
||||
/>
|
||||
<FormControlLabel value="guild" control={<Radio />} label="اصناف" />
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<Autocomplete
|
||||
style={{ width: "100%" }}
|
||||
options={
|
||||
stewardsOptions
|
||||
? stewardsOptions.map((i) => ({
|
||||
id: i.key,
|
||||
label: `${i.guildsName} (${i.user?.mobile}) / نوع فعالیت: ${i.typeActivity} / حوزه فعالیت: ${i.areaActivity}`,
|
||||
item: i,
|
||||
}))
|
||||
: []
|
||||
}
|
||||
value={formik.values.guild}
|
||||
onChange={(e, item) => {
|
||||
formik.setFieldValue("steward_key", item?.id);
|
||||
formik.validateForm();
|
||||
}}
|
||||
error={formik.touched.guild && Boolean(formik.errors.guild)}
|
||||
helperText={formik.touched.guild && formik.errors.guild}
|
||||
getOptionLabel={(option) => option.label}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label={`انتخاب ${userType === "steward" ? "مباشر" : "صنف"}`}
|
||||
variant="outlined"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="allocation_limit"
|
||||
label="وزن تعهد روزانه"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%" }}
|
||||
value={formik.values.allocation_limit}
|
||||
error={
|
||||
formik.touched.allocation_limit
|
||||
? Boolean(formik.errors.allocation_limit)
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.allocation_limit &&
|
||||
Boolean(formik.errors.allocation_limit)
|
||||
? formik.errors.allocation_limit
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
aria-labelledby="demo-controlled-radio-buttons-group"
|
||||
name="controlled-radio-buttons-group"
|
||||
value={value}
|
||||
onChange={handleChangeRadioButton}
|
||||
row
|
||||
sx={{ alignItems: "center" }}
|
||||
>
|
||||
<FormLabel id="demo-radio-buttons-group-label">
|
||||
نوع تعهد: {" "}
|
||||
</FormLabel>
|
||||
|
||||
<FormControlLabel
|
||||
value="forced"
|
||||
control={<Radio />}
|
||||
label="اجباری"
|
||||
/>
|
||||
<FormControlLabel
|
||||
value="optional"
|
||||
control={<Radio />}
|
||||
label="اختیاری"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
|
||||
<Grid container xs={12}>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
disabled={!formik.isValid}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceDispensersAddSteward({
|
||||
guilds_key: formik.values.steward_key,
|
||||
choose: true,
|
||||
type: type,
|
||||
owner_key: killHousekey,
|
||||
allocation_limit: formik.values.allocation_limit,
|
||||
allocation_type: value,
|
||||
choose_type: userType,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
dispatch(CLOSE_MODAL());
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,102 @@
|
||||
import React, { useContext } from "react";
|
||||
import { TextField, Button, Grid } from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { useDispatch } from "react-redux";
|
||||
import {
|
||||
provinceGetAllocatedRequestsService,
|
||||
provinceUpdateAllocatedRequestService,
|
||||
} from "../../services/province-get-allocated-requests";
|
||||
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
|
||||
export const ProvinceAllocatedRequestsEditAllocation = ({
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
item,
|
||||
fetchDashboard,
|
||||
}) => {
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const dispatch = useDispatch();
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
amount: item.allocatedQuantity ? item.allocatedQuantity : "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
amount: Yup.number()
|
||||
.required("وارد کردن حجم الزامی است")
|
||||
.min(1, "حجم باید بزرگتر از صفر باشد"),
|
||||
}),
|
||||
onSubmit: (values) => {
|
||||
dispatch(
|
||||
provinceUpdateAllocatedRequestService({
|
||||
edit_allocation_quantity: true,
|
||||
province_kill_request_key: item?.provinceKillRequestKey,
|
||||
quantity: parseInt(values?.amount),
|
||||
role: getRoleFromUrl(),
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
dispatch(
|
||||
provinceGetAllocatedRequestsService({
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
})
|
||||
);
|
||||
fetchDashboard();
|
||||
dispatch(CLOSE_MODAL());
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
spacing={2}
|
||||
direction="column"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Grid item xs={12}>
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="amount"
|
||||
name="amount"
|
||||
label="حجم"
|
||||
value={formik.values.amount}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error={formik.touched.amount && Boolean(formik.errors.amount)}
|
||||
helperText={formik.touched.amount && formik.errors.amount}
|
||||
variant="outlined"
|
||||
/>
|
||||
<Button
|
||||
fullWidth
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{ marginTop: "16px" }}
|
||||
>
|
||||
ارسال
|
||||
</Button>
|
||||
</form>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
import { IconButton, Tooltip } from "@mui/material";
|
||||
import React, { useState, useRef } from "react";
|
||||
import { BsFillFileEarmarkPdfFill } from "react-icons/bs";
|
||||
import { useReactToPrint } from "react-to-print";
|
||||
import ProvinceAllcationInvoice from "../province-allocation-invoice/ProvinceAllcationInvoice";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { provinceGetAllocationLetter } from "../../services/province-get-allocation-letter";
|
||||
import { useEffect } from "react";
|
||||
import { PropTypes } from "prop-types";
|
||||
|
||||
export const ProvinceAllocatedRequestsInvoiceOperation = ({ date1, date2 }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [factorData, setFactorData] = useState(null);
|
||||
const componentRef = useRef();
|
||||
|
||||
const handleDownloadFactor = () => {
|
||||
const result = dispatch(provinceGetAllocationLetter(date1));
|
||||
setFactorData(result);
|
||||
};
|
||||
|
||||
const printPDF = useReactToPrint({
|
||||
content: () => componentRef.current,
|
||||
documentTitle: "گزارش روزانه",
|
||||
onAfterPrint: () => {
|
||||
setFactorData(null);
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (factorData) {
|
||||
printPDF();
|
||||
}
|
||||
}, [factorData, printPDF]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Tooltip title="خروجی PDF">
|
||||
<IconButton
|
||||
disabled={date2 && date1 !== date2}
|
||||
onClick={() => {
|
||||
handleDownloadFactor();
|
||||
}}
|
||||
size={"large"}
|
||||
aria-label="delete"
|
||||
color="success"
|
||||
>
|
||||
<BsFillFileEarmarkPdfFill size={32} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<div style={{ visibility: "hidden", position: "absolute" }}>
|
||||
<ProvinceAllcationInvoice
|
||||
ref={componentRef}
|
||||
item={factorData?.payload?.data}
|
||||
date={date1}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ProvinceAllocatedRequestsInvoiceOperation.propTypes = {
|
||||
date1: PropTypes.any,
|
||||
date2: PropTypes.any,
|
||||
};
|
||||
@@ -0,0 +1,218 @@
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
Popover,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useContext, useState } from "react";
|
||||
import TuneIcon from "@mui/icons-material/Tune";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { provinceAllocatedDeleteService } from "../../services/province-allocated-delete";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { provinceGetAllocatedRequestsService } from "../../services/province-get-allocated-requests";
|
||||
import { provinceAllocatedReturnQuantityService } from "../../services/province-allocated-return-quantity";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { ProvinceAllocatedRequestsEditAllocation } from "../province-allocated-requests-edit-allocation/ProvinceAllocatedRequestsEditAllocation";
|
||||
import KeyboardReturnIcon from "@mui/icons-material/KeyboardReturn";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
export const ProvinceAllocatedRequestsOperations = ({
|
||||
item,
|
||||
fetchDashboard,
|
||||
}) => {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [openNotif, , selectedDate1, , selectedDate2] = useContext(AppContext);
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const id = open ? "simple-popover" : undefined;
|
||||
const btnDisabled =
|
||||
item.allocatedState === "rejected" ||
|
||||
(item.allocatedCarState && item.allocatedRemainQuantity === 0);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<IconButton
|
||||
aria-describedby={id}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={btnDisabled}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<TuneIcon />
|
||||
</IconButton>
|
||||
<Popover
|
||||
id={id}
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
>
|
||||
<div style={{ padding: 10 }}>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
gap={SPACING.TINY}
|
||||
alignItems="flex-start"
|
||||
style={{ width: 180 }}
|
||||
>
|
||||
{getRoleFromUrl() !== "KillHouse" && (
|
||||
<Tooltip placement="left" title="ویرایش">
|
||||
<Button
|
||||
size="small"
|
||||
disabled={item?.directBuying}
|
||||
startIcon={<EditIcon fontSize="small" />}
|
||||
sx={{
|
||||
"&.Mui-disabled": {
|
||||
backgroundColor: "transparent",
|
||||
color: "text.disabled",
|
||||
},
|
||||
}}
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ویرایش تخصیص",
|
||||
content: (
|
||||
<ProvinceAllocatedRequestsEditAllocation
|
||||
item={item}
|
||||
selectedDate1={selectedDate1}
|
||||
selectedDate2={selectedDate2}
|
||||
fetchDashboard={fetchDashboard}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" textAlign="left" fontWeight={600}>
|
||||
ویرایش تخصیص
|
||||
</Typography>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{getRoleFromUrl() !== "KillHouse" && (
|
||||
<Tooltip placement="left" title="تخصیص مانده برگشت">
|
||||
<Button
|
||||
size="small"
|
||||
startIcon={<KeyboardReturnIcon fontSize="small" />}
|
||||
sx={{
|
||||
"&.Mui-disabled": {
|
||||
backgroundColor: "transparent",
|
||||
color: "text.disabled",
|
||||
},
|
||||
}}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceAllocatedReturnQuantityService({
|
||||
province_kill_request_key: item.provinceKillRequestKey,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
handleClose();
|
||||
dispatch(
|
||||
provinceGetAllocatedRequestsService({
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
})
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" textAlign="left" fontWeight={600}>
|
||||
تخصیص مانده برگشت
|
||||
</Typography>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
<Tooltip placement="left" title="حذف">
|
||||
<Button
|
||||
size="small"
|
||||
disabled={
|
||||
getRoleFromUrl() !== "AdminX" && item.allocatedCarState
|
||||
}
|
||||
color="error"
|
||||
startIcon={<DeleteIcon fontSize="small" />}
|
||||
sx={{
|
||||
"&.Mui-disabled": {
|
||||
backgroundColor: "transparent",
|
||||
color: "text.disabled",
|
||||
},
|
||||
}}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceAllocatedDeleteService({
|
||||
province_kill_request_key: item.provinceKillRequestKey,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
handleClose();
|
||||
dispatch(
|
||||
provinceGetAllocatedRequestsService({
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
})
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" textAlign="left" fontWeight={600}>
|
||||
حذف
|
||||
</Typography>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</div>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,400 @@
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
Tab,
|
||||
Tabs,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import axios from "axios";
|
||||
import moment from "moment/moment";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { formatJustDate, formatTime } from "../../../../utils/formatTime";
|
||||
import { provinceGetAllocatedRequestsService } from "../../services/province-get-allocated-requests";
|
||||
import { ProvinceAllocatedRequestsOperations } from "../province-allocated-requests-operations/ProvinceAllocatedRequestsOperations";
|
||||
import { ProvinceGetDeletedAllocatedRequests } from "../province-get-deleted-allocated-requests/ProvinceGetDeletedAllocatedRequests";
|
||||
import { provinceGetDashboardKillRequestService } from "../../services/get-dahsnoard-province-kill-request";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { checkPathStartsWith } from "../../../../utils/checkPathStartsWith";
|
||||
|
||||
export const ProvinceAllocatedRequests = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [dataTable, setDataTable] = useState();
|
||||
const [hasDocumentState, setHasDocumentState] = useState(false);
|
||||
const [selectedTab, setSelectedTab] = useState(0);
|
||||
const selectedSubUser = useSelector(
|
||||
(state) => state.userSlice.selectedSubUser
|
||||
);
|
||||
const userKey = useSelector((state) => state.userSlice.userProfile.key);
|
||||
|
||||
const [textValue, setTextValue] = useState("");
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
const handleChangeDocumentState = (event) => {
|
||||
const checked = event.target.checked;
|
||||
setHasDocumentState(checked);
|
||||
|
||||
dispatch(
|
||||
provinceGetAllocatedRequestsService({
|
||||
role_key: checkPathStartsWith("province")
|
||||
? selectedSubUser?.key || ""
|
||||
: "",
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
textValue,
|
||||
hasDocumentState: checked,
|
||||
})
|
||||
);
|
||||
|
||||
fetchDashboard(checked);
|
||||
};
|
||||
|
||||
const handleTabChange = (event, newValue) => {
|
||||
setSelectedTab(newValue);
|
||||
};
|
||||
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, []);
|
||||
|
||||
const { provinceGetAllocatedRequests } = useSelector(
|
||||
(state) => state.provinceSlice
|
||||
);
|
||||
|
||||
const [dashboardData, setDashboardData] = useState([]);
|
||||
|
||||
const fetchDashboard = (checked = hasDocumentState) => {
|
||||
const params = {
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
textValue,
|
||||
hasDocumentState: checked,
|
||||
role_key: checkPathStartsWith("province")
|
||||
? selectedSubUser?.key || ""
|
||||
: "",
|
||||
};
|
||||
|
||||
dispatch(provinceGetDashboardKillRequestService(params)).then((r) => {
|
||||
setDashboardData(r.payload.data);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedTab === 0) {
|
||||
dispatch(
|
||||
provinceGetAllocatedRequestsService({
|
||||
role_key: checkPathStartsWith("province")
|
||||
? selectedSubUser?.key || ""
|
||||
: "",
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
textValue,
|
||||
hasDocumentState,
|
||||
})
|
||||
);
|
||||
fetchDashboard();
|
||||
}
|
||||
}, [selectedDate1, selectedDate2, selectedTab, selectedSubUser?.key]);
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (selectedTab === 0) {
|
||||
dispatch(
|
||||
provinceGetAllocatedRequestsService({
|
||||
role_key: checkPathStartsWith("province")
|
||||
? selectedSubUser?.key || ""
|
||||
: "",
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
textValue,
|
||||
hasDocumentState,
|
||||
})
|
||||
);
|
||||
fetchDashboard(hasDocumentState);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const sortedRequests = provinceGetAllocatedRequests
|
||||
?.slice()
|
||||
.sort((a, b) => b.allocatedRemainQuantity - a.allocatedRemainQuantity)
|
||||
.map((item, i) => {
|
||||
let state = "";
|
||||
if (item.allocatedState === "pending") {
|
||||
state = "در انتظار تایید";
|
||||
} else if (item.allocatedState === "accepted") {
|
||||
state = "تایید شده";
|
||||
} else if (item.allocatedState === "rejected") {
|
||||
state = "رد شده";
|
||||
}
|
||||
let sellType = "";
|
||||
if (item?.market) {
|
||||
sellType = "پنل معاملات";
|
||||
} else if (item?.directBuying) {
|
||||
sellType = "خرید مستقیم";
|
||||
} else if (item?.union) {
|
||||
sellType = "خرید خارج از استان";
|
||||
} else {
|
||||
sellType = "اتحادیه";
|
||||
}
|
||||
return [
|
||||
i + 1,
|
||||
item?.orderCode,
|
||||
sellType,
|
||||
item?.freeSaleInProvince === false ? "دولتی" : "آزاد",
|
||||
item?.freezing ? "انجماد" : item?.export ? "صادرات" : "عادی",
|
||||
item?.poultryUnitName,
|
||||
`${item?.poultryFullName} (${item?.poultryMobile})`,
|
||||
item?.poultryCity,
|
||||
formatJustDate(item?.sendDate),
|
||||
item?.poultryQuantity?.toLocaleString(),
|
||||
formatTime(item?.dateOfAllocate),
|
||||
item?.killHouseName,
|
||||
item?.killHouseCity,
|
||||
item?.allocatedQuantity?.toLocaleString(),
|
||||
item?.indexWeight?.toLocaleString(),
|
||||
item?.totalWeight?.toLocaleString(),
|
||||
item?.amount?.toLocaleString() + " ﷼",
|
||||
item?.killHousePrice?.toLocaleString() + " ﷼",
|
||||
state,
|
||||
item?.allocatedCarState ? "دارد" : "ندارد",
|
||||
item?.allocatedRemainQuantity?.toLocaleString(),
|
||||
item?.returnToProvince === false ? (
|
||||
<ProvinceAllocatedRequestsOperations
|
||||
item={item}
|
||||
key={i}
|
||||
fetchDashboard={fetchDashboard}
|
||||
/>
|
||||
) : (
|
||||
<Tooltip
|
||||
disableHoverListener={!item?.returner}
|
||||
key={i}
|
||||
title={
|
||||
<>
|
||||
{item?.returner && (
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
justifyContent="center"
|
||||
xs={12}
|
||||
>
|
||||
<Typography variant="body2">
|
||||
{item?.returner?.fullname || "-"} (
|
||||
{item?.returner?.mobile || "-"})
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{item?.returner?.date
|
||||
? formatJustDate(item?.returner?.date)
|
||||
: "-"}
|
||||
</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
cursor: item?.returner ? "pointer" : "default",
|
||||
}}
|
||||
>
|
||||
تخصیص برگشت داده شده
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
),
|
||||
];
|
||||
});
|
||||
setDataTable(sortedRequests);
|
||||
}, [provinceGetAllocatedRequests]);
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<Grid
|
||||
container
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
mb={SPACING.MEDIUM}
|
||||
mt={SPACING.SMALL}
|
||||
>
|
||||
<Tabs
|
||||
scrollButtons="auto"
|
||||
variant="scrollable"
|
||||
allowScrollButtonsMobile
|
||||
value={selectedTab}
|
||||
onChange={handleTabChange}
|
||||
>
|
||||
<Tab label="تخصیص ها" />
|
||||
<Tab label="تخصیص های حذف شده" />
|
||||
</Tabs>
|
||||
</Grid>
|
||||
{selectedTab === 0 && (
|
||||
<Grid container alignItems="center" justifyContent="center">
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
<Grid style={{ width: 160 }}>
|
||||
<DatePicker
|
||||
label="از تاریخ"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid style={{ width: 160 }}>
|
||||
<DatePicker
|
||||
label="تا تاریخ"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
<TextField
|
||||
size="small"
|
||||
autoComplete="off"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
endIcon={<RiSearchLine />}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<a
|
||||
href={`${
|
||||
axios.defaults.baseURL
|
||||
}allocated_excel/?start=${selectedDate1}&end=${selectedDate2}&role=${getRoleFromUrl()}${
|
||||
checkPathStartsWith("province")
|
||||
? `&role_key=${selectedSubUser?.key}`
|
||||
: ""
|
||||
}&key=${userKey}&filter=search&value=${textValue}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={hasDocumentState}
|
||||
onChange={handleChangeDocumentState}
|
||||
name="hasDocumentState"
|
||||
/>
|
||||
}
|
||||
label="نمایش تخصیصات بدون بار"
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid container mt={2} mb={4} isDashboard xs={12}>
|
||||
<ResponsiveTable
|
||||
noPagination
|
||||
isDashboard
|
||||
columns={[
|
||||
"تعداد تخصیصات",
|
||||
"حجم تخصیصات",
|
||||
"وزن تخصیصات",
|
||||
"تعداد تخصیصات تایید شده",
|
||||
"حجم تخصیصات تایید شده",
|
||||
"تعداد تخصیصات در انتظار تایید",
|
||||
"حجم تخصیصات در انتظار تایید",
|
||||
"تعداد تخصیصات رد شده",
|
||||
"حجم تخصیصات رد شده",
|
||||
"تعداد تخصیصات دارای ماشین",
|
||||
"حجم تخصیصات دارای ماشین",
|
||||
"وزن تخصیصات دارای ماشین",
|
||||
"تعداد بارها",
|
||||
"حجم بارها",
|
||||
"وزن بارها",
|
||||
"تعداد تخصیصات فاقد ماشین",
|
||||
"حجم تخصیصات فاقد ماشین",
|
||||
"وزن تخصیصات فاقد ماشین",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
dashboardData?.lenProvinceRequest?.toLocaleString(),
|
||||
dashboardData?.quantity?.toLocaleString(),
|
||||
dashboardData?.weight?.toLocaleString(),
|
||||
dashboardData?.acceptedProvinceKillRequests?.toLocaleString(),
|
||||
dashboardData?.acceptedProvinceKillRequestsQuantity?.toLocaleString(),
|
||||
dashboardData?.pendingProvinceKillRequests?.toLocaleString(),
|
||||
dashboardData?.pendingProvinceKillRequestsQuantity?.toLocaleString(),
|
||||
dashboardData?.rejectedProvinceKillRequests?.toLocaleString(),
|
||||
dashboardData?.rejectedProvinceKillRequestsQuantity?.toLocaleString(),
|
||||
dashboardData?.lenHasCar?.toLocaleString(),
|
||||
dashboardData?.hasCarQuantity?.toLocaleString(),
|
||||
dashboardData?.hasCarWeight?.toLocaleString(),
|
||||
dashboardData?.lenKillRequests?.toLocaleString(),
|
||||
dashboardData?.realQuantity?.toLocaleString(),
|
||||
dashboardData?.realWeight?.toLocaleString(),
|
||||
dashboardData?.lenHasntCar?.toLocaleString(),
|
||||
dashboardData?.hasntCarQuantity?.toLocaleString(),
|
||||
dashboardData?.hasntCarWeight?.toLocaleString(),
|
||||
],
|
||||
]}
|
||||
title={"خلاصه اطلاعات"}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<ResponsiveTable
|
||||
title="تخصیص های انجام شده"
|
||||
paginated
|
||||
noSearch
|
||||
columns={[
|
||||
"ردیف",
|
||||
"کدسفارش",
|
||||
"درخواست",
|
||||
"فروش",
|
||||
"کشتار",
|
||||
"نام فارم",
|
||||
"نام مرغدار",
|
||||
"شهر",
|
||||
"تاریخ کشتار",
|
||||
"تعداد کشتار",
|
||||
"تاریخ تخصیص",
|
||||
"خریدار",
|
||||
"شهر خریدار",
|
||||
"تعداد تخصیص",
|
||||
"میانگین وزنی",
|
||||
"وزن تقریبی",
|
||||
"قیمت مرغدار",
|
||||
"قیمت کشتارگاه",
|
||||
"وضعیت تایید خریدار",
|
||||
"وضعیت تخصیص ماشین",
|
||||
"مانده قابل تخصیص",
|
||||
"عملیات",
|
||||
]}
|
||||
data={dataTable}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
{selectedTab === 1 && <ProvinceGetDeletedAllocatedRequests />}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,406 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import logo from "../../../../assets/images/ChickenLogo.png";
|
||||
import { PropTypes } from "prop-types";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import { getCeoName } from "../../../../utils/getCeoName";
|
||||
import { useSystemName } from "../../../../utils/getSystemName";
|
||||
|
||||
const styles = {
|
||||
page: {
|
||||
width: "210mm",
|
||||
margin: "0 auto",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
position: "relative",
|
||||
direction: "rtl",
|
||||
fontFamily: "nazanin",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
container: {
|
||||
width: "95%",
|
||||
alignSelf: "center",
|
||||
pageBreakInside: "avoid",
|
||||
},
|
||||
p: {
|
||||
fontFamily: "nazanin",
|
||||
fontWeight: "bold",
|
||||
pAlign: "justify",
|
||||
},
|
||||
span: {
|
||||
fontFamily: "nazanin",
|
||||
fontWeight: "bold",
|
||||
pAlign: "justify",
|
||||
},
|
||||
invoiceTable: {
|
||||
width: "100%",
|
||||
borderCollapse: "collapse",
|
||||
alignSelf: "center",
|
||||
},
|
||||
tableCell: {
|
||||
border: "1px solid #000",
|
||||
pAlign: "left",
|
||||
textAlign: "center",
|
||||
fontSize: 11,
|
||||
},
|
||||
tableCellMobile: {
|
||||
border: "1px solid #000",
|
||||
pAlign: "left",
|
||||
textAlign: "center",
|
||||
fontSize: 10,
|
||||
},
|
||||
tableInnerCell: {
|
||||
border: "1px solid #000",
|
||||
pAlign: "left",
|
||||
textAlign: "center",
|
||||
fontSize: 8,
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
tableHeader: {
|
||||
backgroundColor: "rgba(255, 229, 153, 0.5)",
|
||||
pageBreakAfter: "auto",
|
||||
},
|
||||
headerRow: {
|
||||
backgroundColor: "rgba(255, 229, 153, 0.6)",
|
||||
color: "black",
|
||||
pageBreakInside: "avoid",
|
||||
pageBreakAfter: "auto",
|
||||
},
|
||||
logo: {
|
||||
width: "60px",
|
||||
height: "auto",
|
||||
marginBottom: "10px",
|
||||
},
|
||||
contentContainer: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
marginTop: "20px",
|
||||
marginLeft: "100px",
|
||||
marginRight: "30px",
|
||||
},
|
||||
contentInLine: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
},
|
||||
mainTitle: {
|
||||
fontFamily: "nazanin",
|
||||
fontSize: 11,
|
||||
pAlign: "center",
|
||||
fontWeight: "bolder",
|
||||
},
|
||||
signature: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "flex-end",
|
||||
marginLeft: "20px",
|
||||
},
|
||||
watermarkContainer: {
|
||||
position: "fixed",
|
||||
top: 450,
|
||||
left: 0,
|
||||
right: 30,
|
||||
bottom: 0,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
opacity: 0.2,
|
||||
zIndex: -1,
|
||||
},
|
||||
watermarkp: {
|
||||
fontSize: 100,
|
||||
fontWeight: "bolder",
|
||||
color: "grey",
|
||||
transform: "rotate(-45deg)",
|
||||
left: "50%",
|
||||
},
|
||||
title: {
|
||||
fontSize: 12,
|
||||
fontWeight: "bolder",
|
||||
pAlign: "center",
|
||||
},
|
||||
titleTopic: {
|
||||
marginTop: "10px",
|
||||
fontSize: 12,
|
||||
fontWeight: "bolder",
|
||||
pAlign: "center",
|
||||
},
|
||||
firsttitle: {
|
||||
fontSize: 14,
|
||||
fontWeight: "bolder",
|
||||
marginLeft: "40px",
|
||||
pAlign: "center",
|
||||
},
|
||||
title2: {
|
||||
fontSize: 10,
|
||||
marginBottom: 10,
|
||||
pAlign: "center",
|
||||
},
|
||||
options: {
|
||||
marginLeft: "50px",
|
||||
padding: "10px",
|
||||
marginTop: "15px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "flex-start",
|
||||
},
|
||||
divider: {
|
||||
width: "100%",
|
||||
height: "2px",
|
||||
backgroundColor: "red",
|
||||
marginBottom: 15,
|
||||
},
|
||||
pTitleContainer: {
|
||||
pAlign: "right",
|
||||
margin: "15px",
|
||||
textAlign: "justify",
|
||||
textJustify: "inter-word",
|
||||
},
|
||||
tableHeaderCell: {
|
||||
backgroundColor: "rgba(255, 229, 153, 0.5)",
|
||||
fontSize: 10,
|
||||
border: "1px solid #000",
|
||||
padding: "4px",
|
||||
textAlign: "center",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
footer: {
|
||||
pageBreakAfter: "always",
|
||||
position: "fixed",
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
width: "100%",
|
||||
},
|
||||
};
|
||||
|
||||
const ProvinceAllcationInvoice = forwardRef((props, ref) => {
|
||||
const { item } = props;
|
||||
const { date } = props;
|
||||
|
||||
const totalCapacity = item?.reduce(
|
||||
(total, currentItem) => total + (currentItem?.quantity || 0),
|
||||
0
|
||||
);
|
||||
|
||||
function getItemInfoQuantity(item) {
|
||||
let totalQuantity = 0;
|
||||
item?.forEach((option) => {
|
||||
if (option?.provinceKillRequests) {
|
||||
option.provinceKillRequests.forEach((request) => {
|
||||
if (request.info?.quantity !== undefined) {
|
||||
totalQuantity += request.info.quantity;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return totalQuantity;
|
||||
}
|
||||
|
||||
function getItemInfoWeight(item) {
|
||||
let totalQuantity = 0;
|
||||
item?.forEach((option) => {
|
||||
if (option?.provinceKillRequests) {
|
||||
option.provinceKillRequests.forEach((request) => {
|
||||
if (request.info?.weight !== undefined) {
|
||||
totalQuantity += request.info.weight;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return totalQuantity;
|
||||
}
|
||||
|
||||
// function getAddressContent(systemName) {
|
||||
// switch (systemName) {
|
||||
// case "استان اردبیل":
|
||||
// return "آدرس : اردبیل، شهرک کارشناسان ،جنب ساختمان نظام مهندسی، ساختمان فرهنگ، طبقه دوم تلفن : 33749254 تلفاکس : 33749253 ";
|
||||
|
||||
// case "استان همدان":
|
||||
// return "همدان، بلوار آیت اله مدنی، کوچه امامزاده یحیی یک تلفن: 081 32523689 ";
|
||||
|
||||
// case "استان آذربایجان شرقی":
|
||||
// return "تبریز خیابان راه آهن نبش کوی اشکان ساختمان ۱۴ طبقه دوم تلفن: 041 34502363";
|
||||
|
||||
// default:
|
||||
// return "خرم آباد، مطهری، شرکت مهندسی نرم افزار آرتا مهر آرتان تلفن: 09011110919";
|
||||
// }
|
||||
// }
|
||||
|
||||
const systemName = useSystemName();
|
||||
|
||||
return (
|
||||
<div style={styles.page} ref={ref}>
|
||||
<div style={styles.contentContainer}>
|
||||
<div style={styles.contentInLine}>
|
||||
<img alt="logo" src={logo} style={styles.logo} />
|
||||
<span style={styles.mainTitle}>
|
||||
اتحادیه سراسری تعاونیهای کشاورزی پرورش دهندگان مرغ گوشتی ایران
|
||||
</span>
|
||||
<span style={styles.title}>
|
||||
اتحادیه شرکت های تعاونی کشاورزی مرغداران {" "} {systemName}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span style={styles.firsttitle}>بسمه تعالی</span>
|
||||
</div>
|
||||
|
||||
<div style={styles.options}>
|
||||
<span style={styles.title}>شماره:</span>
|
||||
<span style={styles.titleTopic}>تاریخ:</span>
|
||||
<span style={styles.titleTopic}>پیوست:</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr style={styles.divider} />
|
||||
|
||||
<p style={styles.pTitleContainer}>
|
||||
<strong style={{ fontSize: "20px" }}>
|
||||
معاونت محترم توسعه بازرگانی و صنایع کشاورزی
|
||||
<br />
|
||||
با سلام
|
||||
<br />
|
||||
</strong>
|
||||
<br />
|
||||
احتراماً گزارش تخصیص و کشتار مورخ {" "}
|
||||
{formatJustDate(date)}، مرغ گوشتی استان جهت استحضار بحضورتان ارسال می
|
||||
گردد.
|
||||
</p>
|
||||
|
||||
<div style={styles.container}>
|
||||
<p style={{ marginTop: "40px" }}>
|
||||
اطلاعات تخصیص:{" "}
|
||||
<span style={{ color: "green", fontWeight: "boler" }}>
|
||||
{" "}
|
||||
تعداد درخواست کشتار (
|
||||
{totalCapacity !== undefined && totalCapacity.toLocaleString()}{" "}
|
||||
قطعه)، تخصیص داده شده ({getItemInfoQuantity(item).toLocaleString()}{" "}
|
||||
قطعه)، وزن کل تخصیص ({" "}
|
||||
{Math.round(getItemInfoWeight(item)).toLocaleString()} کیلوگرم).
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<table style={styles.invoiceTable}>
|
||||
<thead style={styles.tableHeader}>
|
||||
<tr style={styles.headerRow}>
|
||||
<th style={styles.tableHeaderCell}>ردیف</th>
|
||||
<th style={styles.tableHeaderCell}>مرغدار</th>
|
||||
<th style={styles.tableHeaderCell}>تلفن</th>
|
||||
<th style={styles.tableHeaderCell}>شهر</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد</th>
|
||||
<th style={styles.tableHeaderCell}>میانگین وزنی</th>
|
||||
<th style={styles.tableHeaderCell}>سن</th>
|
||||
<th style={styles.tableHeaderCell}>خریدار</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد</th>
|
||||
<th style={styles.tableHeaderCell}>وزن تقریبی بار</th>
|
||||
<th style={styles.tableHeaderCell}>محل کشتار</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{item?.map((item, i) => (
|
||||
<tr key={i}>
|
||||
<td style={styles.tableCell}>{i + 1}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.poultry?.user?.fullname}
|
||||
</td>
|
||||
<td style={styles.tableCellMobile}>
|
||||
{item?.poultry?.user?.mobile}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.poultry?.address?.city?.name}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.quantity.toLocaleString()}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.IndexWeight.toLocaleString()}
|
||||
</td>
|
||||
<td style={styles.tableCell}>{item?.hatching?.age}</td>
|
||||
<td style={styles.tableInnerCell}>
|
||||
{item?.provinceKillRequests?.map((item, i, array) => (
|
||||
<>
|
||||
{item?.killhouseUser?.killHouseOperator?.user?.fullname
|
||||
? item?.killhouseUser?.killHouseOperator?.user?.fullname
|
||||
: "............"}
|
||||
<br />
|
||||
{i < array.length - 1 && (
|
||||
<div style={{ borderBottom: "1px solid #000" }} />
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</td>
|
||||
<td style={styles.tableInnerCell}>
|
||||
{item?.provinceKillRequests?.map((item, i, array) => (
|
||||
<>
|
||||
{item?.info?.quantity
|
||||
? item?.info?.quantity.toLocaleString()
|
||||
: "............"}
|
||||
<br />
|
||||
{i < array.length - 1 && (
|
||||
<div style={{ borderBottom: "1px solid #000" }} />
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</td>
|
||||
<td style={styles.tableInnerCell}>
|
||||
{item?.provinceKillRequests?.map((item, i, array) => (
|
||||
<>
|
||||
{Math.round(item?.info?.weight)
|
||||
? Math.round(item?.info?.weight).toLocaleString()
|
||||
: "............"}
|
||||
<br />
|
||||
{i < array.length - 1 && (
|
||||
<div style={{ borderBottom: "1px solid #000" }} />
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</td>
|
||||
<td style={styles.tableInnerCell}>
|
||||
{item?.provinceKillRequests?.map((item, i, array) => (
|
||||
<>
|
||||
{item?.info?.killPlace
|
||||
? item?.info?.killPlace
|
||||
: "............"}
|
||||
<br />
|
||||
{i < array.length - 1 && (
|
||||
<div style={{ borderBottom: "1px solid #000" }} />
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div style={{ flexDirection: "row", marginTop: "20px" }}>
|
||||
<div style={styles.signature}>
|
||||
<div style={styles.contentInLine}>
|
||||
<span style={styles.title}>{getCeoName()}</span>
|
||||
<span style={styles.title}>
|
||||
مدیرعامل اتحادیه مرغداران{" "}
|
||||
{systemName}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={styles.watermarkContainer}>
|
||||
<p style={styles.watermarkp}>سامانه رصدیار </p>
|
||||
</div>
|
||||
|
||||
{/* <div style={styles.footer}>
|
||||
<div style={styles.divider} />
|
||||
<p style={{ fontSize: 12, padding: "10px", marginRight: "10px" }}>
|
||||
{getAddressContent(systemName)}
|
||||
</p>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
ProvinceAllcationInvoice.displayName = "ProvinceAllcationInvoice";
|
||||
|
||||
export default ProvinceAllcationInvoice;
|
||||
|
||||
ProvinceAllcationInvoice.propTypes = {
|
||||
item: PropTypes.any,
|
||||
};
|
||||
@@ -0,0 +1,86 @@
|
||||
import { Button, Checkbox, FormControlLabel, TextField } from "@mui/material";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { getLossesPermissionService } from "../../services/get-losses-permission";
|
||||
import { updateLossesPermissionService } from "../../services/update-losses-permission";
|
||||
|
||||
export const ProvinceApplyDefaultLosses = () => {
|
||||
const [isChecked, setIsChecked] = useState(true);
|
||||
const [numberValue, setNumberValue] = useState("");
|
||||
const [data, setData] = useState();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getLossesPermissionService()).then((r) => {
|
||||
setIsChecked(r.payload.data.allow);
|
||||
setNumberValue(r.payload.data.percent);
|
||||
setData(r.payload.data);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isChecked) {
|
||||
dispatch(
|
||||
updateLossesPermissionService({
|
||||
permission_key: data.key,
|
||||
allow: false,
|
||||
percent: parseInt(numberValue),
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [isChecked]);
|
||||
|
||||
const handleChange = (event) => {
|
||||
setIsChecked(event.target.checked);
|
||||
};
|
||||
|
||||
// Define a handleChange function to update the state when the text field value changes
|
||||
const handleChangeNumber = (event) => {
|
||||
// Ensure that the entered value is a number (or an empty string)
|
||||
const newValue = event.target.value;
|
||||
if (/^\d*$/.test(newValue) || newValue === "") {
|
||||
setNumberValue(newValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container alignItems="center" gap={SPACING.TINY}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox checked={isChecked} onChange={handleChange} name="item4" />
|
||||
}
|
||||
label="اعمال درصد تلفات پیش فرض:"
|
||||
/>
|
||||
<Grid>
|
||||
<TextField
|
||||
disabled={!isChecked}
|
||||
type="number"
|
||||
label="درصد تلفات"
|
||||
size="small"
|
||||
value={numberValue}
|
||||
onChange={handleChangeNumber}
|
||||
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={!isChecked || !numberValue}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
updateLossesPermissionService({
|
||||
permission_key: data.key,
|
||||
percent: parseInt(numberValue),
|
||||
allow: isChecked,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Typography } from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { formatTime } from "../../../../utils/formatTime";
|
||||
import { getFaUserRole } from "../../../../utils/getFaUserRole";
|
||||
|
||||
export const ProvinceArchiveFeeDetails = ({ item }) => {
|
||||
return (
|
||||
<Grid container width="100%">
|
||||
<Grid container width="100%" justifyContent="space-between">
|
||||
<Typography>تاریخ و زمان:</Typography>
|
||||
<Typography>{formatTime(item?.archiver?.date)}</Typography>
|
||||
</Grid>
|
||||
<Grid container width="100%" justifyContent="space-between">
|
||||
<Typography>بایگانی کننده:</Typography>
|
||||
<Typography>
|
||||
{item?.archiver?.fullname} ({getFaUserRole(item.archiver.role)})
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container width="100%" justifyContent="space-between">
|
||||
<Typography>دلیل بایگانی:</Typography>
|
||||
<Typography>{item?.archiveMessage}</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
import { Button, TextField } from "@mui/material";
|
||||
import { Box } from "@mui/system";
|
||||
import { useContext, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { provinceArchiveFeeOperationService } from "../../services/province-archive-fee-operation";
|
||||
|
||||
export const ProvinceArchiveFeeOperation = ({ selectedItems, updateTable }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [text, setText] = useState("");
|
||||
|
||||
const handleChange = (event) => {
|
||||
setText(event.target.value);
|
||||
};
|
||||
|
||||
const submitForm = () => {
|
||||
dispatch(
|
||||
provinceArchiveFeeOperationService({
|
||||
role: getRoleFromUrl(),
|
||||
message: text,
|
||||
province_kill_request_list: selectedItems,
|
||||
type: "archive",
|
||||
})
|
||||
).then((r) => {
|
||||
updateTable();
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
dispatch(CLOSE_MODAL());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid width="100%">
|
||||
<Box>
|
||||
<TextField
|
||||
id="outlined-multiline-static"
|
||||
label="دلیل بایگانی"
|
||||
multiline
|
||||
rows={3}
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
value={text}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</Box>
|
||||
<Box mt={1}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={submitForm}
|
||||
disabled={!text}
|
||||
fullWidth
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
</Box>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,365 @@
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import axios from "axios";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { PageTable } from "../../../../components/page-table/PageTable";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { ROUTE_PROVINCE_PAYING_FEES_REQUESTS } from "../../../../routes/routes";
|
||||
import moment from "moment";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
|
||||
export const ProvinceArchiveFees = () => {
|
||||
const userInfo = useSelector((state) => state.userSlice);
|
||||
const navigate = useNavigate();
|
||||
const [data, setData] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [withDate, setWithDate] = useState(false);
|
||||
|
||||
const [textValue, setTextValue] = useState("");
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, []);
|
||||
|
||||
const fetchApiData = async (page, textValue) => {
|
||||
setLoading(true);
|
||||
const response = await axios.get(
|
||||
`kill_house_total_wage/?search=filter&value=${textValue}&role=${getRoleFromUrl()}&type=archive&page=${page}&page_size=${perPage}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page, textValue);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = async (newPerPage, page) => {
|
||||
setLoading(true);
|
||||
const response = await axios.get(
|
||||
`kill_house_total_wage/?search=filter&value=${textValue}&role=${getRoleFromUrl()}&type=archive&page=${page}&page_size=${newPerPage}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}`
|
||||
);
|
||||
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
setPerPage(newPerPage);
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, []);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`kill_house_total_wage/?search=filter&value=${textValue}&role=${getRoleFromUrl()}&type=archive${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, [selectedDate1, selectedDate2, withDate]);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: "خریدار",
|
||||
selector: (item) => {
|
||||
const type = item?.info?.killer ? "کشتارکن" : "کشتارگاه";
|
||||
return `${type} ${item?.info?.killHouseName} - ${item?.info?.killHouseFullname} (${item?.info?.killHouseMobile})`;
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "شهر",
|
||||
selector: (item) => `${item?.info?.killHouseCity}`,
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "80px",
|
||||
},
|
||||
// {
|
||||
// name: "تعداد کل سفارشات",
|
||||
// selector: (item) => item?.info?.totalCount,
|
||||
// sortable: true,
|
||||
// wrap: true,
|
||||
// allowOverflow: true,
|
||||
// center: true,
|
||||
// // width: "80px",
|
||||
// },
|
||||
// {
|
||||
// name: "تعداد کل تخصیص (قطعه)",
|
||||
// selector: (item) => item?.info?.totalQuantity?.toLocaleString(),
|
||||
// sortable: true,
|
||||
// wrap: true,
|
||||
// allowOverflow: true,
|
||||
// center: true,
|
||||
// },
|
||||
// {
|
||||
// name: "وزن کل (کیلوگرم)",
|
||||
// selector: (item) => item?.info?.totalWeight,
|
||||
// sortable: true,
|
||||
// wrap: true,
|
||||
// allowOverflow: true,
|
||||
// center: true,
|
||||
// // width: "80px",
|
||||
// },
|
||||
// {
|
||||
// name: "پرداخت شده (سفارش)",
|
||||
// selector: (item) => item.info?.paidCount,
|
||||
// sortable: true,
|
||||
// wrap: true,
|
||||
// allowOverflow: true,
|
||||
// center: true,
|
||||
// // width: "90px",
|
||||
// },
|
||||
{
|
||||
name: "تعداد پرونده",
|
||||
selector: (item) => item?.info?.archiveCount?.toLocaleString(),
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "حجم",
|
||||
selector: (item) => item.info?.totalArchiveQuantity?.toLocaleString(),
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "وزن سفارشات (کیلوگرم)",
|
||||
selector: (item) => {
|
||||
return item.info?.totalWeightArchive?.toLocaleString();
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
// {
|
||||
// name: "مبلغ کل تعرفه (ریال)",
|
||||
// selector: (item) => item?.info?.totalWage?.toLocaleString(),
|
||||
// sortable: true,
|
||||
// wrap: true,
|
||||
// allowOverflow: true,
|
||||
// center: true,
|
||||
// // width: "90px",
|
||||
// },
|
||||
// {
|
||||
// name: "مبلغ تسویه شده (تعرفه )",
|
||||
// selector: (item) => item?.info?.totalPaidWage?.toLocaleString(),
|
||||
// sortable: true,
|
||||
// wrap: true,
|
||||
// allowOverflow: true,
|
||||
// center: true,
|
||||
// // width: "90px",
|
||||
// },
|
||||
{
|
||||
name: "مبلغ تعرفه (﷼)",
|
||||
selector: (item) => item?.info?.totalArchiveWage?.toLocaleString(),
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
{
|
||||
name: "جزییات سفارش",
|
||||
selector: (item) => {
|
||||
return (
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigate(
|
||||
`${ROUTE_PROVINCE_PAYING_FEES_REQUESTS}/archive/${item.key}`
|
||||
);
|
||||
}}
|
||||
>
|
||||
مشاهده
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
sortable: true,
|
||||
wrap: true,
|
||||
allowOverflow: true,
|
||||
center: true,
|
||||
// width: "90px",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Grid container justifyContent="end">
|
||||
<PageTable
|
||||
title={
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
gap={2}
|
||||
paddingTop={2}
|
||||
mb={1}
|
||||
width="100%"
|
||||
>
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
<Typography>تعرفه های معوقه</Typography>
|
||||
<Grid
|
||||
container
|
||||
style={{
|
||||
borderStyle: "solid",
|
||||
borderWidth: "1px",
|
||||
padding: "10px",
|
||||
borderRadius: "15px",
|
||||
borderColor: "gray",
|
||||
justifyContent: "left",
|
||||
}}
|
||||
>
|
||||
<Grid>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={withDate}
|
||||
onChange={() => setWithDate(!withDate)}
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
disabled={!withDate}
|
||||
label="از تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
size="small"
|
||||
style={{ width: "160px" }}
|
||||
{...params}
|
||||
/>
|
||||
)}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
disabled={!withDate}
|
||||
label="تا تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
size="small"
|
||||
style={{ width: "160px" }}
|
||||
{...params}
|
||||
/>
|
||||
)}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
id="outlined-basic"
|
||||
size="small"
|
||||
autoComplete="off"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button
|
||||
// disabled={!textValue}
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
endIcon={<RiSearchLine />}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
</form>
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<a
|
||||
href={`${
|
||||
axios.defaults.baseURL
|
||||
}kill_house_total_wage_archive_excel/?key=${
|
||||
userInfo?.userProfile?.key
|
||||
}${textValue}${
|
||||
withDate
|
||||
? `&date1=${selectedDate1}&date2=${selectedDate2}`
|
||||
: ``
|
||||
}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</Grid>
|
||||
}
|
||||
columns={columns}
|
||||
data={data}
|
||||
progressPending={loading}
|
||||
pagination
|
||||
paginationServer
|
||||
paginationTotalRows={totalRows}
|
||||
onChangeRowsPerPage={handlePerRowsChange}
|
||||
onChangePage={handlePageChange}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,180 @@
|
||||
import { Button, IconButton } from "@mui/material";
|
||||
import PrintIcon from "@mui/icons-material/Print";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
|
||||
export const ProvinceAutoAllocatedView = ({
|
||||
dataTable,
|
||||
item,
|
||||
setIsSingleView,
|
||||
}) => {
|
||||
const sumOfAllocationQuantity =
|
||||
Array.isArray(dataTable) &&
|
||||
dataTable?.reduce((total, item) => {
|
||||
return (
|
||||
total +
|
||||
item.allocations?.reduce((allocationTotal, allocation) => {
|
||||
return allocationTotal + allocation.allocationQuantity;
|
||||
}, 0)
|
||||
);
|
||||
}, 0);
|
||||
|
||||
const sumAllocationsSum =
|
||||
Array.isArray(dataTable) &&
|
||||
dataTable?.reduce((total, item) => {
|
||||
return total + item.allocationsSum;
|
||||
}, 0);
|
||||
|
||||
const sumOfKillRequests =
|
||||
Array.isArray(dataTable) &&
|
||||
dataTable?.reduce((total, item) => {
|
||||
return total + item.poultryQuantity;
|
||||
}, 0);
|
||||
|
||||
return (
|
||||
<Grid container alignItems="start" my={SPACING.SMALL}>
|
||||
<table className="auto-allocation-table">
|
||||
<tr>
|
||||
<th>
|
||||
<Grid>
|
||||
<Button
|
||||
color="error"
|
||||
onClick={() => {
|
||||
setIsSingleView(null);
|
||||
}}
|
||||
>
|
||||
<KeyboardArrowRightIcon />
|
||||
بازگشت به بایگانی
|
||||
</Button>
|
||||
</Grid>
|
||||
</th>
|
||||
<th>کد تخصیص خودکار {item.allocationOrderCode}</th>
|
||||
<th>تاریخ تخصیص {formatJustDate(item.allocationDate)}</th>
|
||||
</tr>
|
||||
</table>
|
||||
<table className="auto-allocation-table">
|
||||
<tr>
|
||||
<th>ردیف</th>
|
||||
<th>نام واحد (مرغدار)</th>
|
||||
<th>تلفن مرغدار</th>
|
||||
<th>آدرس</th>
|
||||
<th>تعداد درخواست کشتار</th>
|
||||
<th>مانده قابل تخصیص</th>
|
||||
<th>ماهیت خریدار</th>
|
||||
<th>نام خریدار</th>
|
||||
<th>تلفن خریدار</th>
|
||||
<th>آدرس</th>
|
||||
<th>محل کشتار</th>
|
||||
<th>تعداد تخصیص</th>
|
||||
<th>جمع مرغ تخصیصی</th>
|
||||
<th>سهم درصد</th>
|
||||
<th>حواله مرغدار</th>
|
||||
<th>حواله خریدار</th>
|
||||
</tr>
|
||||
{dataTable?.map((poultryRequestItem, j) => {
|
||||
// const sumOfAllocation = poultryRequestItem.allocations?.reduce(
|
||||
// (total, item) => {
|
||||
// return total + item.allocationQuantity;
|
||||
// },
|
||||
// 0
|
||||
// );
|
||||
return poultryRequestItem?.allocations?.map((slaughter, i) => {
|
||||
const reaminForAllocation =
|
||||
poultryRequestItem?.poultryQuantity -
|
||||
poultryRequestItem?.allocationsSum;
|
||||
|
||||
// if (reaminForAllocation < 0) {
|
||||
// reaminForAllocation = (
|
||||
// <Typography color={"red"}>{reaminForAllocation}</Typography>
|
||||
// );
|
||||
// }
|
||||
|
||||
return (
|
||||
<tr key={i}>
|
||||
{!i && (
|
||||
<td rowSpan={poultryRequestItem?.allocations.length}>
|
||||
{j + 1}
|
||||
</td>
|
||||
)}
|
||||
|
||||
{!i && (
|
||||
<td rowSpan={poultryRequestItem?.allocations.length}>
|
||||
{poultryRequestItem?.poultryName}
|
||||
</td>
|
||||
)}
|
||||
|
||||
{!i && (
|
||||
<td rowSpan={poultryRequestItem?.allocations.length}>
|
||||
{poultryRequestItem?.poultryMobile}
|
||||
</td>
|
||||
)}
|
||||
|
||||
{!i && (
|
||||
<td rowSpan={poultryRequestItem?.allocations.length}>
|
||||
{poultryRequestItem?.poultryAddress}
|
||||
</td>
|
||||
)}
|
||||
|
||||
{!i && (
|
||||
<td rowSpan={poultryRequestItem?.allocations.length}>
|
||||
{poultryRequestItem?.poultryQuantity?.toLocaleString()}
|
||||
</td>
|
||||
)}
|
||||
|
||||
{!i && (
|
||||
<td rowSpan={poultryRequestItem?.allocations.length}>
|
||||
{/* {poultryRequestItem?.poultryRemainQuantity} */}
|
||||
{reaminForAllocation.toLocaleString()}
|
||||
</td>
|
||||
)}
|
||||
|
||||
<td>{slaughter?.type ? "کشتارکن" : "کشتارگاه"}</td>
|
||||
|
||||
<td>{slaughter?.buyerName}</td>
|
||||
<td>{slaughter?.buyerMobile}</td>
|
||||
<td>{slaughter?.buyerAddress}</td>
|
||||
<td>{slaughter?.KillingPlace}</td>
|
||||
<td>{slaughter?.allocationQuantity}</td>
|
||||
{!i && (
|
||||
<td rowSpan={poultryRequestItem?.allocations.length}>
|
||||
{poultryRequestItem?.allocationsSum?.toLocaleString()}
|
||||
{/* {sumOfAllocation} */}
|
||||
</td>
|
||||
)}
|
||||
<td>
|
||||
%
|
||||
{(
|
||||
(slaughter?.allocationQuantity / sumOfAllocationQuantity) *
|
||||
100
|
||||
).toFixed(2)}
|
||||
</td>
|
||||
{!i && (
|
||||
<td rowSpan={poultryRequestItem?.allocations.length}>
|
||||
<IconButton disabled={true} color="primary">
|
||||
<PrintIcon />
|
||||
</IconButton>
|
||||
</td>
|
||||
)}
|
||||
<td>
|
||||
<IconButton disabled={true} color="primary">
|
||||
<PrintIcon />
|
||||
</IconButton>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
})}
|
||||
<tr>
|
||||
<td colSpan={"11"}>جمع کل</td>
|
||||
<td>{sumOfAllocationQuantity.toLocaleString()}</td>
|
||||
<td>{sumAllocationsSum.toLocaleString()}</td>
|
||||
<td>
|
||||
{((sumOfAllocationQuantity / sumOfKillRequests) * 100).toFixed(2)}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,130 @@
|
||||
import { IconButton, TextField, Typography } from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment/moment";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { provinceGetArchiveAutoAllocationsService } from "../../services/province-get-archive-auto-allocations";
|
||||
import PlagiarismIcon from "@mui/icons-material/Plagiarism";
|
||||
import { ProvinceAutoAllocatedView } from "../province-auto-allocated-view/ProvinceAutoAllocatedView";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
|
||||
export const ProvinceAutoAllocationArchive = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const [isSingleView, setIsSingleView] = useState();
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, []);
|
||||
|
||||
const { provinceGetArchiveAutoAllocations } = useSelector(
|
||||
(state) => state.provinceSlice
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
provinceGetArchiveAutoAllocationsService({ selectedDate1, selectedDate2 })
|
||||
);
|
||||
}, [selectedDate1, selectedDate2]);
|
||||
|
||||
useEffect(() => {
|
||||
const d = provinceGetArchiveAutoAllocations?.map((item, i) => {
|
||||
return [
|
||||
i + 1,
|
||||
item.allocationOrderCode,
|
||||
formatJustDate(item.allocationDate),
|
||||
item.totalQuantity.toLocaleString(),
|
||||
item.allocatedQuantity.toLocaleString(),
|
||||
item.numberOfPoultry.toLocaleString(),
|
||||
item.numberOfKillHouse.toLocaleString(),
|
||||
<IconButton
|
||||
color="primary"
|
||||
key={i}
|
||||
onClick={() => {
|
||||
setIsSingleView(item);
|
||||
}}
|
||||
>
|
||||
<PlagiarismIcon />
|
||||
</IconButton>,
|
||||
];
|
||||
});
|
||||
setDataTable(d);
|
||||
}, [provinceGetArchiveAutoAllocations]);
|
||||
|
||||
return (
|
||||
<Grid mt={SPACING.SMALL} xs={12} px={2}>
|
||||
{!isSingleView && (
|
||||
<>
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL} mb={2}>
|
||||
<Grid>
|
||||
<Typography>بایگانی تخصیصات خودکار</Typography>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
label="از تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField style={{ width: "160px" }} {...params} />
|
||||
)}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
label="تا تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField style={{ width: "160px" }} {...params} />
|
||||
)}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<ResponsiveTable
|
||||
title="بایگانی تخصیصات خودکار"
|
||||
columns={[
|
||||
"ردیف",
|
||||
"کد تخصیص خودکار",
|
||||
"تاریخ تخصیص",
|
||||
"تعداد درخواست کشتار",
|
||||
"تعداد تخصیصی",
|
||||
"تعداد مرغدار",
|
||||
"تعداد کشتارگاه",
|
||||
"مشاهده",
|
||||
]}
|
||||
data={dataTable}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{isSingleView && (
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
alignItems="start"
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
<ProvinceAutoAllocatedView
|
||||
dataTable={isSingleView.allocationsList}
|
||||
item={isSingleView}
|
||||
setIsSingleView={setIsSingleView}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,791 @@
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
Popover,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { getPoultryRequestsTotalQuantityService } from "../../../city/services/get-poultry-requests-total-quantity";
|
||||
import { provinceCreateAutoAllocationService } from "../../services/province-create-auto-allocation";
|
||||
import { provinceEditAutoAllocationService } from "../../services/province-edit-auto-allocation";
|
||||
import { provinceGetAutoAllocationsService } from "../../services/province-get-auto-allocations";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import { OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { ProvinceAddBuyerAutoAllocation } from "../province-add-buyer-auto-allocation/ProvinceAddBuyerAutoAllocation";
|
||||
import { provinceDeleteAutoAllocationService } from "../../services/province-delete-auto-allocation";
|
||||
import { provinceAddAutoAllocationService } from "../../services/province-add-auto-allocation";
|
||||
import PrintIcon from "@mui/icons-material/Print";
|
||||
import { provinceSubmitFinalAutoAllocationsService } from "../../services/province-submit-final-auto-allocations";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment/moment";
|
||||
import { ProvinceAutoSelectOptions } from "../province-auto-select-options/ProvinceAutoSelectOptions";
|
||||
|
||||
export const ProvinceAutoAllocationRequests = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const [deletedRows, setDeletedRows] = useState([]);
|
||||
const [addedRows, setAddedRows] = useState([]);
|
||||
|
||||
const [selectedProiority, setSelectedProiority] = useState({});
|
||||
// const [allocationSumState, setAllocationSumState] = useState(0);
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const id = open ? "popoverr" : undefined;
|
||||
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
handleClose();
|
||||
}, []);
|
||||
|
||||
const { poultryRequestsTotalQuantity } = useSelector(
|
||||
(state) => state.citySlice
|
||||
);
|
||||
|
||||
const { provinceGetAutoAllocations } = useSelector(
|
||||
(state) => state.provinceSlice
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetAutoAllocationsService());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setDataTable(deepCopy(provinceGetAutoAllocations));
|
||||
}, [provinceGetAutoAllocations]);
|
||||
|
||||
const sendEditTableService = () => {
|
||||
const combinedArr = dataTable?.reduce((acc, curr) => {
|
||||
let d = deepCopy(curr.allocations);
|
||||
d = d.filter((item) => item.allocationKey);
|
||||
return [...acc, ...d];
|
||||
}, []);
|
||||
dispatch(
|
||||
provinceDeleteAutoAllocationService({
|
||||
allocation_delete_list: deletedRows?.filter(
|
||||
(item) => item.allocationKey
|
||||
),
|
||||
})
|
||||
).then(() => {
|
||||
setDeletedRows([]);
|
||||
dispatch(
|
||||
provinceAddAutoAllocationService({
|
||||
allocation_add_list: addedRows,
|
||||
})
|
||||
).then(() => {
|
||||
dispatch(
|
||||
provinceEditAutoAllocationService({
|
||||
allocation_list: combinedArr,
|
||||
})
|
||||
).then((r) => {
|
||||
setAddedRows([]);
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(getPoultryRequestsTotalQuantityService());
|
||||
dispatch(provinceGetAutoAllocationsService());
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const checkForDebt = () => {
|
||||
// check if there are debt
|
||||
|
||||
const mapedDebts = dataTable.map((element) => {
|
||||
const hasDebt = element.allocations.some((allocation) => allocation.debt);
|
||||
return hasDebt;
|
||||
});
|
||||
const res = mapedDebts.some((item) => item);
|
||||
return res;
|
||||
};
|
||||
|
||||
const sendFinalTableService = () => {
|
||||
const combinedArr = dataTable?.reduce((acc, curr) => {
|
||||
let d = deepCopy(curr.allocations);
|
||||
d = d.filter((item) => item.allocationKey);
|
||||
return [...acc, ...d];
|
||||
}, []);
|
||||
dispatch(
|
||||
provinceDeleteAutoAllocationService({
|
||||
allocation_delete_list: deletedRows?.filter(
|
||||
(item) => item.allocationKey
|
||||
),
|
||||
})
|
||||
).then(() => {
|
||||
setDeletedRows([]);
|
||||
dispatch(
|
||||
provinceAddAutoAllocationService({
|
||||
allocation_add_list: addedRows,
|
||||
})
|
||||
).then(() => {
|
||||
dispatch(
|
||||
provinceEditAutoAllocationService({
|
||||
allocation_list: combinedArr,
|
||||
})
|
||||
).then(() => {
|
||||
setAddedRows([]);
|
||||
|
||||
const allocationsForCancel = provinceGetAutoAllocations?.reduce(
|
||||
(total, item) => {
|
||||
return [...total, ...item.allocations];
|
||||
},
|
||||
[]
|
||||
);
|
||||
const allocationsKeys = allocationsForCancel.map((item) => {
|
||||
return { allocationKey: item.allocationKey };
|
||||
});
|
||||
dispatch(
|
||||
provinceSubmitFinalAutoAllocationsService({
|
||||
final_registration_list: allocationsKeys,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(getPoultryRequestsTotalQuantityService());
|
||||
dispatch(provinceGetAutoAllocationsService());
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const sumOfAllocationQuantity =
|
||||
Array.isArray(dataTable) &&
|
||||
dataTable?.reduce((total, item) => {
|
||||
return (
|
||||
total +
|
||||
item.allocations?.reduce((allocationTotal, allocation) => {
|
||||
return allocationTotal + allocation.allocationQuantity;
|
||||
}, 0)
|
||||
);
|
||||
}, 0);
|
||||
|
||||
const sumAllocationsSum =
|
||||
Array.isArray(dataTable) &&
|
||||
dataTable?.reduce((total, item) => {
|
||||
return total + item.allocationsSum;
|
||||
}, 0);
|
||||
|
||||
// const sumOfAllocationPercent = provinceGetAutoAllocations?.reduce(
|
||||
// (total, item) => {
|
||||
// return (
|
||||
// total +
|
||||
// item.allocations.reduce((allocationTotal, allocation) => {
|
||||
// return allocationTotal + allocation.allocationPercent;
|
||||
// }, 0)
|
||||
// );
|
||||
// },
|
||||
// 0
|
||||
// );
|
||||
|
||||
const sumOfKillRequests =
|
||||
Array.isArray(dataTable) &&
|
||||
dataTable?.reduce((total, item) => {
|
||||
return total + item.poultryQuantity;
|
||||
}, 0);
|
||||
|
||||
const [dateForAutoAlloction, setDateForAutoAllocation] = useState(
|
||||
moment(new Date()).format("YYYY-MM-DD")
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getPoultryRequestsTotalQuantityService(dateForAutoAlloction));
|
||||
}, [dateForAutoAlloction]);
|
||||
|
||||
const handleList = (selected) => {
|
||||
const d = selected.map((item) => {
|
||||
return {
|
||||
[item.key]: item.value,
|
||||
};
|
||||
});
|
||||
setSelectedProiority(d);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
my={SPACING.SMALL}
|
||||
direction="column"
|
||||
alignItems="start"
|
||||
xs={12}
|
||||
pt={2}
|
||||
px={2}
|
||||
>
|
||||
<SimpleTable
|
||||
name={
|
||||
<Grid xs={12} mb={2}>
|
||||
<DatePicker
|
||||
label="تاریخ تخصیص"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField style={{ width: "180px" }} {...params} />
|
||||
)}
|
||||
value={dateForAutoAlloction}
|
||||
onChange={(e) => {
|
||||
setDateForAutoAllocation(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
}
|
||||
columns={[
|
||||
"تعداد کل درخواست کشتار",
|
||||
"تخصیص داده شده",
|
||||
"قابل تخصیص",
|
||||
"تعداد خریداران آماده به تخصیص",
|
||||
"تعداد مرغدار",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
`${poultryRequestsTotalQuantity?.acceptedQuantity?.toLocaleString()} قطعه`,
|
||||
`${poultryRequestsTotalQuantity?.allocatedQuantity?.toLocaleString()} قطعه`,
|
||||
`${poultryRequestsTotalQuantity?.assignableQuantity?.toLocaleString()} قطعه`,
|
||||
`${poultryRequestsTotalQuantity?.numberOfKillHouse?.toLocaleString()} واحد`,
|
||||
`${poultryRequestsTotalQuantity?.numberOfPoultry?.toLocaleString()} واحد`,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.SMALL}
|
||||
my={SPACING.SMALL}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
width="100%"
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
direction="column"
|
||||
gap={SPACING.SMALL}
|
||||
width="100%"
|
||||
>
|
||||
<Typography fontWeight="bold">اولویت بندی کشتارگاه</Typography>
|
||||
<ProvinceAutoSelectOptions handleList={handleList} />
|
||||
<Grid>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={dataTable.length}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceCreateAutoAllocationService({
|
||||
date: dateForAutoAlloction,
|
||||
filter_list: selectedProiority,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(getPoultryRequestsTotalQuantityService());
|
||||
dispatch(provinceGetAutoAllocationsService());
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ایجاد تخصیص خودکار
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{!!dataTable?.length && (
|
||||
<>
|
||||
<Grid mb={SPACING.SMALL}>
|
||||
<Typography fontWeight="bold" color="error">
|
||||
* توجه: رنگ قرمز خریدار نشان دهنده بدهی قبلی است.
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<table className="auto-allocation-table">
|
||||
<tr>
|
||||
<th>ردیف</th>
|
||||
<th>واحد (مرغدار)</th>
|
||||
<th>تعداد درخواست کشتار</th>
|
||||
<th>وزن تقریبی درخواست کشتار</th>
|
||||
<th>مانده قابل تخصیص</th>
|
||||
<th>اضافه</th>
|
||||
<th>ماهیت خریدار</th>
|
||||
<th>خریدار</th>
|
||||
<th>محل کشتار</th>
|
||||
<th>تعداد تخصیص</th>
|
||||
<th>جمع مرغ تخصیصی</th>
|
||||
<th>سهم درصد</th>
|
||||
<th>حواله مرغدار</th>
|
||||
<th>حواله خریدار</th>
|
||||
<th>حذف</th>
|
||||
</tr>
|
||||
{dataTable?.map((poultryRequestItem, j) => {
|
||||
// const sumOfAllocation = poultryRequestItem.allocations?.reduce(
|
||||
// (total, item) => {
|
||||
// return total + item.allocationQuantity;
|
||||
// },
|
||||
// 0
|
||||
// );
|
||||
return poultryRequestItem?.allocations?.map((slaughter, i) => {
|
||||
let reaminForAllocation =
|
||||
poultryRequestItem?.poultryQuantity -
|
||||
poultryRequestItem?.allocationsSum;
|
||||
|
||||
// if (reaminForAllocation < 0) {
|
||||
// reaminForAllocation = (
|
||||
// <Typography color={"#f2f2f2"}>{reaminForAllocation}</Typography>
|
||||
// );
|
||||
// }
|
||||
|
||||
return (
|
||||
<tr key={i}>
|
||||
{!i && (
|
||||
<td
|
||||
rowSpan={poultryRequestItem?.allocations.length}
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
}}
|
||||
>
|
||||
{j + 1}
|
||||
</td>
|
||||
)}
|
||||
|
||||
{!i && (
|
||||
<td
|
||||
rowSpan={poultryRequestItem?.allocations.length}
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
}}
|
||||
>
|
||||
{poultryRequestItem?.poultryName} (
|
||||
{poultryRequestItem?.poultryAddress}) (
|
||||
{poultryRequestItem?.poultryMobile})
|
||||
</td>
|
||||
)}
|
||||
|
||||
{!i && (
|
||||
<td
|
||||
rowSpan={poultryRequestItem?.allocations.length}
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
}}
|
||||
>
|
||||
{poultryRequestItem?.poultryQuantity?.toLocaleString()}
|
||||
</td>
|
||||
)}
|
||||
|
||||
{!i && (
|
||||
<td
|
||||
rowSpan={poultryRequestItem?.allocations.length}
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
}}
|
||||
>
|
||||
وزن تقریبی:{" "}
|
||||
{poultryRequestItem?.poultryRequestWeight?.toLocaleString()}
|
||||
<hr />
|
||||
میانگین وزن:{" "}
|
||||
{poultryRequestItem?.poultryRequestIndexWeight}
|
||||
</td>
|
||||
)}
|
||||
|
||||
{!i && (
|
||||
<td
|
||||
rowSpan={poultryRequestItem?.allocations.length}
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
}}
|
||||
>
|
||||
{/* {poultryRequestItem?.poultryRemainQuantity} */}
|
||||
{reaminForAllocation.toLocaleString()}
|
||||
</td>
|
||||
)}
|
||||
{!i && (
|
||||
<td
|
||||
rowSpan={poultryRequestItem?.allocations.length}
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "اضافه کردن خریدار",
|
||||
content: (
|
||||
<ProvinceAddBuyerAutoAllocation
|
||||
dataTable={dataTable}
|
||||
poultryIndex={j}
|
||||
setDataTable={setDataTable}
|
||||
setAddedRows={setAddedRows}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
// setDataTable((prevState) => {
|
||||
// // let edited = Array.from(prevState);
|
||||
// let edited = deepCopy(prevState);
|
||||
|
||||
// edited[j].allocationsSum = edited[
|
||||
// j
|
||||
// ].allocations?.reduce((total, item) => {
|
||||
// return total + item.allocationQuantity;
|
||||
// }, 0);
|
||||
|
||||
// return edited;
|
||||
// });
|
||||
}}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</td>
|
||||
)}
|
||||
|
||||
<td
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
color: slaughter.debt ? "red" : "",
|
||||
}}
|
||||
>
|
||||
{slaughter?.type ? "کشتارکن" : "کشتارگاه"}{" "}
|
||||
{slaughter.debt ? "(بدهکار)" : ""}
|
||||
</td>
|
||||
|
||||
<td
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
color: slaughter.debt ? "red" : "",
|
||||
}}
|
||||
>
|
||||
{slaughter?.buyerName} ({slaughter?.buyerAddress}) (
|
||||
{slaughter?.buyerMobile})
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
color: slaughter.debt ? "red" : "",
|
||||
}}
|
||||
>
|
||||
{slaughter?.KillingPlace}
|
||||
</td>
|
||||
|
||||
<td
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
}}
|
||||
>
|
||||
<TextField
|
||||
style={{
|
||||
width: "100px",
|
||||
}}
|
||||
type={"number"}
|
||||
color={slaughter.debt ? "error" : ""}
|
||||
inputProps={{
|
||||
style: {
|
||||
color: slaughter.debt ? "red" : "", // Set your desired color here
|
||||
},
|
||||
}}
|
||||
value={slaughter?.allocationQuantity}
|
||||
onChange={(e) => {
|
||||
if (Number(e.target.value) < 1) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "در صورت نیاز به کاهش کمتر از 1 از گزینه حذف استفاده نمایید.",
|
||||
severity: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
setDataTable((prevState) => {
|
||||
// let edited = Array.from(prevState);
|
||||
let edited = deepCopy(prevState);
|
||||
edited[j].allocations[i].allocationQuantity =
|
||||
Number(e.target.value);
|
||||
|
||||
edited[j].allocationsSum = edited[
|
||||
j
|
||||
].allocations?.reduce((total, item) => {
|
||||
return total + item.allocationQuantity;
|
||||
}, 0);
|
||||
|
||||
return edited;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
{!i && (
|
||||
<td
|
||||
rowSpan={poultryRequestItem?.allocations.length}
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
color: slaughter.debt ? "red" : "",
|
||||
}}
|
||||
>
|
||||
{poultryRequestItem?.allocationsSum?.toLocaleString()}
|
||||
{/* {sumOfAllocation} */}
|
||||
</td>
|
||||
)}
|
||||
<td
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
color: slaughter.debt ? "red" : "",
|
||||
}}
|
||||
>
|
||||
%
|
||||
{(
|
||||
(slaughter?.allocationQuantity /
|
||||
sumOfAllocationQuantity) *
|
||||
100
|
||||
).toFixed(2)}
|
||||
</td>
|
||||
{!i && (
|
||||
<td
|
||||
rowSpan={poultryRequestItem?.allocations.length}
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
}}
|
||||
>
|
||||
<IconButton disabled={true} color="primary">
|
||||
<a
|
||||
href={`https://core-inventory.iran.liara.run/pdf/aviculture-remittance?poultryRequestKey=${poultryRequestItem.poultryRequestKey}&which=${window.location.origin}`}
|
||||
>
|
||||
<PrintIcon />
|
||||
</a>
|
||||
</IconButton>
|
||||
</td>
|
||||
)}
|
||||
<td
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
}}
|
||||
>
|
||||
<IconButton disabled={true} color="primary">
|
||||
<a
|
||||
href={`https://core-inventory.iran.liara.run/pdf/buyer-remittance?allocationKey=${slaughter.allocationKey}&which=${window.location.origin}`}
|
||||
>
|
||||
<PrintIcon />
|
||||
</a>
|
||||
</IconButton>
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
backgroundColor: j % 2 === 0 ? "#fff" : "#f2f2f2",
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
color="error"
|
||||
onClick={() => {
|
||||
setDataTable((prevState) => {
|
||||
// let edited = Array.from(prevState);
|
||||
let edited = deepCopy(prevState);
|
||||
setDeletedRows([
|
||||
...deletedRows,
|
||||
edited[j].allocations[i],
|
||||
]);
|
||||
edited[j].allocations.splice(i, 1);
|
||||
|
||||
edited[j].allocationsSum = edited[
|
||||
j
|
||||
].allocations?.reduce((total, item) => {
|
||||
return total + item.allocationQuantity;
|
||||
}, 0);
|
||||
return edited;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
})}
|
||||
<tr>
|
||||
<td colSpan={"10"}>جمع کل</td>
|
||||
<td>{sumOfAllocationQuantity.toLocaleString()}</td>
|
||||
<td>{sumAllocationsSum.toLocaleString()}</td>
|
||||
<td>
|
||||
{/* {sumOfAllocationPercent} */}%
|
||||
{((sumOfAllocationQuantity / sumOfKillRequests) * 100).toFixed(
|
||||
2
|
||||
)}
|
||||
</td>
|
||||
<td colSpan={3}>
|
||||
<Button
|
||||
aria-describedby={id}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleClick}
|
||||
fullWidth
|
||||
>
|
||||
عملیات
|
||||
</Button>
|
||||
<Popover
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
id={id}
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
>
|
||||
<div style={{ padding: "20px" }}>
|
||||
<Grid container direction="column" gap={SPACING.TINY}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="success"
|
||||
onClick={() => {
|
||||
sendEditTableService();
|
||||
}}
|
||||
>
|
||||
ثبت موقت
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={() => {
|
||||
const allocationsForCancel =
|
||||
provinceGetAutoAllocations?.reduce(
|
||||
(total, item) => {
|
||||
return [...total, ...item.allocations];
|
||||
},
|
||||
[]
|
||||
);
|
||||
const allocationsKeys = allocationsForCancel.map(
|
||||
(item) => {
|
||||
return { allocationKey: item.allocationKey };
|
||||
}
|
||||
);
|
||||
dispatch(
|
||||
provinceSubmitFinalAutoAllocationsService({
|
||||
cancellation: allocationsKeys,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(
|
||||
getPoultryRequestsTotalQuantityService()
|
||||
);
|
||||
dispatch(provinceGetAutoAllocationsService());
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
لغو تخصیص خودکار
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
if (checkForDebt()) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عدم بدهی در اولویت تخصیص خودکار شما می باشد. لطفا تخصیص را مدیریت نمایید.",
|
||||
severity: "error",
|
||||
});
|
||||
handleClose();
|
||||
} else {
|
||||
sendFinalTableService();
|
||||
handleClose();
|
||||
}
|
||||
}}
|
||||
>
|
||||
ثبت نهایی
|
||||
</Button>
|
||||
</Grid>
|
||||
</div>
|
||||
</Popover>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!dataTable.length && (
|
||||
<Grid container>
|
||||
<Typography>تخصیص خودکار ایجاد نشده است!</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
function deepCopy(obj) {
|
||||
let newObj = Array.isArray(obj) ? [] : {};
|
||||
for (let key in obj) {
|
||||
if (typeof obj[key] === "object" && obj[key] !== null) {
|
||||
newObj[key] = deepCopy(obj[key]);
|
||||
} else {
|
||||
newObj[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return newObj;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Tab, Tabs } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { ProvinceAutoAllocationArchive } from "../province-auto-allocation-archive/ProvinceAutoAllocationArchive";
|
||||
import { ProvinceAutoAllocationRequests } from "../province-auto-allocation-requests/ProvinceAutoAllocationRequests";
|
||||
import { ProvinceSlaughterhouseQuota } from "../province-slaughterhouse-quota/ProvinceSlaughterhouseQuota";
|
||||
|
||||
export const ProvinceAutoAllocation = () => {
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
const handleTabChange = (event, newValue) => {
|
||||
setActiveTab(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container justifyContent="center" xs={12}>
|
||||
<Grid container xs={12} justifyContent="center">
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
onChange={handleTabChange}
|
||||
aria-label="simple tabs example"
|
||||
>
|
||||
<Tab label="تخصیص خودکار" />
|
||||
<Tab label="سهم بندی کشتارگاه" />
|
||||
<Tab label="بایگانی" />
|
||||
</Tabs>
|
||||
</Grid>
|
||||
{activeTab === 0 && <ProvinceAutoAllocationRequests />}
|
||||
{activeTab === 1 && <ProvinceSlaughterhouseQuota />}
|
||||
{activeTab === 2 && <ProvinceAutoAllocationArchive />}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,206 @@
|
||||
import React, { useEffect } from "react";
|
||||
import {
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
Button,
|
||||
Checkbox,
|
||||
ListItemIcon,
|
||||
Paper,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
|
||||
export const ProvinceAutoSelectOptions = ({ handleList }) => {
|
||||
function not(a, b) {
|
||||
return a.filter((value) => b.indexOf(value) === -1);
|
||||
}
|
||||
|
||||
function intersection(a, b) {
|
||||
return a.filter((value) => b.indexOf(value) !== -1);
|
||||
}
|
||||
|
||||
const [checked, setChecked] = React.useState([]);
|
||||
const [left, setLeft] = React.useState([
|
||||
{ label: "شهر", key: "city", value: true },
|
||||
{ label: "عدم بدهی", key: "no_debt", value: true },
|
||||
{ label: "حداقل تعداد تخصیص", key: "minimum_allocation", value: true },
|
||||
]);
|
||||
const [right, setRight] = React.useState([
|
||||
{ label: "شهر محل کشتار", key: "kill_place", value: true },
|
||||
]);
|
||||
|
||||
const leftChecked = intersection(checked, left);
|
||||
const rightChecked = intersection(checked, right);
|
||||
|
||||
const handleToggle = (value) => () => {
|
||||
const currentIndex = checked.indexOf(value);
|
||||
const newChecked = [...checked];
|
||||
|
||||
if (currentIndex === -1) {
|
||||
newChecked.push(value);
|
||||
} else {
|
||||
newChecked.splice(currentIndex, 1);
|
||||
}
|
||||
|
||||
setChecked(newChecked);
|
||||
};
|
||||
|
||||
const handleAllRight = () => {
|
||||
setRight(right.concat(left));
|
||||
setLeft([]);
|
||||
};
|
||||
|
||||
const handleCheckedRight = () => {
|
||||
setRight(right.concat(leftChecked));
|
||||
setLeft(not(left, leftChecked));
|
||||
setChecked(not(checked, leftChecked));
|
||||
};
|
||||
|
||||
const handleCheckedLeft = () => {
|
||||
setLeft(left.concat(rightChecked));
|
||||
setRight(not(right, rightChecked));
|
||||
setChecked(not(checked, rightChecked));
|
||||
};
|
||||
|
||||
const handleAllLeft = () => {
|
||||
setLeft(left.concat(right));
|
||||
setRight([]);
|
||||
};
|
||||
|
||||
const handleChange = (event) => {
|
||||
const fieldToUpdateLeft = left.find(
|
||||
(item) => item.key === "minimum_allocation"
|
||||
);
|
||||
const fieldToUpdateRight = right.find(
|
||||
(item) => item.key === "minimum_allocation"
|
||||
);
|
||||
if (fieldToUpdateLeft) {
|
||||
setLeft((prevState) => [
|
||||
...prevState.filter((item) => item.key !== "minimum_allocation"),
|
||||
{ ...fieldToUpdateLeft, value: event.target.value },
|
||||
]);
|
||||
} else if (fieldToUpdateRight) {
|
||||
setRight((prevState) => [
|
||||
...prevState.filter((item) => item.key !== "minimum_allocation"),
|
||||
{ ...fieldToUpdateRight, value: event.target.value },
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
handleList(right);
|
||||
}, [right]);
|
||||
|
||||
const customList = (items) => (
|
||||
<Paper sx={{ width: "100%", height: 150, overflow: "auto" }}>
|
||||
<List dense component="div" role="list">
|
||||
{items.map((value, i) => {
|
||||
const labelId = `transfer-list-item-${value}-label`;
|
||||
return (
|
||||
<ListItem key={value} role="listitem" onClick={handleToggle(value)}>
|
||||
<Grid container alignItems="center">
|
||||
<ListItemIcon>
|
||||
<Checkbox
|
||||
checked={checked.indexOf(value) !== -1}
|
||||
tabIndex={-1}
|
||||
disableRipple
|
||||
inputProps={{
|
||||
"aria-labelledby": labelId,
|
||||
}}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
id={labelId}
|
||||
primary={`${i + 1}. ${value.label}`}
|
||||
/>
|
||||
{value.label === "حداقل تعداد تخصیص" && (
|
||||
<Grid>
|
||||
<TextField
|
||||
label="تعداد"
|
||||
type={"number"}
|
||||
style={{ width: "100px" }}
|
||||
value={value.value}
|
||||
onChange={handleChange}
|
||||
size={"small"}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</ListItem>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Paper>
|
||||
);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
spacing={2}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
mt={SPACING.TINY}
|
||||
width="100%"
|
||||
>
|
||||
<Grid item flex={1}>
|
||||
<Typography>انتخاب اولویت های تخصیص خودکار</Typography>
|
||||
{customList(left)}
|
||||
</Grid>
|
||||
<Grid item flex={1}>
|
||||
<Grid container direction="column" alignItems="center">
|
||||
<Button
|
||||
sx={{ my: 0.5 }}
|
||||
variant="outlined"
|
||||
size="large"
|
||||
onClick={handleAllRight}
|
||||
// disabled={left.length === 0}
|
||||
disabled={true}
|
||||
aria-label="move all right"
|
||||
>
|
||||
≫
|
||||
</Button>
|
||||
<Button
|
||||
sx={{ my: 0.5 }}
|
||||
variant="outlined"
|
||||
size="large"
|
||||
onClick={handleCheckedRight}
|
||||
// disabled={leftChecked.length === 0}
|
||||
disabled={true}
|
||||
aria-label="move selected right"
|
||||
>
|
||||
>
|
||||
</Button>
|
||||
<Button
|
||||
sx={{ my: 0.5 }}
|
||||
variant="outlined"
|
||||
size="large"
|
||||
onClick={handleCheckedLeft}
|
||||
// disabled={rightChecked.length === 0}
|
||||
disabled={true}
|
||||
aria-label="move selected left"
|
||||
>
|
||||
<
|
||||
</Button>
|
||||
<Button
|
||||
sx={{ my: 0.5 }}
|
||||
variant="outlined"
|
||||
size="large"
|
||||
onClick={handleAllLeft}
|
||||
// disabled={right.length === 0}
|
||||
disabled={true}
|
||||
aria-label="move all left"
|
||||
>
|
||||
≪
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item flex={1}>
|
||||
<Typography>اولویت های انتخاب شده تخصیص خودکار</Typography>
|
||||
{customList(right)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,304 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Button, IconButton, TextField } from "@mui/material";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { RiSearchLine } from "react-icons/ri";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import {
|
||||
DRAWER,
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
OPEN_MODAL,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import { ProvinceSubmitBarDifference } from "../province-submit-bar-difference/ProvinceSubmitBarDifference";
|
||||
import { ProvinceBarDifferencesOperations } from "../province-bar-differences-operations/ProvinceBarDifferencesOperations";
|
||||
// import EmailIcon from "@mui/icons-material/Email";
|
||||
import { provinceGetDashboardBarDiffrenceRequest } from "../../services/province-dashboard-bar-diffrence-get-request";
|
||||
import { ProvinceBarDifferencesModal } from "../province-bar-differences-modal/ProvinceBarDifferencesModal";
|
||||
import { checkPathStartsWith } from "../../../../utils/checkPathStartsWith";
|
||||
|
||||
export const ProvinceBarDifferenceRequests = ({ state }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
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 [dashboardData, setDashboardData] = useState([]);
|
||||
const selectedSubUser = useSelector(
|
||||
(state) => state.userSlice.selectedSubUser
|
||||
);
|
||||
const fetchApiData = async (page) => {
|
||||
dispatch(LOADING_START());
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`bar-difference-request/?search=filter&value=${textValue}&role=${getRoleFromUrl()}${
|
||||
checkPathStartsWith("province")
|
||||
? `&role_key=${selectedSubUser?.key}`
|
||||
: ""
|
||||
}&page=${page}&page_size=${perPage}&state=${state}&date1=${selectedDate1}&date2=${selectedDate2}`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
} finally {
|
||||
dispatch(LOADING_END());
|
||||
}
|
||||
};
|
||||
|
||||
const fetchDashboardData = () => {
|
||||
dispatch(
|
||||
provinceGetDashboardBarDiffrenceRequest({
|
||||
role: getRoleFromUrl(),
|
||||
role_key: checkPathStartsWith("slaughter")
|
||||
? selectedSubUser?.key || ""
|
||||
: "",
|
||||
state: state,
|
||||
filter: "search",
|
||||
value: textValue,
|
||||
date1: selectedDate1,
|
||||
date2: selectedDate2,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload?.data) {
|
||||
setDashboardData(r.payload.data);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
const updateTable = () => {
|
||||
fetchApiData(page !== 0 ? page : 1);
|
||||
fetchDashboardData();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const d = data?.map((item, i) => {
|
||||
return [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
item?.registerFullname,
|
||||
formatJustDate(item?.createDate),
|
||||
`${item?.hatching?.poultry?.unitName || ""} (${
|
||||
item?.hatching?.poultry?.user?.mobile || ""
|
||||
})`,
|
||||
`${item?.killHouse?.name || ""} (${
|
||||
item?.killHouse?.killHouseOperator?.user?.mobile || ""
|
||||
})`,
|
||||
item?.barInfo?.totalQuantity?.toLocaleString(),
|
||||
item?.barInfo?.totalWeight?.toLocaleString(),
|
||||
item?.barInfo?.firstTotalQuantity?.toLocaleString(),
|
||||
item?.barInfo?.differenceQuantity?.toLocaleString(),
|
||||
item?.quantity?.toLocaleString(),
|
||||
item?.weight?.toLocaleString(),
|
||||
|
||||
item?.acceptorImages?.[0] ||
|
||||
item?.acceptorMessage ||
|
||||
item?.registerMessage ||
|
||||
item?.violationImage?.[0] ? (
|
||||
<Grid container key={i}>
|
||||
<IconButton
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
content: <ProvinceBarDifferencesModal item={item} />,
|
||||
title: "پیوست",
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
✉️
|
||||
</IconButton>
|
||||
</Grid>
|
||||
) : (
|
||||
"-"
|
||||
),
|
||||
|
||||
item.state === "pending"
|
||||
? "در انتظار تایید"
|
||||
: item.state === "rejected"
|
||||
? "رد شده"
|
||||
: "تایید شده",
|
||||
state === "pending" ? (
|
||||
<ProvinceBarDifferencesOperations
|
||||
key={i}
|
||||
updateTable={updateTable}
|
||||
item={item}
|
||||
/>
|
||||
) : (
|
||||
"-"
|
||||
),
|
||||
];
|
||||
});
|
||||
|
||||
setTableData(d);
|
||||
}, [data, state, page, perPage]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
fetchDashboardData();
|
||||
}, [state, perPage, selectedDate1, selectedDate2, selectedSubUser?.key]);
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
fetchApiData(1);
|
||||
fetchDashboardData();
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
>
|
||||
<Grid container mt={2} mb={4} isDashboard xs={12}>
|
||||
<ResponsiveTable
|
||||
noPagination
|
||||
isDashboard
|
||||
columns={[
|
||||
"تعداد",
|
||||
"وزن تقریبی کشتار",
|
||||
"حجم سفارشات دریافتی توسط کشتارگاه",
|
||||
"اختلاف کشتار (حجم)",
|
||||
"اختلاف حجم",
|
||||
"اختلاف وزن",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
dashboardData?.count?.toLocaleString(),
|
||||
dashboardData?.totalWeight?.toLocaleString(),
|
||||
dashboardData?.firstTotalQuantity?.toLocaleString(),
|
||||
dashboardData?.differenceQuantity?.toLocaleString(),
|
||||
dashboardData?.quantity?.toLocaleString(),
|
||||
dashboardData?.weight?.toLocaleString(),
|
||||
],
|
||||
]}
|
||||
title={"خلاصه اطلاعات"}
|
||||
/>
|
||||
</Grid>
|
||||
{getRoleFromUrl() !== "KillHouse" && (
|
||||
<Grid>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: (
|
||||
<ProvinceSubmitBarDifference updateTable={updateTable} />
|
||||
),
|
||||
title: " ثبت اختلاف کشتار",
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ثبت اختلاف کشتار
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid>
|
||||
<DatePicker
|
||||
label="از تاریخ"
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} style={{ width: "160px" }} size="small" />
|
||||
)}
|
||||
value={selectedDate1}
|
||||
onChange={(newValue) => {
|
||||
setSelectedDate1(moment(newValue).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
label="تا تاریخ"
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} style={{ width: "160px" }} size="small" />
|
||||
)}
|
||||
value={selectedDate2}
|
||||
onChange={(newValue) => {
|
||||
setSelectedDate2(moment(newValue).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
id="outlined-basic"
|
||||
size="small"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button type="submit" endIcon={<RiSearchLine />}>
|
||||
جستجو
|
||||
</Button>
|
||||
</form>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<ResponsiveTable
|
||||
data={tableData}
|
||||
customColors={[
|
||||
{
|
||||
name: "اختلاف حجم",
|
||||
color: "#ff5555",
|
||||
},
|
||||
{
|
||||
name: "اختلاف وزن",
|
||||
color: "#ff5555",
|
||||
},
|
||||
]}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"ثبت کننده",
|
||||
"تاریخ ثبت",
|
||||
"مرغدار",
|
||||
"کشتارگاه",
|
||||
"حجم کم شده از سالن مرغدار",
|
||||
"وزن تقریبی کشتار (کیلوگرم)",
|
||||
"حجم سفارشات دریافتی توسط کشتارگاه",
|
||||
" اختلاف کشتار(حجم)",
|
||||
"اختلاف حجم",
|
||||
"اختلاف وزن",
|
||||
"پیوست",
|
||||
"وضعیت",
|
||||
"عملیات",
|
||||
]}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title={state === "pending" ? "اختلاف کشتار" : "بایگانی اختلاف کشتار"}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
import React, { useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { Tab, Tabs } from "@mui/material";
|
||||
import { ProvinceBarDifferenceRequests } from "../province-bar-difference-requests/ProvinceBarDifferenceRequests";
|
||||
import { ProvinceBarDashboardService } from "../../services/province-bar-dashbored";
|
||||
|
||||
export const ProvinceBarDifference = () => {
|
||||
const [value, setValue] = useState("0");
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleChange = (event, newValue) => {
|
||||
setValue(newValue);
|
||||
dispatch(
|
||||
ProvinceBarDashboardService({
|
||||
state: newValue === "0" ? "pending" : "archive",
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center">
|
||||
<Tabs value={value} onChange={handleChange}>
|
||||
<Tab value="0" label="جدید" />
|
||||
<Tab value="1" label="بایگانی شده" />
|
||||
</Tabs>
|
||||
|
||||
<Grid container xs={12} justifyContent="center" alignItem="center" mt={2}>
|
||||
<ProvinceBarDifferenceRequests
|
||||
state={value === "0" ? "pending" : "archive"}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,127 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Tabs, Tab, TextField, Typography } from "@mui/material";
|
||||
import ShowImage from "../../../../components/show-image/ShowImage";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
|
||||
export const ProvinceBarDifferencesModal = ({ item }) => {
|
||||
const [tabIndex, setTabIndex] = useState(0);
|
||||
|
||||
const handleTabChange = (event, newValue) => {
|
||||
setTabIndex(newValue);
|
||||
};
|
||||
|
||||
const tabs = [];
|
||||
if (item?.registerMessage || item?.violationImage?.[0]) {
|
||||
tabs.push({ key: "register", label: "درخواست کننده" });
|
||||
}
|
||||
if (item?.acceptorMessage || item?.acceptorImage?.[0]) {
|
||||
tabs.push({ key: "acceptor", label: "کشتارگاه" });
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (tabIndex >= tabs.length) {
|
||||
setTabIndex(0);
|
||||
}
|
||||
}, [tabs.length, tabIndex]);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
flexDirection="column"
|
||||
sx={{ width: "100%", justifyContent: "center", alignItems: "center" }}
|
||||
>
|
||||
<Tabs value={tabIndex} onChange={handleTabChange} centered>
|
||||
{tabs.map((t, idx) => (
|
||||
<Tab key={t.key} label={t.label} />
|
||||
))}
|
||||
</Tabs>
|
||||
|
||||
{tabs[tabIndex]?.key === "register" && (
|
||||
<Grid container sx={{ padding: 2, width: "100%", marginTop: "10px" }}>
|
||||
{item?.registerMessage && (
|
||||
<TextField
|
||||
label="پیغام درخواست کننده"
|
||||
value={item?.registerMessage}
|
||||
fullWidth
|
||||
multiline
|
||||
variant="outlined"
|
||||
InputProps={{
|
||||
readOnly: true,
|
||||
style: { color: "black" },
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: "white",
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
borderColor: "#c4c4c4",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{item?.violationImage?.[0] && (
|
||||
<Grid
|
||||
item
|
||||
mt={2}
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: "5px",
|
||||
}}
|
||||
>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
پیوست درخواست کننده:
|
||||
</Typography>
|
||||
<ShowImage src={item?.violationImage[0]} />
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{tabs[tabIndex]?.key === "acceptor" && (
|
||||
<Grid container sx={{ padding: 2, width: "100%" }}>
|
||||
{item?.acceptorMessage && (
|
||||
<TextField
|
||||
label="پیغام کشتارگاه"
|
||||
value={item?.acceptorMessage}
|
||||
fullWidth
|
||||
multiline
|
||||
variant="outlined"
|
||||
InputProps={{
|
||||
readOnly: true,
|
||||
style: { color: "black" },
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: "white",
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
borderColor: "#c4c4c4",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{item?.acceptorImage?.[0] && (
|
||||
<Grid
|
||||
item
|
||||
mt={2}
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: "5px",
|
||||
}}
|
||||
>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
پیوست کشتارگاه:
|
||||
</Typography>
|
||||
<ShowImage src={item?.acceptorImage[0]} />
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,313 @@
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Popover,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useState, useContext } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import TuneIcon from "@mui/icons-material/Tune";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import SettingsSuggestIcon from "@mui/icons-material/SettingsSuggest";
|
||||
import { ProvinceSubmitBarDifference } from "../province-submit-bar-difference/ProvinceSubmitBarDifference";
|
||||
import {
|
||||
CLOSE_MODAL,
|
||||
DRAWER,
|
||||
OPEN_MODAL,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import {
|
||||
provinceDeleteBarDifferenceService,
|
||||
provinceEditBarDifferenceService,
|
||||
} from "../../services/province-bar-differences-services";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { ImageUpload } from "../../../../components/image-upload/ImageUpload";
|
||||
import { fixBase64 } from "../../../../utils/toBase64";
|
||||
import { resizeImage } from "../../../../utils/resizeImage";
|
||||
|
||||
export const ProvinceBarDifferencesOperations = ({ item, updateTable }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const handleClick = (event) => setAnchorEl(event.currentTarget);
|
||||
const handleClose = () => setAnchorEl(null);
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const id = open ? "popover" : undefined;
|
||||
|
||||
const handleDelete = () => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "آیا مطمئن هستید؟",
|
||||
content: (
|
||||
<Grid container spacing={2}>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(provinceDeleteBarDifferenceService(item?.key)).then(
|
||||
(r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
dispatch(CLOSE_MODAL());
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.data.result,
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}}
|
||||
>
|
||||
تایید
|
||||
</Button>
|
||||
<Button onClick={() => dispatch(CLOSE_MODAL())}>لغو</Button>
|
||||
</Grid>
|
||||
),
|
||||
})
|
||||
);
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const openAcceptRejectModal = () => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "تایید/ رد",
|
||||
content: (
|
||||
<AcceptRejectModal
|
||||
item={item}
|
||||
updateTable={updateTable}
|
||||
openNotif={openNotif}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
handleClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<IconButton aria-describedby={id} color="primary" onClick={handleClick}>
|
||||
<TuneIcon />
|
||||
</IconButton>
|
||||
|
||||
<Popover
|
||||
id={id}
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
|
||||
transformOrigin={{ vertical: "top", horizontal: "left" }}
|
||||
>
|
||||
<List dense sx={{ py: 0, minWidth: 200 }}>
|
||||
{getRoleFromUrl() !== "KillHouse" ? (
|
||||
<>
|
||||
<Tooltip title="ویرایش" placement="left-start">
|
||||
<ListItem disablePadding>
|
||||
<ListItemButton
|
||||
sx={{ py: 0.5 }}
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
dispatch(
|
||||
DRAWER({
|
||||
right: !(window.innerWidth <= 600),
|
||||
bottom: window.innerWidth <= 600,
|
||||
content: (
|
||||
<ProvinceSubmitBarDifference
|
||||
item={item}
|
||||
isEdit
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
title: "ویرایش اختلاف کشتار",
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 40 }}>
|
||||
<EditIcon color="primary" fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="ویرایش اختلاف کشتار"
|
||||
primaryTypographyProps={{
|
||||
color: "primary",
|
||||
variant: "body2",
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title="حذف" placement="left-start">
|
||||
<ListItem disablePadding>
|
||||
<ListItemButton
|
||||
sx={{ py: 0.5 }}
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
handleDelete();
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 40 }}>
|
||||
<DeleteIcon color="error" fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="حذف اختلاف کشتار"
|
||||
primaryTypographyProps={{
|
||||
color: "error",
|
||||
variant: "body2",
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
</Tooltip>
|
||||
</>
|
||||
) : (
|
||||
<Tooltip title="تایید/ رد" placement="left-start">
|
||||
<ListItem disablePadding>
|
||||
<ListItemButton
|
||||
sx={{ py: 0.5 }}
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
openAcceptRejectModal();
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 40 }}>
|
||||
<SettingsSuggestIcon color="primary" fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="تایید/ رد اختلاف"
|
||||
primaryTypographyProps={{
|
||||
color: "primary",
|
||||
variant: "body2",
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
</Tooltip>
|
||||
)}
|
||||
</List>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const AcceptRejectModal = ({ item, updateTable, openNotif }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [acceptorMessage, setAcceptorMessage] = useState("");
|
||||
const [profileImages, setProfileImages] = useState([]);
|
||||
const [acceptorImages, setAcceptorImages] = useState([]);
|
||||
|
||||
const handleEditOrAccept = (newState) => {
|
||||
dispatch(
|
||||
provinceEditBarDifferenceService({
|
||||
bar_key: item?.key,
|
||||
kill_house_check: true,
|
||||
acceptor_message: acceptorMessage,
|
||||
acceptor_images: acceptorImages,
|
||||
state: newState,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
dispatch(CLOSE_MODAL());
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.data.result,
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleImageChange = (imageList) => {
|
||||
if (imageList.length === 0) {
|
||||
setProfileImages([]);
|
||||
setAcceptorImages([]);
|
||||
return;
|
||||
}
|
||||
|
||||
Promise.all(
|
||||
imageList.map(
|
||||
(image) =>
|
||||
new Promise((resolve) =>
|
||||
resizeImage(image.file, (resized) => resolve(fixBase64(resized)))
|
||||
)
|
||||
)
|
||||
).then((resizedImages) => {
|
||||
setProfileImages(imageList);
|
||||
setAcceptorImages(resizedImages);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container spacing={2} justifyContent="center">
|
||||
<Grid item xs={12} justifyContent="center">
|
||||
<Typography variant="body2" color="error">
|
||||
توجه: در صورت تایید حجم قطعه اعلام شده، حجم مورد نظر از سالن مرغدار
|
||||
کسر شده و با میانگین وزن کشتار مرغدار به انبار شما اضافه میگردد.
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} justifyContent="center">
|
||||
<ImageUpload
|
||||
onChange={handleImageChange}
|
||||
images={profileImages}
|
||||
maxNumber={1}
|
||||
title="سند"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} justifyContent="center">
|
||||
<TextField
|
||||
label="توضیحات"
|
||||
value={acceptorMessage}
|
||||
onChange={(e) => setAcceptorMessage(e.target.value)}
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="success"
|
||||
onClick={() => handleEditOrAccept("accepted")}
|
||||
>
|
||||
تایید
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={() => handleEditOrAccept("rejected")}
|
||||
>
|
||||
رد
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
|
||||
export const ProvinceBarInfos = () => {
|
||||
return (
|
||||
<Grid>
|
||||
<AdvancedTable />
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,616 @@
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { getProvinceBuyerStewardAllocationService } from "../../services/get-province-buyer-steward-allocation";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { AdvancedTable } from "../../../../components/advanced-table/AdvancedTable";
|
||||
import { Button, TextField, Tooltip, Typography } from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { NumberInput } from "../../../../components/number-format-custom/NumberFormatCustom";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { provinceBuyerRealCarcassesService } from "../../services/province-buyer-real-carcasses";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { provinceAutomaticStewardAllocationService } from "../../services/province-automatic-steward-allocation";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { provinceUpdateAllocateStewardsService } from "../../services/province-update-allocate-stewards";
|
||||
import { CLOSE_MODAL, OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
|
||||
import { RiFileExcel2Fill } from "react-icons/ri";
|
||||
import axios from "axios";
|
||||
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
|
||||
import { slaughterGetUpdatedInventoryStock } from "../../../slaughter-house/services/salughter-get-updated-inventory-stock";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment/moment";
|
||||
import { useFormik } from "formik";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import { ProvinceManageStewardAllocations } from "../province-manage-steward-allocations/ProvinceManageStewardAllocations";
|
||||
import { provinceGetTotalReportAgentShareService } from "../../services/province-get-total-report-agent-share";
|
||||
|
||||
export const ProvinceBuyerStewardAllocation = () => {
|
||||
const dispatch = useDispatch();
|
||||
let currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
const { id, date } = useParams();
|
||||
const [datePicker, setDatePicker] = useState(
|
||||
moment(new Date()).format("YYYY-MM-DD")
|
||||
);
|
||||
|
||||
if (getRoleFromUrl() === "KillHouse") {
|
||||
currentDate = datePicker;
|
||||
} else {
|
||||
currentDate = date;
|
||||
}
|
||||
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const {
|
||||
getProvinceBuyerStewardAllocation,
|
||||
provinceGetTotalReportAgentShare,
|
||||
} = useSelector((state) => state.provinceSlice);
|
||||
|
||||
const { slaughterUpdatedInventoryStock } = useSelector(
|
||||
(state) => state.slaughterSlice
|
||||
);
|
||||
|
||||
const updateInventory = () => {
|
||||
dispatch(
|
||||
slaughterGetUpdatedInventoryStock({
|
||||
date: currentDate,
|
||||
kill_house_key: id,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
provinceGetTotalReportAgentShareService({
|
||||
date: currentDate,
|
||||
kill_house_key: id,
|
||||
})
|
||||
);
|
||||
if (getRoleFromUrl() === "KillHouse") {
|
||||
dispatch(
|
||||
provinceUpdateAllocateStewardsService({
|
||||
kill_house_key: id,
|
||||
date: currentDate,
|
||||
})
|
||||
).then(() => {
|
||||
dispatch(
|
||||
getProvinceBuyerStewardAllocationService({
|
||||
date: currentDate,
|
||||
killHouseKey: id,
|
||||
})
|
||||
).then(() => {
|
||||
dispatch(
|
||||
slaughterGetUpdatedInventoryStock({
|
||||
date: currentDate,
|
||||
kill_house_key: id,
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (getRoleFromUrl() === "ProvinceOperator") {
|
||||
dispatch(
|
||||
getProvinceBuyerStewardAllocationService({
|
||||
date: currentDate,
|
||||
killHouseKey: id,
|
||||
})
|
||||
).then(() => {
|
||||
dispatch(
|
||||
slaughterGetUpdatedInventoryStock({
|
||||
date: currentDate,
|
||||
kill_house_key: id,
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
}, [currentDate]);
|
||||
|
||||
const updateTable = () => {
|
||||
dispatch(
|
||||
getProvinceBuyerStewardAllocationService({
|
||||
date: currentDate,
|
||||
killHouseKey: id,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const d = getProvinceBuyerStewardAllocation?.map((item) => {
|
||||
return [
|
||||
item.steward.guilds.guildsId,
|
||||
// formatJustDate(item.steward.guilds.createDate),
|
||||
item.steward.guilds.steward ? "مباشر" : "صنف",
|
||||
item.steward.guilds.guildsName,
|
||||
item.steward.guilds.user.fullname,
|
||||
// item.steward?.guilds?.user?.nationalId,
|
||||
item.steward?.guilds?.user?.mobile,
|
||||
`${item.steward?.guilds?.typeActivity}/${item.steward?.guilds?.areaActivity}`,
|
||||
item.steward?.guilds?.licenseNumber,
|
||||
item.steward?.guilds?.address.city.name,
|
||||
<Grid container key={item.key} direction="column">
|
||||
<Grid>{`${item?.numberOfCarcasses?.toLocaleString()} قطعه`}</Grid>
|
||||
<Grid>{`${item?.weightOfCarcasses?.toLocaleString()} کیلوگرم`}</Grid>
|
||||
</Grid>,
|
||||
<Grid container key={item.key} direction="column">
|
||||
{item.state === "accepted" && (
|
||||
<>
|
||||
<Grid>{`${item?.realNumberOfCarcasses?.toLocaleString()} قطعه`}</Grid>
|
||||
<Grid>{`${item?.realWeightOfCarcasses?.toLocaleString()} کیلوگرم`}</Grid>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!item.systemRegistrationCode && (
|
||||
<Grid>
|
||||
<Button
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ویرایش تعداد / وزن لاشه",
|
||||
content: (
|
||||
<RealCarcassesInput
|
||||
key={item.key}
|
||||
realWeightOfCarcasses={item.realWeightOfCarcasses}
|
||||
realNumberOfCarcasses={item.realNumberOfCarcasses}
|
||||
item={item}
|
||||
updateTable={updateTable}
|
||||
/>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
{item.state === "accepted" ? "ویرایش" : "وارد کردن اطلاعات"}
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>,
|
||||
// <RealCarcassesInput
|
||||
// key={item.key}
|
||||
// realWeightOfCarcasses={item.realWeightOfCarcasses}
|
||||
// realNumberOfCarcasses={item.realNumberOfCarcasses}
|
||||
// item={item}
|
||||
// updateTable={updateTable}
|
||||
// />,
|
||||
<RegistrationInput
|
||||
key={item.key}
|
||||
loggedRegistrationCode={item.loggedRegistrationCode}
|
||||
item={item}
|
||||
updateTable={updateTable}
|
||||
updateInventory={updateInventory}
|
||||
/>,
|
||||
];
|
||||
});
|
||||
|
||||
setDataTable(d);
|
||||
}, [getProvinceBuyerStewardAllocation]);
|
||||
|
||||
const [inventoryDate, setInventoryDate] = useState(new Date(currentDate));
|
||||
|
||||
useEffect(() => {
|
||||
const tempDate = new Date(inventoryDate);
|
||||
tempDate.setDate(new Date(currentDate).getDate() - 1);
|
||||
setInventoryDate(tempDate);
|
||||
}, [currentDate]);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="start"
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="start"
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
{/* <Typography>سهم بندی ها</Typography> */}
|
||||
{getRoleFromUrl() === "KillHouse" && (
|
||||
<DatePicker
|
||||
label="تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField style={{ width: "150px" }} {...params} />
|
||||
)}
|
||||
value={currentDate}
|
||||
onChange={(e) => {
|
||||
setDatePicker(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid width="100%">
|
||||
<SimpleTable
|
||||
name={
|
||||
<Grid container alignItems="center">
|
||||
<Typography>
|
||||
سهم بندی برای تاریخ کشتار مورخ {formatJustDate(inventoryDate)}{" "}
|
||||
{provinceGetTotalReportAgentShare?.killer
|
||||
? "کشتارکن"
|
||||
: "کشتارگاه"}{" "}
|
||||
{provinceGetTotalReportAgentShare?.name}
|
||||
</Typography>
|
||||
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<a
|
||||
href={`${axios.defaults.baseURL}Broadcast_management/?date=${date}&kill_house_key=${id}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
}
|
||||
columns={[
|
||||
"حجم لاشه ها",
|
||||
"وزن لاشه ها (کیلوگرم)",
|
||||
"حجم لاشه تخصیص داده شده",
|
||||
"وزن تخصیص داده شده (کیلوگرم)",
|
||||
"حجم لاشه قابل تخصیص",
|
||||
"وزن قابل تخصیص (کیلوگرم)",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
slaughterUpdatedInventoryStock?.totalNumberOfCarcasses?.toLocaleString(),
|
||||
slaughterUpdatedInventoryStock?.totalWeightOfCarcasses?.toLocaleString(),
|
||||
slaughterUpdatedInventoryStock?.allocatedTotalNumberOfCarcasses?.toLocaleString(),
|
||||
slaughterUpdatedInventoryStock?.allocatedTotalWeightOfCarcasses?.toLocaleString(),
|
||||
slaughterUpdatedInventoryStock?.remainTotalNumberOfCarcasses?.toLocaleString(),
|
||||
slaughterUpdatedInventoryStock?.remainTotalWeightOfCarcasses?.toLocaleString(),
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
{(getRoleFromUrl() === "ProvinceOperator" ||
|
||||
getRoleFromUrl() === "SuperAdmin") && (
|
||||
<ProvinceManageStewardAllocations />
|
||||
)}
|
||||
|
||||
{getRoleFromUrl() === "KillHouse" && (
|
||||
<AdvancedTable
|
||||
name={
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
{/* <Typography>سهم بندی اتوماتیک</Typography>
|
||||
{getRoleFromUrl() === "KillHouse" && (
|
||||
<DatePicker
|
||||
label="تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField style={{ width: "150px" }} {...params} />
|
||||
)}
|
||||
value={date}
|
||||
onChange={(e) => {
|
||||
setDatePicker(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
)} */}
|
||||
|
||||
{/* <Button
|
||||
variant="contained"
|
||||
disabled={
|
||||
getProvinceBuyerStewardAllocation?.length
|
||||
? getProvinceBuyerStewardAllocation?.some(
|
||||
(item) => item.state === "accepted"
|
||||
)
|
||||
: true
|
||||
}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceAutomaticStewardAllocationService({
|
||||
send_registration_code: true,
|
||||
steward_allocation_list:
|
||||
getProvinceBuyerStewardAllocation?.map(
|
||||
(item) => item.key
|
||||
),
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت و ارسال کداحراز
|
||||
</Button> */}
|
||||
</Grid>
|
||||
}
|
||||
columns={[
|
||||
"شناسه صنف",
|
||||
// "تاریخ ثبت",
|
||||
"ماهیت",
|
||||
"نام واحد صنفی",
|
||||
"نام شخص/شرکت",
|
||||
// "کدملی",
|
||||
"موبایل",
|
||||
"نوع/حوزه فعالیت",
|
||||
"شماره مجوز",
|
||||
"شهرستان",
|
||||
"تعداد/وزن لاشه پیشنهادی",
|
||||
"تعداد/وزن لاشه تحویلی",
|
||||
"کداحراز",
|
||||
]}
|
||||
data={dataTable}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
number1: Yup.number().required("این فیلد اجباری است"),
|
||||
number2: Yup.number().required("این فیلد اجباری است"),
|
||||
});
|
||||
const RealCarcassesInput = ({
|
||||
// realWeightOfCarcasses,
|
||||
// realNumberOfCarcasses,
|
||||
updateTable,
|
||||
item,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
number1: item.realNumberOfCarcasses,
|
||||
number2: item.realWeightOfCarcasses,
|
||||
},
|
||||
validationSchema: validationSchema,
|
||||
onSubmit: (values) => {
|
||||
// Handle form submission
|
||||
// console.log(values);
|
||||
},
|
||||
});
|
||||
// const [numberInput, setNumberInput] = useState(realNumberOfCarcasses);
|
||||
// const [textInput, setTextInput] = useState(realWeightOfCarcasses);
|
||||
|
||||
// const handleNumberInputChange = (e) => {
|
||||
// setNumberInput(e.target.value);
|
||||
// };
|
||||
|
||||
// const handleTextInputChange = (e) => {
|
||||
// setTextInput(e.target.value);
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
width="100%"
|
||||
// flexWrap="nowrap"
|
||||
gap={SPACING.SMALL}
|
||||
>
|
||||
<NumberInput
|
||||
// value={textInput}
|
||||
label="وزن (کیلوگرم)"
|
||||
id="number2"
|
||||
// size="small"
|
||||
allowLeadingZeros
|
||||
thousandSeparator=","
|
||||
// onChange={handleTextInputChange}
|
||||
// style={{ width: "85px" }}
|
||||
// disabled={item.state === "accepted"}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
value={formik.values.number2}
|
||||
error={formik.touched.number2 && Boolean(formik.errors.number2)}
|
||||
helperText={formik.touched.number2 && formik.errors.number2}
|
||||
/>
|
||||
<NumberInput
|
||||
label="تعداد"
|
||||
// value={numberInput}
|
||||
id="number1"
|
||||
// size="small"
|
||||
// onChange={handleNumberInputChange}
|
||||
allowLeadingZeros
|
||||
thousandSeparator=","
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
value={formik.values.number1}
|
||||
error={formik.touched.number1 && Boolean(formik.errors.number1)}
|
||||
helperText={formik.touched.number1 && formik.errors.number1}
|
||||
// style={{ width: "75px" }}
|
||||
// disabled={item.state === "accepted"}
|
||||
/>
|
||||
{/* {item.state !== "accepted" && ( */}
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={!formik.isValid}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceBuyerRealCarcassesService({
|
||||
confirm_information: true,
|
||||
steward_allocation_key: item.key,
|
||||
real_number_of_carcasses: Number(formik.values.number1),
|
||||
real_weight_of_carcasses: Number(formik.values.number2),
|
||||
})
|
||||
).then((r) => {
|
||||
dispatch(CLOSE_MODAL());
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
{/* )} */}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
const RegistrationInput = ({
|
||||
loggedRegistrationCode,
|
||||
item,
|
||||
updateTable,
|
||||
updateInventory,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [textInput, setTextInput] = useState(loggedRegistrationCode);
|
||||
|
||||
const handleTextInputChange = (e) => {
|
||||
setTextInput(e.target.value);
|
||||
};
|
||||
|
||||
console.log(item.systemRegistrationCode, "zzzz");
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
width="100%"
|
||||
flexWrap="nowrap"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
{item.systemRegistrationCode ? (
|
||||
<Grid>
|
||||
<TextField
|
||||
value={textInput}
|
||||
size="small"
|
||||
onChange={handleTextInputChange}
|
||||
style={{ width: "85px" }}
|
||||
disabled={item?.finalRegistration}
|
||||
/>
|
||||
{!item?.finalRegistration && (
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceBuyerRealCarcassesService({
|
||||
enter_registration_code: true,
|
||||
steward_allocation_key: item.key,
|
||||
logged_registration_code: textInput,
|
||||
role: getRoleFromUrl(),
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
updateTable();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ثبت
|
||||
</Button>
|
||||
)}
|
||||
</Grid>
|
||||
) : (
|
||||
<Button
|
||||
disabled={item.state !== "accepted"}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
OPEN_MODAL({
|
||||
title: "ارسال کداحراز",
|
||||
content: (
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography>
|
||||
در صورت ارسال کداحراز انجام هیچگونه عملیاتی مانند حذف و
|
||||
ویرایش امکان پذیر نمی باشد.
|
||||
</Typography>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
gap={SPACING.TINY}
|
||||
width="100%"
|
||||
>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceAutomaticStewardAllocationService({
|
||||
send_registration_code: true,
|
||||
steward_allocation_list: [item.key],
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(CLOSE_MODAL());
|
||||
updateTable();
|
||||
updateInventory();
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
تایید
|
||||
</Button>
|
||||
<Button
|
||||
fullWidth
|
||||
color="error"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
dispatch(CLOSE_MODAL());
|
||||
}}
|
||||
>
|
||||
لغو
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
ارسال کداحراز
|
||||
</Button>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,222 @@
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import { Button, TextField, Tooltip } from "@mui/material";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import moment from "moment";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { RiFileExcel2Fill } from "react-icons/ri";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { totalReportDailyBroadCastService } from "../../../slaughter-house/services/salughter-total-report-daily-broad-cast";
|
||||
import { getProvinceBuyersAllocationsService } from "../../services/get-province-buyers-allocations";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
|
||||
export const ProvinceBuyersAllocations = () => {
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
// const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const { getProvinceBuyersAllocations, totalReportDailyBroadCast } =
|
||||
useSelector((state) => state.provinceSlice);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
getProvinceBuyersAllocationsService({ selectedDate1, selectedDate2 })
|
||||
);
|
||||
dispatch(
|
||||
totalReportDailyBroadCastService({
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
})
|
||||
);
|
||||
}, [selectedDate1, selectedDate2]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
getProvinceBuyersAllocationsService({ selectedDate1, selectedDate2 })
|
||||
);
|
||||
dispatch(
|
||||
totalReportDailyBroadCastService({
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
})
|
||||
);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const d = getProvinceBuyersAllocations?.map((item, i) => {
|
||||
return [
|
||||
i + 1,
|
||||
item?.informations?.buyers,
|
||||
item?.informations?.city,
|
||||
item?.informations?.numberOfSteward.toLocaleString(),
|
||||
item?.informations?.numberOfGuild.toLocaleString(),
|
||||
item?.informations?.incomingWeightOfColdHouse?.toLocaleString(),
|
||||
item?.informations?.incomingQuantityOfColdHouse?.toLocaleString(),
|
||||
item?.informations?.totalPreColdWeight?.toLocaleString(),
|
||||
item?.informations?.totalPreColdQuantity?.toLocaleString(),
|
||||
item?.informations?.totalNumberOfFreeCarcasses?.toLocaleString(),
|
||||
item?.informations?.totalFreeWeightOfCarcasses?.toLocaleString(),
|
||||
item?.informations?.totalWeightOfCarcasses?.toLocaleString(),
|
||||
item?.informations?.totalNumberOfCarcasses?.toLocaleString(),
|
||||
item?.informations?.finalTotalWeightOfCarcasses?.toLocaleString(),
|
||||
item?.informations?.finalTotalNumberOfCarcasses?.toLocaleString(),
|
||||
item?.informations?.totalAllocatedWeight?.toLocaleString(),
|
||||
item?.informations?.totalAllocatedQuantity?.toLocaleString(),
|
||||
item?.informations?.totalAcceptedAllocatedWeight?.toLocaleString(),
|
||||
item?.informations?.totalAcceptedAllocatedQuantity?.toLocaleString(),
|
||||
item?.informations?.totalRemainQuantity?.toLocaleString(),
|
||||
item?.informations?.totalRemainWeight?.toLocaleString(),
|
||||
<Tooltip key={i} title="خروجی اکسل">
|
||||
<a
|
||||
href={`${axios.defaults.baseURL}Broadcast_management/?date1=${selectedDate1}&date2=${selectedDate2}&kill_house_key=${item?.key}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button color="success">
|
||||
<RiFileExcel2Fill size={24} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>,
|
||||
];
|
||||
});
|
||||
setDataTable(d);
|
||||
}, [getProvinceBuyersAllocations]);
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="start"
|
||||
gap={SPACING.SMALL}
|
||||
mt={SPACING.TINY}
|
||||
mb={SPACING.SMALL}
|
||||
>
|
||||
<Grid style={{ width: 160 }}>
|
||||
<DatePicker
|
||||
label="از تاریخ"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid style={{ width: 160 }}>
|
||||
<DatePicker
|
||||
label="تا تاریخ"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<a
|
||||
href={
|
||||
dataTable?.length
|
||||
? `${axios.defaults.baseURL}all_inventory_excel/?date1=${selectedDate1}&date2=${selectedDate2}`
|
||||
: "#"
|
||||
}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button disabled={!dataTable?.length} color="success">
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
<Grid mb={SPACING.SMALL} isDashboard xs={12}>
|
||||
<ResponsiveTable
|
||||
noPagination
|
||||
isDashboard
|
||||
title={"خلاصه اطلاعات"}
|
||||
columns={[
|
||||
"تعداد خریداران",
|
||||
"وزن ورودی از سردخانه",
|
||||
"تعداد ورودی از سردخانه",
|
||||
"تعداد پیش سرد",
|
||||
"وزن پیش سرد",
|
||||
"وزن خرید خارج از استان",
|
||||
"تعداد خرید خارج از استان",
|
||||
"وزن بارهای امروز",
|
||||
"تعداد بارهای امروز",
|
||||
"وزن کل انبار",
|
||||
"تعداد کل انبار",
|
||||
"وزن توزیع شده",
|
||||
"تعداد توزیع شده",
|
||||
"وزن توزیع تحویل شده",
|
||||
"تعداد توزیع تحویل شده",
|
||||
"وزن مانده در انبار",
|
||||
"تعداد مانده در انبار",
|
||||
"تعداد مباشر تخصیصی",
|
||||
"تعداد صنف تخصیصی",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
totalReportDailyBroadCast?.buyers?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.incomingWeightOfColdHouse?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.incomingQuantityOfColdHouse?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalPreColdQuantity?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalPreColdWeight?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalFreeWeightOfCarcasses?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalNumberOfFreeCarcasses?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalWeightOfCarcasses?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalNumberOfCarcasses?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.finalTotalWeightOfCarcasses?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.finalTotalNumberOfCarcasses?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalAllocatedWeight?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalAllocatedQuantity?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalAcceptedAllocatedWeight?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalAcceptedAllocatedQuantity?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalRemainQuantity?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.totalRemainWeight?.toLocaleString(),
|
||||
totalReportDailyBroadCast?.numberOfSteward.toLocaleString(),
|
||||
totalReportDailyBroadCast?.numberOfGuild.toLocaleString(),
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="start"
|
||||
gap={SPACING.SMALL}
|
||||
mt={SPACING.MEDIUM}
|
||||
></Grid>
|
||||
<ResponsiveTable
|
||||
paginated
|
||||
title="جزئیات پخش"
|
||||
columns={[
|
||||
"ردیف",
|
||||
"خریدار",
|
||||
"شهرستان",
|
||||
"تعداد مباشر تخصیصی",
|
||||
"تعداد صنف تخصیصی",
|
||||
"وزن ورودی از سردخانه",
|
||||
"تعداد ورودی از سردخانه",
|
||||
"وزن پیش سرد",
|
||||
"تعداد پیش سرد",
|
||||
"تعداد خرید خارج از استان",
|
||||
"وزن خرید خارج از استان",
|
||||
"وزن بارهای امروز",
|
||||
"تعداد بارهای امروز",
|
||||
"وزن کل انبار",
|
||||
"تعداد کل انبار",
|
||||
"وزن توزیع شده",
|
||||
"تعداد توزیع شده",
|
||||
"وزن توزیع تحویل شده",
|
||||
"تعداد توزیع تحویل شده",
|
||||
"تعداد مانده در انبار",
|
||||
"وزن مانده در انبار",
|
||||
"جزئیات",
|
||||
]}
|
||||
data={dataTable}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,139 @@
|
||||
import { Typography } from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
|
||||
export const ProvinceCaseOverview = ({ item }) => {
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
direction={{ xs: "column", sm: "row" }}
|
||||
justifyContent="space-between"
|
||||
gap={SPACING.SMALL}
|
||||
mt={SPACING.SMALL}
|
||||
>
|
||||
<Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">مرغداری:</Typography>
|
||||
<Typography variant="caption">{item?.poultry?.unitName}</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">مرغدار:</Typography>
|
||||
<Typography variant="caption">
|
||||
{item?.poultry?.user?.fullname}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">موبایل:</Typography>
|
||||
<Typography variant="caption">
|
||||
{item?.poultry?.user?.mobile}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">تاریخ کشتار:</Typography>
|
||||
<Typography variant="caption">
|
||||
{formatJustDate(item?.sendDate)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">زمان و تاریخ ثبت:</Typography>
|
||||
<Typography variant="caption">
|
||||
{formatJustDate(item?.createDate)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">شهرستان:</Typography>
|
||||
<Typography variant="caption">
|
||||
{item?.poultry?.address?.city?.name}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">تعداد:</Typography>
|
||||
<Typography variant="caption">
|
||||
{item?.quantity?.toLocaleString()}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">متوسط وزن:</Typography>
|
||||
<Typography variant="caption">{item?.IndexWeight}</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">وزن حدودی:</Typography>
|
||||
<Typography variant="caption">{item?.hatching?.weight}</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">سن گله:</Typography>
|
||||
<Typography variant="caption">{item?.hatching?.age}</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">نژاد:</Typography>
|
||||
<Typography variant="caption">{item?.chickenBreed}</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">قیمت پیشنهادی:</Typography>
|
||||
<Typography variant="caption">
|
||||
{item?.amount?.toLocaleString()} ریال
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid>
|
||||
{item?.provinceKillRequests?.provinceKillRequestSerializer.length ? (
|
||||
<>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">خریداران:</Typography>
|
||||
</Grid>
|
||||
{item?.provinceKillRequests?.provinceKillRequestSerializer?.map(
|
||||
(item, i) => {
|
||||
return (
|
||||
<Grid key={i} container gap={SPACING.TINY}>
|
||||
<Typography variant="caption">{i + 1}- </Typography>
|
||||
<Typography variant="caption">
|
||||
{item?.killhouseUser?.name}
|
||||
</Typography>
|
||||
<Typography variant="caption">
|
||||
({item?.killhouseUser?.killHouseOperator?.user?.mobile})
|
||||
</Typography>
|
||||
<Typography variant="caption">تعداد: </Typography>
|
||||
<Typography variant="caption">
|
||||
{item?.mainQuantity?.toLocaleString()}
|
||||
</Typography>
|
||||
<Typography variant="caption">محل کشتار: </Typography>
|
||||
<Typography variant="caption">{item?.killPlace}</Typography>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">خریداران: بدون خریدار</Typography>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">قیمت مرغ:</Typography>
|
||||
<Typography variant="caption">
|
||||
{item?.amount?.toLocaleString()} ریال
|
||||
</Typography>
|
||||
</Grid>
|
||||
{/* <Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">مبلغ قابل پرداخت:</Typography>
|
||||
<Typography variant="caption">55112</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">باقی مانده قابل پرداخت:</Typography>
|
||||
<Typography variant="caption">44</Typography>
|
||||
</Grid>
|
||||
<Grid container gap={SPACING.SMALL}>
|
||||
<Typography variant="caption">مبلغ پرداخت شده:</Typography>
|
||||
<Typography variant="caption">258522</Typography>
|
||||
</Grid> */}
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,511 @@
|
||||
import {
|
||||
// Divider,
|
||||
// Paper,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableRow,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment/moment";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { provinceGetCaseStatusService } from "../../services/province-get-case-status";
|
||||
|
||||
export const ProvinceCaseStatusComponent = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { provinceGetCaseStatus } = useSelector((state) => state.provinceSlice);
|
||||
|
||||
const [selectedDate, setSelectedDate] = useState(
|
||||
moment(new Date()).format("YYYY-MM-DD")
|
||||
);
|
||||
|
||||
const handleDateChange = (date) => {
|
||||
setSelectedDate(date);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(provinceGetCaseStatusService(selectedDate));
|
||||
}, [selectedDate]);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
alignItems="start"
|
||||
width="1300px"
|
||||
overflowX="scroll"
|
||||
style={{ overflowX: "scroll" }}
|
||||
>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
label="تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={selectedDate}
|
||||
onChange={(e) => {
|
||||
handleDateChange(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Grid>
|
||||
{provinceGetCaseStatus?.map((item, i) => {
|
||||
// city state color
|
||||
let cityStateColor;
|
||||
if (item?.cityState?.state === "pending") {
|
||||
cityStateColor = "#ff7410";
|
||||
}
|
||||
if (item?.cityState?.state === "accept") {
|
||||
cityStateColor = "green";
|
||||
}
|
||||
if (item?.cityState?.state === "reject") {
|
||||
cityStateColor = "red";
|
||||
}
|
||||
|
||||
// province state color
|
||||
let provinceStateColor;
|
||||
if (item?.provinceState?.state === "pending") {
|
||||
provinceStateColor = "#ff7410";
|
||||
}
|
||||
if (item?.provinceState?.state === "accept") {
|
||||
provinceStateColor = "green";
|
||||
}
|
||||
if (item?.provinceState?.state === "reject") {
|
||||
provinceStateColor = "red";
|
||||
}
|
||||
|
||||
return (
|
||||
<Table
|
||||
className="my-table"
|
||||
key={i}
|
||||
style={{ borderTop: "1px solid", marginTop: "10px" }}
|
||||
>
|
||||
<TableBody>
|
||||
<TableRow
|
||||
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
|
||||
>
|
||||
<TableCell
|
||||
component="th"
|
||||
scope="row"
|
||||
className="no-border-flex-table"
|
||||
>
|
||||
<Grid style={{ marginBottom: "2px" }}>
|
||||
<Typography
|
||||
variant="button"
|
||||
textAlign="center"
|
||||
style={{
|
||||
borderBottom: "1px solid gray",
|
||||
paddingBottom: "2px",
|
||||
}}
|
||||
>
|
||||
مرغدار
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container direction="column">
|
||||
<Typography variant="caption">
|
||||
{item?.poultry?.poultryName} (
|
||||
{item?.poultry?.userFullname})
|
||||
</Typography>
|
||||
<Typography variant="caption">
|
||||
تلفن: {item?.poultry?.userMobile}
|
||||
</Typography>
|
||||
<Typography variant="caption">
|
||||
{item?.poultry?.poultryRequestQuantity.toLocaleString()}{" "}
|
||||
قطعه
|
||||
</Typography>
|
||||
<Typography variant="caption" color="blue">
|
||||
دامپزشک فارم: {item?.poultry?.vetFarmName}
|
||||
</Typography>
|
||||
<Typography variant="caption" color="blue">
|
||||
تلفن دامپزشک: {item?.poultry?.vetFarmMobile}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
component="th"
|
||||
scope="row"
|
||||
className="no-border-flex-table"
|
||||
>
|
||||
<Grid style={{ marginBottom: "2px" }}>
|
||||
<Typography
|
||||
variant="button"
|
||||
textAlign="center"
|
||||
style={{
|
||||
borderBottom: "1px solid gray",
|
||||
paddingBottom: "2px",
|
||||
}}
|
||||
>
|
||||
شهرستان
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container direction="column">
|
||||
<Typography variant="caption" color={cityStateColor}>
|
||||
{item?.cityState?.operatorCity} (
|
||||
{item?.cityState?.operatorName})
|
||||
</Typography>
|
||||
<Typography variant="caption" color={cityStateColor}>
|
||||
تلفن: {item?.cityState?.operatorMobile}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
component="th"
|
||||
scope="row"
|
||||
className="no-border-flex-table"
|
||||
>
|
||||
<Grid style={{ marginBottom: "2px" }}>
|
||||
<Typography
|
||||
variant="button"
|
||||
textAlign="center"
|
||||
style={{
|
||||
borderBottom: "1px solid gray",
|
||||
paddingBottom: "2px",
|
||||
}}
|
||||
>
|
||||
استان
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container direction="column">
|
||||
<Typography
|
||||
variant="caption"
|
||||
color={provinceStateColor}
|
||||
>
|
||||
{item?.provinceState?.provinceOperatorProvinc} (
|
||||
{item?.provinceState?.provinceOperatorName})
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color={provinceStateColor}
|
||||
>
|
||||
تلفن: {item?.provinceState?.provinceOperatorMobile}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
component="th"
|
||||
scope="row"
|
||||
className="loop-kill-request no-border-flex-table"
|
||||
>
|
||||
{item?.provinceKillRequests?.map((killRequest, i) => {
|
||||
// killhouse state color
|
||||
let killHouseStateColor;
|
||||
if (killRequest?.state === "pending") {
|
||||
killHouseStateColor = "#ff7410";
|
||||
}
|
||||
if (killRequest?.state === "accepted") {
|
||||
killHouseStateColor = "green";
|
||||
}
|
||||
if (killRequest?.state === "rejected") {
|
||||
killHouseStateColor = "red";
|
||||
}
|
||||
return (
|
||||
<TableRow
|
||||
className="row-kill-request"
|
||||
key={i}
|
||||
sx={{
|
||||
"&:last-child td, &:last-child th": { border: 0 },
|
||||
}}
|
||||
>
|
||||
<TableCell component="th" scope="row">
|
||||
<Grid style={{ marginBottom: "2px" }}>
|
||||
<Typography
|
||||
variant="button"
|
||||
textAlign="center"
|
||||
style={{
|
||||
borderBottom: "1px solid gray",
|
||||
paddingBottom: "2px",
|
||||
}}
|
||||
>
|
||||
خریدار
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container direction="column">
|
||||
<Typography
|
||||
variant="caption"
|
||||
color={killHouseStateColor}
|
||||
>
|
||||
{killRequest?.buyerName}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color={killHouseStateColor}
|
||||
>
|
||||
{killRequest?.quantity} قطعه
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color={killHouseStateColor}
|
||||
>
|
||||
تلفن: {killRequest?.buyerMobile}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</TableCell>
|
||||
<TableCell component="th" scope="row">
|
||||
<Grid style={{ marginBottom: "2px" }}>
|
||||
<Typography
|
||||
variant="button"
|
||||
textAlign="center"
|
||||
style={{
|
||||
borderBottom: "1px solid gray",
|
||||
paddingBottom: "2px",
|
||||
}}
|
||||
>
|
||||
راننده
|
||||
</Typography>
|
||||
</Grid>
|
||||
{killRequest?.killHouseRequests?.map((car, i) => {
|
||||
let carStateColor = "";
|
||||
if (car?.clearanceCode) {
|
||||
carStateColor = "green";
|
||||
} else {
|
||||
carStateColor = "red";
|
||||
}
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
key={i}
|
||||
style={{ whiteSpace: "nowrap" }}
|
||||
>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color={carStateColor}
|
||||
>
|
||||
{car?.driverName} / تعداد{" "}
|
||||
{car?.quantity.toLocaleString()} /
|
||||
کدبهداشتی {car?.trafficCode} / کدترخیص{" "}
|
||||
{car?.clearanceCode
|
||||
? car?.clearanceCode
|
||||
: "در انتظار"}
|
||||
</Typography>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</TableCell>
|
||||
<TableCell component="th" scope="row">
|
||||
<Grid style={{ marginBottom: "2px" }}>
|
||||
<Typography
|
||||
variant="button"
|
||||
textAlign="center"
|
||||
style={{
|
||||
borderBottom: "1px solid gray",
|
||||
paddingBottom: "2px",
|
||||
}}
|
||||
>
|
||||
دامپزشک کشتارگاه
|
||||
</Typography>
|
||||
</Grid>
|
||||
{killRequest?.killHouseRequests?.map((car, i) => {
|
||||
let vetStateColor = "";
|
||||
if (car?.vetState === "pending") {
|
||||
vetStateColor = "#ff7410";
|
||||
} else if (car?.vetState === "accepted") {
|
||||
vetStateColor = "green";
|
||||
} else {
|
||||
vetStateColor = "red";
|
||||
}
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
key={i}
|
||||
style={{ whiteSpace: "nowrap" }}
|
||||
>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color={vetStateColor}
|
||||
>
|
||||
{car?.killHouseVetName
|
||||
? car?.killHouseVetName
|
||||
: "ندارد"}{" "}
|
||||
/{" "}
|
||||
{car?.killHouseVetMobile
|
||||
? car.killHouseVetMobile
|
||||
: "ندارد"}
|
||||
</Typography>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</TableCell>
|
||||
<TableCell component="th" scope="row">
|
||||
<Grid style={{ marginBottom: "2px" }}>
|
||||
<Typography
|
||||
variant="button"
|
||||
textAlign="center"
|
||||
style={{
|
||||
borderBottom: "1px solid gray",
|
||||
paddingBottom: "2px",
|
||||
}}
|
||||
>
|
||||
اطلاعات بار
|
||||
</Typography>
|
||||
</Grid>
|
||||
{killRequest?.killHouseRequests
|
||||
?.filter((car) => car.bar)
|
||||
?.map((car, i) => {
|
||||
// city state color
|
||||
let barStateColor;
|
||||
if (car?.bar?.state === "pending") {
|
||||
barStateColor = "#ff7410";
|
||||
}
|
||||
if (car?.bar?.state === "accepted") {
|
||||
barStateColor = "green";
|
||||
}
|
||||
if (car?.bar?.state === "rejected") {
|
||||
barStateColor = "red";
|
||||
}
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
key={i}
|
||||
style={{ whiteSpace: "nowrap" }}
|
||||
>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color={barStateColor}
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
gap={1}
|
||||
style={{ flexFlow: "nowrap" }}
|
||||
>
|
||||
<a
|
||||
href={
|
||||
car?.bar?.carWeightWithLoadImage
|
||||
}
|
||||
>
|
||||
<img
|
||||
src={
|
||||
car?.bar?.carWeightWithLoadImage
|
||||
}
|
||||
width="20"
|
||||
height="20"
|
||||
alt=""
|
||||
style={{ borderRadius: "4px" }}
|
||||
/>
|
||||
</a>
|
||||
وزن با بار:{" "}
|
||||
{car?.bar?.carWeightWithLoad?.toLocaleString()}{" "}
|
||||
/
|
||||
<a
|
||||
href={
|
||||
car?.bar
|
||||
?.carWeightWithoutLoadImage
|
||||
}
|
||||
>
|
||||
<img
|
||||
src={
|
||||
car?.bar
|
||||
?.carWeightWithoutLoadImage
|
||||
}
|
||||
width="20"
|
||||
height="20"
|
||||
alt=""
|
||||
style={{ borderRadius: "4px" }}
|
||||
/>
|
||||
</a>
|
||||
وزن بدون بار:{" "}
|
||||
{car?.bar?.carWeightWithoutLoad?.toLocaleString()}{" "}
|
||||
/ وزن خالص:
|
||||
{car?.bar?.netWeight.toLocaleString()}{" "}
|
||||
/ تعداد واقعی:
|
||||
{car?.bar?.realQuantity.toLocaleString()}
|
||||
</Grid>
|
||||
</Typography>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</TableCell>
|
||||
<TableCell component="th" scope="row">
|
||||
<Grid style={{ marginBottom: "2px" }}>
|
||||
<Typography
|
||||
variant="button"
|
||||
textAlign="center"
|
||||
style={{
|
||||
borderBottom: "1px solid gray",
|
||||
paddingBottom: "2px",
|
||||
}}
|
||||
>
|
||||
فاکتور استان
|
||||
</Typography>
|
||||
</Grid>
|
||||
{killRequest?.killHouseRequests
|
||||
?.filter((car) => car.provinceFactor)
|
||||
?.map((car, i) => {
|
||||
// city state color
|
||||
let provinceFactorStateColor;
|
||||
if (
|
||||
car?.killHouseFactor?.state === "pending"
|
||||
) {
|
||||
provinceFactorStateColor = "#ff7410";
|
||||
}
|
||||
if (
|
||||
car?.killHouseFactor?.state === "accepted"
|
||||
) {
|
||||
provinceFactorStateColor = "green";
|
||||
}
|
||||
if (
|
||||
car?.killHouseFactor?.state === "rejected"
|
||||
) {
|
||||
provinceFactorStateColor = "red";
|
||||
}
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
key={i}
|
||||
style={{ whiteSpace: "nowrap" }}
|
||||
>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color={provinceFactorStateColor}
|
||||
>
|
||||
فی:{" "}
|
||||
{car?.provinceFactor?.factorFee.toLocaleString()}
|
||||
{" / "}
|
||||
وزن:{" "}
|
||||
{car?.provinceFactor?.totalWeight.toLocaleString()}
|
||||
{" / "}
|
||||
مبلغ کل:{" "}
|
||||
{car?.provinceFactor?.totalPrice.toLocaleString()}
|
||||
<a
|
||||
href={
|
||||
car?.killHouseFactor?.factorImage
|
||||
}
|
||||
>
|
||||
<img
|
||||
src={
|
||||
car?.killHouseFactor?.factorImage
|
||||
}
|
||||
width="20"
|
||||
height="20"
|
||||
alt=""
|
||||
style={{ borderRadius: "4px" }}
|
||||
/>
|
||||
</a>
|
||||
شناسه پرداخت:
|
||||
{car?.killHouseFactor?.paymentCode}
|
||||
</Typography>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Typography } from "@mui/material";
|
||||
|
||||
export const ProvinceCaseStepBarsInfo = () => {
|
||||
return <Typography>اطلاعات بارها</Typography>;
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Typography } from "@mui/material";
|
||||
|
||||
export const ProvinceCaseStepPaymentInformation = () => {
|
||||
return <Typography>اطلاعات پرداخت</Typography>;
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Typography } from "@mui/material";
|
||||
|
||||
export const ProvinceCaseStepShipping = () => {
|
||||
return <Typography>گواهی حمل</Typography>;
|
||||
};
|
||||
@@ -0,0 +1,143 @@
|
||||
import { Step, StepLabel, Stepper, Typography } from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export const ProvinceCaseSteps = ({ stepClickedHandler, item }) => {
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
let step = 0;
|
||||
|
||||
if (
|
||||
item?.cityState?.state === "reject" ||
|
||||
item?.provinceState?.state === "reject"
|
||||
) {
|
||||
step = -1;
|
||||
} else {
|
||||
if (item?.cityState?.date) {
|
||||
step = 1;
|
||||
}
|
||||
if (item?.provinceState?.date) {
|
||||
step = 2;
|
||||
}
|
||||
if (
|
||||
item?.provinceKillRequests?.provinceKillRequestSerializer.length > 0
|
||||
) {
|
||||
step = 3;
|
||||
}
|
||||
if (item?.killHouseRequests?.killHouseRequestsSerializer.length > 0) {
|
||||
step = 4;
|
||||
}
|
||||
if (
|
||||
item?.killHouseRequests?.killHouseRequestVetCheckSerializer?.length > 0
|
||||
) {
|
||||
step = 5;
|
||||
}
|
||||
if (
|
||||
item?.killHouseRequests?.killHouseRequestAssignmentSerializer?.length >
|
||||
0
|
||||
) {
|
||||
step = 6;
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentStep(step);
|
||||
}, [item]);
|
||||
|
||||
const steps = item.out
|
||||
? ["درخواست کشتار", "تایید شهرستان", "تایید استان"]
|
||||
: [
|
||||
"درخواست کشتار",
|
||||
"تایید شهرستان",
|
||||
"تایید استان",
|
||||
"تخصیص به خریدار",
|
||||
"ایجاد بار",
|
||||
"تخلیه",
|
||||
"اطلاعات بار",
|
||||
"اطلاعات پرداخت",
|
||||
];
|
||||
|
||||
const isStepFailed = (step) => {
|
||||
let isFailed = false;
|
||||
switch (step) {
|
||||
case 1:
|
||||
isFailed = item?.cityState?.state === "reject";
|
||||
break;
|
||||
case 2:
|
||||
isFailed = item?.provinceState?.state === "reject";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return isFailed;
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
width="100%"
|
||||
mt={SPACING.MEDIUM}
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
>
|
||||
<Grid display={{ xs: "none", sm: "grid" }} width="100%">
|
||||
<Stepper activeStep={currentStep} alternativeLabel>
|
||||
{steps.map((label, index) => {
|
||||
const labelProps = {};
|
||||
if (isStepFailed(index)) {
|
||||
labelProps.optional = (
|
||||
<Typography variant="caption" color="error">
|
||||
پرونده در این مرحله رد شد.
|
||||
</Typography>
|
||||
);
|
||||
labelProps.error = true;
|
||||
}
|
||||
|
||||
return (
|
||||
<Step
|
||||
sx={{ cursor: "pointer" }}
|
||||
key={label}
|
||||
onClick={() => {
|
||||
if (currentStep >= index) {
|
||||
stepClickedHandler(index);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<StepLabel {...labelProps}>{label}</StepLabel>
|
||||
</Step>
|
||||
);
|
||||
})}
|
||||
</Stepper>
|
||||
</Grid>
|
||||
<Grid display={{ xs: "block", sm: "none" }}>
|
||||
<Stepper activeStep={currentStep} orientation="vertical">
|
||||
{steps.map((label, index) => {
|
||||
const labelProps = {};
|
||||
if (isStepFailed(index)) {
|
||||
labelProps.optional = (
|
||||
<Typography variant="caption" color="error">
|
||||
پرونده در این مرحله رد شد.
|
||||
</Typography>
|
||||
);
|
||||
labelProps.error = true;
|
||||
}
|
||||
|
||||
return (
|
||||
<Step
|
||||
key={label}
|
||||
onClick={() => {
|
||||
if (currentStep >= index) {
|
||||
stepClickedHandler(index);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<StepLabel {...labelProps}>{label}</StepLabel>
|
||||
</Step>
|
||||
);
|
||||
})}
|
||||
</Stepper>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
580
src/features/province/components/province-cases-item/Pages.js
Normal file
580
src/features/province/components/province-cases-item/Pages.js
Normal file
@@ -0,0 +1,580 @@
|
||||
import { Typography } from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
|
||||
const styles = {
|
||||
tableInNewPage: {
|
||||
pageBreakAfter: "always",
|
||||
paddingLeft: "40px",
|
||||
paddingRight: "40px",
|
||||
direction: "rtl",
|
||||
fontFamily: "titr",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
container: {
|
||||
width: "95%",
|
||||
alignSelf: "center",
|
||||
pageBreakInside: "avoid",
|
||||
},
|
||||
|
||||
invoiceTable: {
|
||||
width: "100%",
|
||||
borderCollapse: "collapse",
|
||||
alignSelf: "center",
|
||||
fontFamily: "titr",
|
||||
marginBottom: "5px",
|
||||
marginTop: "15px",
|
||||
borderRadius: "10px",
|
||||
},
|
||||
tableCell: {
|
||||
border: "1px solid #000",
|
||||
pAlign: "left",
|
||||
textAlign: "center",
|
||||
fontSize: 12,
|
||||
fontWeight: "bolder",
|
||||
color: "#403e3e",
|
||||
},
|
||||
tableCellGreen: {
|
||||
border: "1px solid #000",
|
||||
pAlign: "left",
|
||||
textAlign: "center",
|
||||
fontSize: 12,
|
||||
color: "white",
|
||||
fontWeight: "bolder",
|
||||
backgroundColor: "rgba(26, 188, 156, 0.7)",
|
||||
},
|
||||
tableCellMobile: {
|
||||
border: "1px solid #000",
|
||||
pAlign: "left",
|
||||
textAlign: "center",
|
||||
fontSize: 12,
|
||||
},
|
||||
tableInnerCell: {
|
||||
border: "1px solid #000",
|
||||
pAlign: "left",
|
||||
textAlign: "center",
|
||||
fontSize: 9,
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
tableHeader: {
|
||||
backgroundColor: "rgba(211, 211, 211, 0.3)",
|
||||
pageBreakAfter: "auto",
|
||||
},
|
||||
headerRow: {
|
||||
background: "linear-gradient(to right, #E684AE, #79CBCA, #77A1D3)",
|
||||
backgroundColor: "rgba(232, 67, 147, 0.4)",
|
||||
color: "#422020",
|
||||
pageBreakInside: "avoid",
|
||||
pageBreakAfter: "auto",
|
||||
},
|
||||
|
||||
tableHeaderCell: {
|
||||
fontSize: 14,
|
||||
border: "1px solid #000",
|
||||
padding: "4px",
|
||||
textAlign: "center",
|
||||
fontWeight: "bolder",
|
||||
},
|
||||
tableHeaderCellGreen: {
|
||||
backgroundColor: "rgba(26, 188, 156, 0.7)",
|
||||
fontSize: 12,
|
||||
border: "1px solid #000",
|
||||
padding: "4px",
|
||||
textAlign: "center",
|
||||
fontWeight: "bolder",
|
||||
color: "white",
|
||||
},
|
||||
footer: {
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
width: "100%",
|
||||
position: "absolute",
|
||||
},
|
||||
footerContainer: {
|
||||
alignItems: "center",
|
||||
display: "flex",
|
||||
},
|
||||
|
||||
tableRowEven: {
|
||||
backgroundColor: "rgba(170, 183, 255, 0.3)",
|
||||
},
|
||||
titleOfTable: {
|
||||
marginRight: "20px",
|
||||
fontSize: "15px",
|
||||
},
|
||||
tableCellAlert: {
|
||||
border: "1px solid #000",
|
||||
pAlign: "left",
|
||||
textAlign: "center",
|
||||
fontSize: 12,
|
||||
color: "red",
|
||||
},
|
||||
levelDetails: {
|
||||
color: "red",
|
||||
fontSize: 12,
|
||||
},
|
||||
};
|
||||
|
||||
export const TableCityLevel = ({ item }) => {
|
||||
return (
|
||||
<Grid mt={SPACING.SMALL}>
|
||||
<Typography variant={"body2"}>مرحله شهرستان</Typography>
|
||||
<table style={styles.invoiceTable}>
|
||||
<thead style={styles.tableHeader}>
|
||||
<tr style={styles.headerRow}>
|
||||
<th style={styles.tableHeaderCell}>اپراتور</th>
|
||||
<th style={styles.tableHeaderCell}>سمت</th>
|
||||
<th style={styles.tableHeaderCell}>تلفن</th>
|
||||
<th style={styles.tableHeaderCell}>تعاونی مرغدار</th>
|
||||
<th style={styles.tableHeaderCell}>آدرس</th>
|
||||
<th style={styles.tableHeaderCell}>وضعیت</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{item?.cityState?.date ? (
|
||||
<tbody>
|
||||
<tr style={styles.tableRow}>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.cityState?.cityOperatorFullname}
|
||||
</td>
|
||||
<td style={styles.tableCell}>اپراتور شهرستان</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.cityState?.cityOperatorMobile}
|
||||
</td>
|
||||
<td style={styles.tableCell}>{item?.cityState?.poultry}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.cityState?.province + " - " + item?.cityState?.city}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.cityState?.state === "accept" ? "تایید شده" : "رد شده"}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
) : (
|
||||
<td style={styles.tableCellAlert} colSpan={6}>
|
||||
هنوز شهرستان پرونده را تائید نکرده است
|
||||
</td>
|
||||
)}
|
||||
</table>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export const TableProvinceLevel = ({ item }) => {
|
||||
return (
|
||||
<Grid mt={SPACING.SMALL}>
|
||||
<Typography variant={"body2"}>مرحله استان</Typography>
|
||||
<table style={styles.invoiceTable}>
|
||||
<thead style={styles.tableHeader}>
|
||||
<tr style={styles.headerRow}>
|
||||
<th style={styles.tableHeaderCell}>اپراتور</th>
|
||||
<th style={styles.tableHeaderCell}>سمت</th>
|
||||
<th style={styles.tableHeaderCell}>تلفن</th>
|
||||
<th style={styles.tableHeaderCell}>تعاونی مرغدار</th>
|
||||
<th style={styles.tableHeaderCell}>آدرس</th>
|
||||
<th style={styles.tableHeaderCell}>وضعیت</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{item?.provinceState?.date ? (
|
||||
<tbody>
|
||||
<tr style={styles.tableRow}>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.provinceState?.provinceOperatorFullname}
|
||||
</td>
|
||||
<td style={styles.tableCell}>اپراتور استان</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.provinceState?.provinceOperatorMobile}
|
||||
</td>
|
||||
<td style={styles.tableCell}>{item?.provinceState?.poultry}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.provinceState?.province +
|
||||
" - " +
|
||||
item?.provinceState?.city}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.provinceState?.state === "accept"
|
||||
? "تایید شده"
|
||||
: "رد شده"}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
) : (
|
||||
<td style={styles.tableCellAlert} colSpan={6}>
|
||||
هنوز استان پرونده را تائید نکرده است
|
||||
</td>
|
||||
)}
|
||||
</table>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export const TableSalughterAllocationLevel = ({ item }) => {
|
||||
return (
|
||||
<Grid mt={SPACING.SMALL}>
|
||||
<Typography variant={"body2"}>
|
||||
مرحله تخصیص به خریدار {" ( "}
|
||||
<span style={styles.levelDetails}>
|
||||
تعداد درخواست:{" "}
|
||||
{item?.provinceKillRequests?.provinceKillRequestsTotalInfo?.poultryRequestQuantity.toLocaleString()}
|
||||
، تعداد تخصیصی به کشتارگاه:{" "}
|
||||
{item?.provinceKillRequests?.provinceKillRequestsTotalInfo?.allocatedQuantity.toLocaleString()}
|
||||
، مانده قابل تخصیصی:{" "}
|
||||
{item?.provinceKillRequests?.provinceKillRequestsTotalInfo?.poultryRequestRemainQuantity.toLocaleString()}
|
||||
</span>
|
||||
{" ) "}
|
||||
</Typography>
|
||||
<table style={styles.invoiceTable}>
|
||||
<thead style={styles.tableHeader}>
|
||||
<tr style={styles.headerRow}>
|
||||
<th style={styles.tableHeaderCell}>ردیف</th>
|
||||
<th style={styles.tableHeaderCell}>ماهیت خریدار</th>
|
||||
<th style={styles.tableHeaderCell}>خریدار</th>
|
||||
<th style={styles.tableHeaderCell}>نوع تخصیص</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد تخصیصی</th>
|
||||
<th style={styles.tableHeaderCell}>میانگین وزن</th>
|
||||
<th style={styles.tableHeaderCell}>وزن تخصیصی</th>
|
||||
<th style={styles.tableHeaderCell}>وضعیت</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{item?.provinceKillRequests?.provinceKillRequestSerializer ? (
|
||||
<tbody>
|
||||
{item?.provinceKillRequests?.provinceKillRequestSerializer.map(
|
||||
(item, i) => (
|
||||
<tr key={i} style={styles.tableRow}>
|
||||
<td style={styles.tableCell}>{i + 1}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.killhouseUser?.killer === false
|
||||
? "کشتارگاه"
|
||||
: "کشتارکن"}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{`${item?.killhouseUser?.killHouseOperator?.user?.fullname} (${item?.killhouseUser?.killHouseOperator?.user?.mobile})`}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.automatic === false ? "دستی" : "اتوماتیک"}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.weightInfo?.provinceKillRequestQuantity}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.weightInfo?.provinceKillRequestIndexWeight}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.weightInfo?.provinceKillRequestWeight}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.state === "accepted"
|
||||
? "تایید شده"
|
||||
: item?.state === "rejected"
|
||||
? "رد شده"
|
||||
: "در انتظار تایید"}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
</tbody>
|
||||
) : (
|
||||
<td style={styles.tableCellAlert} colSpan={8}>
|
||||
داده ای ثبت نشده!
|
||||
</td>
|
||||
)}
|
||||
</table>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export const TableSlaughterAddCar = ({ item }) => {
|
||||
return (
|
||||
<Grid mt={SPACING.SMALL}>
|
||||
<Typography variant={"body2"}>
|
||||
مرحله ایجاد بار
|
||||
{" ( "}
|
||||
<span style={styles.levelDetails}>
|
||||
تعداد تخصیص به خریداران:{" "}
|
||||
{item?.killHouseRequests?.allocatedQuantity?.toLocaleString()}، تعداد
|
||||
بارها: {item?.killHouseRequests?.numberOfBars?.toLocaleString()}،
|
||||
تعداد تخصیص به ماشین:{" "}
|
||||
{item?.killHouseRequests?.killHouseRequestQuantity?.toLocaleString()}،
|
||||
مانده قابل تخصیص:{" "}
|
||||
{item?.killHouseRequests?.remainQuantity?.toLocaleString()}
|
||||
</span>
|
||||
{" ) "}
|
||||
</Typography>
|
||||
<table style={styles.invoiceTable}>
|
||||
<thead style={styles.tableHeader}>
|
||||
<tr style={styles.headerRow}>
|
||||
<th style={styles.tableHeaderCell}>ردیف</th>
|
||||
<th style={styles.tableHeaderCell}>کد بار</th>
|
||||
<th style={styles.tableHeaderCell}>خریدار</th>
|
||||
<th style={styles.tableHeaderCell}>ماشین</th>
|
||||
<th style={styles.tableHeaderCell}>راننده</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد</th>
|
||||
<th style={styles.tableHeaderCell}>وزن بار</th>
|
||||
<th style={styles.tableHeaderCell}>میانگین وزن</th>
|
||||
<th style={styles.tableHeaderCell}>کد قرنطینه</th>
|
||||
<th style={styles.tableHeaderCell}>محل کشتار</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{item?.killHouseRequests?.killHouseRequestsSerializer ? (
|
||||
<tbody>
|
||||
{item?.killHouseRequests?.killHouseRequestsSerializer.map(
|
||||
(item, i) => (
|
||||
<tr key={i} style={styles.tableRow}>
|
||||
<td style={styles.tableCell}>{i + 1}</td>
|
||||
<td style={styles.tableCell}>{item?.barCode}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{`${item?.killhouseUser?.killHouseOperator?.user?.fullname} (${item?.killhouseUser?.killHouseOperator?.user?.mobile})`}
|
||||
</td>
|
||||
<td
|
||||
style={styles.tableCell}
|
||||
>{`${item?.addCar?.driver?.typeCar} (${item?.addCar?.driver?.pelak})`}</td>
|
||||
<td
|
||||
style={styles.tableCell}
|
||||
>{`${item?.addCar?.driver?.driverName} (${item?.addCar?.driver?.driverMobile})`}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.quantity.toLocaleString()}
|
||||
</td>
|
||||
<td style={styles.tableCell}>{item?.weightInfo?.weight}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.weightInfo?.indexWeight}
|
||||
</td>
|
||||
<td style={styles.tableCell}>{item?.clearanceCode}</td>
|
||||
<td style={styles.tableCell}>{item?.killPlace}</td>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
</tbody>
|
||||
) : (
|
||||
<td style={styles.tableCellAlert} colSpan={10}>
|
||||
داده ای ثبت نشده!
|
||||
</td>
|
||||
)}
|
||||
</table>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export const TableSVetAcceptDischarge = ({ item }) => {
|
||||
return (
|
||||
<Grid mt={SPACING.SMALL}>
|
||||
<Typography variant={"body2"}>
|
||||
مرحله تخلیه بار
|
||||
{" ( "}
|
||||
<span style={styles.levelDetails}>
|
||||
تعداد بارها: {item?.killHouseRequests?.numberOfBars?.toLocaleString()}
|
||||
، تایید تخلیه:{" "}
|
||||
{item?.killHouseRequests?.vetAcceptedNumberOfBars?.toLocaleString()}،
|
||||
تخلیه نشده:{" "}
|
||||
{item?.killHouseRequests?.vetRemainNumberOfBars?.toLocaleString()}
|
||||
</span>
|
||||
{" ) "}
|
||||
</Typography>
|
||||
<table style={styles.invoiceTable}>
|
||||
<thead style={styles.tableHeader}>
|
||||
<tr style={styles.headerRow}>
|
||||
<th style={styles.tableHeaderCell}>ردیف</th>
|
||||
<th style={styles.tableHeaderCell}>کد بار</th>
|
||||
<th style={styles.tableHeaderCell}>خریدار</th>
|
||||
<th style={styles.tableHeaderCell}>ماشین</th>
|
||||
<th style={styles.tableHeaderCell}>راننده</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد</th>
|
||||
<th style={styles.tableHeaderCell}>وزن بار</th>
|
||||
<th style={styles.tableHeaderCell}>میانگین وزن</th>
|
||||
<th style={styles.tableHeaderCell}>کد قرنطینه</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد تخلیه شده </th>
|
||||
<th style={styles.tableHeaderCell}>وزن تخلیه شده </th>
|
||||
<th style={styles.tableHeaderCell}>وضعیت</th>
|
||||
<th style={styles.tableHeaderCell}>اطلاعات تخلیه</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{item?.killHouseRequests?.killHouseRequestVetCheckSerializer.length ? (
|
||||
<tbody>
|
||||
{item?.killHouseRequests?.killHouseRequestVetCheckSerializer.map(
|
||||
(item, i) => (
|
||||
<tr key={i} style={styles.tableRow}>
|
||||
<td style={styles.tableCell}>{i + 1}</td>
|
||||
<td style={styles.tableCell}>{item?.barCode}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{`${item?.killhouseUser?.killHouseOperator?.user?.fullname} (${item?.killhouseUser?.killHouseOperator?.user?.mobile})`}
|
||||
</td>
|
||||
<td
|
||||
style={styles.tableCell}
|
||||
>{`${item?.addCar?.driver?.typeCar} (${item?.addCar?.driver?.pelak})`}</td>
|
||||
<td
|
||||
style={styles.tableCell}
|
||||
>{`${item?.addCar?.driver?.driverName} (${item?.addCar?.driver?.driverMobile})`}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.quantity.toLocaleString()}
|
||||
</td>
|
||||
<td style={styles.tableCell}>{item?.weightInfo?.weight}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.weightInfo?.indexWeight}
|
||||
</td>
|
||||
<td style={styles.tableCell}>{item?.clearanceCode}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.vetAcceptedRealQuantity?.toLocaleString()}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.vetAcceptedRealWeight?.toLocaleString()}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.vetState === "accepted"
|
||||
? "تخلیه شده"
|
||||
: "در انتظار تخلیه"}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.vetState === "accepted"
|
||||
? `${item?.killHouseVet?.fullname} (${item?.killHouseVet?.mobile})`
|
||||
: "-"}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
</tbody>
|
||||
) : (
|
||||
<td style={styles.tableCellAlert} colSpan={13}>
|
||||
تخلیه بار تایید نشده است.
|
||||
</td>
|
||||
)}
|
||||
</table>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export const TableSlaughterInputBarData = ({ item }) => {
|
||||
return (
|
||||
<Grid mt={SPACING.SMALL}>
|
||||
<Typography variant={"body2"}>اطلاعات بار</Typography>
|
||||
<table style={styles.invoiceTable}>
|
||||
<thead style={styles.tableHeader}>
|
||||
<tr style={styles.headerRow}>
|
||||
<th style={styles.tableHeaderCell}>ردیف</th>
|
||||
<th style={styles.tableHeaderCell}>کد بار</th>
|
||||
<th style={styles.tableHeaderCell}>خریدار</th>
|
||||
<th style={styles.tableHeaderCell}>ماشین</th>
|
||||
<th style={styles.tableHeaderCell}>راننده</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد</th>
|
||||
<th style={styles.tableHeaderCell}>وزن بار</th>
|
||||
<th style={styles.tableHeaderCell}>میانگین وزن</th>
|
||||
<th style={styles.tableHeaderCell}>کد قرنطینه</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد تخلیه شده (دامپزشک)</th>
|
||||
<th style={styles.tableHeaderCell}>وزن تخلیه شده (دامپزشک)</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد نهایی</th>
|
||||
<th style={styles.tableHeaderCell}>وزن خالص واقعی</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{item?.killHouseRequests?.killHouseRequestAssignmentSerializer ? (
|
||||
<tbody>
|
||||
{item?.killHouseRequests?.killHouseRequestAssignmentSerializer.map(
|
||||
(item, i) => (
|
||||
<tr key={i} style={styles.tableRow}>
|
||||
<td style={styles.tableCell}>{i + 1}</td>
|
||||
<td style={styles.tableCell}>{item?.barCode}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{`${item?.killhouseUser?.killHouseOperator?.user?.fullname} (${item?.killhouseUser?.killHouseOperator?.user?.mobile})`}
|
||||
</td>
|
||||
<td
|
||||
style={styles.tableCell}
|
||||
>{`${item?.addCar?.driver?.typeCar} (${item?.addCar?.driver?.pelak})`}</td>
|
||||
<td
|
||||
style={styles.tableCell}
|
||||
>{`${item?.addCar?.driver?.driverName} (${item?.addCar?.driver?.driverMobile})`}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.quantity.toLocaleString()}
|
||||
</td>
|
||||
<td style={styles.tableCell}>{item?.weightInfo?.weight}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.weightInfo?.indexWeight}
|
||||
</td>
|
||||
<td style={styles.tableCell}>{item?.clearanceCode}</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.vetAcceptedRealQuantity?.toLocaleString()}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.vetAcceptedRealWeight?.toLocaleString()}
|
||||
</td>
|
||||
<td style={styles.tableCell}>
|
||||
{item?.acceptedRealQuantity?.toLocaleString()}
|
||||
</td>{" "}
|
||||
<td style={styles.tableCell}>
|
||||
{item?.acceptedRealWeight?.toLocaleString()}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
</tbody>
|
||||
) : (
|
||||
<td style={styles.tableCellAlert} colSpan={13}>
|
||||
داده ای ثبت نشده!
|
||||
</td>
|
||||
)}
|
||||
</table>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export const TableSlaughterFinanceInfo = ({ item }) => {
|
||||
return (
|
||||
<table style={styles.invoiceTable}>
|
||||
<thead style={styles.tableHeader}>
|
||||
<tr style={styles.headerRow}>
|
||||
<th style={styles.tableHeaderCell}>ردیف</th>
|
||||
<th style={styles.tableHeaderCell}>کد بار</th>
|
||||
<th style={styles.tableHeaderCell}>خریدار</th>
|
||||
<th style={styles.tableHeaderCell}>ماشین</th>
|
||||
<th style={styles.tableHeaderCell}>راننده</th>
|
||||
<th style={styles.tableHeaderCell}>نژاد</th>
|
||||
<th style={styles.tableHeaderCell}>کد قرنطینه</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد نهایی</th>
|
||||
<th style={styles.tableHeaderCell}>وزن خالص بار</th>
|
||||
<th style={styles.tableHeaderCell}>میانگین وزن</th>
|
||||
<th style={styles.tableHeaderCell}>مبلغ فاکتور</th>
|
||||
<th style={styles.tableHeaderCell}>وضعیت</th>
|
||||
<th style={styles.tableHeaderCell}>اطلاعات پرداخت (شناسه پرداخت)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{item?.provinceState?.date && (
|
||||
<tbody>
|
||||
<tr style={styles.tableRow}>
|
||||
{/* <td style={styles.tableCell}>
|
||||
{item?.provinceState?.provinceOperatorFullname}
|
||||
</td> */}
|
||||
</tr>
|
||||
</tbody>
|
||||
)}
|
||||
</table>
|
||||
);
|
||||
};
|
||||
|
||||
export const TableInspector = ({ item }) => {
|
||||
return (
|
||||
<table style={styles.invoiceTable}>
|
||||
<thead style={styles.tableHeader}>
|
||||
<tr style={styles.headerRow}>
|
||||
<th style={styles.tableHeaderCell}>ردیف</th>
|
||||
<th style={styles.tableHeaderCell}>کد بار</th>
|
||||
<th style={styles.tableHeaderCell}>خریدار</th>
|
||||
<th style={styles.tableHeaderCell}>ماشین</th>
|
||||
<th style={styles.tableHeaderCell}>راننده</th>
|
||||
<th style={styles.tableHeaderCell}>نژاد</th>
|
||||
<th style={styles.tableHeaderCell}>کد قرنطینه</th>
|
||||
<th style={styles.tableHeaderCell}>تعداد نهایی</th>
|
||||
<th style={styles.tableHeaderCell}>وزن خالص بار</th>
|
||||
<th style={styles.tableHeaderCell}>میانگین وزن</th>
|
||||
<th style={styles.tableHeaderCell}>مبلغ فاکتور</th>
|
||||
<th style={styles.tableHeaderCell}>وضعیت پرداخت</th>
|
||||
<th style={styles.tableHeaderCell}>وضعیت</th>
|
||||
<th style={styles.tableHeaderCell}>نظر بازرس</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{item?.provinceState?.date && (
|
||||
<tbody>
|
||||
<tr style={styles.tableRow}>
|
||||
{/* <td style={styles.tableCell}>
|
||||
{item?.provinceState?.provinceOperatorFullname}
|
||||
</td> */}
|
||||
</tr>
|
||||
</tbody>
|
||||
)}
|
||||
</table>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,253 @@
|
||||
import {
|
||||
Collapse,
|
||||
IconButton,
|
||||
Paper,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useEffect, useState, useRef, useContext } from "react";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { ProvinceCaseOverview } from "../province-case-overview/ProvinceCaseOverview";
|
||||
import { ProvinceCaseSteps } from "../province-case-steps/ProvinceCaseSteps";
|
||||
import { ProvinceCaseStepPaymentInformation } from "../province-case-step-payment-information/ProvinceCaseStepPaymentInformation";
|
||||
import { BsFillFileEarmarkPdfFill } from "react-icons/bs";
|
||||
import { useReactToPrint } from "react-to-print";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import ProvinceGetCaseFile from "../province-get-case-file/ProvinceGetCaseFile";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import {
|
||||
TableCityLevel,
|
||||
TableProvinceLevel,
|
||||
TableSVetAcceptDischarge,
|
||||
TableSalughterAllocationLevel,
|
||||
TableSlaughterAddCar,
|
||||
TableSlaughterInputBarData,
|
||||
} from "./Pages";
|
||||
|
||||
export const ProvinceCasesItem = ({ caseData, caseIndex, pageIndex, data }) => {
|
||||
const [isCollapsed, setIsCollapsed] = useState(false);
|
||||
const [clickedStep, setClickedStep] = useState(null);
|
||||
|
||||
const [statusColor, setStatusColor] = useState("black");
|
||||
|
||||
const [, , selectedDate1] = useContext(AppContext);
|
||||
|
||||
const [currentStep, setCurrentStep] = useState("تایید شهرستان");
|
||||
|
||||
useEffect(() => {
|
||||
let step = "تایید شهرستان";
|
||||
|
||||
if (
|
||||
caseData?.cityState?.state === "reject" ||
|
||||
caseData?.provinceState?.state === "reject"
|
||||
) {
|
||||
step = "درخواست رد شد";
|
||||
setStatusColor("red");
|
||||
} else {
|
||||
if (caseData?.cityState?.date) {
|
||||
step = "تایید شهرستان";
|
||||
}
|
||||
if (caseData?.provinceState?.date) {
|
||||
step = "تایید استان";
|
||||
}
|
||||
if (
|
||||
caseData?.provinceKillRequests?.provinceKillRequestSerializer?.length >
|
||||
0
|
||||
) {
|
||||
step = "تخصیص به خریدار";
|
||||
}
|
||||
if (
|
||||
caseData?.killHouseRequests?.killHouseRequestsSerializer?.length > 0
|
||||
) {
|
||||
step = "ایجاد بار";
|
||||
}
|
||||
if (
|
||||
caseData?.killHouseRequests?.killHouseRequestVetCheckSerializer
|
||||
?.length > 0
|
||||
) {
|
||||
step = "تخلیه بار";
|
||||
}
|
||||
if (
|
||||
caseData?.killHouseRequests?.killHouseRequestAssignmentSerializer
|
||||
?.length > 0
|
||||
) {
|
||||
step = "اطلاعات بار";
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentStep(step);
|
||||
}, [caseData]);
|
||||
|
||||
const componentRef = useRef();
|
||||
const printPDF = useReactToPrint({
|
||||
content: () => componentRef.current,
|
||||
documentTitle: `گزارش پرونده `,
|
||||
});
|
||||
|
||||
const setPdfOptions = () => {
|
||||
if (caseData) {
|
||||
printPDF();
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleCollapse = () => {
|
||||
setIsCollapsed(!isCollapsed);
|
||||
};
|
||||
|
||||
const stepClickedHandler = (step) => {
|
||||
setClickedStep(step);
|
||||
};
|
||||
|
||||
let clickedStepComponent;
|
||||
|
||||
switch (clickedStep) {
|
||||
case 1:
|
||||
clickedStepComponent = <TableCityLevel item={caseData} />;
|
||||
break;
|
||||
case 2:
|
||||
clickedStepComponent = <TableProvinceLevel item={caseData} />;
|
||||
break;
|
||||
case 3:
|
||||
clickedStepComponent = <TableSalughterAllocationLevel item={caseData} />;
|
||||
break;
|
||||
case 4:
|
||||
clickedStepComponent = <TableSlaughterAddCar item={caseData} />;
|
||||
break;
|
||||
case 5:
|
||||
clickedStepComponent = <TableSVetAcceptDischarge item={caseData} />;
|
||||
break;
|
||||
case 6:
|
||||
clickedStepComponent = <TableSlaughterInputBarData item={caseData} />;
|
||||
break;
|
||||
case 7:
|
||||
clickedStepComponent = <ProvinceCaseStepPaymentInformation />;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper>
|
||||
<Grid container direction="row" mb={2}>
|
||||
<div
|
||||
style={{
|
||||
width: "3%",
|
||||
background: caseData.out ? "rgb(255 123 123)" : "rgb(172 235 230)",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<Typography color={caseData?.out ? "white" : "grey"}>
|
||||
{pageIndex + caseIndex}.
|
||||
</Typography>
|
||||
<div
|
||||
style={{
|
||||
background: caseData.out
|
||||
? "rgb(255 123 123)"
|
||||
: "rgb(172 235 230)",
|
||||
writingMode: "vertical-rl",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
style={{
|
||||
background: "#2196f3",
|
||||
borderRadius: "10px",
|
||||
padding: "2px",
|
||||
color: "white",
|
||||
fontSize: "10px",
|
||||
}}
|
||||
>
|
||||
{caseData.out ? "خارج استان" : "داخل استان"}
|
||||
</Typography>
|
||||
</div>
|
||||
<div style={{ height: "10px" }}></div>
|
||||
</div>
|
||||
<div style={{ width: "97%" }}>
|
||||
<Grid
|
||||
style={{
|
||||
backgroundColor:
|
||||
caseIndex % 2 === 0 ? "white" : "rgb(247, 249, 250)",
|
||||
padding: "10px",
|
||||
cursor: "pointer",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<div style={{ visibility: "hidden", position: "absolute" }}>
|
||||
<ProvinceGetCaseFile
|
||||
ref={componentRef}
|
||||
item={caseData}
|
||||
inDate={selectedDate1}
|
||||
reportType={"slaughter"}
|
||||
/>
|
||||
</div>
|
||||
<Grid
|
||||
container
|
||||
onClick={handleToggleCollapse}
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
height="100px"
|
||||
>
|
||||
<Grid xs={2}>
|
||||
<Typography variant="body2">
|
||||
شماره سفارش: {caseData?.orderCode}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid xs={2}>
|
||||
<Typography variant="body2" color={statusColor}>
|
||||
نوع کشتار: {caseData?.freezing ? "انجماد" : "عادی"}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid xs={2}>
|
||||
<Typography variant="body2">
|
||||
تاریخ کشتار: {formatJustDate(caseData?.sendDate)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid xs={2}>
|
||||
<Typography variant="body2">
|
||||
مرغدار: {caseData?.poultry?.unitName}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid xs={2}>
|
||||
<Typography variant="body2" color={statusColor}>
|
||||
وضعیت: {currentStep}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid xs={1}>
|
||||
<Tooltip title="خروجی PDF">
|
||||
<IconButton
|
||||
aria-label="delete"
|
||||
color="success"
|
||||
onClick={setPdfOptions}
|
||||
>
|
||||
<BsFillFileEarmarkPdfFill size={25} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Collapse in={isCollapsed}>
|
||||
<Grid style={{ padding: "20px" }}>
|
||||
<ProvinceCaseOverview item={caseData} />
|
||||
<ProvinceCaseSteps
|
||||
stepClickedHandler={stepClickedHandler}
|
||||
item={caseData}
|
||||
/>
|
||||
{clickedStepComponent}
|
||||
</Grid>
|
||||
</Collapse>
|
||||
</div>
|
||||
</Grid>
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
290
src/features/province/components/province-cases/ProvinceCases.js
Normal file
290
src/features/province/components/province-cases/ProvinceCases.js
Normal file
@@ -0,0 +1,290 @@
|
||||
import {
|
||||
Button,
|
||||
Pagination,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment/moment";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import axios from "axios";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { ProvinceCasesItem } from "../province-cases-item/ProvinceCasesItem";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import { provinceGetCasesOverview } from "../../services/get-cases-overview";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
|
||||
export const ProvinceCases = () => {
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const [data, setData] = useState([]);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const { casesOverview } = useSelector((item) => item.provinceSlice);
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
setPage(1);
|
||||
dispatch(LOADING_START());
|
||||
const response = await axios.get(
|
||||
`poultry_requests_for_total_information/?date1=${selectedDate1}&date2=${selectedDate2}&search=filter&value=${
|
||||
textValue ? textValue : ""
|
||||
}&page=${page}&page_size=${perPage}&role=${getRoleFromUrl()}`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
dispatch(LOADING_END());
|
||||
};
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
const handleChangePage = (event, newPage) => {
|
||||
setPage(newPage + 1, fetchApiData(newPage + 1));
|
||||
};
|
||||
|
||||
// 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);
|
||||
// };
|
||||
const userKey = useSelector((state) => state.userSlice.userProfile.key);
|
||||
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
useEffect(() => {
|
||||
setPerPage(10);
|
||||
fetchApiData(1);
|
||||
dispatch(
|
||||
provinceGetCasesOverview({ date1: selectedDate1, date2: selectedDate2 })
|
||||
);
|
||||
}, [selectedDate1, selectedDate2]);
|
||||
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, []);
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
fetchApiData(1);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container p={SPACING.TINY} xs={12}>
|
||||
<Grid container alignItems="center" gap={SPACING.SMALL}>
|
||||
<Typography>روند پرونده ها</Typography>
|
||||
<Grid style={{ width: "150px" }}>
|
||||
<DatePicker
|
||||
label="از تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid style={{ width: "150px" }}>
|
||||
<DatePicker
|
||||
label="تا تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
{/* <form onSubmit={handleSubmit}> */}
|
||||
<TextField
|
||||
autoComplete="off"
|
||||
size="small"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
value={textValue}
|
||||
/>
|
||||
<Button
|
||||
// disabled={!textValue}
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
endIcon={<RiSearchLine />}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
{/* </form> */}
|
||||
<Tooltip title="خروجی اکسل">
|
||||
{/* <a
|
||||
href={`${axios.defaults.baseURL}poultry_request_report_excel/?start=${selectedDate1}&end=${selectedDate2}`}
|
||||
rel="noreferrer"
|
||||
> */}
|
||||
<Button
|
||||
color="success"
|
||||
onClick={() => {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
|
||||
severity: "success",
|
||||
});
|
||||
const link = `${
|
||||
axios.defaults.baseURL
|
||||
}poultry_request_report_excel/?start=${selectedDate1}&end=${selectedDate2}&role=${getRoleFromUrl()}&key=${userKey}`;
|
||||
window.location.href = link;
|
||||
}}
|
||||
>
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
{/* </a> */}
|
||||
</Tooltip>
|
||||
<Tooltip title="خروجی اکسل گزارش جامع">
|
||||
{/* <a
|
||||
href={`${axios.defaults.baseURL}detail_of_killing_excel/?date1=${selectedDate1}&date2=${selectedDate2}`}
|
||||
rel="noreferrer"
|
||||
> */}
|
||||
<Button
|
||||
color="warning"
|
||||
onClick={() => {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
|
||||
severity: "success",
|
||||
});
|
||||
const link = `${
|
||||
axios.defaults.baseURL
|
||||
}detail_of_killing_excel/?date1=${selectedDate1}&date2=${selectedDate2}&role=${getRoleFromUrl()}&key=${userKey}`;
|
||||
window.location.href = link;
|
||||
}}
|
||||
>
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
{/* </a> */}
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
<Grid width="100%" mt={SPACING.SMALL} isDashboard>
|
||||
<Grid container mb={2}>
|
||||
<ResponsiveTable
|
||||
title={"خلاصه اطلاعات"}
|
||||
noPagination
|
||||
isDashboard
|
||||
columns={[
|
||||
"تعداد پرونده ها",
|
||||
"تعداد مرغداران",
|
||||
"درخواست های کشتار (حجم)",
|
||||
"درخواست های کشتار (وزن)",
|
||||
"تعداد پرونده خارج از استان",
|
||||
"خارج استان (تعداد)",
|
||||
"خارج استان (وزن)",
|
||||
"تعداد تخصیصات",
|
||||
"تعداد بار",
|
||||
"تعداد خریداران",
|
||||
"تعداد بار دارای کد قرنطینه",
|
||||
"تعداد بار بدون کد قرنطینه",
|
||||
"تعداد بار تخلیه شده توسط دامپزشک",
|
||||
"تعداد بار تخلیه نشده توسط دامپزشک",
|
||||
"تعداد بار تکمیل شده توسط کشتارگاه",
|
||||
"تعداد بار تکمیل نشده توسط کشتارگاه",
|
||||
"جزئیات کامل",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
casesOverview?.poultryRequests?.toLocaleString(),
|
||||
casesOverview?.poultry?.toLocaleString(),
|
||||
casesOverview?.poultryRequestsQuantity?.toLocaleString(),
|
||||
casesOverview?.poultryRequestsWeight?.toLocaleString(),
|
||||
casesOverview?.outPoultryRequest?.toLocaleString(),
|
||||
parseInt(
|
||||
casesOverview?.outPoultryRequestQuantity
|
||||
)?.toLocaleString(),
|
||||
parseInt(
|
||||
casesOverview?.outPoultryRequestWeight
|
||||
)?.toLocaleString(),
|
||||
casesOverview?.provinceKillRequests?.toLocaleString(),
|
||||
casesOverview?.killHouseRequests?.toLocaleString(),
|
||||
casesOverview?.provinceKillRequestsBuyers?.toLocaleString(),
|
||||
casesOverview?.killHouseRequestsWithQuarantineCode?.toLocaleString(),
|
||||
casesOverview?.killHouseRequestsWithoutQuarantineCode?.toLocaleString(),
|
||||
casesOverview?.killHouseRequestsWithKillHouseVetAccepted?.toLocaleString(),
|
||||
casesOverview?.killHouseRequestsWithoutKillHouseVetAccepted?.toLocaleString(),
|
||||
casesOverview?.killHouseRequestsWithKillHouseAssignment?.toLocaleString(),
|
||||
casesOverview?.killHouseRequestsWithoutKillHouseAssignment?.toLocaleString(),
|
||||
<Button
|
||||
key="ss"
|
||||
color="warning"
|
||||
onClick={() => {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
|
||||
severity: "success",
|
||||
});
|
||||
const link = `${
|
||||
axios.defaults.baseURL
|
||||
}detail_of_killing_excel/?date1=${selectedDate1}&date2=${selectedDate2}&role=${getRoleFromUrl()}&key=${userKey}`;
|
||||
window.location.href = link;
|
||||
}}
|
||||
>
|
||||
<RiFileExcel2Fill size={30} />
|
||||
</Button>,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid alignItems="center" justifyContent="center">
|
||||
{data.map((item, i) => (
|
||||
<ProvinceCasesItem
|
||||
key={i}
|
||||
caseData={item}
|
||||
caseIndex={i}
|
||||
pageIndex={page !== 1 ? page * perPage - 9 : 1}
|
||||
data={data}
|
||||
/>
|
||||
))}
|
||||
{!!data?.length && (
|
||||
<Grid container justifyContent="center" mt={SPACING.SMALL}>
|
||||
<Pagination
|
||||
count={Math.ceil(totalRows / perPage)}
|
||||
page={page}
|
||||
variant="outlined"
|
||||
onChange={(event, newPage) => {
|
||||
handleChangePage(event, newPage - 1);
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,129 @@
|
||||
import { Button, TextField, Typography } from "@mui/material";
|
||||
import { useContext, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { provinceCheckChainAllocationService } from "../../services/province-check-chain-allocation";
|
||||
|
||||
export const ProvinceCheckChainAllocation = ({ item, fetchApiData }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [value, setValue] = useState("");
|
||||
|
||||
const handleChange = (event) => {
|
||||
setValue(event.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container direction="column">
|
||||
<Grid>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
اطلاعات مرغدار
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
نام: {item?.poultryHatching?.poultry?.unitName} (
|
||||
{item?.poultryHatching?.poultry?.user?.mobile})
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
شرکت زنجیره:{" "}
|
||||
{`${item?.chainCompany?.name} (${item?.chainCompany?.user.mobile})`}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
نوع تخصیص: {item?.outProvince ? "خارج استان" : "داخل استان"}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
خریدار:{" "}
|
||||
{item?.killHouse?.killHouseOperator?.user.fullname
|
||||
? `${item?.killHouse?.killHouseOperator?.user.fullname} (${item?.killHouse?.killHouseOperator?.user.mobile})`
|
||||
: `${item?.buyerName} (${item?.buyerMobile})`}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid container gap={SPACING.TINY} mt={SPACING.SMALL}>
|
||||
<TextField
|
||||
label="یادداشت"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
multiline
|
||||
rows={4}
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<Button
|
||||
style={{ flex: 0.5 }}
|
||||
variant="contained"
|
||||
color="success"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceCheckChainAllocationService({
|
||||
chain_allcation_key: item?.key,
|
||||
check_allocation: true,
|
||||
state: "accepted",
|
||||
})
|
||||
).then((r) => {
|
||||
fetchApiData(1);
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
تایید
|
||||
</Button>
|
||||
<Button
|
||||
style={{ flex: 0.5 }}
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceCheckChainAllocationService({
|
||||
chain_allcation_key: item?.key,
|
||||
check_allocation: true,
|
||||
state: "rejected",
|
||||
})
|
||||
).then((r) => {
|
||||
fetchApiData(1);
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
رد
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,407 @@
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
FormControlLabel,
|
||||
FormLabel,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import { SPACING } from "../../../../data/spacing";
|
||||
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
|
||||
import { provinceCheckFreeSaleService } from "../../services/province-check-free-sale";
|
||||
import { provinceGetFreeSalesRequestsService } from "../../services/province-get-free-sales-requests";
|
||||
import { useFormik } from "formik";
|
||||
import { Yup } from "../../../../lib/yup/yup";
|
||||
import { provinceEditFreeSaleService } from "../../services/province-edit-free-sale";
|
||||
import { useProvinceName } from "../../../../utils/getProvinceName";
|
||||
|
||||
export const ProvinceCheckFreeSale = ({
|
||||
buyer,
|
||||
poultryRequestKey,
|
||||
item,
|
||||
isEdit,
|
||||
}) => {
|
||||
const [, , selectedDate1, , selectedDate2] = useContext(AppContext);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
const [value, setValue] = useState("");
|
||||
const [payerValue, setPayerValue] = useState(
|
||||
isEdit ? item.payerType : "poultry"
|
||||
);
|
||||
const handleChange = (event) => {
|
||||
setValue(event.target.value);
|
||||
};
|
||||
|
||||
const provinceName = useProvinceName();
|
||||
|
||||
const handleChangePayer = (event) => {
|
||||
setPayerValue(event.target.value);
|
||||
if (event.target.value === "buyer") {
|
||||
formik.setFieldValue("mobile", buyer.mobile);
|
||||
} else {
|
||||
formik.setFieldValue("mobile", item.poultry.user.mobile);
|
||||
}
|
||||
};
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
mobile: item.poultry.user.mobile,
|
||||
weight: isEdit ? item?.IndexWeight : "",
|
||||
quantity: isEdit ? item?.quantity : "",
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
mobile: Yup.string()
|
||||
.required("شماره موبایل الزامی است")
|
||||
.min(11, "شماره موبایل باید 11 رقم باشد")
|
||||
.max(11, "شماره موبایل باید 11 رقم باشد")
|
||||
.matches(/^09\d{9}$/, "شماره موبایل باید با 09 شروع شود و 11 رقم باشد"),
|
||||
weight: Yup.number(),
|
||||
quantity: Yup.number(),
|
||||
}),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let newVal = formik.values.weight;
|
||||
const mystring = formik.values.weight.toString().split(".").join("");
|
||||
if (formik.values.weight) {
|
||||
if (mystring.length <= 3) {
|
||||
if (mystring.length === 2) {
|
||||
newVal = mystring[0] + "." + mystring[1];
|
||||
}
|
||||
if (mystring.length === 3) {
|
||||
newVal = mystring[0] + "." + mystring[1] + mystring[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isNaN(Number.parseFloat(newVal))) {
|
||||
formik.setFieldValue("weight", "");
|
||||
} else {
|
||||
formik.setFieldValue("weight", Number.parseFloat(newVal));
|
||||
}
|
||||
}, [formik.values.weight]);
|
||||
|
||||
let buyerType = "-";
|
||||
if (buyer.buyerType === "freezing") {
|
||||
buyerType = "انجماد";
|
||||
} else if (buyer.buyerType === "killer") {
|
||||
buyerType = "کشتارکن";
|
||||
} else if (buyer.buyerType === "killhouse") {
|
||||
buyerType = "کشتارگاه";
|
||||
}
|
||||
|
||||
const reg = new RegExp(/^09\d{9}$/);
|
||||
|
||||
return (
|
||||
<Grid container direction="column">
|
||||
<Grid>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
اطلاعات خریدار
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
نام: {buyer.firstName} {buyer.lastName}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
موبایل: {buyer.mobile}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
شهر: {buyer.city}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
استان: {buyer.province}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
ماهیت خریدار: {buyerType}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
{provinceName !== "hamedan" && (
|
||||
<>
|
||||
<FormControl>
|
||||
<FormLabel id="demo-controlled-radio-buttons-group">
|
||||
پرداخت کننده
|
||||
</FormLabel>
|
||||
<RadioGroup
|
||||
row
|
||||
aria-labelledby="demo-controlled-radio-buttons-group"
|
||||
name="controlled-radio-buttons-group"
|
||||
value={payerValue}
|
||||
onChange={handleChangePayer}
|
||||
>
|
||||
<FormControlLabel
|
||||
value="poultry"
|
||||
control={<Radio />}
|
||||
label="مرغدار"
|
||||
/>
|
||||
<FormControlLabel
|
||||
value="buyer"
|
||||
control={<Radio />}
|
||||
label="خریدار"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
mt={1}
|
||||
p={1}
|
||||
gap={1}
|
||||
style={{
|
||||
borderStyle: "solid",
|
||||
borderWidth: "2px",
|
||||
borderColor: "gray",
|
||||
borderRadius: "5px",
|
||||
}}
|
||||
>
|
||||
{payerValue === "poultry" ? (
|
||||
<Typography variant="body2" color="error">
|
||||
{!reg.test(item.poultry.user.mobile)
|
||||
? "فرمت تلفن مرغدار نادرست است! لطفا یک شماره موبایل معتبر وارد کنید."
|
||||
: "از این قسمت میتوانید تلفن مرغدار را ویرایش کنید."}
|
||||
</Typography>
|
||||
) : (
|
||||
<Typography variant="body2" color="error">
|
||||
{!reg.test(buyer.mobile)
|
||||
? "فرمت تلفن خریدار نادرست است! لطفا یک شماره موبایل معتبر وارد کنید."
|
||||
: "از این قسمت میتوانید تلفن خریدار را ویرایش کنید."}
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
id="mobile"
|
||||
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
|
||||
}
|
||||
label="موبایل"
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
{isEdit && (
|
||||
<Grid container xs={12} gap={1} mt={2}>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
id="quantity"
|
||||
fullWidth
|
||||
label="حجم (قطعه)"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%" }}
|
||||
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
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
id="weight"
|
||||
fullWidth
|
||||
label="میانگین وزن"
|
||||
variant="outlined"
|
||||
sx={{ width: "100%" }}
|
||||
value={formik.values.weight}
|
||||
error={
|
||||
formik.touched.weight ? Boolean(formik.errors.weight) : null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
helperText={
|
||||
formik.touched.weight && Boolean(formik.errors.weight)
|
||||
? formik.errors.weight
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<Grid container gap={SPACING.TINY} mt={SPACING.SMALL}>
|
||||
{!isEdit && (
|
||||
<TextField
|
||||
label="یادداشت"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
multiline
|
||||
rows={4}
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
)}
|
||||
{isEdit ? (
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={provinceName !== "hamedan" ? !formik.isValid : false}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceEditFreeSaleService({
|
||||
poultry_request_key: poultryRequestKey,
|
||||
payer_type: payerValue,
|
||||
buyer_mobile:
|
||||
payerValue === "buyer" ? formik.values.mobile : null,
|
||||
poultry_mobile:
|
||||
payerValue === "poultry" ? formik.values.mobile : null,
|
||||
Index_weight: formik.values.weight,
|
||||
quantity: parseInt(formik.values.quantity),
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(
|
||||
provinceGetFreeSalesRequestsService({
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
ویرایش
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
style={{ flex: 0.5 }}
|
||||
variant="contained"
|
||||
color="success"
|
||||
disabled={provinceName !== "hamedan" ? !formik.isValid : false}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceCheckFreeSaleService({
|
||||
poultry_request_key: poultryRequestKey,
|
||||
state: "accepted",
|
||||
message: value,
|
||||
payer_type: payerValue,
|
||||
buyer_mobile:
|
||||
payerValue === "buyer" ? formik.values.mobile : null,
|
||||
poultry_mobile:
|
||||
payerValue === "poultry" ? formik.values.mobile : null,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(
|
||||
provinceGetFreeSalesRequestsService({
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
تایید
|
||||
</Button>
|
||||
<Button
|
||||
style={{ flex: 0.5 }}
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
provinceCheckFreeSaleService({
|
||||
poultry_request_key: poultryRequestKey,
|
||||
state: "rejected",
|
||||
message: value,
|
||||
})
|
||||
).then((r) => {
|
||||
if (r.payload.error) {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: r.payload.error,
|
||||
severity: "error",
|
||||
});
|
||||
} else {
|
||||
dispatch(
|
||||
provinceGetFreeSalesRequestsService({
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
DRAWER({ right: false, bottom: false, content: null })
|
||||
);
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "عملیات با موفقیت انجام شد.",
|
||||
severity: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
رد
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,269 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Button, Checkbox, TextField, Tooltip } from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment";
|
||||
import { useDispatch } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { formatJustDate } from "../../../../utils/formatTime";
|
||||
import ToggleOffOutlinedIcon from "@mui/icons-material/ToggleOffOutlined";
|
||||
import ToggleOnIcon from "@mui/icons-material/ToggleOn";
|
||||
import { CheckCleanceCode } from "../../../../components/check-clearance-code/ChechClearanceCode";
|
||||
|
||||
export const ProvinceChickenDistributionsAndSalesDetails = () => {
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
const { unitkey, name, type } = useParams();
|
||||
const [withDate, setWithDate] = useState(false);
|
||||
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, []);
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const [data, setData] = useState([]);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const [page, setPage] = useState(1);
|
||||
const [tableData, setTableData] = useState([]);
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
let response;
|
||||
dispatch(LOADING_START());
|
||||
response = await axios.get(
|
||||
`https://rsibackend.rasadyar.com/app/${
|
||||
type === "Steward" ? "guilds-" : ""
|
||||
}transport-carcass-detail/?search=${textValue}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}&page=${page}&page_size=${perPage}&code=${unitkey}`
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
// const updateTable = () => {
|
||||
// fetchApiData(page !== 0 ? page : 1);
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
const d = data?.map((item, i) => {
|
||||
return [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
item?.productDate ? formatJustDate(item?.productDate) : "-",
|
||||
`${formatJustDate(item?.date)} (${item?.time?.slice(0, 5)})`,
|
||||
item?.out ? "خارج استان" : "داخل استان",
|
||||
item?.product,
|
||||
item?.quantity?.toLocaleString(),
|
||||
<CheckCleanceCode clearanceCode={item?.tracking || "-"} key={i} />,
|
||||
item?.origin,
|
||||
item?.originProvince,
|
||||
item?.originCity,
|
||||
item?.destination,
|
||||
item?.destinationProvince,
|
||||
item?.destinationCity,
|
||||
item?.driverName,
|
||||
item?.owner,
|
||||
item?.carTrackingCode,
|
||||
item?.plate,
|
||||
item?.unloading ? "تخلیه شده" : "در انتظار تخلیه",
|
||||
];
|
||||
});
|
||||
|
||||
setTableData(d);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, [dispatch, selectedDate1, selectedDate2, perPage, withDate]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`https://rsibackend.rasadyar.com/app/${
|
||||
type === "Steward" ? "guilds-" : ""
|
||||
}transport-carcass-detail/?search=${textValue}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}&page=${1}&page_size=${perPage}&code=${unitkey}`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
dispatch(LOADING_END());
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
gap={1}
|
||||
style={{
|
||||
borderStyle: "solid",
|
||||
borderWidth: "1px",
|
||||
padding: "5px",
|
||||
borderRadius: "15px",
|
||||
borderColor: "gray",
|
||||
justifyContent: "left",
|
||||
}}
|
||||
alignItems="center"
|
||||
>
|
||||
<Checkbox
|
||||
icon={<ToggleOffOutlinedIcon />}
|
||||
checkedIcon={<ToggleOnIcon />}
|
||||
checked={withDate}
|
||||
onChange={() => setWithDate(!withDate)}
|
||||
color="primary"
|
||||
size="large"
|
||||
/>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
disabled={!withDate}
|
||||
label="از تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
size="small"
|
||||
style={{ width: "160px" }}
|
||||
{...params}
|
||||
/>
|
||||
)}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
disabled={!withDate}
|
||||
label="تا تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
size="small"
|
||||
style={{ width: "160px" }}
|
||||
{...params}
|
||||
/>
|
||||
)}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
id="outlined-basic"
|
||||
size="small"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button
|
||||
// disabled={!textValue}
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
endIcon={<RiSearchLine />}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
</form>
|
||||
</Grid>
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<Button
|
||||
color="success"
|
||||
onClick={() => {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
|
||||
severity: "success",
|
||||
});
|
||||
const link = `https://rsibackend.rasadyar.com/app/${
|
||||
type === "Steward" ? "guilds-" : ""
|
||||
}transport-carcass-detail-excel/?search=${textValue}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}&code=${unitkey}`;
|
||||
window.location.href = link;
|
||||
}}
|
||||
>
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
{/* </a> */}
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
|
||||
<ResponsiveTable
|
||||
data={tableData}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"تاریخ توزیع",
|
||||
"تاریخ ثبت",
|
||||
"نوع بار",
|
||||
"محصول",
|
||||
"وزن",
|
||||
"کد قرنطینه",
|
||||
"فروشنده",
|
||||
"استان فروشنده",
|
||||
"شهر فروشنده",
|
||||
"خریدار",
|
||||
"استان خریدار",
|
||||
"شهر خریدار",
|
||||
"راننده",
|
||||
"مالک",
|
||||
"رهگیری خودرو",
|
||||
"پلاک خودرو",
|
||||
"وضعیت",
|
||||
]}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title={`توزیع / فروش گوشت ${name} `}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,437 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
Autocomplete,
|
||||
Button,
|
||||
Checkbox,
|
||||
IconButton,
|
||||
MenuItem,
|
||||
Select,
|
||||
TextField,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment";
|
||||
import { useDispatch } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { getSamasatProvinces } from "../../../../utils/getSamasatProvinces";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import {
|
||||
ROUTE_ADMINX_ROUTE_NATIONAL_INFO_SLAUGHTER,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_NATIONAL_INFO_SLAUGHTER,
|
||||
} from "../../../../routes/routes";
|
||||
import { ProvinceChickenDistributionsAndSalesDashboardService } from "../../services/province-chicken-distribution-and-sales-dashboard";
|
||||
import { formatTime } from "../../../../utils/formatTime";
|
||||
import ToggleOffOutlinedIcon from "@mui/icons-material/ToggleOffOutlined";
|
||||
import ToggleOnIcon from "@mui/icons-material/ToggleOn";
|
||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||
|
||||
export const ProvinceChickenDistributionsAndSales = () => {
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
const dispatch = useDispatch();
|
||||
const [selectedRole, setSelectedRole] = useState("KillHouse");
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, []);
|
||||
const [dashboardData, setDashboardData] = useState([]);
|
||||
const [withDate, setWithDate] = useState(false);
|
||||
const [openNotif] = useContext(AppContext);
|
||||
|
||||
const [selectedProvince, setSelectedProvince] = useState("");
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const [data, setData] = useState([]);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const [page, setPage] = useState(1);
|
||||
const [tableData, setTableData] = useState([]);
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
let response;
|
||||
getDashboardData();
|
||||
dispatch(LOADING_START());
|
||||
response = await axios.get(
|
||||
`https://rsibackend.rasadyar.com/app/transport-carcass-detail/?search=${textValue}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}&role=${selectedRole}&province=${selectedProvince}&page=${page}&page_size=${perPage}`
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
// const updateTable = () => {
|
||||
// fetchApiData(page !== 0 ? page : 1);
|
||||
// };
|
||||
|
||||
const getDashboardData = () => {
|
||||
dispatch(
|
||||
ProvinceChickenDistributionsAndSalesDashboardService({
|
||||
role: selectedRole,
|
||||
province: selectedProvince,
|
||||
date1: withDate ? selectedDate1 : null,
|
||||
date2: withDate ? selectedDate2 : null,
|
||||
})
|
||||
).then((r) => {
|
||||
setDashboardData(r.payload.data);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const d = data?.map((item, i) => {
|
||||
const distributonWeight =
|
||||
item?.info?.totalInputBarsWight + item?.info?.totalOutputBarsWight;
|
||||
return [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
item?.info?.role,
|
||||
item?.UnitName || item?.name,
|
||||
item?.PartIdCode || item?.jihadiCode,
|
||||
item?.Province || item?.province,
|
||||
item?.City || item?.city,
|
||||
"گوشت مرغ تازه",
|
||||
item?.info?.totalInputBuyBarsCount?.toLocaleString(),
|
||||
item?.info?.totalInputBuyBarsWight?.toLocaleString(),
|
||||
item?.info?.totalOutputBuyBarsCount?.toLocaleString(),
|
||||
item?.info?.totalOutputBuyBarsWight?.toLocaleString(),
|
||||
item?.info?.totalWareHouse?.toLocaleString(),
|
||||
distributonWeight?.toLocaleString(),
|
||||
"%" +
|
||||
(item?.info?.totalWareHouse
|
||||
? ((distributonWeight / item?.info?.totalWareHouse) * 100).toFixed(
|
||||
1
|
||||
)
|
||||
: 0),
|
||||
item?.info?.inputBars?.toLocaleString(),
|
||||
item?.info?.totalInputBarsWight?.toLocaleString(),
|
||||
"%" + item?.info?.totalInputBarsPercent?.toLocaleString(),
|
||||
item?.info?.totalOutputBarsWight?.toLocaleString(),
|
||||
"%" + item?.info?.totalOutputBarsPercent?.toLocaleString(),
|
||||
<IconButton
|
||||
key={i}
|
||||
color="success"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
window.open(
|
||||
getRoleFromUrl() === "AdminX"
|
||||
? `${ROUTE_ADMINX_ROUTE_NATIONAL_INFO_SLAUGHTER}/${
|
||||
selectedRole === "KillHouse"
|
||||
? item.PartIdCode
|
||||
: item?.jihadiCode
|
||||
}/${item?.UnitName || item?.name}/distribution`
|
||||
: `${ROUTE_SUPER_ADMIN_ROUTE_NATIONAL_INFO_SLAUGHTER}/${
|
||||
selectedRole === "KillHouse"
|
||||
? item.PartIdCode
|
||||
: item?.jihadiCode
|
||||
}/${item?.UnitName || item?.name}/distribution`,
|
||||
"_blank"
|
||||
);
|
||||
}}
|
||||
>
|
||||
<VisibilityIcon />
|
||||
</IconButton>,
|
||||
];
|
||||
});
|
||||
|
||||
setTableData(d);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, [
|
||||
dispatch,
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
perPage,
|
||||
selectedRole,
|
||||
selectedProvince,
|
||||
withDate,
|
||||
]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
getDashboardData();
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`https://rsibackend.rasadyar.com/app/transport-carcass-detail/?role=${selectedRole}&province=${selectedProvince}&search=${textValue}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}&page=${1}&page_size=${perPage}`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
dispatch(LOADING_END());
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const getProvinceList = () => {
|
||||
return [{ name: "همه" }, ...getSamasatProvinces()];
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
|
||||
<Grid container mt={2} mb={4} isDashboard xs={12}>
|
||||
<ResponsiveTable
|
||||
noPagination
|
||||
isDashboard
|
||||
columns={[
|
||||
"نقش",
|
||||
"تعداد",
|
||||
"محصول",
|
||||
"وزن خرید داخل استان",
|
||||
"وزن خرید خارج استان",
|
||||
"وزن کل انبار",
|
||||
"وزن کل توزیع",
|
||||
"درصد توزیع نسبت به انبار",
|
||||
"تعداد توزیع داخل استان",
|
||||
"وزن توزیع داخل استان",
|
||||
"درصد توزیع داخل استان",
|
||||
"تعداد توزیع خارج استان",
|
||||
"وزن توزیع خارج استان",
|
||||
"درصد توزیع خارج استان",
|
||||
"آخرین آپدیت",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
dashboardData?.role,
|
||||
selectedRole === "KillHouse"
|
||||
? dashboardData?.totalCountKillHouse?.toLocaleString()
|
||||
: dashboardData?.totalCountSteward?.toLocaleString(),
|
||||
dashboardData?.product,
|
||||
dashboardData?.totalInputBuyBarsWight?.toLocaleString(),
|
||||
dashboardData?.totalOutputBuyBarsWight?.toLocaleString(),
|
||||
dashboardData?.totalWareHouse?.toLocaleString(),
|
||||
(
|
||||
dashboardData?.totalInputBarsWight +
|
||||
dashboardData?.totalOutputBarsWight
|
||||
)?.toLocaleString(),
|
||||
dashboardData?.totalWareHouse
|
||||
? "%" +
|
||||
(dashboardData?.totalWareHouse
|
||||
? (
|
||||
((dashboardData?.totalInputBarsWight +
|
||||
dashboardData?.totalOutputBarsWight) /
|
||||
dashboardData?.totalWareHouse) *
|
||||
100
|
||||
).toFixed(1)
|
||||
: 0)
|
||||
: "",
|
||||
dashboardData?.inputBars?.toLocaleString(),
|
||||
dashboardData?.totalInputBarsWight?.toLocaleString(),
|
||||
dashboardData?.totalInputBarsPercent
|
||||
? "%" + dashboardData?.totalInputBarsPercent?.toLocaleString()
|
||||
: "",
|
||||
dashboardData?.outputBars?.toLocaleString(),
|
||||
dashboardData?.totalOutputBarsWight?.toLocaleString(),
|
||||
dashboardData?.totalOutputBarsPercent
|
||||
? "%" + dashboardData?.totalOutputBarsPercent?.toLocaleString()
|
||||
: "",
|
||||
dashboardData?.lastUpdate &&
|
||||
formatTime(dashboardData?.lastUpdate),
|
||||
],
|
||||
]}
|
||||
title={"خلاصه اطلاعات"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
>
|
||||
<Autocomplete
|
||||
sx={{ minWidth: "220px" }}
|
||||
size="small"
|
||||
disablePortal
|
||||
id="hatching"
|
||||
options={getProvinceList().map((i) => {
|
||||
return {
|
||||
label: i.name,
|
||||
};
|
||||
})}
|
||||
onChange={(event, value) => {
|
||||
if (value.label !== "همه") {
|
||||
setSelectedProvince(value.label);
|
||||
} else {
|
||||
setSelectedProvince("");
|
||||
}
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="انتخاب استان" />
|
||||
)}
|
||||
/>
|
||||
|
||||
<Select
|
||||
size="small"
|
||||
labelId="demo-simple-select-label"
|
||||
id="race"
|
||||
label="نژاد مرغ"
|
||||
value={selectedRole}
|
||||
onChange={(e) => {
|
||||
setSelectedRole(e.target.value);
|
||||
}}
|
||||
>
|
||||
<MenuItem value={"KillHouse"}>کشتارگاه</MenuItem>
|
||||
<MenuItem value={"Steward"}>مباشر</MenuItem>
|
||||
</Select>
|
||||
<Grid
|
||||
container
|
||||
gap={1}
|
||||
style={{
|
||||
borderStyle: "solid",
|
||||
borderWidth: "1px",
|
||||
padding: "5px",
|
||||
borderRadius: "15px",
|
||||
borderColor: "gray",
|
||||
justifyContent: "left",
|
||||
}}
|
||||
alignItems="center"
|
||||
>
|
||||
<Checkbox
|
||||
icon={<ToggleOffOutlinedIcon />}
|
||||
checkedIcon={<ToggleOnIcon />}
|
||||
checked={withDate}
|
||||
onChange={() => setWithDate(!withDate)}
|
||||
color="primary"
|
||||
size="large"
|
||||
/>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
disabled={!withDate}
|
||||
label="از تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
size="small"
|
||||
sx={{ width: { xs: "126px", md: "160px" } }}
|
||||
{...params}
|
||||
/>
|
||||
)}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
disabled={!withDate}
|
||||
label="تا تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
size="small"
|
||||
sx={{ width: { xs: "126px", md: "160px" } }}
|
||||
{...params}
|
||||
/>
|
||||
)}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
id="outlined-basic"
|
||||
size="small"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button
|
||||
// disabled={!textValue}
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
endIcon={<RiSearchLine />}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
</form>
|
||||
</Grid>
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<Button
|
||||
color="success"
|
||||
onClick={() => {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
|
||||
severity: "success",
|
||||
});
|
||||
const link = `https://rsibackend.rasadyar.com/app/transport-carcass-detail-excel/?search=${textValue}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}&role=${selectedRole}&province=${selectedProvince}`;
|
||||
window.location.href = link;
|
||||
}}
|
||||
>
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
{/* </a> */}
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
|
||||
<ResponsiveTable
|
||||
data={tableData}
|
||||
columns={[
|
||||
"ردیف",
|
||||
"نقش",
|
||||
"نام واحد",
|
||||
"شناسه یکتا",
|
||||
"استان",
|
||||
"شهرستان",
|
||||
"محصول",
|
||||
"تعداد خرید داخل استان",
|
||||
"وزن خرید داخل استان",
|
||||
"تعداد خرید خارج استان",
|
||||
"وزن خرید خارج استان",
|
||||
"وزن کل انبار",
|
||||
"وزن کل توزیع",
|
||||
"درصد توزیع نسبت به انبار",
|
||||
"تعداد توزیع داخل استان",
|
||||
"وزن توزیع داخل استان",
|
||||
"درصد توزیع داخل استان",
|
||||
"وزن توزیع خارج استان",
|
||||
"درصد توزیع خارج استان",
|
||||
"جزئیات",
|
||||
]}
|
||||
handlePageChange={handlePageChange}
|
||||
totalRows={totalRows}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
handlePerRowsChange={handlePerRowsChange}
|
||||
title="توزیع / فروش گوشت مرغ"
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,365 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
Autocomplete,
|
||||
Button,
|
||||
Checkbox,
|
||||
IconButton,
|
||||
TextField,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import moment from "moment";
|
||||
import { useDispatch } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
|
||||
import { AppContext } from "../../../../contexts/AppContext";
|
||||
import {
|
||||
LOADING_END,
|
||||
LOADING_START,
|
||||
} from "../../../../lib/redux/slices/appSlice";
|
||||
import { Grid } from "../../../../components/grid/Grid";
|
||||
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
|
||||
import { getSamasatProvinces } from "../../../../utils/getSamasatProvinces";
|
||||
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
|
||||
import {
|
||||
ROUTE_ADMINX_ROUTE_NATIONAL_INFO_SLAUGHTER,
|
||||
ROUTE_SUPER_ADMIN_ROUTE_NATIONAL_INFO_SLAUGHTER,
|
||||
} from "../../../../routes/routes";
|
||||
import { ProvinceStewardChickenDistributionsAndSalesDashboardService } from "../../services/province-chicken-distribution-and-sales-dashboard";
|
||||
import { formatTime } from "../../../../utils/formatTime";
|
||||
import ToggleOffOutlinedIcon from "@mui/icons-material/ToggleOffOutlined";
|
||||
import ToggleOnIcon from "@mui/icons-material/ToggleOn";
|
||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||
|
||||
export const ProvinceChickenStewardSales = () => {
|
||||
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
|
||||
useContext(AppContext);
|
||||
const dispatch = useDispatch();
|
||||
const [openNotif] = useContext(AppContext);
|
||||
useEffect(() => {
|
||||
const currentDate = moment(new Date()).format("YYYY-MM-DD");
|
||||
setSelectedDate1(currentDate);
|
||||
setSelectedDate2(currentDate);
|
||||
}, []);
|
||||
const [dashboardData, setDashboardData] = useState([]);
|
||||
const [withDate, setWithDate] = useState(false);
|
||||
|
||||
const [selectedProvince, setSelectedProvince] = useState("");
|
||||
|
||||
const handleTextChange = (event) => {
|
||||
setTextValue(event.target.value);
|
||||
};
|
||||
|
||||
const [data, setData] = useState([]);
|
||||
const [totalRows, setTotalRows] = useState(0);
|
||||
const [perPage, setPerPage] = useState(10);
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const [page, setPage] = useState(1);
|
||||
const [tableData, setTableData] = useState([]);
|
||||
|
||||
const fetchApiData = async (page) => {
|
||||
let response;
|
||||
getDashboardData();
|
||||
dispatch(LOADING_START());
|
||||
response = await axios.get(
|
||||
`https://rsibackend.rasadyar.com/app/guilds-transport-carcass-detail/?search=${textValue}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}&province=${selectedProvince}&page=${page}&page_size=${perPage}`
|
||||
);
|
||||
dispatch(LOADING_END());
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
fetchApiData(page);
|
||||
setPage(page);
|
||||
};
|
||||
|
||||
const handlePerRowsChange = (perRows) => {
|
||||
setPerPage(perRows);
|
||||
setPage(1);
|
||||
};
|
||||
|
||||
// const updateTable = () => {
|
||||
// fetchApiData(page !== 0 ? page : 1);
|
||||
// };
|
||||
|
||||
const getDashboardData = () => {
|
||||
dispatch(
|
||||
ProvinceStewardChickenDistributionsAndSalesDashboardService({
|
||||
province: selectedProvince,
|
||||
date1: withDate ? selectedDate1 : null,
|
||||
date2: withDate ? selectedDate2 : null,
|
||||
})
|
||||
).then((r) => {
|
||||
setDashboardData(r.payload.data);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const d = data?.map((item, i) => {
|
||||
return [
|
||||
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
|
||||
item?.info?.role,
|
||||
item?.name,
|
||||
item?.PartIdCode || item?.jihadiCode,
|
||||
item?.Province || item?.province,
|
||||
item?.City || item?.city,
|
||||
"گوشت مرغ تازه",
|
||||
item?.info?.totalInputBuyBarsCount?.toLocaleString(),
|
||||
item?.info?.totalInputBuyBarsWight?.toLocaleString(),
|
||||
item?.info?.totalOutputBuyBarsCount?.toLocaleString(),
|
||||
item?.info?.totalOutputBuyBarsWight?.toLocaleString(),
|
||||
item?.info?.totalWareHouse?.toLocaleString(),
|
||||
item?.info?.totalInputBuyBarsPercent?.toLocaleString(),
|
||||
item?.info?.totalOutputBuyBarsPercent?.toLocaleString(),
|
||||
|
||||
<IconButton
|
||||
key={i}
|
||||
color="success"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
window.open(
|
||||
getRoleFromUrl() === "AdminX"
|
||||
? `${ROUTE_ADMINX_ROUTE_NATIONAL_INFO_SLAUGHTER}/${item?.jihadiCode}/${item?.name}/Steward`
|
||||
: `${ROUTE_SUPER_ADMIN_ROUTE_NATIONAL_INFO_SLAUGHTER}/${item?.jihadiCode}/${item?.name}/Steward`,
|
||||
"_blank"
|
||||
);
|
||||
}}
|
||||
>
|
||||
<VisibilityIcon />
|
||||
</IconButton>,
|
||||
];
|
||||
});
|
||||
|
||||
setTableData(d);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiData(1);
|
||||
}, [
|
||||
dispatch,
|
||||
selectedDate1,
|
||||
selectedDate2,
|
||||
perPage,
|
||||
selectedProvince,
|
||||
withDate,
|
||||
]);
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
getDashboardData();
|
||||
dispatch(LOADING_START());
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`https://rsibackend.rasadyar.com/app/guilds-transport-carcass-detail/?&province=${selectedProvince}&search=${textValue}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}&page=${1}&page_size=${perPage}`
|
||||
);
|
||||
setData(response.data.results);
|
||||
setTotalRows(response.data.count);
|
||||
dispatch(LOADING_END());
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const getProvinceList = () => {
|
||||
return [{ name: "همه" }, ...getSamasatProvinces()];
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center" alignItems="center" gap={2}>
|
||||
<Grid container mt={2} mb={4} isDashboard xs={12}>
|
||||
<ResponsiveTable
|
||||
noPagination
|
||||
isDashboard
|
||||
columns={[
|
||||
"تعداد",
|
||||
"نقش",
|
||||
"محصول",
|
||||
"وزن خرید داخل استان",
|
||||
"وزن خرید خارج استان",
|
||||
"وزن کل خرید",
|
||||
"درصد خرید داخل استان",
|
||||
"درصد خرید خارج استان",
|
||||
"آخرین آپدیت",
|
||||
]}
|
||||
data={[
|
||||
[
|
||||
dashboardData?.totalCountGuild?.toLocaleString(),
|
||||
dashboardData?.role,
|
||||
dashboardData?.product,
|
||||
dashboardData?.totalInputBuyBarsWight?.toLocaleString(),
|
||||
dashboardData?.totalOutputBuyBarsWight?.toLocaleString(),
|
||||
dashboardData?.totalWareHouse?.toLocaleString(),
|
||||
dashboardData?.totalInputBuyBarsPercent?.toLocaleString(),
|
||||
dashboardData?.totalOutputBuyBarsPercent?.toLocaleString(),
|
||||
dashboardData?.lastUpdate &&
|
||||
formatTime(dashboardData?.lastUpdate),
|
||||
],
|
||||
]}
|
||||
title={"خلاصه اطلاعات"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
xs={12}
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
gap={2}
|
||||
>
|
||||
<Autocomplete
|
||||
sx={{ minWidth: "220px" }}
|
||||
size="small"
|
||||
disablePortal
|
||||
id="hatching"
|
||||
options={getProvinceList().map((i) => {
|
||||
return {
|
||||
label: i.name,
|
||||
};
|
||||
})}
|
||||
onChange={(event, value) => {
|
||||
if (value.label !== "همه") {
|
||||
setSelectedProvince(value.label);
|
||||
} else {
|
||||
setSelectedProvince("");
|
||||
}
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="انتخاب استان" />
|
||||
)}
|
||||
/>
|
||||
|
||||
<Grid
|
||||
container
|
||||
gap={1}
|
||||
style={{
|
||||
borderStyle: "solid",
|
||||
borderWidth: "1px",
|
||||
padding: "5px",
|
||||
borderRadius: "15px",
|
||||
borderColor: "gray",
|
||||
justifyContent: "left",
|
||||
}}
|
||||
alignItems="center"
|
||||
>
|
||||
<Checkbox
|
||||
icon={<ToggleOffOutlinedIcon />}
|
||||
checkedIcon={<ToggleOnIcon />}
|
||||
checked={withDate}
|
||||
onChange={() => setWithDate(!withDate)}
|
||||
color="primary"
|
||||
size="large"
|
||||
/>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
disabled={!withDate}
|
||||
label="از تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
size="small"
|
||||
sx={{ width: { xs: "126px", md: "160px" } }}
|
||||
{...params}
|
||||
/>
|
||||
)}
|
||||
value={selectedDate1}
|
||||
onChange={(e) => {
|
||||
setSelectedDate1(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<DatePicker
|
||||
disabled={!withDate}
|
||||
label="تا تاریخ"
|
||||
id="date"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
size="small"
|
||||
sx={{ width: { xs: "126px", md: "160px" } }}
|
||||
{...params}
|
||||
/>
|
||||
)}
|
||||
value={selectedDate2}
|
||||
onChange={(e) => {
|
||||
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
id="outlined-basic"
|
||||
size="small"
|
||||
label="جستجو"
|
||||
variant="outlined"
|
||||
style={{ width: 250 }}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<Button
|
||||
// disabled={!textValue}
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
endIcon={<RiSearchLine />}
|
||||
>
|
||||
جستجو
|
||||
</Button>
|
||||
</form>
|
||||
</Grid>
|
||||
<Tooltip title="خروجی اکسل">
|
||||
<Button
|
||||
color="success"
|
||||
onClick={() => {
|
||||
openNotif({
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
|
||||
severity: "success",
|
||||
});
|
||||
const link = `https://rsibackend.rasadyar.com/app/guilds-transport-carcass-detail-excel/?search=${textValue}${
|
||||
withDate ? `&date1=${selectedDate1}&date2=${selectedDate2}` : ``
|
||||
}&province=${selectedProvince}`;
|
||||
window.location.href = link;
|
||||
}}
|
||||
>
|
||||
<RiFileExcel2Fill size={32} />
|
||||
</Button>
|
||||
{/* </a> */}
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
|
||||
<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