Merge branch 'master' of https://github.com/cheminova2024/cheminova-admin
This commit is contained in:
commit
9654247d77
12
src/_nav.js
12
src/_nav.js
@ -54,16 +54,16 @@ const _nav = [
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: "Products",
|
||||
icon: <CIcon icon={cilClipboard} customClassName="nav-icon" />,
|
||||
to: "/products",
|
||||
name: "Brands",
|
||||
icon: <CIcon icon={cilCat} customClassName="nav-icon" />,
|
||||
to: "/brands",
|
||||
group: "Product Management",
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: "GST",
|
||||
icon: <CIcon icon={cilTablet} customClassName="nav-icon" />,
|
||||
to: "/tax",
|
||||
name: "Products",
|
||||
icon: <CIcon icon={cilClipboard} customClassName="nav-icon" />,
|
||||
to: "/products",
|
||||
group: "Product Management",
|
||||
},
|
||||
],
|
||||
|
@ -42,10 +42,6 @@ import DeliveredOrders from "./views/orders/DeliveredOrders.js";
|
||||
import CancelledOrders from "./views/orders/CancelledOrders.js";
|
||||
import ReturnedOrders from "./views/orders/ReturnedOrders.js";
|
||||
import AddOrder from "./views/orders/AddOrder";
|
||||
//Taxes
|
||||
import Tax from "./views/configuration/tax/Tax";
|
||||
import Addtax from "./views/configuration/tax/Addtax";
|
||||
import Edittax from "./views/configuration/tax/Edittax";
|
||||
import EditOrder from "./views/orders/EditOrder";
|
||||
import ViewOrders from "./views/orders/ViewOrders";
|
||||
import Departures from "./views/Departures/Departures";
|
||||
@ -81,6 +77,7 @@ import AddNewAppointment from "./views/Appointments/AddNewAppointment";
|
||||
import Campaign from "./views/Campaigns/Campaign.js";
|
||||
import AddCampaign from "./views/Campaigns/AddCampaign.js";
|
||||
import Categories from "./views/Categories/categories";
|
||||
import Brands from "./views/Brands/Brands";
|
||||
import Content from "./views/Content/content";
|
||||
|
||||
import EditPrivacyPolicy from "./views/Content/editPrivacyPolicy";
|
||||
@ -199,6 +196,12 @@ const routes = [
|
||||
element: Categories,
|
||||
navName: "Product Management",
|
||||
},
|
||||
{
|
||||
path: "/brands",
|
||||
name: "Brands",
|
||||
element: Brands,
|
||||
navName: "Product Management",
|
||||
},
|
||||
//SalesCoOrdinator
|
||||
{
|
||||
path: "/salescoordinator/edit/:id",
|
||||
@ -287,25 +290,6 @@ const routes = [
|
||||
element: SingleUserleave,
|
||||
navName: "Leaves",
|
||||
},
|
||||
//Gst tax
|
||||
{
|
||||
path: "/tax",
|
||||
name: "Tax Rates",
|
||||
element: Tax,
|
||||
navName: "Product Management",
|
||||
},
|
||||
{
|
||||
path: "/tax/add",
|
||||
name: "Add Tax",
|
||||
element: Addtax,
|
||||
navName: "Product Management",
|
||||
},
|
||||
{
|
||||
path: "/tax/edit/:id",
|
||||
name: "Edit Tax",
|
||||
element: Edittax,
|
||||
navName: "Product Management",
|
||||
},
|
||||
// RetailDistributor
|
||||
{
|
||||
path: "/retail-distributor",
|
||||
|
460
src/views/Brands/Brands.js
Normal file
460
src/views/Brands/Brands.js
Normal file
@ -0,0 +1,460 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import axios from "axios";
|
||||
import { isAutheticated } from "src/auth";
|
||||
import {
|
||||
Button,
|
||||
Box,
|
||||
IconButton,
|
||||
Modal,
|
||||
Pagination,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import { ClipLoader } from "react-spinners";
|
||||
import swal from "sweetalert";
|
||||
|
||||
const style = {
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "background.paper",
|
||||
borderRadius: "0.5rem",
|
||||
boxShadow: 24,
|
||||
width: "500px",
|
||||
};
|
||||
|
||||
const Brands = () => {
|
||||
const token = isAutheticated();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [updating, setUpdating] = useState(true);
|
||||
const [saveLoding, setSaveLoading] = useState(true);
|
||||
const [edit, setEdit] = useState(false);
|
||||
const [brandName, setbrandName] = useState("");
|
||||
const [brandId, setbrandId] = useState("");
|
||||
const [brand, setbrand] = useState([]);
|
||||
const [itemPerPage, setItemPerPage] = useState(10);
|
||||
const [page, setPage] = useState(1);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [olderbrandName, setOlderBrandName] = useState("");
|
||||
|
||||
|
||||
const handleOpen = () => setOpen(true);
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
setEdit(false);
|
||||
setbrandName("");
|
||||
setbrandId("");
|
||||
};
|
||||
|
||||
const getBrands = async () => {
|
||||
try {
|
||||
const response = await axios.get("/api/brand/getBrands");
|
||||
if (response.status === 200) {
|
||||
setbrand(response.data.brands);
|
||||
setLoading(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch brands:", error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getBrands();
|
||||
}, []);
|
||||
|
||||
const handleEditClick = (_id, brandName) => {
|
||||
setOpen(true);
|
||||
setbrandName(brandName);
|
||||
setbrandId(_id);
|
||||
setOlderBrandName(brandName);
|
||||
setEdit(true);
|
||||
};
|
||||
|
||||
const handleUpdate = async () => {
|
||||
const filteredBrandNames = brand
|
||||
.filter((brand) => brand.brandName.toLowerCase() !== olderbrandName.toLowerCase())
|
||||
.map((brand) => brand.brandName.toLowerCase());
|
||||
|
||||
if (filteredBrandNames.includes(brandName.toLowerCase())) {
|
||||
swal("Warning", "Brand already exists", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!brandName) {
|
||||
swal("Warning", "Please fill all the required fields!", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
setUpdating(false);
|
||||
const formData = new FormData();
|
||||
formData.append("brandName", brandName);
|
||||
|
||||
try {
|
||||
await axios.patch(`/api/brand/update/${brandId}`, formData, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
handleClose();
|
||||
swal("Success", "The brand was updated successfully!", "success");
|
||||
getBrands();
|
||||
} catch (err) {
|
||||
swal("Error", "Failed to update brand", "error");
|
||||
} finally {
|
||||
setUpdating(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = (_id) => {
|
||||
swal({
|
||||
title: "Are you sure?",
|
||||
icon: "warning",
|
||||
buttons: {
|
||||
Yes: { text: "Yes", value: true },
|
||||
Cancel: { text: "Cancel", value: "cancel" },
|
||||
},
|
||||
}).then(async (value) => {
|
||||
if (value === true) {
|
||||
try {
|
||||
await axios.delete(`/api/brand/delete/${_id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
swal("Success", "The brand was deleted successfully!", "success");
|
||||
getBrands();
|
||||
} catch (err) {
|
||||
swal("Error", "Failed to delete brand", "error");
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleSavebrand = async () => {
|
||||
if (brand.some((brand) => brand.brandName.toLowerCase() === brandName.toLowerCase())) {
|
||||
swal("Warning", "Brand already exists.", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!brandName) {
|
||||
swal("Warning", "Please fill all the required fields!", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
setSaveLoading(false);
|
||||
const formData = new FormData();
|
||||
formData.append("brandName", brandName);
|
||||
|
||||
try {
|
||||
await axios.post("/api/brand/add", formData, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "multipart/formdata",
|
||||
},
|
||||
});
|
||||
handleClose();
|
||||
swal("Success", "New brand added successfully!", "success");
|
||||
getBrands();
|
||||
} catch (error) {
|
||||
swal("Error", "Failed to add brand", "error");
|
||||
} finally {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
};
|
||||
|
||||
const getPageCount = () => Math.max(1, Math.ceil(brand.length / itemPerPage));
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: "22px" }} className="fw-bold">
|
||||
Brands
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
onClick={handleOpen}
|
||||
// onClick={() => {
|
||||
// navigate("/testimonial/new", { replace: true });
|
||||
// }}
|
||||
>
|
||||
Add New brand
|
||||
</Button>
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Box sx={style}>
|
||||
<Box p={2} display={"flex"}>
|
||||
<Typography
|
||||
id="modal-modal-title"
|
||||
variant="body"
|
||||
component="h2"
|
||||
flex={1}
|
||||
>
|
||||
Brand Name
|
||||
</Typography>
|
||||
<IconButton onClick={() => handleClose()}>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<hr />
|
||||
<TextField
|
||||
placeholder="brand name"
|
||||
value={brandName}
|
||||
fullWidth
|
||||
inputProps={{
|
||||
maxLength: 25,
|
||||
}}
|
||||
style={{
|
||||
padding: "1rem",
|
||||
}}
|
||||
onChange={(e) =>
|
||||
setbrandName(
|
||||
e.target.value.charAt(0).toUpperCase() +
|
||||
e.target.value.slice(1)
|
||||
)
|
||||
}
|
||||
/>
|
||||
{brandName ? (
|
||||
<>
|
||||
<small className="charLeft mt-2 ml-3 fst-italic">
|
||||
{25 - brandName.length} characters left
|
||||
</small>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
|
||||
<Box
|
||||
p={2}
|
||||
display={"flex"}
|
||||
justifyContent={"right"}
|
||||
// width={"500px"}
|
||||
>
|
||||
{!edit && (
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
}}
|
||||
onClick={() => handleSavebrand()}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
<ClipLoader loading={!saveLoding} size={18} />
|
||||
{saveLoding && "Save"}
|
||||
</button>
|
||||
)}
|
||||
{edit && (
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
}}
|
||||
onClick={() => handleUpdate()}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
<ClipLoader loading={!updating} size={18} />
|
||||
{updating && "update"}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
style={{
|
||||
color: "black",
|
||||
marginRight: "1rem",
|
||||
background: "grey",
|
||||
}}
|
||||
onClick={() => setOpen(false)}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
<div className="col-sm-12 col-md-12">
|
||||
<div className="dataTables_length">
|
||||
<label className="w-100">
|
||||
Show
|
||||
<select
|
||||
style={{ width: "10%" }}
|
||||
onChange={(e) => setItemPerPage(e.target.value)}
|
||||
className="
|
||||
select-w
|
||||
custom-select custom-select-sm
|
||||
form-control form-control-sm
|
||||
"
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
entries
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
<table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{ border: "1px solid" }}
|
||||
>
|
||||
<thead
|
||||
className="thead-info"
|
||||
style={{ background: "rgb(140, 213, 213)" }}
|
||||
>
|
||||
<tr>
|
||||
|
||||
<th> Brand Name</th>
|
||||
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{!loading && brand.length === 0 && (
|
||||
<tr className="text-center">
|
||||
<td colSpan="6">
|
||||
<h5>No Data Available</h5>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td className="text-center" colSpan="6">
|
||||
Loading...
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
brand &&
|
||||
brand
|
||||
.slice(
|
||||
(`${page}` - 1) * itemPerPage,
|
||||
`${page}` * itemPerPage
|
||||
)
|
||||
.map((item, i) => (
|
||||
<tr key={i}>
|
||||
<td>
|
||||
<h5>{item.brandName} </h5>
|
||||
</td>
|
||||
<td className="text-start">
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
}}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
onClick={() =>
|
||||
handleEditClick(
|
||||
item._id,
|
||||
item.brandName,
|
||||
)
|
||||
}
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
background: "red",
|
||||
}}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
onClick={() => handleDelete(item._id)}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div style={{ display: "flex", justifyContent: "right" }}>
|
||||
<Pagination
|
||||
style={{ margin: "2rem" }}
|
||||
variant="outlined"
|
||||
size="large"
|
||||
count={getPageCount()}
|
||||
color="primary"
|
||||
onChange={(event, value) => setPage(value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Brands;
|
@ -13,8 +13,6 @@ import {
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import { ClipLoader } from "react-spinners";
|
||||
import swal from "sweetalert";
|
||||
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
|
||||
import DeleteSharpIcon from "@mui/icons-material/DeleteSharp";
|
||||
|
||||
const style = {
|
||||
position: "absolute",
|
||||
@ -31,20 +29,17 @@ const style = {
|
||||
const Categories = () => {
|
||||
const token = isAutheticated();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [updating, setUpdating] = useState(true); // for loading state
|
||||
// const [isUpdate, setIsUpdate] = useState(false); // for edit state
|
||||
const [updating, setUpdating] = useState(true);
|
||||
const [saveLoding, setSaveLoading] = useState(true);
|
||||
const [edit, setEdit] = useState(false);
|
||||
const [categoryName, setCategoryName] = useState("");
|
||||
const [categoryImage, setCategoryImage] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [categoryId, setCategoryId] = useState("");
|
||||
const [category, setCategory] = useState([]);
|
||||
const [itemPerPage, setItemPerPage] = useState(10);
|
||||
const [page, setPage] = useState(1);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [olderCategoryName, setOlderCategoruName] = useState("");
|
||||
const [olderImage, setOlderImage] = useState("");
|
||||
|
||||
|
||||
const handleOpen = () => setOpen(true);
|
||||
const handleClose = () => {
|
||||
@ -54,8 +49,6 @@ const Categories = () => {
|
||||
|
||||
setCategoryName("");
|
||||
setCategoryId("");
|
||||
setOlderImage("");
|
||||
setCategoryImage("");
|
||||
};
|
||||
|
||||
const getCategories = async () => {
|
||||
@ -71,47 +64,30 @@ const Categories = () => {
|
||||
setLoading(false);
|
||||
}
|
||||
} catch (error) {
|
||||
swal({
|
||||
title: error,
|
||||
text: " please login to access the resource ",
|
||||
icon: "error",
|
||||
button: "Retry",
|
||||
dangerMode: true,
|
||||
});
|
||||
console.error("Failed to fetch brands:", error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getCategories();
|
||||
}, [token]);
|
||||
}, []);
|
||||
|
||||
const handleEditClick = (_id, categoryName, categoryImage) => {
|
||||
const handleEditClick = (_id, categoryName) => {
|
||||
setOpen(true);
|
||||
setOlderImage(categoryImage);
|
||||
setCategoryName(categoryName);
|
||||
setCategoryId(_id);
|
||||
setOlderCategoruName(categoryName);
|
||||
setEdit(true);
|
||||
// setUpdating(false);
|
||||
};
|
||||
const categoryNamesArray = [];
|
||||
const setCategoryNamesArray = () => {
|
||||
category &&
|
||||
category.map((category) => {
|
||||
categoryNamesArray.push(category.categoryName.toLowerCase());
|
||||
});
|
||||
};
|
||||
setCategoryNamesArray();
|
||||
|
||||
const handleUpdate = () => {
|
||||
const filteredArrayNames = categoryNamesArray.filter(
|
||||
(item) => item !== olderCategoryName.toLowerCase()
|
||||
const handleUpdate = async () => {
|
||||
const filteredArrayNames = category.filter(
|
||||
(item) => item.categoryName.toLowerCase() !== olderCategoryName.toLowerCase())
|
||||
.map((item) => item.categoryName.toLowerCase()
|
||||
);
|
||||
console.log(filteredArrayNames, "filter");
|
||||
const categoryExits = filteredArrayNames.includes(
|
||||
categoryName.toLowerCase()
|
||||
);
|
||||
if (categoryExits) {
|
||||
// console.log(filteredArrayNames, "filter");
|
||||
if(filteredArrayNames.includes(categoryName.toLowerCase())){
|
||||
swal({
|
||||
title: "Warning",
|
||||
text: "Category already exists ",
|
||||
@ -119,10 +95,8 @@ const Categories = () => {
|
||||
button: "Retry",
|
||||
dangerMode: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!categoryName || (!categoryImage && !olderImage)) {
|
||||
if (!categoryName) {
|
||||
swal({
|
||||
title: "Warning",
|
||||
text: "Please fill all the required fields!",
|
||||
@ -135,45 +109,32 @@ const Categories = () => {
|
||||
setUpdating(false);
|
||||
const formData = new FormData();
|
||||
formData.append("categoryName", categoryName);
|
||||
|
||||
formData.append("categoryImage", categoryImage);
|
||||
|
||||
formData.append("olderImage", JSON.stringify(olderImage));
|
||||
|
||||
axios
|
||||
try{
|
||||
await axios
|
||||
.patch(`/api/category/update/${categoryId}`, formData, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
// setUpdating(true);
|
||||
// setIsUpdate(false);
|
||||
handleClose();
|
||||
setCategoryId("");
|
||||
setCategoryName("");
|
||||
setCategoryImage("");
|
||||
setOlderImage("");
|
||||
setUpdating(true);
|
||||
setEdit(false);
|
||||
swal({
|
||||
title: "Congratulations!!",
|
||||
text: "The category was updated successfully!",
|
||||
icon: "success",
|
||||
button: "OK",
|
||||
});
|
||||
// getCategories(); // Refresh the category list after updating
|
||||
})
|
||||
.catch((err) => {
|
||||
getCategories();
|
||||
}catch(err){
|
||||
swal({
|
||||
title: "Sorry, please try again",
|
||||
text: err,
|
||||
title: "",
|
||||
text: "Something went wrong!",
|
||||
icon: "error",
|
||||
button: "Retry",
|
||||
dangerMode: true,
|
||||
});
|
||||
}finally{
|
||||
setUpdating(true);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = (_id) => {
|
||||
@ -184,24 +145,23 @@ const Categories = () => {
|
||||
Yes: { text: "Yes", value: true },
|
||||
Cancel: { text: "Cancel", value: "cancel" },
|
||||
},
|
||||
}).then((value) => {
|
||||
}).then(async (value) => {
|
||||
if (value === true) {
|
||||
axios
|
||||
try {
|
||||
await axios
|
||||
.delete(`/api/category/delete/${_id}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
});
|
||||
swal({
|
||||
title: "Congratulations!!",
|
||||
text: "The category was deleted successfully!",
|
||||
icon: "success",
|
||||
button: "OK",
|
||||
});
|
||||
// getCategories(); // Refresh the category list after deleting
|
||||
})
|
||||
.catch((err) => {
|
||||
getCategories();
|
||||
}catch(err) {
|
||||
swal({
|
||||
title: "",
|
||||
text: "Something went wrong!",
|
||||
@ -209,26 +169,22 @@ const Categories = () => {
|
||||
button: "Retry",
|
||||
dangerMode: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}});
|
||||
};
|
||||
|
||||
const handleSaveCategory = async () => {
|
||||
const categoryExits = categoryNamesArray.includes(
|
||||
categoryName.toLowerCase()
|
||||
);
|
||||
if (categoryExits) {
|
||||
if(category.some((item) => item.categoryName.toLowerCase() === categoryName.toLowerCase())){
|
||||
swal({
|
||||
title: "Warning",
|
||||
text: "Category Already exits.",
|
||||
text: "Category already exists ",
|
||||
icon: "error",
|
||||
button: "Retry",
|
||||
dangerMode: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!categoryName || !categoryImage) {
|
||||
if (!categoryName) {
|
||||
swal({
|
||||
title: "Warning",
|
||||
text: "Please fill all the required fields!",
|
||||
@ -242,59 +198,38 @@ const Categories = () => {
|
||||
setLoading(true);
|
||||
const formData = new FormData();
|
||||
formData.append("categoryName", categoryName);
|
||||
formData.append("categoryImage", categoryImage);
|
||||
|
||||
axios
|
||||
try{
|
||||
await axios
|
||||
.post("/api/category/add", formData, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "multipart/formdata",
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status === 201) {
|
||||
setOpen(false);
|
||||
setLoading(false);
|
||||
setSaveLoading(true);
|
||||
setCategoryName("");
|
||||
setCategoryImage("");
|
||||
setOlderImage("");
|
||||
handleClose();
|
||||
swal({
|
||||
title: "Added",
|
||||
text: "New category added successfully!",
|
||||
title: "Congratulations!!",
|
||||
text: "The category was added successfully!",
|
||||
icon: "success",
|
||||
button: "OK",
|
||||
});
|
||||
// getCategories(); // Refresh the category list after adding
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
setSaveLoading(true);
|
||||
getCategories();
|
||||
}catch(err){
|
||||
swal({
|
||||
title: error,
|
||||
text: "something went wrong",
|
||||
title: "",
|
||||
text: "Something went wrong!",
|
||||
icon: "error",
|
||||
button: "Retry",
|
||||
dangerMode: true,
|
||||
});
|
||||
});
|
||||
}finally{
|
||||
setSaveLoading(true);
|
||||
}
|
||||
};
|
||||
const getPageCount = () => {
|
||||
return Math.max(1, Math.ceil(category.length / itemPerPage));
|
||||
};
|
||||
|
||||
const handleFileChange = (e) => {
|
||||
const files = e.target.files[0];
|
||||
|
||||
// Check file types and append to selectedFiles
|
||||
const allowedTypes = ["image/jpeg", "image/png", "image/jpg"];
|
||||
if (allowedTypes.includes(files.type)) {
|
||||
setCategoryImage(files);
|
||||
}
|
||||
};
|
||||
const handeldeleteImage = () => {
|
||||
setCategoryImage("");
|
||||
};
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
@ -377,111 +312,6 @@ const Categories = () => {
|
||||
<></>
|
||||
)}
|
||||
|
||||
<Box
|
||||
style={{
|
||||
padding: "1rem",
|
||||
}}
|
||||
>
|
||||
<label htmlFor="upload-Image">
|
||||
<TextField
|
||||
style={{
|
||||
display: "none",
|
||||
width: "350px",
|
||||
height: "350px",
|
||||
borderRadius: "10%",
|
||||
}}
|
||||
fullWidth
|
||||
id="upload-Image"
|
||||
type="file"
|
||||
accept=".jpg , .png ,.jpeg"
|
||||
label="file"
|
||||
variant="outlined"
|
||||
onChange={(e) => handleFileChange(e)}
|
||||
/>
|
||||
<Box
|
||||
style={{ borderRadius: "10%" }}
|
||||
sx={{
|
||||
margin: "1rem 0rem",
|
||||
cursor: "pointer",
|
||||
width: "140px",
|
||||
height: "140px",
|
||||
border: "2px solid grey",
|
||||
// borderRadius: '50%',
|
||||
|
||||
"&:hover": {
|
||||
background: "rgba(112,112,112,0.5)",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<CloudUploadIcon
|
||||
style={{
|
||||
color: "grey",
|
||||
margin: "auto",
|
||||
fontSize: "5rem",
|
||||
}}
|
||||
fontSize="large"
|
||||
/>
|
||||
</Box>
|
||||
</label>
|
||||
{categoryImage && (
|
||||
<Box>
|
||||
<img
|
||||
src={URL.createObjectURL(categoryImage)}
|
||||
alt="categoryImage"
|
||||
style={{
|
||||
width: 100,
|
||||
height: 100,
|
||||
borderRadius: "1rem",
|
||||
marginLeft: "1rem",
|
||||
}}
|
||||
/>
|
||||
<DeleteSharpIcon
|
||||
onClick={() => handeldeleteImage()}
|
||||
fontSize="small"
|
||||
sx={{
|
||||
color: "white",
|
||||
position: "absolute",
|
||||
cursor: "pointer",
|
||||
padding: "0.2rem",
|
||||
background: "black",
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{olderImage && (
|
||||
<Box>
|
||||
<img
|
||||
src={olderImage?.secure_url}
|
||||
alt="categoryImage"
|
||||
style={{
|
||||
width: 100,
|
||||
height: 100,
|
||||
borderRadius: "1rem",
|
||||
marginLeft: "1rem",
|
||||
}}
|
||||
/>
|
||||
<DeleteSharpIcon
|
||||
onClick={() => setOlderImage("")}
|
||||
fontSize="small"
|
||||
sx={{
|
||||
color: "white",
|
||||
position: "absolute",
|
||||
cursor: "pointer",
|
||||
padding: "0.2rem",
|
||||
background: "black",
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{error && <p style={{ color: "red" }}>{error}</p>}
|
||||
<p className="pt-1 pl-2 text-secondary">
|
||||
Upload jpg, jpeg and png only*
|
||||
</p>
|
||||
|
||||
<Box
|
||||
p={2}
|
||||
display={"flex"}
|
||||
@ -593,9 +423,8 @@ const Categories = () => {
|
||||
style={{ background: "rgb(140, 213, 213)" }}
|
||||
>
|
||||
<tr>
|
||||
<th> Image</th>
|
||||
|
||||
<th> Categories Name</th>
|
||||
<th> Category Name</th>
|
||||
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
@ -623,15 +452,6 @@ const Categories = () => {
|
||||
)
|
||||
.map((item, i) => (
|
||||
<tr key={i}>
|
||||
<td>
|
||||
<img
|
||||
className="me-2"
|
||||
src={item?.categoryImage?.secure_url}
|
||||
width="40"
|
||||
alt=""
|
||||
/>
|
||||
<h5>{ } </h5>
|
||||
</td>
|
||||
<td>
|
||||
<h5>{item.categoryName} </h5>
|
||||
</td>
|
||||
@ -653,7 +473,6 @@ const Categories = () => {
|
||||
handleEditClick(
|
||||
item._id,
|
||||
item.categoryName,
|
||||
item.categoryImage
|
||||
)
|
||||
}
|
||||
>
|
||||
|
@ -166,113 +166,6 @@ const Inventory = () => {
|
||||
</div>
|
||||
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
{/* <table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{ border: "1px solid" }}
|
||||
>
|
||||
<thead
|
||||
className="thead-light"
|
||||
style={{ background: "#ecdddd" }}
|
||||
>
|
||||
<tr>
|
||||
<th className="text-start">ID</th>
|
||||
<th className="text-start">Date</th>
|
||||
<th className="text-start">Time</th>
|
||||
<th className="text-start">Trade Name</th>
|
||||
<th className="text-start">PD/RD</th>
|
||||
<th className="text-start">Product SKU</th>
|
||||
<th className="text-start">Product Name</th>
|
||||
<th className="text-start">Sale</th>
|
||||
<th className="text-start">Inventory</th>
|
||||
<th className="text-start">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td className="text-center" colSpan="10">
|
||||
Loading...
|
||||
</td>
|
||||
</tr>
|
||||
) : inventoryData.length > 0 ? (
|
||||
inventoryData.map((entry, i) =>
|
||||
entry.products.map((product, j) => (
|
||||
<tr key={`${i}-${j}`}>
|
||||
<td className="text-start">{entry.uniqueId}</td>
|
||||
<td className="text-start">
|
||||
{new Date(entry.createdAt).toLocaleString(
|
||||
"en-IN",
|
||||
{
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</td>
|
||||
<td className="text-start">
|
||||
{new Date(entry.createdAt).toLocaleString(
|
||||
"en-IN",
|
||||
{
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
hour12: true,
|
||||
}
|
||||
)}
|
||||
</td>
|
||||
<td className="text-start">
|
||||
{entry.tradeName}
|
||||
</td>
|
||||
<td className="text-start">
|
||||
{entry.designation}
|
||||
</td>
|
||||
<td className="text-start">{product.SKU}</td>
|
||||
<td className="text-start">
|
||||
{product.ProductName}
|
||||
</td>
|
||||
<td className="text-start">{product.Sale}</td>
|
||||
<td className="text-center">
|
||||
{product.Inventory}
|
||||
</td>
|
||||
<td className="text-start">
|
||||
<Link
|
||||
to={`/inventory/view/${entry.id}`}
|
||||
state={{ product }}
|
||||
>
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
}}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
)
|
||||
) : (
|
||||
!loading &&
|
||||
filteredData.length === 0 && (
|
||||
<tr className="text-center">
|
||||
<td colSpan="10">
|
||||
<h5>No Data Available...</h5>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
</tbody>
|
||||
</table> */}
|
||||
|
||||
<table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{
|
||||
@ -478,7 +371,6 @@ const Inventory = () => {
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
<div className="row mt-20">
|
||||
<div className="col-sm-12 col-md-6 mb-20">
|
||||
|
@ -198,6 +198,7 @@ const AddMultiplePd = () => {
|
||||
<table className="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>uniqueId</th>
|
||||
<th>Principal Distributor Name</th>
|
||||
<th>Email</th>
|
||||
<th>Phone</th>
|
||||
@ -208,11 +209,12 @@ const AddMultiplePd = () => {
|
||||
<tbody>
|
||||
{newlyCreated.map((distributor, index) => (
|
||||
<tr key={index}>
|
||||
<td>{distributor.name || "N/A"}</td>
|
||||
<td>{distributor.email || "N/A"}</td>
|
||||
<td>{distributor.phone || "N/A"}</td>
|
||||
<td>{distributor.panNumber || "N/A"}</td>
|
||||
<td>{distributor.gstNumber || "N/A"}</td>
|
||||
<td>{distributor?.distributor?.uniqueId || "N/A"}</td>
|
||||
<td>{distributor?.distributor?.name || "N/A"}</td>
|
||||
<td>{distributor?.distributor?.email || "N/A"}</td>
|
||||
<td>{distributor?.distributor?.phone || "N/A"}</td>
|
||||
<td>{distributor?.address?.panNumber || "N/A"}</td>
|
||||
<td>{distributor?.address?.gstNumber || "N/A"}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
@ -8,6 +8,8 @@ import {
|
||||
FormHelperText,
|
||||
Autocomplete,
|
||||
CircularProgress,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
} from "@mui/material";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { toast } from "react-hot-toast";
|
||||
@ -21,6 +23,7 @@ const AddPrincipalDistributor = () => {
|
||||
|
||||
const [user, setUser] = useState({
|
||||
PD_ID: "",
|
||||
SBU: "",
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
@ -165,11 +168,22 @@ const AddPrincipalDistributor = () => {
|
||||
Add Principal Distributor
|
||||
</Typography>
|
||||
<form onSubmit={handleFormSubmit}>
|
||||
<Typography variant="h6" sx={{ mb: 2 }}>
|
||||
<Typography variant="h5" sx={{ mb: 2 }}>
|
||||
Basic Information
|
||||
</Typography>
|
||||
<Grid container spacing={2} sx={{ mb: 2 }}>
|
||||
<Grid item xs={6}>
|
||||
{/* Principal Distributor ID */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="PD_ID"
|
||||
className="form-label"
|
||||
>
|
||||
Principal Distributor ID*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="PD_ID"
|
||||
required
|
||||
@ -177,12 +191,49 @@ const AddPrincipalDistributor = () => {
|
||||
fullWidth
|
||||
name="PD_ID"
|
||||
value={user.PD_ID}
|
||||
label="Principal Distributor ID"
|
||||
variant="outlined"
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
</Grid>
|
||||
|
||||
{/* Principal Distributor SBU */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="SBU"
|
||||
className="form-label"
|
||||
>
|
||||
SBU*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="SBU"
|
||||
required
|
||||
type="text"
|
||||
fullWidth
|
||||
name="SBU"
|
||||
value={user.SBU}
|
||||
variant="outlined"
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* Name */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="name"
|
||||
className="form-label"
|
||||
>
|
||||
Name*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="name"
|
||||
required
|
||||
@ -190,12 +241,24 @@ const AddPrincipalDistributor = () => {
|
||||
fullWidth
|
||||
name="name"
|
||||
value={user.name}
|
||||
label="Name"
|
||||
variant="outlined"
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
</Grid>
|
||||
|
||||
{/* Email */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="email"
|
||||
className="form-label"
|
||||
>
|
||||
Email*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="email"
|
||||
required
|
||||
@ -203,12 +266,24 @@ const AddPrincipalDistributor = () => {
|
||||
fullWidth
|
||||
name="email"
|
||||
value={user.email}
|
||||
label="Email"
|
||||
variant="outlined"
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
</Grid>
|
||||
|
||||
{/* Phone Number */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="phone"
|
||||
className="form-label"
|
||||
>
|
||||
Phone Number*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="phone"
|
||||
required
|
||||
@ -216,18 +291,29 @@ const AddPrincipalDistributor = () => {
|
||||
fullWidth
|
||||
name="phone"
|
||||
value={user.phone}
|
||||
label="Phone Number"
|
||||
variant="outlined"
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Typography variant="h6" sx={{ mb: 2 }}>
|
||||
<Typography variant="h5" sx={{ mb: 2 }}>
|
||||
Business Details
|
||||
</Typography>
|
||||
<Grid container spacing={2} sx={{ mb: 2 }}>
|
||||
<Grid item xs={12} sm={4}>
|
||||
{/* PAN Number */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="panNumber"
|
||||
className="form-label"
|
||||
>
|
||||
PAN Number*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="panNumber"
|
||||
required
|
||||
@ -235,12 +321,24 @@ const AddPrincipalDistributor = () => {
|
||||
fullWidth
|
||||
name="panNumber"
|
||||
value={data.panNumber}
|
||||
label="PAN Number"
|
||||
variant="outlined"
|
||||
onChange={handleDataChange}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
</Grid>
|
||||
|
||||
{/* Trade Name */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="tradeName"
|
||||
className="form-label"
|
||||
>
|
||||
Trade Name*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="tradeName"
|
||||
required
|
||||
@ -248,12 +346,24 @@ const AddPrincipalDistributor = () => {
|
||||
fullWidth
|
||||
name="tradeName"
|
||||
value={data.tradeName}
|
||||
label="Trade Name"
|
||||
variant="outlined"
|
||||
onChange={handleDataChange}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
</Grid>
|
||||
|
||||
{/* GST Number */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="gstNumber"
|
||||
className="form-label"
|
||||
>
|
||||
GST Number*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="gstNumber"
|
||||
required
|
||||
@ -261,18 +371,29 @@ const AddPrincipalDistributor = () => {
|
||||
fullWidth
|
||||
name="gstNumber"
|
||||
value={data.gstNumber}
|
||||
label="GST Number"
|
||||
variant="outlined"
|
||||
onChange={handleDataChange}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Typography variant="h6" sx={{ mb: 2 }}>
|
||||
<Typography variant="h5" sx={{ mb: 2 }}>
|
||||
Address
|
||||
</Typography>
|
||||
<Grid container spacing={2} sx={{ mb: 2 }}>
|
||||
<Grid item xs={12} sm={4}>
|
||||
{/* Country */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="country"
|
||||
className="form-label"
|
||||
>
|
||||
Country*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="country"
|
||||
required
|
||||
@ -280,12 +401,24 @@ const AddPrincipalDistributor = () => {
|
||||
fullWidth
|
||||
name="country"
|
||||
value={data.country}
|
||||
label="Country"
|
||||
variant="outlined"
|
||||
disabled
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
</Grid>
|
||||
|
||||
{/* State */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="state"
|
||||
className="form-label"
|
||||
>
|
||||
State*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<Autocomplete
|
||||
id="state"
|
||||
options={stateOptions}
|
||||
@ -296,15 +429,28 @@ const AddPrincipalDistributor = () => {
|
||||
<TextField
|
||||
{...params}
|
||||
fullWidth
|
||||
label="State"
|
||||
variant="outlined"
|
||||
label="Select State"
|
||||
error={!selectedState}
|
||||
helperText={!selectedState ? "Select a state" : null}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
</Grid>
|
||||
|
||||
{/* City */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="city"
|
||||
className="form-label"
|
||||
>
|
||||
City*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<Autocomplete
|
||||
id="city"
|
||||
options={cityOptions}
|
||||
@ -315,15 +461,28 @@ const AddPrincipalDistributor = () => {
|
||||
<TextField
|
||||
{...params}
|
||||
fullWidth
|
||||
label="City"
|
||||
variant="outlined"
|
||||
label="Select City"
|
||||
error={!selectedCity}
|
||||
helperText={!selectedCity ? "Select a city" : null}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
</Grid>
|
||||
|
||||
{/* Street */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="street"
|
||||
className="form-label"
|
||||
>
|
||||
Street*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="street"
|
||||
required
|
||||
@ -331,12 +490,24 @@ const AddPrincipalDistributor = () => {
|
||||
fullWidth
|
||||
name="street"
|
||||
value={data.street}
|
||||
label="Street"
|
||||
variant="outlined"
|
||||
onChange={handleDataChange}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
</Grid>
|
||||
|
||||
{/* Postal Code */}
|
||||
<Grid item xs={12} className="d-flex align-items-center">
|
||||
<Grid item xs={2}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
htmlFor="postalCode"
|
||||
className="form-label"
|
||||
>
|
||||
Postal Code*
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<TextField
|
||||
id="postalCode"
|
||||
required
|
||||
@ -344,12 +515,12 @@ const AddPrincipalDistributor = () => {
|
||||
fullWidth
|
||||
name="postalCode"
|
||||
value={data.postalCode}
|
||||
label="Postal Code"
|
||||
variant="outlined"
|
||||
onChange={handleDataChange}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
|
@ -148,7 +148,9 @@ const principalDistributor = () => {
|
||||
color="primary"
|
||||
className="font-bold mb-2 capitalize"
|
||||
onClick={() =>
|
||||
navigate("/add-principal-distributor/multiple", { replace: true })
|
||||
navigate("/add-principal-distributor/multiple", {
|
||||
replace: true,
|
||||
})
|
||||
}
|
||||
>
|
||||
Upload Spreadsheet
|
||||
@ -199,6 +201,7 @@ const principalDistributor = () => {
|
||||
>
|
||||
<tr>
|
||||
<th>Unique Id </th>
|
||||
<th>SBU</th>
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
{/* <th>Profile Image</th> */}
|
||||
@ -228,6 +231,7 @@ const principalDistributor = () => {
|
||||
return (
|
||||
<tr key={i}>
|
||||
<td>{user.uniqueId}</td>
|
||||
<td>{user.SBU?user.SBU:"N/A"}</td>
|
||||
<td className="text-start">{user.name}</td>
|
||||
<td>{user.email}</td>
|
||||
<td className="text-start">
|
||||
|
@ -137,35 +137,85 @@ const SinglePrincipalDistributorAllDetails = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="card" style={{ padding: "1rem" }}>
|
||||
<h5 style={{ fontWeight: "bold" }}>• Principal Distributor Profile </h5>
|
||||
<h5 style={{ fontWeight: "bold" }}>
|
||||
• Principal Distributor Profile{" "}
|
||||
</h5>
|
||||
<div style={{ marginLeft: "1rem", marginTop: "1rem" }}>
|
||||
<Typography style={{ fontWeight: "bold", fontSize: "1.2rem" }}>
|
||||
Principal Distributor ID:
|
||||
<Typography component="span" style={{ fontWeight: "normal", fontSize: "1.2rem",marginLeft: "0.5rem" }}>
|
||||
<Typography
|
||||
component="span"
|
||||
style={{
|
||||
fontWeight: "normal",
|
||||
fontSize: "1.2rem",
|
||||
marginLeft: "0.5rem",
|
||||
}}
|
||||
>
|
||||
{user?.uniqueId}
|
||||
</Typography>
|
||||
</Typography>
|
||||
<Typography style={{ fontWeight: "bold", fontSize: "1.2rem" }}>
|
||||
SBU:
|
||||
<Typography
|
||||
component="span"
|
||||
style={{
|
||||
fontWeight: "normal",
|
||||
fontSize: "1.2rem",
|
||||
marginLeft: "0.5rem",
|
||||
}}
|
||||
>
|
||||
{user?.SBU}
|
||||
</Typography>
|
||||
</Typography>
|
||||
<Typography style={{ fontWeight: "bold", fontSize: "1.2rem" }}>
|
||||
Name:
|
||||
<Typography component="span" style={{ fontWeight: "normal", fontSize: "1.2rem",marginLeft: "0.5rem"}}>
|
||||
<Typography
|
||||
component="span"
|
||||
style={{
|
||||
fontWeight: "normal",
|
||||
fontSize: "1.2rem",
|
||||
marginLeft: "0.5rem",
|
||||
}}
|
||||
>
|
||||
{user?.name}
|
||||
</Typography>
|
||||
</Typography>
|
||||
<Typography style={{ fontWeight: "bold", fontSize: "1.2rem" }}>
|
||||
Email:
|
||||
<Typography component="span" style={{ fontWeight: "normal", fontSize: "1.2rem" ,marginLeft: "0.5rem"}}>
|
||||
<Typography
|
||||
component="span"
|
||||
style={{
|
||||
fontWeight: "normal",
|
||||
fontSize: "1.2rem",
|
||||
marginLeft: "0.5rem",
|
||||
}}
|
||||
>
|
||||
{user?.email}
|
||||
</Typography>
|
||||
</Typography>
|
||||
<Typography style={{ fontWeight: "bold", fontSize: "1.2rem" }}>
|
||||
Mobile Number:
|
||||
<Typography component="span" style={{ fontWeight: "normal", fontSize: "1.2rem" ,marginLeft: "0.5rem"}}>
|
||||
<Typography
|
||||
component="span"
|
||||
style={{
|
||||
fontWeight: "normal",
|
||||
fontSize: "1.2rem",
|
||||
marginLeft: "0.5rem",
|
||||
}}
|
||||
>
|
||||
{user?.phone}
|
||||
</Typography>
|
||||
</Typography>
|
||||
<Typography style={{ fontWeight: "bold", fontSize: "1.2rem" }}>
|
||||
Date Registered:
|
||||
<Typography component="span" style={{ fontWeight: "normal", fontSize: "1.2rem" ,marginLeft: "0.5rem"}}>
|
||||
<Typography
|
||||
component="span"
|
||||
style={{
|
||||
fontWeight: "normal",
|
||||
fontSize: "1.2rem",
|
||||
marginLeft: "0.5rem",
|
||||
}}
|
||||
>
|
||||
{new Date(user?.createdAt).toLocaleString("en-IN", {
|
||||
weekday: "short",
|
||||
month: "short",
|
||||
@ -179,7 +229,14 @@ const SinglePrincipalDistributorAllDetails = () => {
|
||||
</Typography>
|
||||
<Typography style={{ fontWeight: "bold", fontSize: "1.2rem" }}>
|
||||
Last Purchase:
|
||||
<Typography component="span" style={{ fontWeight: "normal", fontSize: "1.2rem", marginLeft: "1.5rem" }}>
|
||||
<Typography
|
||||
component="span"
|
||||
style={{
|
||||
fontWeight: "normal",
|
||||
fontSize: "1.2rem",
|
||||
marginLeft: "1.5rem",
|
||||
}}
|
||||
>
|
||||
{userOrder?.length > 0
|
||||
? new Date(userOrder[0]?.createdAt).toLocaleString("en-IN", {
|
||||
weekday: "short",
|
||||
@ -195,7 +252,7 @@ const SinglePrincipalDistributorAllDetails = () => {
|
||||
: "Loading"}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: "2rem" }}>
|
||||
<h5 style={{ fontWeight: "bold", marginBottom: "1rem" }}>
|
||||
@ -239,9 +296,8 @@ const SinglePrincipalDistributorAllDetails = () => {
|
||||
? `${address.tradeName},`
|
||||
: "No tradeName "}
|
||||
{address.gstNumber ? `${address.gstNumber},` : ""}
|
||||
{address?.street},
|
||||
{address?.city},{address?.state},{address?.country},
|
||||
{address?.postalCode}
|
||||
{address?.street},{address?.city},{address?.state},
|
||||
{address?.country},{address?.postalCode}
|
||||
</strong>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -134,7 +134,9 @@ try{
|
||||
<tr>
|
||||
<th>Product Name</th>
|
||||
<th>Category</th>
|
||||
<th>Brand</th>
|
||||
<th>GST</th>
|
||||
<th>HSN_Code</th>
|
||||
<th>price</th>
|
||||
<th>Message</th>
|
||||
</tr>
|
||||
@ -144,7 +146,9 @@ try{
|
||||
<tr key={index}>
|
||||
<td>{error.productName || "N/A"}</td>
|
||||
<td>{error.category || "N/A"}</td>
|
||||
<td>{error.brand || "N/A"}</td>
|
||||
<td>{error.GST || "N/A"}</td>
|
||||
<td>{error.HSN_Code || "N/A"}</td>
|
||||
<td>{error.price || "N/A"}</td>
|
||||
<td>{error.message}</td>
|
||||
</tr>
|
||||
@ -161,7 +165,9 @@ try{
|
||||
<tr>
|
||||
<th>Product Name</th>
|
||||
<th>Category</th>
|
||||
<th>Brand</th>
|
||||
<th>GST</th>
|
||||
<th>HSN_Code</th>
|
||||
<th>price</th>
|
||||
<th>Message</th>
|
||||
</tr>
|
||||
@ -171,7 +177,9 @@ try{
|
||||
<tr key={index}>
|
||||
<td>{update.name || "N/A"}</td>
|
||||
<td>{update.category || "N/A"}</td>
|
||||
<td>{update.brand || "N/A"}</td>
|
||||
<td>{update.GST || "N/A"}</td>
|
||||
<td>{update.HSN_Code || "N/A"}</td>
|
||||
<td>{update.price || "N/A"}</td>
|
||||
<td>{update.updatedFields}</td>
|
||||
</tr>
|
||||
@ -188,7 +196,9 @@ try{
|
||||
<tr>
|
||||
<th>Product Name</th>
|
||||
<th>Category</th>
|
||||
<th>Brand</th>
|
||||
<th>GST</th>
|
||||
<th>HSN_Code</th>
|
||||
<th>price</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -197,7 +207,9 @@ try{
|
||||
<tr key={index}>
|
||||
<td>{create.name || "N/A"}</td>
|
||||
<td>{create.category || "N/A"}</td>
|
||||
<td>{create.brand || "N/A"}</td>
|
||||
<td>{create.GST || "N/A"}</td>
|
||||
<td>{create.HSN_Code || "N/A"}</td>
|
||||
<td>{create.price || "N/A"}</td>
|
||||
</tr>
|
||||
))}
|
||||
|
@ -13,22 +13,21 @@ const AddProduct = () => {
|
||||
const [viewState, setViewState] = useState(1);
|
||||
const [images, setImages] = useState([]);
|
||||
const [categories, setCategories] = useState([]);
|
||||
const [taxes, setTaxes] = useState([]);
|
||||
const [brands, setBrands] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const [data, setData] = useState({
|
||||
SKU:"",
|
||||
name: "",
|
||||
category: "",
|
||||
brand: "",
|
||||
description: "",
|
||||
price: "",
|
||||
GST: "",
|
||||
product_Status: "",
|
||||
special_instructions: "",
|
||||
HSN_Code: "",
|
||||
product_Status: "Active",
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const getCategories = () => {
|
||||
axios
|
||||
.get(`/api/category/getCategories`, {
|
||||
@ -46,22 +45,26 @@ const AddProduct = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const getTaxes = () => {
|
||||
const getbrands = () => {
|
||||
axios
|
||||
.get(`/api/tax/view_tax`, {
|
||||
.get(`/api/brand/getBrands`, {
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setTaxes(res.data);
|
||||
setBrands(res?.data?.brands);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getCategories();
|
||||
getTaxes();
|
||||
getbrands();
|
||||
}, []);
|
||||
|
||||
const handleView = (n) => {
|
||||
@ -100,7 +103,7 @@ const AddProduct = () => {
|
||||
<ProductDetails
|
||||
data={{ data, setData }}
|
||||
categories={categories}
|
||||
taxes={taxes}
|
||||
brands={brands}
|
||||
ProductId={{ productId, setProductId }}
|
||||
loading={{ loading, setLoading }}
|
||||
/>
|
||||
|
@ -22,19 +22,20 @@ const EditProduct = () => {
|
||||
const [viewState, setViewState] = useState(1);
|
||||
const [images, setImages] = useState([]);
|
||||
const [categories, setCategories] = useState([]);
|
||||
const [taxes, setTaxes] = useState([]);
|
||||
const [brands, setBrands] = useState([]);
|
||||
|
||||
const navigate = useNavigate();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const [data, setData] = useState({
|
||||
SKU:"",
|
||||
name: "",
|
||||
category: "",
|
||||
brand: "",
|
||||
description: "",
|
||||
price: "",
|
||||
GST: "",
|
||||
HSN_Code: "",
|
||||
product_Status: "",
|
||||
special_instructions: "",
|
||||
});
|
||||
|
||||
///////////////
|
||||
@ -52,7 +53,7 @@ const EditProduct = () => {
|
||||
...prev,
|
||||
...res.data?.data,
|
||||
category: res.data?.data?.category?._id,
|
||||
GST: res.data?.data?.GST?._id,
|
||||
brand: res.data?.data?.brand?._id,
|
||||
product_Status: res.data?.data?.product_Status,
|
||||
}));
|
||||
setProductId(res.data?.data?._id);
|
||||
@ -80,23 +81,27 @@ const EditProduct = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const getTaxes = () => {
|
||||
const getbrands = () => {
|
||||
axios
|
||||
.get(`/api/tax/view_tax`, {
|
||||
.get(`/api/brand/getBrands`, {
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setTaxes(res.data);
|
||||
setBrands(res?.data?.brands);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getProduct();
|
||||
getCategories();
|
||||
getTaxes();
|
||||
getbrands();
|
||||
}, []);
|
||||
const handleView = (n) => {
|
||||
if (viewState === n) return;
|
||||
@ -145,7 +150,7 @@ const EditProduct = () => {
|
||||
<ProductDetails
|
||||
data={{ data, setData }}
|
||||
categories={categories}
|
||||
taxes={taxes}
|
||||
brands={brands}
|
||||
ProductId={{ productId, setProductId }}
|
||||
loading={{ loading, setLoading }}
|
||||
/>
|
||||
|
@ -8,31 +8,23 @@ const ProductDetails = (props) => {
|
||||
const { data, setData } = props.data;
|
||||
const { productId, setProductId } = props.ProductId;
|
||||
const { loading, setLoading } = props.loading;
|
||||
const taxes = props.taxes;
|
||||
|
||||
const categories = props?.categories || [];
|
||||
const brands = props?.brands || [];
|
||||
|
||||
const handleChange = (e) => {
|
||||
if (e.target.id === "master_price" && /^\D+$/.test(e.target.value)) return;
|
||||
if (e.target.id === "discontinue_on") {
|
||||
if (new Date(e.target.value) < new Date()) {
|
||||
return setData((prev) => ({
|
||||
...prev,
|
||||
[e.target.id]: new Date().toISOString().slice(0, 10),
|
||||
}));
|
||||
}
|
||||
}
|
||||
setData((prev) => ({ ...prev, [e.target.id]: e.target.value }));
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (
|
||||
data.name.trim() === "" ||
|
||||
data.master_price === "" ||
|
||||
data.master_GST === "" ||
|
||||
data.price === "" ||
|
||||
data.GST === "" ||
|
||||
data.category === "" ||
|
||||
data.description === "" ||
|
||||
data.product_Status === ""
|
||||
data.product_Status === ""||
|
||||
data.HSN_Code === "" ||
|
||||
data.brand === ""
|
||||
) {
|
||||
swal({
|
||||
title: "Warning",
|
||||
@ -78,7 +70,7 @@ const ProductDetails = (props) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="d-flex justify-content-between">
|
||||
<div className="d-flex justify-content-between mb-3">
|
||||
<h5>Product Details</h5>
|
||||
<button
|
||||
className="btn btn-primary btn-sm"
|
||||
@ -89,10 +81,12 @@ const ProductDetails = (props) => {
|
||||
{loading ? "Loading" : "Save Details"}
|
||||
</button>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="product" className="form-label">
|
||||
|
||||
<div className="mb-3 row d-flex align-items-center">
|
||||
<label htmlFor="SKU" className="form-label col-sm-3">
|
||||
Product SKU*
|
||||
</label>
|
||||
<div className="col-sm-9">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
@ -102,10 +96,13 @@ const ProductDetails = (props) => {
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="product" className="form-label">
|
||||
</div>
|
||||
|
||||
<div className="mb-3 row d-flex align-items-center">
|
||||
<label htmlFor="name" className="form-label col-sm-3">
|
||||
Product Name*
|
||||
</label>
|
||||
<div className="col-sm-9">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
@ -115,11 +112,13 @@ const ProductDetails = (props) => {
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 row">
|
||||
<div className="col-lg-6 ">
|
||||
<label htmlFor="product" className="form-label">
|
||||
</div>
|
||||
|
||||
<div className="mb-3 row d-flex align-items-center">
|
||||
<label htmlFor="category" className="form-label col-sm-3">
|
||||
Category *
|
||||
</label>
|
||||
<div className="col-sm-9">
|
||||
<select
|
||||
id="category"
|
||||
onChange={(e) => handleChange(e)}
|
||||
@ -140,11 +139,55 @@ const ProductDetails = (props) => {
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-3 row d-flex align-items-center">
|
||||
<label htmlFor="brand" className="form-label col-sm-3">
|
||||
Brand *
|
||||
</label>
|
||||
<div className="col-sm-9">
|
||||
<select
|
||||
id="brand"
|
||||
onChange={(e) => handleChange(e)}
|
||||
className="form-control"
|
||||
value={data.brand}
|
||||
>
|
||||
<option value="">---select---</option>
|
||||
{brands ? (
|
||||
brands.map((item, index) => (
|
||||
<option value={item._id} key={index}>
|
||||
{item.brandName}
|
||||
</option>
|
||||
))
|
||||
) : (
|
||||
<option value="" disabled>
|
||||
Add Brand to select
|
||||
</option>
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-lg-6">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Product Status *
|
||||
</label>{" "}
|
||||
<div className="mb-3 row d-flex align-items-center">
|
||||
<label htmlFor="price" className="form-label col-sm-3">
|
||||
Price*
|
||||
</label>
|
||||
<div className="col-sm-9">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="price"
|
||||
name="price"
|
||||
value={data.price}
|
||||
maxLength="6"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-3 row d-flex align-items-center">
|
||||
<label htmlFor="product_Status" className="form-label col-sm-3">
|
||||
Product Status
|
||||
</label>
|
||||
<div className="col-sm-9">
|
||||
<select
|
||||
className="form-control"
|
||||
name="product_Status"
|
||||
@ -158,48 +201,43 @@ const ProductDetails = (props) => {
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-3 row">
|
||||
<div className="col-lg-6">
|
||||
<label htmlFor="product" className="form-label">
|
||||
Price*
|
||||
|
||||
<div className="mb-3 row d-flex align-items-center">
|
||||
<label htmlFor="GST" className="form-label col-sm-3">
|
||||
GST Rate (in %)*
|
||||
</label>
|
||||
<div className="col-sm-9">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder=""
|
||||
id="price"
|
||||
name="price"
|
||||
value={data.price}
|
||||
maxLength="6"
|
||||
id="GST"
|
||||
value={data.GST}
|
||||
maxLength="3"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-lg-6 ">
|
||||
<label htmlFor="product" className="form-label">
|
||||
GST *
|
||||
</div>
|
||||
<div className="mb-3 row d-flex align-items-center">
|
||||
<label htmlFor="HSN" className="form-label col-sm-3">
|
||||
HSN Code*
|
||||
</label>
|
||||
<select
|
||||
name="GST"
|
||||
// value={r.gst_Id?._id ? r.gst_Id?._id : r.gst_Id}
|
||||
value={data?.GST}
|
||||
onChange={(e) => handleChange(e)}
|
||||
id="GST"
|
||||
<div className="col-sm-9">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
>
|
||||
<option value="">---select---</option>
|
||||
{taxes &&
|
||||
taxes.map((item, index) => (
|
||||
<option value={item._id} key={index}>
|
||||
{item.tax} %{item.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
id="HSN_Code"
|
||||
value={data.HSN_Code}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="product" className="form-label">
|
||||
Description*
|
||||
|
||||
<div className="mb-3 row d-flex align-items-center">
|
||||
<label htmlFor="description" className="form-label col-sm-3">
|
||||
Description
|
||||
</label>
|
||||
<div className="col-sm-9">
|
||||
<textarea
|
||||
className="form-control"
|
||||
id="description"
|
||||
@ -208,25 +246,10 @@ const ProductDetails = (props) => {
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="product" className="form-label">
|
||||
Special Instructions
|
||||
</label>
|
||||
<textarea
|
||||
className="form-control"
|
||||
placeholder="Text..."
|
||||
style={{
|
||||
whiteSpace: "pre-wrap",
|
||||
minHeight: "100px",
|
||||
overflowWrap: "break-word",
|
||||
}}
|
||||
value={data.special_instructions}
|
||||
onChange={handleChange}
|
||||
id="special_instructions"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
export default ProductDetails;
|
||||
|
@ -13,9 +13,11 @@ const Products = () => {
|
||||
const [success, setSuccess] = useState(true);
|
||||
const [productsData, setProductsData] = useState([]);
|
||||
const [categories, setCategories] = useState([]);
|
||||
const [brands, setBrands] = useState([]);
|
||||
|
||||
const nameRef = useRef();
|
||||
const categoryRef = useRef();
|
||||
const brandRef = useRef();
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [itemPerPage, setItemPerPage] = useState(10);
|
||||
@ -33,6 +35,7 @@ const Products = () => {
|
||||
show: itemPerPage,
|
||||
name: nameRef.current?.value || "",
|
||||
category: categoryRef.current?.value || "",
|
||||
brand: brandRef.current?.value || "",
|
||||
},
|
||||
});
|
||||
setProductsData(response.data?.products || []);
|
||||
@ -64,6 +67,20 @@ const Products = () => {
|
||||
setCategories(res?.data?.categories);
|
||||
});
|
||||
};
|
||||
const getBrands = () => {
|
||||
axios
|
||||
.get(`/api/brand/getBrands`, {
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
// console.log(res?.data?.brands);
|
||||
setBrands(res?.data?.brands);
|
||||
});
|
||||
};
|
||||
|
||||
const [currencyDetails, setCurrencyDetails] = useState(null);
|
||||
|
||||
const getCurrency = async () => {
|
||||
@ -84,6 +101,7 @@ const Products = () => {
|
||||
useEffect(() => {
|
||||
getCatagories();
|
||||
getCurrency();
|
||||
getBrands();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
@ -276,6 +294,22 @@ const Products = () => {
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="col-lg-3">
|
||||
<label>Filter by Brand:</label>
|
||||
<select
|
||||
className="form-control"
|
||||
ref={brandRef}
|
||||
onChange={handleSearchChange}
|
||||
disabled={loading}
|
||||
>
|
||||
<option value="">All</option>
|
||||
{brands?.map((e, i) => (
|
||||
<option key={i} value={e._id}>
|
||||
{e?.brandName}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
@ -291,8 +325,8 @@ const Products = () => {
|
||||
<th className="text-start">Image</th>
|
||||
<th className="text-start">SKU</th>
|
||||
<th className="text-start">Product</th>
|
||||
<th className="text-start">Category</th>
|
||||
|
||||
<th className="text-start">Category Name</th>
|
||||
<th className="text-start">Brand Name</th>
|
||||
<th className="text-start">Price</th>
|
||||
<th className="text-start">Status</th>
|
||||
|
||||
@ -340,6 +374,11 @@ const Products = () => {
|
||||
? product.category?.categoryName
|
||||
: "Category Not selected "}
|
||||
</td>
|
||||
<td className="text-start">
|
||||
{product.brand?.brandName !== ""
|
||||
? product.brand?.brandName
|
||||
: "Brand Not selected "}
|
||||
</td>
|
||||
<th className="text-start">
|
||||
{currencyDetails?.CurrencySymbol}
|
||||
{product?.price}
|
||||
|
@ -78,6 +78,10 @@ const ViewProduct = () => {
|
||||
<th>Product Group</th>
|
||||
<td>{productData?.category?.categoryName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Product Brand</th>
|
||||
<td>{productData?.brand?.brandName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Images</th>
|
||||
<td>
|
||||
@ -107,10 +111,17 @@ const ViewProduct = () => {
|
||||
)}
|
||||
{productData?.GST && (
|
||||
<tr>
|
||||
<th>Master GST</th>
|
||||
<th>GST</th>
|
||||
<td>
|
||||
{productData?.GST?.tax}%{" "}
|
||||
{productData?.GST?.name}
|
||||
{productData?.GST}%
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{productData?.HSN_Code && (
|
||||
<tr>
|
||||
<th>HSN_Code</th>
|
||||
<td>
|
||||
{productData?.HSN_Code}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
@ -121,7 +132,7 @@ const ViewProduct = () => {
|
||||
{currencyDetails?.CurrencySymbol}
|
||||
{(
|
||||
(Number(productData?.price) *
|
||||
Number(productData?.GST?.tax)) /
|
||||
Number(productData?.GST)) /
|
||||
100
|
||||
)?.toFixed(2)}
|
||||
</td>
|
||||
@ -143,19 +154,6 @@ const ViewProduct = () => {
|
||||
{productData?.product_Status}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Special Instructions</th>
|
||||
<td>
|
||||
<p
|
||||
style={{ whiteSpace: "pre-line" }}
|
||||
className="m-0 p-0"
|
||||
>
|
||||
{productData?.special_instructions
|
||||
? productData?.special_instructions
|
||||
: "---"}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import axios from "axios";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { isAutheticated } from "src/auth";
|
||||
@ -17,9 +17,35 @@ const AddSalesCoOrdinator = () => {
|
||||
countryCode: "+91",
|
||||
mobileNumber: "",
|
||||
otp: "",
|
||||
territoryManager: "", // Add territoryManager field
|
||||
});
|
||||
|
||||
const [territoryManagers, setTerritoryManagers] = useState([]); // State for storing fetched territory managers
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [loading, setLoading] = useState(false); // Loading state for the Territory Manager dropdown
|
||||
|
||||
// Fetch Territory Managers when the component mounts
|
||||
useEffect(() => {
|
||||
getTerritoryManagers();
|
||||
}, []);
|
||||
|
||||
const getTerritoryManagers = () => {
|
||||
setLoading(true);
|
||||
axios
|
||||
.get(`/api/territorymanager/getAll/`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setTerritoryManagers(res.data.territoryManager || []); // Store the response data
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleChange = (e) => {
|
||||
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||
@ -81,9 +107,8 @@ const AddSalesCoOrdinator = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// Function to handle cancel button click
|
||||
const handleCancel = () => {
|
||||
navigate("/salescoordinators"); // Navigate to '/salescoordinators'
|
||||
navigate("/salescoordinators");
|
||||
};
|
||||
|
||||
return (
|
||||
@ -105,6 +130,26 @@ const AddSalesCoOrdinator = () => {
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<form onSubmit={handleRegister}>
|
||||
<div className="form-group d-flex align-items-center">
|
||||
<label className="mr-2">Add Territory Manager:</label>
|
||||
<select
|
||||
className="form-control"
|
||||
name="territoryManager"
|
||||
onChange={handleChange}
|
||||
value={formData.territoryManager}
|
||||
disabled={loading}
|
||||
required
|
||||
style={{ width: "auto", flex: 1 }}
|
||||
>
|
||||
<option value="">Select Territory Manager</option>
|
||||
{territoryManagers.map((tm) => (
|
||||
<option key={tm._id} value={tm._id}>
|
||||
{tm.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label>Name</label>
|
||||
<input
|
||||
|
@ -1,221 +0,0 @@
|
||||
import axios from "axios";
|
||||
import React, { useState } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { isAutheticated } from "src/auth";
|
||||
import swal from "sweetalert";
|
||||
|
||||
function Addtax() {
|
||||
const navigate = useNavigate();
|
||||
const token = isAutheticated();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [data, setData] = useState({
|
||||
name: "",
|
||||
tax: "",
|
||||
hsn_code: "",
|
||||
});
|
||||
const [limiter, setLimiter] = useState({
|
||||
name: 50,
|
||||
namehas: 50,
|
||||
tax: 2,
|
||||
taxhas: 2,
|
||||
hsn_code: 10,
|
||||
hsn_codehas: 10,
|
||||
});
|
||||
|
||||
const handleChange = (e) => {
|
||||
if (
|
||||
(e.target.name === "tax" || e.target.name === "hsn_code") &&
|
||||
/^\D+$/.test(e.target.value)
|
||||
)
|
||||
return;
|
||||
setData((prev) => ({ ...prev, [e.target.name]: e.target.value }));
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
[e.target.name + "has"]: prev[e.target.name] - e.target.value.length,
|
||||
}));
|
||||
};
|
||||
|
||||
async function handleSubmit() {
|
||||
if (
|
||||
(data.name.trim() === "" || data.tax.trim() === "",
|
||||
data.hsn_code.trim() === "")
|
||||
) {
|
||||
return swal("Error", "All fields are required!", "error");
|
||||
}
|
||||
setLoading(true);
|
||||
await axios
|
||||
.post(`/api/tax/add_tax`, data, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setLoading(false);
|
||||
swal("Success", "Tax added successfully", "success");
|
||||
navigate("/tax", { replace: true });
|
||||
})
|
||||
.catch((err) => {
|
||||
// console.log(err)
|
||||
swal(
|
||||
"Error",
|
||||
err.response.data.message
|
||||
? err.response.data.message
|
||||
: "Something Went Wrong",
|
||||
"error"
|
||||
);
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<h4 className="mb-0">Add New GST Rate</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row my-2">
|
||||
<div className="col-12">
|
||||
<div className="form-group text-right">
|
||||
<button
|
||||
onClick={() => handleSubmit()}
|
||||
type="button"
|
||||
disabled={loading}
|
||||
className="
|
||||
btn btn-success btn-login
|
||||
waves-effect waves-light
|
||||
me-3
|
||||
"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
|
||||
<Link to="/tax">
|
||||
<button
|
||||
type="button"
|
||||
className="
|
||||
btn btn-success btn-cancel
|
||||
waves-effect waves-light
|
||||
mr-3
|
||||
"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-8">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<form>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Name*
|
||||
</label>
|
||||
<input
|
||||
value={data.name}
|
||||
onChange={(e) => handleChange(e)}
|
||||
type="text"
|
||||
name="name"
|
||||
className="form-control input-field"
|
||||
maxLength={limiter.name}
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Remaining Characters: {limiter.namehas}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row mt-2">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
HSN Code*
|
||||
</label>
|
||||
<input
|
||||
value={data.hsn_code}
|
||||
onChange={(e) => handleChange(e)}
|
||||
type="text"
|
||||
name="hsn_code"
|
||||
maxLength={limiter.hsn_code}
|
||||
className="form-control input-field"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Remaining Characters: {limiter.hsn_codehas}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row mt-2">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
GST Rate (in %)*
|
||||
</label>
|
||||
<input
|
||||
value={data.tax}
|
||||
onChange={(e) => handleChange(e)}
|
||||
type="text"
|
||||
name="tax"
|
||||
maxLength={limiter.tax}
|
||||
className="form-control input-field"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Remaining Characters: {limiter.taxhas}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Addtax;
|
@ -1,231 +0,0 @@
|
||||
import axios from "axios";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Link, useParams, useNavigate } from "react-router-dom";
|
||||
import { isAutheticated } from "src/auth";
|
||||
|
||||
function Edittax() {
|
||||
const { id } = useParams();
|
||||
const token = isAutheticated();
|
||||
const navigate = useNavigate();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [data, setData] = useState({
|
||||
name: "",
|
||||
tax: "",
|
||||
hsn_code: "",
|
||||
});
|
||||
const [limiter, setLimiter] = useState({
|
||||
name: 50,
|
||||
namehas: 50,
|
||||
tax: 2,
|
||||
taxhas: 2,
|
||||
hsn_code: 10,
|
||||
hsn_codehas: 10,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
function getTax() {
|
||||
setLoading(true);
|
||||
axios
|
||||
.get(`/api/tax/view_tax/${id}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setLoading(false);
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
name: res.data?.name,
|
||||
tax: res.data?.tax?.toString(),
|
||||
hsn_code: res.data?.hsn_code?.toString(),
|
||||
}));
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
namehas: prev.name - res.data?.name.length,
|
||||
taxhas: prev.tax - res.data?.tax?.toString().length,
|
||||
hsn_codehas: prev.hsn_code - res.data?.hsn_code.toString()?.length,
|
||||
}));
|
||||
})
|
||||
.catch((res) => {
|
||||
setLoading(false);
|
||||
navigate("/tax", { replace: true });
|
||||
});
|
||||
}
|
||||
getTax();
|
||||
}, []);
|
||||
|
||||
const handleChange = (e) => {
|
||||
if (
|
||||
(e.target.name === "tax" || e.target.name === "hsn_code") &&
|
||||
/^\D+$/.test(e.target.value)
|
||||
)
|
||||
return;
|
||||
setData((prev) => ({ ...prev, [e.target.name]: e.target.value }));
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
[e.target.name + "has"]: prev[e.target.name] - e.target.value.length,
|
||||
}));
|
||||
};
|
||||
|
||||
function handleSubmit() {
|
||||
if (
|
||||
(data.name.trim() === "" || data.tax.trim() === "",
|
||||
data.hsn_code.trim() === "")
|
||||
) {
|
||||
return swal("Error", "All fields are required!", "error");
|
||||
}
|
||||
setLoading(true);
|
||||
axios
|
||||
.patch(`/api/tax/update_tax/${id}`, data, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setLoading(false);
|
||||
swal("Success", "Tax updated successfully", "success");
|
||||
navigate("/tax", { replace: true });
|
||||
})
|
||||
.catch((err) => {
|
||||
swal("Error", "Something went wrong!", "error");
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row mb-2">
|
||||
<div className="col-12">
|
||||
<div className="form-group text-right">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
className="
|
||||
btn btn-success btn-login
|
||||
waves-effect waves-light
|
||||
me-3
|
||||
"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
|
||||
<Link to="/tax">
|
||||
<button
|
||||
type="button"
|
||||
className="
|
||||
btn btn-success btn-cancel
|
||||
waves-effect waves-light
|
||||
mr-3
|
||||
"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-8">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<form>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Name*
|
||||
</label>
|
||||
<input
|
||||
value={data.name}
|
||||
onChange={(e) => handleChange(e)}
|
||||
type="text"
|
||||
name="name"
|
||||
className="form-control input-field"
|
||||
maxLength={limiter.name}
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Remaining Characters: {limiter.namehas}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row mt-2">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
HSN Code*
|
||||
</label>
|
||||
<input
|
||||
value={data.hsn_code}
|
||||
onChange={(e) => handleChange(e)}
|
||||
type="text"
|
||||
name="hsn_code"
|
||||
maxLength={limiter.hsn_code}
|
||||
className="form-control input-field"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Remaining Characters: {limiter.hsn_codehas}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row mt-2">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
GST Rate (in %)*
|
||||
</label>
|
||||
<input
|
||||
value={data.tax}
|
||||
onChange={(e) => handleChange(e)}
|
||||
type="text"
|
||||
name="tax"
|
||||
maxLength={limiter.tax}
|
||||
className="form-control input-field"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Remaining Characters: {limiter.taxhas}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Edittax;
|
@ -1,224 +0,0 @@
|
||||
import axios from "axios";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { isAutheticated } from "src/auth";
|
||||
|
||||
import { Link } from "react-router-dom";
|
||||
import swal from "sweetalert";
|
||||
|
||||
function Tax() {
|
||||
const [taxList, settaxList] = useState([]);
|
||||
const [success, setSuccess] = useState(true);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const token = isAutheticated();
|
||||
|
||||
useEffect(() => {
|
||||
function getTaxes() {
|
||||
setLoading(true);
|
||||
axios
|
||||
.get(`/api/tax/view_tax`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setLoading(false);
|
||||
settaxList(res.data);
|
||||
})
|
||||
.catch((err) => setLoading(false));
|
||||
}
|
||||
getTaxes();
|
||||
}, [success]);
|
||||
|
||||
function handleDelete(id) {
|
||||
axios
|
||||
.delete(`/api/tax/delete_tax/${id}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => setSuccess((prev) => !prev))
|
||||
.catch((err) => swal("Error!", "Something went wrong!", "error"));
|
||||
}
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
<div className="col-sm-12 col-md-6"></div>
|
||||
<div className="col-sm-12 col-md-6 text-end">
|
||||
<div className="dropdown d-block">
|
||||
<Link to="/tax/add">
|
||||
<button
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary
|
||||
add-btn
|
||||
waves-effect waves-light
|
||||
float-right
|
||||
"
|
||||
>
|
||||
<i
|
||||
className="fa fa-plus mb-2"
|
||||
aria-hidden="true"
|
||||
></i>{" "}
|
||||
Add New GST Rate
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="table-responsive table-shoot mt-2">
|
||||
<table className="table table-centered table-nowrap mb-0">
|
||||
<thead
|
||||
className="thead"
|
||||
style={{ background: "rgb(140, 213, 213)" }}
|
||||
>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>GST Rate</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{loading && (
|
||||
<tr>
|
||||
<td colSpan="6" className="text-center">
|
||||
Loading...
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{taxList.map((tax, index) => {
|
||||
return (
|
||||
<tr key={index}>
|
||||
<td>{tax.name}</td>
|
||||
<td>{tax.tax}%</td>
|
||||
<td>
|
||||
<Link to={`/tax/edit/${tax._id}`}>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-sm waves-effect waves-light btn-table me-2"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</Link>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className=" btn btn-danger btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
ml-2
|
||||
"
|
||||
onClick={() => handleDelete(tax._id)}
|
||||
id="sa-params"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{/* <div className="row mt-20">
|
||||
<div className="col-sm-12 col-md-6 mb-20">
|
||||
<div
|
||||
className="dataTables_info"
|
||||
id="datatable_info"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
>
|
||||
Showing 1 to 10 of 57 entries
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-sm-12 col-md-6">
|
||||
<div
|
||||
className="
|
||||
dataTables_paginate
|
||||
paging_simple_numbers
|
||||
float-right
|
||||
"
|
||||
>
|
||||
<ul className="pagination">
|
||||
<li
|
||||
className="
|
||||
paginate_button
|
||||
page-item
|
||||
previous
|
||||
disabled
|
||||
"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
aria-controls="datatable"
|
||||
data-dt-idx="0"
|
||||
tabindex="0"
|
||||
className="page-link"
|
||||
>
|
||||
Previous
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="paginate_button page-item active">
|
||||
<a
|
||||
href="#"
|
||||
aria-controls="datatable"
|
||||
data-dt-idx="1"
|
||||
tabindex="0"
|
||||
className="page-link"
|
||||
>
|
||||
1
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="paginate_button page-item">
|
||||
<a
|
||||
href="#"
|
||||
aria-controls="datatable"
|
||||
data-dt-idx="2"
|
||||
tabindex="0"
|
||||
className="page-link"
|
||||
>
|
||||
2
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="paginate_button page-item">
|
||||
<a
|
||||
href="#"
|
||||
aria-controls="datatable"
|
||||
data-dt-idx="3"
|
||||
tabindex="0"
|
||||
className="page-link"
|
||||
>
|
||||
3
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="paginate_button page-item next">
|
||||
<a href="#" tabindex="0" className="page-link">
|
||||
Next
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Tax;
|
Loading…
Reference in New Issue
Block a user