Files
sgeUpdated/sge-frontend/src/views/Notifications.js
Khaled Elagamy 85f1847070 Add 'sge-frontend/' from commit '5fa787e054b25ac53edc7ff0275ea7960a709401'
git-subtree-dir: sge-frontend
git-subtree-mainline: 876c278ac4
git-subtree-split: 5fa787e054
2025-08-04 00:27:23 +03:00

283 lines
8.5 KiB
JavaScript

import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { ChevronDown, Trash } from "react-feather";
import {
Card,
CardHeader,
CardTitle,
Input,
Label,
Row,
Col,
} from "reactstrap";
import DataTable from "react-data-table-component";
import ReactPaginate from "react-paginate";
import { useTranslation } from "react-i18next";
import {
getAllNotifications,
setNotificationRead,
notificationRemove,
} from "../redux/actions/notifications";
import { default as SweetAlert } from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
const Swal = withReactContent(SweetAlert);
const Notifications = () => {
const { t } = useTranslation();
const conditionalRowStyles = [
{
when: (row) => row.read === false,
style: {
backgroundColor: "#028a4a1a",
},
},
];
const serverSideColumns = [
{
name: t("Notifications.title"),
selector: (row) => row.title,
sortable: true,
maxWidth: "500px",
},
{
name: t("Notifications.notificationType"),
selector: (row) => row.notificationType,
sortable: true,
maxWidth: "500px",
},
{
name: t("Notifications.content"),
selector: (row) => row.message,
sortable: true,
maxWidth: "500px",
},
{
name: t("Time"),
selector: (row) => row.createdDateTime,
sortable: true,
width: "250px",
cell: (row) => (
<span>{new Date(row.createdDateTime).toLocaleString("tr-TR")}</span>
),
},
{
name: t("Cruds.delete"),
allowOverflow: false,
maxWidth: "100px",
cell: (row) => {
return (
<div className="d-flex">
<a onClick={() => handleDeleteNotification(row)}>
<Trash size={15} />
</a>
</div>
);
},
},
];
const dispatch = useDispatch();
const [currentPage, setCurrentPage] = useState(1);
const [rowsPerPage, setRowsPerPage] = useState(5);
const [searchValue, setSearchValue] = useState("");
const notificationsStore = useSelector((state) => state.notifications);
const [notifications, setNotifications] = useState([]);
useEffect(() => {
dispatch(getAllNotifications({ currentPage, rowsPerPage }));
}, [currentPage, rowsPerPage]);
useEffect(() => {
if (notificationsStore.notifications?.content) {
setNotifications(notificationsStore.notifications?.content);
}
}, [
notificationsStore.notifications?.content?.length,
notificationsStore.notifications,
]);
const handleFilter = (e) => {
setSearchValue(e.target.value);
if (e.target.value !== "") {
setCurrentPage(1);
setRowsPerPage(notificationsStore.notifications?.pageInfo?.totalElements);
setNotifications(
notificationsStore.notifications?.content.filter((notification) =>
notification.title
.toLowerCase()
.includes(e.target.value.toLowerCase())
)
);
} else {
setCurrentPage(1);
setRowsPerPage(5);
setNotifications(notificationsStore.notifications?.content);
}
};
const handlePagination = (page) => {
setCurrentPage(page.selected + 1);
setNotifications(notificationsStore.notifications?.content);
};
const handlePerPage = (e) => {
setCurrentPage(1);
setRowsPerPage(parseInt(e.target.value));
setNotifications(notificationsStore.notifications?.content);
};
const CustomPagination = () => {
const count = Number(
(
notificationsStore.notifications?.pageInfo?.totalElements / rowsPerPage
).toFixed(1)
);
return (
<ReactPaginate
previousLabel={""}
nextLabel={""}
breakLabel="..."
pageCount={count || 1}
marginPagesDisplayed={2}
pageRangeDisplayed={2}
activeClassName="active"
forcePage={currentPage !== 0 ? currentPage - 1 : 0}
onPageChange={(page) => handlePagination(page)}
pageClassName={"page-item"}
nextLinkClassName={"page-link"}
nextClassName={"page-item next"}
previousClassName={"page-item prev"}
previousLinkClassName={"page-link"}
pageLinkClassName={"page-link"}
breakClassName="page-item"
breakLinkClassName="page-link"
containerClassName={
"pagination react-paginate separated-pagination pagination-sm justify-content-end pr-1 mt-1"
}
/>
);
};
const handleDeleteNotification = async (selectedNotification) => {
const result = await Swal.fire({
title: `${t("Warnings.sureForDelete")}`,
text: t("Warnings.notUndone"),
icon: "warning",
showCancelButton: true,
confirmButtonText: t("Cruds.delete"),
cancelButtonText: t("Cruds.cancel"),
customClass: {
confirmButton: "btn btn-primary",
cancelButton: "btn btn-danger ml-1",
},
buttonsStyling: false,
});
if (result.value !== null && result.value === true) {
let selectedId = selectedNotification.id;
dispatch(notificationRemove({ selectedId, currentPage, rowsPerPage }));
}
//when notifications size is zero in current page and current page is not 1, change current page to previous page
if (notifications?.length == 1 && currentPage != 1) {
const newCurrentPage = currentPage - 1;
setCurrentPage(newCurrentPage);
dispatch(getAllNotifications({ currentPage, rowsPerPage }));
}
};
const ExpandableTable = ({ data }) => {
if (data.read === false) {
dispatch(setNotificationRead(data.id));
dispatch(getAllNotifications({ currentPage, rowsPerPage }));
}
return (
<div className="expandable-content p-2">
<p className="font-weight-bold">
{data?.title} / {data?.notificationType}
</p>
<p className="font-small-3 mt-2">{data.message}</p>
</div>
);
};
let listOfNumber = [5, 10, 25, 50, 75, 100];
return (
<div style={{ marginTop: "2%" }}>
<Card>
<CardHeader className="border-bottom">
<CardTitle tag="h4">{t("Notifications.notifications")}</CardTitle>
</CardHeader>
<Row className="mx-0 mt-1 mb-50">
<Col sm="6" md="2">
<div className="d-flex align-items-center">
<Label for="sort-select">{t("Show")}</Label>
<Input
className="ml-1 dataTable-select"
type="select"
id="sort-select"
value={rowsPerPage}
onChange={(e) => handlePerPage(e)}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={25}>25</option>
<option value={50}>50</option>
<option value={75}>75</option>
<option value={100}>100</option>
{!listOfNumber.includes(rowsPerPage) && (
<option value={rowsPerPage}>{rowsPerPage}</option>
)}
</Input>
</div>
</Col>
<Col
className="d-flex align-items-center justify-content-end mt-sm-0 mt-1 ml-md-auto"
sm="6"
md="3"
>
<Label className="mr-1" for="search-input">
{t("Filter")}
</Label>
<Input
className="dataTable-filter"
type="text"
bsSize="sm"
id="search-input"
value={searchValue}
onChange={handleFilter}
placeholder=""
/>
</Col>
</Row>
<DataTable
noHeader
pagination
paginationServer
className="react-dataTable"
columns={serverSideColumns}
conditionalRowStyles={conditionalRowStyles}
expandableRows
expandOnRowClicked
expandableRowsComponent={ExpandableTable}
sortIcon={<ChevronDown size={10} />}
paginationComponent={CustomPagination}
data={[...notifications]}
noDataComponent={
<p className="p-2">
{t("Notifications.notification")}
{t("Warnings.notFound")}
</p>
}
/>
</Card>
</div>
);
};
export default Notifications;