announcement sort fix
This commit is contained in:
parent
efdbe2377c
commit
9ba77afd6e
@ -27,6 +27,7 @@ import {
|
|||||||
cilLocationPin,
|
cilLocationPin,
|
||||||
cilSettings,
|
cilSettings,
|
||||||
cilMoney,
|
cilMoney,
|
||||||
|
cilBell,
|
||||||
} from "@coreui/icons";
|
} from "@coreui/icons";
|
||||||
import { CNavGroup, CNavItem, CNavTitle, CTabContent } from "@coreui/react";
|
import { CNavGroup, CNavItem, CNavTitle, CTabContent } from "@coreui/react";
|
||||||
|
|
||||||
@ -196,6 +197,13 @@ const _nav = [
|
|||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: CNavItem,
|
||||||
|
name: "Announcement",
|
||||||
|
icon: <CIcon icon={cilBell} customClassName="nav-icon" />,
|
||||||
|
to: "/announcement",
|
||||||
|
group: "Inventory",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: CNavGroup,
|
component: CNavGroup,
|
||||||
name: "Settings",
|
name: "Settings",
|
||||||
|
@ -15,9 +15,9 @@ import { cibGmail } from "@coreui/icons";
|
|||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
|
|
||||||
const setupAxios = () => {
|
const setupAxios = () => {
|
||||||
// axios.defaults.baseURL = "http://localhost:5000";
|
axios.defaults.baseURL = "http://localhost:5000";
|
||||||
// axios.defaults.baseURL = "https://cheminova-api-2.onrender.com";
|
// axios.defaults.baseURL = "https://cheminova-api-2.onrender.com";
|
||||||
axios.defaults.baseURL = "https://api.cnapp.co.in";
|
// axios.defaults.baseURL = "https://api.cnapp.co.in";
|
||||||
|
|
||||||
axios.defaults.headers = {
|
axios.defaults.headers = {
|
||||||
"Cache-Control": "no-cache,no-store",
|
"Cache-Control": "no-cache,no-store",
|
||||||
|
@ -159,6 +159,8 @@ import DistributorStocks from "./views/RetailDistributors/DistributorStock";
|
|||||||
import AddMultiplerd from "./views/RetailDistributors/AddMultipleRD";
|
import AddMultiplerd from "./views/RetailDistributors/AddMultipleRD";
|
||||||
import AddMultipletm from "./views/TerritoryManager/AddMultipleTM";
|
import AddMultipletm from "./views/TerritoryManager/AddMultipleTM";
|
||||||
import AddMultiplesc from "./views/SalesCoOrdinators/AddMultipleSC";
|
import AddMultiplesc from "./views/SalesCoOrdinators/AddMultipleSC";
|
||||||
|
import Announcements from "./views/Announcment/announcement";
|
||||||
|
import CreateAnnouncement from "./views/Announcment/createAnnouncement";
|
||||||
const routes = [
|
const routes = [
|
||||||
//dashboard
|
//dashboard
|
||||||
|
|
||||||
@ -718,7 +720,19 @@ const routes = [
|
|||||||
navName: "Orders",
|
navName: "Orders",
|
||||||
},
|
},
|
||||||
//-------------- End Order Management Routes---------------------------------------
|
//-------------- End Order Management Routes---------------------------------------
|
||||||
|
// Announcement
|
||||||
|
{
|
||||||
|
path: "/announcement",
|
||||||
|
name: "Announcment",
|
||||||
|
element: Announcements,
|
||||||
|
navName: "Announcment",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/announcement/create",
|
||||||
|
name: "Announcment",
|
||||||
|
element: CreateAnnouncement,
|
||||||
|
navName: "Announcment",
|
||||||
|
},
|
||||||
//----------Point of sale orders Routes-----------------------
|
//----------Point of sale orders Routes-----------------------
|
||||||
|
|
||||||
// { path: "/order/:status/:id", name: "View Order", element: ViewOdr },
|
// { path: "/order/:status/:id", name: "View Order", element: ViewOdr },
|
||||||
|
162
src/views/Announcment/announcement.js
Normal file
162
src/views/Announcment/announcement.js
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TablePagination,
|
||||||
|
Paper,
|
||||||
|
Button,
|
||||||
|
Typography,
|
||||||
|
Skeleton,
|
||||||
|
} from "@mui/material";
|
||||||
|
import axios from "axios";
|
||||||
|
import { Box } from "@material-ui/core";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { isAutheticated } from "src/auth";
|
||||||
|
|
||||||
|
const Announcements = () => {
|
||||||
|
const [announcements, setAnnouncements] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [page, setPage] = useState(0);
|
||||||
|
const [rowsPerPage, setRowsPerPage] = useState(5);
|
||||||
|
const [totalAnnouncements, setTotalAnnouncements] = useState(0);
|
||||||
|
const token = isAutheticated();
|
||||||
|
|
||||||
|
const fetchAnnouncements = async (page, rowsPerPage) => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const response = await axios.get("/api/announcement/get", {
|
||||||
|
params: {
|
||||||
|
page: page + 1, // backend uses 1-based index
|
||||||
|
rowsPerPage,
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`, // if token is necessary for authorization
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log(response);
|
||||||
|
const { announcements, totalAnnouncements } = response.data;
|
||||||
|
setAnnouncements(announcements);
|
||||||
|
setTotalAnnouncements(totalAnnouncements);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching announcements", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchAnnouncements(page, rowsPerPage);
|
||||||
|
}, [page, rowsPerPage]);
|
||||||
|
|
||||||
|
const handleChangePage = (event, newPage) => {
|
||||||
|
setPage(newPage);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangeRowsPerPage = (event) => {
|
||||||
|
setRowsPerPage(parseInt(event.target.value, 10));
|
||||||
|
setPage(0); // Reset page to 0 when changing rows per page
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatAMPM = (dateString) => {
|
||||||
|
const date = new Date(dateString);
|
||||||
|
let hours = date.getHours();
|
||||||
|
let minutes = date.getMinutes();
|
||||||
|
const ampm = hours >= 12 ? "PM" : "AM";
|
||||||
|
hours = hours % 12 || 12;
|
||||||
|
minutes = minutes < 10 ? "0" + minutes : minutes;
|
||||||
|
return `${hours}:${minutes} ${ampm}`;
|
||||||
|
};
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box display={"flex"} mb={2}>
|
||||||
|
<Typography
|
||||||
|
flex={1}
|
||||||
|
textAlign={"center"}
|
||||||
|
fontWeight={"bold"}
|
||||||
|
variant="h4"
|
||||||
|
>
|
||||||
|
Announcements
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
onClick={() => navigate("/announcement/create")}
|
||||||
|
sx={{ textTransform: "none" }}
|
||||||
|
>
|
||||||
|
Add New{" "}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<TableContainer component={Paper}>
|
||||||
|
<Table>
|
||||||
|
<TableHead sx={{ fontWeight: "bold" }}>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>ID</TableCell>
|
||||||
|
<TableCell>Time</TableCell>
|
||||||
|
<TableCell>Sent to</TableCell>
|
||||||
|
<TableCell>Message</TableCell>
|
||||||
|
{/* <TableCell>Action</TableCell> */}
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{loading ? (
|
||||||
|
Array.from(new Array(rowsPerPage)).map((_, index) => (
|
||||||
|
<TableRow key={index}>
|
||||||
|
<TableCell colSpan={5}>
|
||||||
|
<Skeleton height={40} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : announcements.length > 0 ? (
|
||||||
|
announcements.map((announcement) => (
|
||||||
|
<TableRow key={announcement._id}>
|
||||||
|
<TableCell>{announcement.uniqueId}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{new Date(announcement.createdAt).toDateString()}
|
||||||
|
<span>, {formatAMPM(announcement.createdAt)}</span>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{announcement.sentTo.join(", ")}</TableCell>
|
||||||
|
<TableCell>{announcement.message}</TableCell>
|
||||||
|
{/* <TableCell>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
onClick={() =>
|
||||||
|
alert(`Viewing announcement ${announcement.id}`)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</Button>
|
||||||
|
</TableCell> */}
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={5} align="center">
|
||||||
|
<Typography variant="body1">Data not found</Typography>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
<TablePagination
|
||||||
|
rowsPerPageOptions={[5, 10, 25]}
|
||||||
|
component="div"
|
||||||
|
count={totalAnnouncements}
|
||||||
|
rowsPerPage={rowsPerPage}
|
||||||
|
page={page}
|
||||||
|
onPageChange={handleChangePage}
|
||||||
|
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||||
|
/>
|
||||||
|
</TableContainer>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Announcements;
|
168
src/views/Announcment/createAnnouncement.js
Normal file
168
src/views/Announcment/createAnnouncement.js
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import {
|
||||||
|
Checkbox,
|
||||||
|
Button,
|
||||||
|
TextField,
|
||||||
|
Container,
|
||||||
|
FormControlLabel,
|
||||||
|
Typography,
|
||||||
|
Box,
|
||||||
|
} from "@mui/material";
|
||||||
|
import axios from "axios";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { isAutheticated } from "src/auth";
|
||||||
|
// import { createAnnouncement } from './api'; // Assume this is the API call
|
||||||
|
|
||||||
|
const CreateAnnouncement = () => {
|
||||||
|
const [sendTo, setSendTo] = useState({
|
||||||
|
PDs: false,
|
||||||
|
RDs: false,
|
||||||
|
SCs: false,
|
||||||
|
TMs: false,
|
||||||
|
});
|
||||||
|
const [message, setMessage] = useState("");
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
const token = isAutheticated();
|
||||||
|
const handleCheckboxChange = (event) => {
|
||||||
|
setSendTo({ ...sendTo, [event.target.name]: event.target.checked });
|
||||||
|
};
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleSendAnnouncement = async () => {
|
||||||
|
if (!message || message.length > 250) {
|
||||||
|
setError("Message is required and should not exceed 250 characters.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
sentTo: Object.keys(sendTo).filter((role) => sendTo[role]),
|
||||||
|
message,
|
||||||
|
};
|
||||||
|
console.log("this is the send to and ", sendTo, message);
|
||||||
|
try {
|
||||||
|
const res = await axios.post(
|
||||||
|
"/api/announcement/create", // URL to your backend endpoint
|
||||||
|
{
|
||||||
|
sentTo: payload.sentTo, // assuming payload contains sentTo and message
|
||||||
|
message: payload.message,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`, // if token is necessary for authorization
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.status === 201) {
|
||||||
|
swal({
|
||||||
|
title: "Added",
|
||||||
|
text: "Announcement added successfully!",
|
||||||
|
icon: "success",
|
||||||
|
button: "ok",
|
||||||
|
});
|
||||||
|
navigate("/announcement");
|
||||||
|
} else {
|
||||||
|
swal({
|
||||||
|
text: "Something went wrong ",
|
||||||
|
icon: "error",
|
||||||
|
buttons: "ok",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
swal({
|
||||||
|
text: "Something went wrong ",
|
||||||
|
icon: "error",
|
||||||
|
buttons: "ok",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Typography variant="h4" mb={1}>
|
||||||
|
New Announcement
|
||||||
|
</Typography>
|
||||||
|
<Box sx={{ background: "#fff", borderRadius: "1rem", padding: "1rem" }}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={sendTo.PDs}
|
||||||
|
onChange={handleCheckboxChange}
|
||||||
|
name="PDs"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="PDs"
|
||||||
|
/>
|
||||||
|
<br />
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={sendTo.RDs}
|
||||||
|
onChange={handleCheckboxChange}
|
||||||
|
name="RDs"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="RDs"
|
||||||
|
/>
|
||||||
|
<br />
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={sendTo.SCs}
|
||||||
|
onChange={handleCheckboxChange}
|
||||||
|
name="SCs"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="SCs"
|
||||||
|
/>
|
||||||
|
<br />
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={sendTo.TMs}
|
||||||
|
onChange={handleCheckboxChange}
|
||||||
|
name="TMs"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="TMs"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<Typography fontWeight={"bold"} variant="h5">
|
||||||
|
Messgae
|
||||||
|
</Typography>
|
||||||
|
<TextField
|
||||||
|
label="Message"
|
||||||
|
value={message}
|
||||||
|
onChange={(e) => setMessage(e.target.value)}
|
||||||
|
multiline
|
||||||
|
rows={4}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
inputProps={{ maxLength: 250 }}
|
||||||
|
helperText={`${message.length}/250`}
|
||||||
|
/>
|
||||||
|
{error && <Typography color="error">{error}</Typography>}
|
||||||
|
<Box sx={{ marginTop: 2 }}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
sx={{ mr: "1rem" }}
|
||||||
|
onClick={handleSendAnnouncement}
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="secondary"
|
||||||
|
onClick={() => navigateBack()}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateAnnouncement;
|
Loading…
Reference in New Issue
Block a user