Files
Rasadyar_FrontEnd/src/pages/TicketList.js

600 lines
19 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useContext, useEffect, useState } from "react";
import {
Box,
Button,
IconButton,
TextField,
Tooltip,
Typography,
} from "@mui/material";
import { useDispatch } from "react-redux";
import axios from "axios";
import { Grid } from "../components/grid/Grid";
import {
CLOSE_MODAL,
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../lib/redux/slices/appSlice";
import ResponsiveTable from "../components/responsive-table/ResponsiveTable";
import { getFaUserRole } from "../utils/getFaUserRole";
import { useNavigate } from "react-router-dom";
import persianDate from "persian-date";
import useUserProfile from "../features/authentication/hooks/useUserProfile";
import CommentsDisabledIcon from "@mui/icons-material/CommentsDisabled";
import { AppContext } from "../contexts/AppContext";
import { CloseTicketService } from "../features/ticket/services/create-ticket";
import personalTicketImage from "../../src/assets/images/Ticket1.png";
import publicTicketImage from "../../src/assets/images/ticket2.png";
import ClosedTicketImage from "../../src/assets/images/ClosedTicketImage.png";
const TicketList = () => {
const navigate = useNavigate();
const handleTextChange = (event) => {
setTextValue(event.target.value);
};
const [role] = useUserProfile();
const isAdmin = () => {
if (
role.includes("CityOperator") ||
role.includes("ProvinceOperator") ||
role.includes("AdminX") ||
role.includes("Supporter") ||
role.includes("SuperAdmin")
) {
return true;
} else {
return false;
}
};
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 [value, setValue] = useState("0");
const [selectedTicket, setSelectedTicket] = useState("0");
const [unreadMessages, setUnredMessages] = useState([]);
// const [ticketCounts, setTicketCounts] = useState({
// personal: 0,
// public: 0,
// closed: 0,
// });
// const handleChange = (event, newValue) => {
// setValue(newValue);
// };
const fetchApiData = async (page) => {
let response;
try {
dispatch(LOADING_START());
let query = `ticket/?search=filter&value=${textValue}&page=${page}&page_size=${perPage}`;
if (value === "0") query += `&type=single&status=open`;
else if (value === "1") query += `&type=public&status=open`;
else if (value === "2") query += `&status=closed`;
response = await axios.get(query);
dispatch(LOADING_END());
setData(response.data.results);
setTotalRows(response.data.count);
} catch {
dispatch(LOADING_END());
}
};
const dispatch = useDispatch();
const handlePageChange = (page) => {
fetchApiData(page);
setPage(page);
};
const handlePerRowsChange = (perRows) => {
setPerPage(perRows);
setPage(1);
};
const updateTable = () => {
fetchApiData(page !== 0 ? page : 1);
};
useEffect(() => {
fetchApiData(1);
}, [dispatch, perPage, value]);
useEffect(() => {
let unread = [];
const d = data?.map((item, i) => {
if (item?.unreadMessage) {
unread[i] = true;
} else {
unread[i] = false;
}
return [
page === 1 ? i + 1 : i + (perPage * page) / 2 + 1,
item?.ticketId,
item.typeTicket === "single" ? "شخصی" : "همگانی",
`${item?.role ? getFaUserRole(item?.role) : ""} (${
item?.user?.fullname
})`,
item?.title,
`${
item?.status === "open"
? `باز${item?.readOnly === true ? " (فقط خواندنی)" : ""}`
: item?.status === "answered"
? "پاسخ داده شده"
: "بسته"
}`,
item.toUser.length
? item?.toUser?.map(
(option, index) =>
`${option?.fullname} ${
index + 1 !== item?.toUser?.length ? " - " : ""
}`
)
: item?.toRole?.map(
(option, index) =>
`${getFaUserRole(option.name)} ${
index + 1 !== item?.toRole?.length ? " - " : ""
}`
),
`${new persianDate(new Date(item?.createDate)).format(
"dddd DD MMMM"
)} (${new Date(item?.createDate).toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
hour12: false,
})})`,
<Grid
xs={12}
container
justifyContent="center"
alignItems="center"
gap={1}
key={i}
>
<Button
onClick={() => {
navigate(`${item?.ticketId}/false`);
}}
>
مشاهده
</Button>
{isAdmin() && (
<Tooltip placement="left" title="بستن تیکت">
<IconButton
disabled={item?.status === "closed"}
color="error"
onClick={() => {
dispatch(
OPEN_MODAL({
title: "از بستن تیکت اطمینان دارید؟",
content: (
<Grid
container
justifyContent="center"
alignItems="center"
>
<Typography color="error" variant="caption">
در صورت بستن تیکت امکان باز کردن مجدد آن وجود ندارد!
</Typography>
<Grid
container
xs={12}
justifyContent="center"
alignItems="center"
mt={2}
gap={2}
>
<Button
variant="contained"
onClick={() => {
dispatch(
CloseTicketService({
ticket: item?.ticketId,
})
).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());
}
});
}}
>
تایید
</Button>
<Button
onClick={() => {
dispatch(CLOSE_MODAL());
}}
>
لغو
</Button>
</Grid>
</Grid>
),
})
);
}}
>
<CommentsDisabledIcon />
</IconButton>
</Tooltip>
)}
</Grid>,
];
});
setTableData(d);
setUnredMessages(unread);
}, [data]);
const handleSubmit = async (event) => {
event.preventDefault();
dispatch(LOADING_START());
try {
let query = `ticket/?search=filter&value=${textValue}&page=1&page_size=${perPage}`;
if (value === "0") query += `&type=single`;
else if (value === "1") query += `&type=public`;
else if (value === "2") query += `&status=closed`;
const response = await axios.get(query);
setData(response.data.results);
setTotalRows(response.data.count);
dispatch(LOADING_END());
} catch (error) {
console.error("Error fetching data:", error);
}
};
const handleTicketTypeSelect = (type) => {
setValue(type);
setSelectedTicket(type);
};
return (
<>
<Box display={"flex"} justifyContent="center">
<Grid
container
direction="column"
justifyContent="center"
xs={12}
sm={12}
md={10}
lg={10}
>
<Grid container direction="column" width="100%" gap={2} mb={2}>
<Box
display="flex"
justifyContent="flex-start"
width="100%"
sx={{
justifyContent: "start",
borderBottom: "1px solid #e2dbdb",
width: "100%",
pb: 1,
color: "#2D5FFF",
}}
>
<Typography sx={{ font_size: "16px" }}>تیکت های من </Typography>
</Box>
<Box display="flex" justifyContent="flex-start" width="100%">
<Button variant="contained" onClick={() => navigate(`noid/true`)}>
ثبت تیکت جدید
</Button>
</Box>
</Grid>
<Grid container xs={12} justifyContent="center" alignItems="center">
{/* <Tabs
value={value}
onChange={handleChange}
aria-label="secondary tabs example"
>
<Tab value="0" label="شخصی" />
<Tab value="1" label="همگانی" />
</Tabs> */}
</Grid>
<Grid
container
xs={12}
justifyContent="center"
alignItems="center"
mt={2}
>
<Grid
container
xs={12}
justifyContent="center"
alignItems="center"
gap={4}
>
<Grid
container
justifyContent="center"
direction="column"
style={{
cursor: "pointer",
}}
onClick={() => handleTicketTypeSelect("0")}
gap={1}
>
<Grid item>
<img
src={personalTicketImage}
alt="Personal Tickets"
width={70}
style={{
filter:
selectedTicket === "0"
? "saturate(100%) invert(22%) sepia(85%) saturate(746%) hue-rotate(200deg)"
: "none",
}}
/>
</Grid>
<Grid item>
<Typography variant="caption">تیکت های شخصی</Typography>
</Grid>
</Grid>
<Grid
container
justifyContent="center"
direction="column"
style={{
cursor: "pointer",
}}
onClick={() => handleTicketTypeSelect("1")}
gap={1}
>
<Grid item>
<img
src={publicTicketImage}
style={{
filter:
selectedTicket === "1"
? "saturate(100%) invert(22%) sepia(85%) saturate(746%) hue-rotate(200deg)"
: "none",
}}
alt="Public Tickets"
width={70}
/>
</Grid>
<Grid item>
<Typography variant="caption">تیکت های همگانی</Typography>
</Grid>
</Grid>
<Grid
container
justifyContent="center"
direction="column"
style={{ cursor: "pointer" }}
onClick={() => handleTicketTypeSelect("2")}
gap={1}
>
<Grid item>
<img
src={ClosedTicketImage}
alt="Closed Tickets"
width={70}
style={{
filter:
selectedTicket === "2"
? "saturate(100%) invert(22%) sepia(85%) saturate(746%) hue-rotate(200deg)"
: "none",
}}
/>
</Grid>
<Grid item>
<Typography variant="caption">تیکتهای بایگانی</Typography>
</Grid>
</Grid>
{/* <Grid>
<img src={closedTicketImage} alt="Closed Tickets" width={100} />
<Typography variant="caption">
تیکت های بسته شده: {ticketCounts.closed}
</Typography>
</Grid> */}
</Grid>
</Grid>
{value === "0" && (
<Grid container xs={12}>
<Grid
container
xs={12}
justifyContent="start"
alignItems="center"
gap={2}
mt={4}
>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button type="submit">جستجو</Button>
</form>
</Grid>
<Grid container xs={12}>
<ResponsiveTable
title="تیکت های شخصی"
columns={[
"ردیف",
"شماره تیکت",
"نوع تیکت",
"سازنده تیکت",
"عنوان",
"وضعیت",
"ارسال شده به",
"زمان ارسال",
"عملیات",
]}
allColors={{ color: "#142B73", text: "white" }}
customColors={[
{ name: "نوع تیکت", color: "#00B88A", text: "white" },
]}
data={tableData}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
activeRows={unreadMessages}
/>
</Grid>
</Grid>
)}
{value === "1" && (
<Grid container xs={12}>
<Grid
container
xs={12}
justifyContent="start"
alignItems="center"
gap={2}
mt={4}
>
<Button
variant="contained"
onClick={() => {
navigate(`noid/true`);
}}
>
ایجاد تیکت
</Button>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button type="submit">جستجو</Button>
</form>
</Grid>
<Grid container xs={12}>
<ResponsiveTable
title="تیکت های همگانی"
columns={[
"ردیف",
"شماره تیکت",
"نوع تیکت",
"سازنده تیکت",
"عنوان",
"وضعیت",
"ارسال شده به",
"زمان ارسال",
"عملیات",
]}
allColors={{ color: "#142B73", text: "white" }}
customColors={[
{ name: "نوع تیکت", color: "#00B88A", text: "white" },
]}
data={tableData}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
activeRows={unreadMessages}
/>
</Grid>
</Grid>
)}
{value === "2" && (
<Grid container xs={12}>
<Grid
container
xs={12}
justifyContent="start"
alignItems="center"
gap={2}
mt={4}
>
<form onSubmit={handleSubmit}>
<TextField
id="outlined-basic"
size="small"
label="جستجو"
variant="outlined"
style={{ width: 250 }}
onChange={handleTextChange}
/>
<Button type="submit">جستجو</Button>
</form>
</Grid>
<Grid container xs={12}>
<ResponsiveTable
title="تیکت‌های بایگانی‌شده"
columns={[
"ردیف",
"شماره تیکت",
"نوع تیکت",
"سازنده تیکت",
"عنوان",
"وضعیت",
"ارسال شده به",
"زمان ارسال",
"عملیات",
]}
allColors={{ color: "#142B73", text: "white" }}
customColors={[
{ name: "نوع تیکت", color: "#00B88A", text: "white" },
]}
data={tableData}
handlePageChange={handlePageChange}
totalRows={totalRows}
page={page}
perPage={perPage}
handlePerRowsChange={handlePerRowsChange}
activeRows={unreadMessages}
/>
</Grid>
</Grid>
)}
</Grid>
</Box>
</>
);
};
export default TicketList;