push rasad front on new repo

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

View File

@@ -0,0 +1,691 @@
import React, { useContext, useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import { useDispatch, useSelector } from "react-redux";
// import { provinceGetBuyersService } from "../../../province/services/province-get-buyers";
import {
Button,
IconButton,
List,
ListItemButton,
ListItemIcon,
ListItemText,
Popover,
TextField,
Tooltip,
Typography,
} from "@mui/material";
import {
CLOSE_MODAL,
DRAWER,
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../../../../lib/redux/slices/appSlice";
import moment from "moment";
import { AppContext } from "../../../../contexts/AppContext";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import axios from "axios";
import { DatePicker } from "@mui/x-date-pickers";
import { SlaughterAllocateToGuild } from "../slaughter-allocate-to-guild/SlaughterAllocateToGuild";
import { slaughterInventoryFinalSubmitService } from "../../services/slaughter-inventory-final-submit";
import { SPACING } from "../../../../data/spacing";
import { SlaughterManageInventoryAllocationOperations } from "../slaughter-manage-inventory-allocation-operations/SlaughterManageInventoryAllocationOperations";
import { formatJustDate, formatTime } from "../../../../utils/formatTime";
import { SlaughterAllocateForFreezing } from "../slaughter-allocate-for-freezing/SlaughterAllocateForFreezing";
import { RiFileExcel2Fill, RiSearchLine } from "react-icons/ri";
import { ROUTE_SLAUGHTER_DAILY_LIST } from "../../../../routes/routes";
import { useNavigate } from "react-router-dom";
import ShowImage from "../../../../components/show-image/ShowImage";
import { SlaughterSellCarcassInProvinceSubmitRegistrationCode } from "../slaughter-sell-carcass-in-province-submit-registration-code/SlaughterSellCarcassInProvinceSubmitRegistrationCode";
import { useProvinceName } from "../../../../utils/getProvinceName";
import { slaughterDeleteAllocatedService } from "../../services/salughter-delete-allocated";
import { fetchSlaughterBroadcastAndProducts } from "../../services/handle-fetch-slaughter-products";
import { slaughterResendStewardAllocationSmsService } from "../../services/slaughter-send-sms-steward-allocation-again";
import TuneIcon from "@mui/icons-material/Tune";
import DeleteIcon from "@mui/icons-material/Delete";
import SmsIcon from "@mui/icons-material/Sms";
import { getAllocationType } from "../../../../utils/getAllocationType";
import { checkPathStartsWith } from "../../../../utils/checkPathStartsWith";
export const ProvinceSellCarcassInProvince = ({ updateTable, priceInfo }) => {
const province = useProvinceName();
const userKey = useSelector((state) => state.userSlice.userProfile.key);
const selectedSubUser = useSelector(
(state) => state.userSlice.selectedSubUser
);
// const [killHouseTable, setKillHouseTable] = useState();
const { slaughterProducts } = useSelector((state) => state.slaughterSlice);
const dispatch = useDispatch();
const navigate = useNavigate();
//allocations ****************************************************************************************************************
const [, , selectedDate1, setSelectedDate1, selectedDate2, setSelectedDate2] =
useContext(AppContext);
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 [openNotif] = useContext(AppContext);
const fetchApiData = async (page) => {
dispatch(LOADING_START());
const response = await axios.get(
`steward-allocation/?search=filter&value=${textValue}&role=${getRoleFromUrl()}${
checkPathStartsWith("slaughter")
? `&role_key=${selectedSubUser?.key}`
: ""
}&date1=${selectedDate1}&date2=${selectedDate2}&page=${
page ? page : 1
}&page_size=${perPage}`
);
dispatch(LOADING_END());
setData(response.data.results);
setTotalRows(response.data.count);
};
const handlePageChange = (page) => {
fetchApiData(page);
setPage(page);
};
const getAllocationData = (item) => {
let type = `${item?.toKillHouse?.name} - ${item?.toKillHouse?.killHouseOperator?.user?.fullname} (${item?.toKillHouse?.killHouseOperator?.user?.mobile})`;
switch (item?.allocationType) {
case "killhouse_killhouse":
type = `${item?.toKillHouse?.name} - ${item?.toKillHouse?.killHouseOperator?.user?.fullname} (${item?.toKillHouse?.killHouseOperator?.user?.mobile})`;
break;
case "killhouse_steward":
type = `${item?.toStewards?.name} - ${item?.toStewards?.user?.fullname} (${item?.toStewards?.user?.mobile})`;
break;
case "killhouse_guild":
type = `${item?.toGuilds?.guildsName} - ${item?.toGuilds?.user?.fullname} (${item?.toGuilds?.user?.mobile})`;
break;
case "ColdHouse":
type = `${item?.toColdHouse?.name}`;
break;
default:
type = `${item?.toKillHouse?.name} - ${item?.toKillHouse?.killHouseOperator?.user?.fullname} (${item?.toKillHouse?.killHouseOperator?.user?.mobile})`;
break;
}
return type;
};
const handlePerRowsChange = (perRows) => {
setPerPage(perRows);
setPage(1);
};
useEffect(() => {
const d = data?.map((item, i) => {
return [
page === 1 ? i + 1 : i + perPage * (page - 1) + 1,
item?.date ? formatTime(item?.date) : "-",
item?.productionDate ? formatJustDate(item?.productionDate) : "-",
(item?.distributionType === "web"
? "سایت"
: item?.distributionType === "app"
? "موبایل"
: item?.distributionType === "pos"
? "پوز"
: item?.distributionType) || "-",
getAllocationType(item),
getAllocationData(item),
item?.interfaceNumber || "-",
item?.sellType === "exclusive" ? "اختصاصی" : "آزاد",
item?.amount?.toLocaleString() + " ریال",
item?.totalAmount?.toLocaleString() + " ریال",
item?.realNumberOfCarcasses?.toLocaleString(),
item?.realWeightOfCarcasses?.toLocaleString(),
item?.receiverRealNumberOfCarcasses?.toLocaleString(),
item?.receiverRealWeightOfCarcasses?.toLocaleString(),
item?.receiverState === "accepted" ? (
"تایید شده"
) : item?.loggedRegistrationCode ? (
item.loggedRegistrationCode
) : item?.registrationCode ? (
<SlaughterSellCarcassInProvinceSubmitRegistrationCode
key={i}
fetchApiData={fetchApiData}
item={item}
/>
) : (
"-"
),
item?.registrationCode ? "ارسال شده" : "ارسال نشده",
<ShowImage key={i} src={item.image} />,
item?.quota === "governmental"
? "دولتی"
: item?.quota === "free"
? "آزاد"
: "-",
item?.approvedPriceStatus ? "دولتی" : "آزاد",
item?.receiverState === "accepted" || item?.loggedRegistrationCode
? "تایید شده"
: item?.receiverState === "rejected"
? "رد شده"
: item?.activeExpireDateTime &&
!item?.loggedRegistrationCode &&
item?.registrationCode
? "در انتظار ورود کد احراز"
: "در انتظار تایید",
item?.receiverState === "pending" &&
item?.activeExpireDateTime &&
!item?.loggedRegistrationCode &&
item?.registrationCode ? (
<PendingOperationsPopover
key={`pending-ops-${item.key}`}
item={item}
fetchApiData={fetchApiData}
updateTable={updateTable}
/>
) : (
<SlaughterManageInventoryAllocationOperations
item={item}
key={i}
fetchApiData={fetchApiData}
priceInfo={priceInfo}
remainWeight={slaughterProducts[0]?.totalRemainWeight}
/>
),
];
});
setTableData(d);
}, [data]);
useEffect(() => {
fetchApiData(1);
}, [dispatch, selectedDate1, selectedDate2, perPage, selectedSubUser?.key]);
const PendingOperationsPopover = ({ item, fetchApiData, updateTable }) => {
const [anchorEl, setAnchorEl] = useState(null);
const open = Boolean(anchorEl);
const id = open ? `pending-popover-${item.key}` : undefined;
const handleOpen = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleDelete = () => {
dispatch(
OPEN_MODAL({
title: "آیا مطمئن هستید؟",
content: (
<Grid container spacing={2}>
<Grid item>
<Button
variant="contained"
color="error"
onClick={() => {
dispatch(
slaughterDeleteAllocatedService({
steward_allocation_key: item.key,
})
).then(() => {
dispatch(CLOSE_MODAL());
dispatch(
fetchSlaughterBroadcastAndProducts({
role_key: checkPathStartsWith("slaughter")
? selectedSubUser?.key
: "",
})
);
fetchApiData(1);
});
}}
>
تایید
</Button>
</Grid>
<Grid item>
<Button
onClick={() => {
dispatch(CLOSE_MODAL());
}}
>
لغو
</Button>
</Grid>
</Grid>
),
})
);
};
const handleResend = () => {
dispatch(
slaughterResendStewardAllocationSmsService({
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",
});
}
});
};
const options = [
{
key: "delete",
label: "حذف",
icon: DeleteIcon,
color: "error.main",
action: handleDelete,
},
{
key: "resend",
label: "ارسال مجدد کد",
icon: SmsIcon,
color: "primary.main",
action: handleResend,
},
];
return (
<Grid container justifyContent="center">
<IconButton
size="small"
color="primary"
aria-describedby={id}
onClick={handleOpen}
>
<TuneIcon />
</IconButton>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<List sx={{ minWidth: 160, p: 0.5 }}>
{options.map((option) => {
const IconComponent = option.icon;
return (
<ListItemButton
key={option.key}
onClick={() => {
handleClose();
option.action();
}}
sx={{
borderRadius: 1,
mb: 0.25,
py: 0.5,
"&:last-of-type": { mb: 0 },
}}
>
<ListItemIcon sx={{ minWidth: 32, color: option.color }}>
<IconComponent fontSize="small" />
</ListItemIcon>
<ListItemText
primary={option.label}
primaryTypographyProps={{
sx: {
color: option.color,
fontSize: "0.82rem",
fontWeight: 600,
},
}}
/>
</ListItemButton>
);
})}
</List>
</Popover>
</Grid>
);
};
const handleSubmit = async (event) => {
event.preventDefault();
dispatch(LOADING_START());
try {
const response = await axios.get(
`steward-allocation/?role=${getRoleFromUrl()}${
checkPathStartsWith("slaughter")
? `&role_key=${selectedSubUser?.key}`
: ""
}&search=filter&value=${textValue}&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);
}
};
//end allocations ****************************************************************************************************************
return (
<Grid container xs={12} justifyContent="center" alignItems="center">
<Grid container xs={12} my={2} gap={2}>
<Button
disabled={!slaughterProducts}
variant="contained"
onClick={() => {
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
title: "ثبت توزیع/ فروش درون استان",
size: {
xs: "100%",
// sm: "400px",
},
content: (
<SlaughterAllocateToGuild
updateTable={updateTable}
sellerType={"KillHouse"}
sellType="exclusive"
fetchApiData={fetchApiData}
priceInfo={priceInfo}
killHouseAllocation={true}
/>
),
})
);
}}
>
ثبت توزیع/ فروش
</Button>
<Button
disabled={!slaughterProducts}
variant="contained"
onClick={() => {
dispatch(
OPEN_MODAL({
title: "انتقال به سردخانه",
content: (
<SlaughterAllocateForFreezing
updateTable={updateTable}
sellerType={"KillHouse"}
sellType="free"
fetchApiData={fetchApiData}
priceInfo={priceInfo}
remainWeight={slaughterProducts[0]?.totalRemainWeight}
killHouseAllocation={false}
/>
),
})
);
}}
>
انتقال به سردخانه
</Button>
<Button
// disabled={!slaughterProducts}
disabled
variant="contained"
color="success"
onClick={() => {
navigate(ROUTE_SLAUGHTER_DAILY_LIST);
}}
>
لیست روزانه
</Button>
</Grid>
<Grid
container
xs={12}
justifyContent="center"
alignItems="center"
gap={2}
mt={4}
>
<Grid
container
xs={12}
justifyContent="start"
alignItems="center"
gap={2}
>
<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>
<DatePicker
label="تا تاریخ"
id="date"
renderInput={(params) => (
<TextField
style={{ width: "160px" }}
{...params}
size="small"
/>
)}
value={selectedDate2}
onChange={(e) => {
setSelectedDate2(moment(e).format("YYYY-MM-DD"));
}}
/>
</Grid>
<Grid>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button
// disabled={!textValue}
type="submit"
onClick={handleSubmit}
endIcon={<RiSearchLine />}
>
جستجو
</Button>
</form>
</Grid>
<Button
variant="outlined"
onClick={() => {
dispatch(
OPEN_MODAL({
title: "ثبت نهایی",
content: (
<Grid container gap={1}>
{province === "hamedan" ? (
<Grid container gap={SPACING.SMALL}>
<Typography color="error" variant="body2">
لطفاً توجه داشته باشید:
</Typography>
<Typography color="error" variant="body2">
درصورتیکه کد احراز ظرف مدت ۱۰ دقیقه وارد نشود،
ثبتنام شما بهطور خودکار حذف خواهد شد.
</Typography>
<Typography color="error" variant="body2">
درصورت استفاده از شماره واسط برای ثبت کد احراز،
مسئولیت صحت و تأیید شماره بر عهده کشتارگاه خواهد
بود.
</Typography>
</Grid>
) : (
<Typography>
در صورت ثبت نهایی انجام هیچگونه عملیاتی مانند حذف و
ویرایش امکان پذیر نمی باشد.
</Typography>
)}
<Grid
container
direction="column"
gap={SPACING.TINY}
width="100%"
>
<Button
fullWidth
variant="contained"
onClick={() => {
dispatch(
slaughterInventoryFinalSubmitService({
steward_allocation_list: data.map(
(item) => item.key
),
})
).then((r) => {
dispatch(CLOSE_MODAL());
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
updateTable();
fetchApiData(1);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
تایید
</Button>
<Button
fullWidth
color="error"
variant="contained"
onClick={() => {
dispatch(CLOSE_MODAL());
}}
>
لغو
</Button>
</Grid>
</Grid>
),
})
);
}}
>
تایید نهایی (یکجا)
</Button>
<Tooltip title="خروجی اکسل">
<Button
color="success"
onClick={() => {
openNotif({
vertical: "top",
horizontal: "center",
msg: "فایل اکسل در حال دانلود می باشد، این علمیات ممکن است زمان بر باشد لطفا صبر کنید.",
severity: "success",
});
const link = `${
axios.defaults.baseURL
}steward_allocation_excel/?role=${getRoleFromUrl()}${
checkPathStartsWith("slaughter")
? `&role_key=${selectedSubUser?.key}`
: ""
}&key=${userKey}&search=filter&value=${textValue}&date1=${selectedDate1}&date2=${selectedDate2}&trash=false&type=KillHouse"&kill_house_key=all"
}`;
window.location.href = link;
}}
>
<RiFileExcel2Fill size={32} />
</Button>
</Tooltip>
</Grid>
<ResponsiveTable
data={tableData}
columns={[
"ردیف",
"تاریخ توزیع",
"تاریخ تولید گوشت",
"ثبت شده",
"نوع تخصیص",
"مشخصات خریدار",
"شماره واسط",
"تخصیص",
"قیمت هر کیلو",
"قیمت کل",
"حجم تخصیصی",
"وزن تخصیصی",
"حجم تایید شده",
"وزن تایید شده",
"کداحراز",
"وضعیت کد احراز",
"سند",
"سهمیه",
"نوع فروش",
"وضعیت",
"عملیات",
]}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
title="تخصیصات صورت گرفته"
/>
</Grid>
</Grid>
);
};