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,387 @@
import {
Button,
Card,
IconButton,
List,
ListItemButton,
ListItemIcon,
ListItemText,
Popover,
Tooltip,
} from "@mui/material";
import { useContext, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
// import { slaughterGetCars } from "../../services/slaughter-get-cars";
// import { slaughterDeleteCar } from "../../services/slaughter-delete-car";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
// import { SlaughterNewCar } from "../slaughter-new-car/SlaughterNewCar";
// import { ProvinceRegisterCar } from "../province-register-car/ProvinceRegisterCar";
import { provinceGetCars } from "../../services/province-get-cars";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { ProvinceRegisterCarForm } from "../province-register-car-form/ProvinceRegisterCarForm";
import { provinceRemoveCar } from "../../services/province-remove-car";
import { AppContext } from "../../../../contexts/AppContext";
import { ProvinceAllocateCarsForm } from "../province-allocate-cars-form/ProvinceAllocateCarsForm";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { ManageCarState } from "../manage-car-state/ManageCarState";
import axios from "axios";
import { RiFileExcel2Fill } from "react-icons/ri";
import TuneIcon from "@mui/icons-material/Tune";
import LocalShippingIcon from "@mui/icons-material/LocalShipping";
import EditOutlinedIcon from "@mui/icons-material/EditOutlined";
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
import ResponsiveTable from "../../../../components/responsive-table/ResponsiveTable";
import { provinceCarsDashboardService } from "../../services/province-cars-dashboard";
import { checkPathStartsWith } from "../../../../utils/checkPathStartsWith";
export const ProvinceManageCars = () => {
const dispatch = useDispatch();
const [dataTable, setDataTable] = useState([]);
const [openNotif] = useContext(AppContext);
const { provinceCars } = useSelector((state) => state.provinceSlice);
// const userInfo = useSelector((state) => state.userSlice);
const userKey = useSelector((state) => state.userSlice.userProfile.key);
const selectedSubUser = useSelector(
(state) => state.userSlice.selectedSubUser
);
useEffect(() => {
dispatch(
provinceGetCars({
role_key: checkPathStartsWith("province")
? selectedSubUser?.key || ""
: "",
})
);
}, [selectedSubUser?.key]);
const [dashboardData, setDashboardData] = useState([]);
useEffect(() => {
dispatch(
provinceCarsDashboardService({
role_key: checkPathStartsWith("province")
? selectedSubUser?.key || ""
: "",
})
).then((r) => {
setDashboardData(r.payload.data);
});
}, [dispatch, provinceCars, selectedSubUser?.key]);
useEffect(() => {
const d = provinceCars?.map((item, i) => {
let carIdentity = "-";
if (item.type === "rental") {
carIdentity = "اجاره ای";
} else if (item.type === "exclusive") {
carIdentity = "اختصاصی";
}
// const handleDisable =
// getRoleFromUrl() === "ProvinceOperator" ||
// getRoleFromUrl() === "SuperAdmin" ||
// getRoleFromUrl() === "AdminX"
// ? false
// : true;
const killhouseList =
item.type === "rental"
? "همه کشتارگاه ها/کشتارکن ها"
: item?.killHouseList?.map((killHouse, index) => {
const separator =
index + 1 === item.killHouseList.length ? "" : " - ";
return killHouse?.killHouseName + separator;
});
return [
i + 1,
item.typeCar,
carIdentity,
item.pelak,
item.capocity,
parseInt(item.healthCode),
// Number(item.healthCode),
item.driverName,
item.driverMobile,
killhouseList,
<ManageCarState key={item.key} item={item} />,
<CarActions
key={`car-action-${item.key}`}
item={item}
openNotif={openNotif}
/>,
];
});
setDataTable(d);
}, [provinceCars, dispatch, openNotif]);
const [tableDataCol] = useState([
"ردیف",
"مدل خودرو",
"ماهیت",
"پلاک",
"ظرفیت",
"کد بهداشتی",
"نام راننده",
"موبایل راننده",
"کشتارگاه ها/کشتارکن ها",
"وضعیت",
"عملیات",
]);
return (
<>
<Grid
container
alignItems="center"
justifyContent="space-between"
gap={SPACING.SMALL}
xs={12}
>
<Button
variant="contained"
onClick={() => {
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
title: "افزودن خودرو",
content: <ProvinceRegisterCarForm />,
})
);
}}
>
افزودن خودرو
</Button>
<Tooltip title="خروجی اکسل">
<a
href={`${
axios.defaults.baseURL
}car_province_excel/?key=${userKey}&role=${getRoleFromUrl()}${
checkPathStartsWith("province")
? `&role_key=${selectedSubUser?.key}`
: ""
}`}
rel="noreferrer"
>
<Button color="success">
<RiFileExcel2Fill size={32} />
</Button>
</a>
</Tooltip>
<Card sx={{ width: "100%" }}>
<Grid container mt={2} mb={4} isDashboard xs={12}>
<ResponsiveTable
noPagination
isDashboard
columns={[
"تعداد خودرو ها",
"اختصاصی",
"اجاره ای",
"فعال",
"غیر فعال",
"معلق",
]}
data={[
[
dashboardData?.total?.toLocaleString(),
dashboardData?.exclusive?.toLocaleString(),
dashboardData?.rental?.toLocaleString(),
dashboardData?.active?.toLocaleString(),
dashboardData?.inactive?.toLocaleString(),
dashboardData?.suspended?.toLocaleString(),
],
]}
title={"خلاصه اطلاعات"}
/>
</Grid>
<ResponsiveTable
paginated
title="خودروها"
columns={tableDataCol}
data={dataTable}
/>
</Card>
</Grid>
</>
);
};
const CarActions = ({ item, openNotif }) => {
const dispatch = useDispatch();
const [anchorEl, setAnchorEl] = useState(null);
const handleDisable = !(
getRoleFromUrl() === "ProvinceOperator" ||
getRoleFromUrl() === "SuperAdmin" ||
getRoleFromUrl() === "AdminX"
);
const hasForbiddenKillhouse = item.killHouseList?.some(
(killItem) => !killItem.allowState
);
const hasAccess = !handleDisable || !hasForbiddenKillhouse;
const isRental = item.type === "rental";
const open = Boolean(anchorEl);
const id = open ? `province-cars-popover-${item.key}` : undefined;
const closePopover = () => setAnchorEl(null);
const handleAllocate = () => {
closePopover();
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
title: "تخصیص/حذف کشتارگاه",
content: (
<ProvinceAllocateCarsForm
driverKey={item.key}
killHouseList={item.killHouseList}
/>
),
})
);
};
const handleEdit = () => {
closePopover();
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
title: "ویرایش خودرو",
content: (
<ProvinceRegisterCarForm
first_name={item.firstName}
pelak={item.pelak}
city_name={item.city}
type_car={item.typeCar}
last_name={item.lastName}
capocity={item.capocity}
health_code={item.healthCode}
driver_mobile={item.driverMobile}
driverKey={item?.key}
type={item?.type}
/>
),
})
);
};
const handleDelete = () => {
closePopover();
dispatch(LOADING_START());
dispatch(provinceRemoveCar(item.key)).then((r) => {
if (r.error) {
if (r.error.message.includes("403")) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "امکان حذف بدلیل تخصیص بار فعال به خودرو وجود ندارد!",
severity: "error",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
}
} else {
dispatch(DRAWER({ right: false, bottom: false, content: null }));
dispatch(provinceGetCars());
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
dispatch(LOADING_END());
});
};
const actionsDisabled = !hasAccess || (handleDisable && isRental);
return (
<div>
<IconButton
aria-describedby={id}
color="primary"
size="small"
onClick={(event) => setAnchorEl(event.currentTarget)}
disabled={!hasAccess}
>
<TuneIcon />
</IconButton>
<Popover
id={id}
anchorEl={anchorEl}
open={open}
onClose={closePopover}
anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
transformOrigin={{ vertical: "top", horizontal: "left" }}
disableRestoreFocus
PaperProps={{ sx: { p: 2 } }}
>
<List sx={{ py: 0 }}>
<ListItemButton onClick={handleAllocate} disabled={actionsDisabled}>
<ListItemIcon>
<LocalShippingIcon
fontSize="small"
color={actionsDisabled ? "disabled" : "primary"}
/>
</ListItemIcon>
<ListItemText
primary="تخصیص به کشتارگاه"
primaryTypographyProps={{
variant: "body2",
color: actionsDisabled ? "text.secondary" : "primary",
}}
/>
</ListItemButton>
<ListItemButton onClick={handleEdit} disabled={actionsDisabled}>
<ListItemIcon>
<EditOutlinedIcon
fontSize="small"
color={actionsDisabled ? "disabled" : "primary"}
/>
</ListItemIcon>
<ListItemText
primary="ویرایش"
primaryTypographyProps={{
variant: "body2",
color: actionsDisabled ? "text.secondary" : "primary",
}}
/>
</ListItemButton>
<ListItemButton onClick={handleDelete} disabled={actionsDisabled}>
<ListItemIcon>
<DeleteOutlineIcon
fontSize="small"
color={actionsDisabled ? "disabled" : "error"}
/>
</ListItemIcon>
<ListItemText
primary="حذف"
primaryTypographyProps={{
variant: "body2",
color: actionsDisabled ? "text.secondary" : "error",
}}
/>
</ListItemButton>
</List>
</Popover>
</div>
);
};