This commit is contained in:
Sibunnayak 2024-04-16 15:36:15 +05:30
commit 0cd74fcf00
10 changed files with 2587 additions and 1154 deletions

View File

@ -136,6 +136,7 @@ import CityRevenueCharts from "./views/Charts/CityRevenue";
import { element } from "prop-types"; import { element } from "prop-types";
import OrderdayChart from "./views/Charts/OrderDaywise"; import OrderdayChart from "./views/Charts/OrderDaywise";
import RevenueCharts from "./views/Charts/RevenueCharts"; import RevenueCharts from "./views/Charts/RevenueCharts";
import AddCustomer from "./views/customerDetails/addCustomer";
import Pos from "./views/PointOfSale/Pos"; import Pos from "./views/PointOfSale/Pos";
const routes = [ const routes = [
{ path: "/", exact: true, name: "Home" }, { path: "/", exact: true, name: "Home" },
@ -186,6 +187,11 @@ const routes = [
name: "User Table", name: "User Table",
element: SingleUserAllDetails, element: SingleUserAllDetails,
}, },
{
path: "/add-customer",
name: "User Table",
element: AddCustomer,
},
// { // {
// path: "/users-address/add", // path: "/users-address/add",
// name: "User Address", // name: "User Address",

View File

@ -1,214 +1,182 @@
import React, { useEffect, useState } from "react"; import React, { useState, useEffect } from "react";
import Button from "@material-ui/core/Button"; import { Button } from "@mui/material";
import { Link, useNavigate } from "react-router-dom";
import swal from "sweetalert";
import axios from "axios"; import axios from "axios";
import { isAutheticated } from "src/auth"; // import { API } from "src/API";
import CloudUploadIcon from "@mui/icons-material/CloudUpload"; // import { isAutheticated } from "../../components/auth/authhelper";
import DeleteSharpIcon from "@mui/icons-material/DeleteSharp"; import { Link, useNavigate } from "react-router-dom";
import { import {
Box, CCard,
FormControl, CCardBody,
IconButton, CCardGroup,
MenuItem, CCol,
Select, CContainer,
TextField, CRow,
} from "@mui/material"; } from "@coreui/react";
// import { WebsiteURL } from '../WebsiteURL' import ProductDetails from "./Productcomponents/ProductDetails.js";
import ProductVarients from "./Productcomponents/ProductVarients.js";
import ProductsImages from "./Productcomponents/ProductImages.js";
import { isAutheticated } from "src/auth.js";
// import ReleventProduct from "./Productcomponents/ReleventProduct";
// import ProductFabric from "./Productcomponents/ProductFabric.js";
const AddProduct = () => { const AddProduct = () => {
const token = isAutheticated(); const token = isAutheticated();
const [productId, setProductId] = useState("");
const [viewState, setViewState] = useState(1);
const [images, setImages] = useState([]);
const [categories, setCategories] = useState([]);
const [taxes, setTaxes] = useState([]);
const [sizes, setSizes] = useState([]);
const [relevantProduct, setRelevantProduct] = useState([]);
const [allreleventSelectedProduct, setallReleventSelectedProduct] = useState(
[]
);
const navigate = useNavigate(); const navigate = useNavigate();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [allTax, setAllTax] = useState([]);
const [categories, setCategoies] = useState([]);
const [imagesPreview, setImagesPreview] = useState([]); const [data, setData] = useState({
// const [allimage, setAllImage] = useState([]); name: "",
const [name, setName] = useState(""); category: "",
const [description, setDescription] = useState(""); // sku: "",
const [productImages, setProductImages] = useState([]); description: "",
const [price, setPrice] = useState(0); master_price: "",
const [category, setCategoryName] = useState(""); // discontinue_on: "",
const [error, setError] = useState(""); // hsn_code: "",
const [selectedTax, setselectedTax] = useState(); product_Status: "",
const [product_Status, setproduct_Status] = useState("");
const [totalAmt, setTotalAmt] = useState(0);
const [gst_amount, setGst_amount] = useState(0);
const handleFileChange = (e) => { special_instructions: "",
const files = e.target.files; // productImages.length == 0 ||
// gst_amount === "" ||
// price === "" ||
// totalAmt === "" ||
// gst_amount === "" ||
});
// Check the total number of selected files const [varients, setVarients] = useState([
if (productImages.length + files.length > 4) { {
setError("You can only upload up to 4 images."); variant_Name: "",
return; weight: "",
} volume: "",
price: "",
// Check file types and append to selectedFiles gst_Id: "",
const allowedTypes = ["image/jpeg", "image/png", "image/jpg"]; },
const selected = []; {
variant_Name: "",
weight: "",
volume: "",
price: "",
for (let i = 0; i < files.length; i++) { gst_Id: "",
if (productImages.length + selected.length >= 4) { },
break; // Don't allow more than 4 images
}
if (allowedTypes.includes(files[i].type)) { {
selected.push(files[i]); variant_Name: "",
} weight: "",
} volume: "",
price: "",
if (selected.length === 0) { gst_Id: "",
setError("Please upload only PNG, JPEG, or JPG files."); },
} else { ]);
setError(""); const [allFabrics, setAllFabrics] = useState([]);
setProductImages([...productImages, ...selected]); const [fabrics, setFabrics] = useState([
} { _id: "", fabric_Name: "", for_Part: "" },
}; { _id: "", fabric_Name: "", for_Part: "" },
{ _id: "", fabric_Name: "", for_Part: "" },
const handelDelete = (image) => { ]);
const filtered = productImages.filter((item) => item !== image);
setProductImages(filtered);
};
// get All categories
const getCategories = async () => {
try {
const response = await axios.get("/api/category/getCategories", {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (response.status === 200) {
setCategoies(response?.data?.categories);
}
} catch (error) {
swal({
title: error,
text: " please login to access the resource ",
icon: "error",
button: "Retry",
dangerMode: true,
});
}
};
// Get all tax
const getAllTax = async () => {
const res = await axios.get(`/api/tax/view_tax`, {
headers: {
"Access-Control-Allow-Origin": "*",
Authorization: `Bearer ${token}`,
},
});
if (res.data) {
setAllTax(res.data);
}
};
useEffect(() => {
getAllTax();
getCategories();
}, [token]);
const TaxRatechange = async (e) => {
let m = JSON.parse(e.target.value);
if (m?.tax) {
let totalprice = Number(price) + Number((price * m?.tax) / 100);
setGst_amount(Number((price * m?.tax) / 100)?.toFixed(2));
setTotalAmt(totalprice?.toFixed(2));
setselectedTax(m?._id);
}
};
const handleSubmit = () => {
if (
name === "" ||
description === "" ||
productImages.length == 0 ||
category === "" ||
selectedTax === "" ||
gst_amount === "" ||
product_Status === "" ||
price === ""
) {
swal({
title: "Warning",
text: "Fill all mandatory fields",
icon: "error",
button: "Close",
dangerMode: true,
});
return;
}
setLoading(true);
const formData = new FormData();
formData.append("name", name);
formData.append("description", description);
formData.append("price", price);
formData.append("category", category);
formData.append("total_amount", totalAmt);
formData.append("gst_amount", gst_amount);
formData.append("product_Status", product_Status);
formData.append("gst", selectedTax);
productImages.forEach((Singleimage) => {
// console.log(Singleimage)
formData.append("image", Singleimage);
});
const getCategories = () => {
axios axios
.post(`/api/product/create/`, formData, { .get(`/api/category/getCategories`, {
headers: { headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "multipart/formdata",
"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Origin": "*",
Authorization: `Bearer ${token}`,
}, },
}) })
.then((res) => { .then((res) => {
swal({ setCategories(res?.data?.categories);
title: "Added",
text: "Product added successfully!",
icon: "success",
button: "ok",
});
setLoading(false); setLoading(false);
navigate("/products", { replace: true });
}) })
.catch((err) => { .catch((err) => {
setLoading(false); setLoading(false);
const message = err.response?.data?.message
? err.response?.data?.message
: "Something went wrong!";
swal({
title: "Warning",
text: message,
icon: "error",
button: "Retry",
dangerMode: true,
});
}); });
}; };
const handlePriceChange = (e) => {
const newPrice = e.target.value;
setPrice(newPrice);
const selectedTaxObj = allTax.find((t) => t._id === selectedTax);
if (selectedTaxObj && !isNaN(newPrice)) { const getTaxes = () => {
const gstAmount = (newPrice * selectedTaxObj.tax) / 100; axios
const totalAmount = Number(newPrice) + gstAmount; .get(`/api/tax/view_tax`, {
headers: {
setGst_amount(gstAmount.toFixed(2)); "Access-Control-Allow-Origin": "*",
setTotalAmt(totalAmount.toFixed(2)); Authorization: `Bearer ${token}`,
} },
})
.then((res) => {
setTaxes(res.data);
});
}; };
// console.log(data);
// console.log(productImages); // const getSizes = () => {
// axios
// .get(`/api/erp/sizemaster/size`, {
// headers: {
// "Access-Control-Allow-Origin": "*",
// Authorization: `Bearer ${token}`,
// },
// })
// .then((res) => {
// setSizes(res.data?.data);
// });
// };
// const getItemWhichcontaiNameFabric = () => {
// axios
// .get(`/api/erp/item/name_contain_fabric`, {
// headers: {
// "Access-Control-Allow-Origin": "*",
// Authorization: `Bearer ${token}`,
// },
// })
// .then((res) => {
// console.log(res?.data);
// // setSizes(res.data?.data)
// setAllFabrics(res?.data?.data);
// })
// .catch((err) => {
// console.log(err);
// });
// };
// const getProductsData = async () => {
// axios
// .get(`/api/product`, {
// headers: {
// Authorization: `Bearer ${token}`,
// },
// })
// .then((res) => {
// setRelevantProduct(res.data?.data);
// })
// .catch((err) => {
// console.log(err);
// });
// };
useEffect(() => {
getCategories();
getTaxes();
// getSizes();
// getProductsData();
// getItemWhichcontaiNameFabric();
}, []);
const handleView = (n) => {
if (viewState === n) return;
setViewState(n);
};
return ( return (
<div className="container"> <CContainer>
<div className="row"> <CRow className="mt-3">
<div className="col-12"> <CCol md={12}>
<div <div
className=" className="
page-title-box page-title-box
@ -218,27 +186,9 @@ const AddProduct = () => {
" "
> >
<div style={{ fontSize: "22px" }} className="fw-bold"> <div style={{ fontSize: "22px" }} className="fw-bold">
Add Product Add Product : {data?.name && data?.name}
</div> </div>
<div style={{ display: "flex", gap: "1rem" }}>
<h4 className="mb-0"></h4>
</div>
<div className="page-title-right"> <div className="page-title-right">
<Button
variant="contained"
color="primary"
style={{
fontWeight: "bold",
marginBottom: "1rem",
textTransform: "capitalize",
marginRight: "5px",
}}
onClick={() => handleSubmit()}
disabled={loading}
>
{loading ? "Loading" : "Save"}
</Button>
<Link to="/products"> <Link to="/products">
<Button <Button
variant="contained" variant="contained"
@ -254,302 +204,140 @@ const AddProduct = () => {
</Link> </Link>
</div> </div>
</div> </div>
</div> </CCol>
</div> </CRow>
<div className="row"> <CRow>
<div className="col-lg-6 col-md-6 col-sm-12 my-1"> <CCol md={9} className="mt-1">
<div className="card h-100"> <CCardGroup>
<div className="card-body px-5"> <CCard className="p-4 mb-3">
<div className="mb-3"> <CCardBody>
<label htmlFor="title" className="form-label"> {viewState === 1 && (
Product Name* <ProductDetails
</label> data={{ data, setData }}
<input categories={categories}
type="text" ProductId={{ productId, setProductId }}
className="form-control" loading={{ loading, setLoading }}
id="name"
value={name}
maxLength={35}
onChange={(e) => setName(e.target.value)}
/>
{name ? (
<>
<small className="charLeft mt-4 fst-italic">
{35 - name.length} characters left
</small>
</>
) : (
<></>
)}{" "}
</div>
<div className="mb-3">
<label htmlFor="title" className="form-label">
Description*
</label>
<textarea
type="text"
className="form-control"
id="description"
value={description}
rows={8}
maxLength="400"
onChange={(e) => setDescription(e.target.value)}
/>
{description ? (
<>
<small className="charLeft mt-4 fst-italic">
{400 - description.length} characters left
</small>
</>
) : (
<></>
)}
</div>
<div className="mb-3">
<label htmlFor="image" className="form-label">
Product Image*
</label>
<Box>
<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"
multiple
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>
</Box>
{error && <p style={{ color: "red" }}>{error}</p>}
<p className="pt-1 pl-2 text-secondary">
Upload jpg, jpeg and png only*
</p>
<Box style={{ display: "flex" }}>
{productImages &&
productImages.map((image, i) => (
<Box marginRight={"2rem"}>
<img
src={URL.createObjectURL(image)}
alt="profileImage"
style={{
width: 70,
height: 70,
marginBottom: "1rem",
}}
/>
<DeleteSharpIcon
onClick={() => handelDelete(image)}
fontSize="small"
sx={{
color: "white",
position: "absolute",
cursor: "pointer",
padding: "0.2rem",
background: "black",
borderRadius: "50%",
}}
/>
{/* </IconButton> */}
</Box>
))}
</Box>
</div>
<div>
<strong className="fs-6 fst-italic">
*You cannot upload more than 4 images !!
</strong>
</div>
<div id="createProductFormImage" className="w-25 d-flex">
{imagesPreview.map((image, index) => (
<img
className=" w-50 p-1 "
key={index}
src={image}
alt="Product Preview"
/> />
))} )}
</div> {viewState === 2 && (
</div> <ProductVarients
</div> productId={productId}
</div> data={{ varients, setVarients }}
<div className="col-lg-6 col-md-6 col-sm-12 my-1"> taxes={taxes}
<div className="card h-100"> sizes={sizes}
<div className="card-body px-5"> loading={{ loading, setLoading }}
<div className="mb-3 me-3"> />
<label htmlFor="title" className="form-label"> )}
Price(Rs)* {viewState === 3 && (
</label> <ProductsImages
<input productId={productId}
type="number" data={{ images, setImages }}
className="form-control" loading={{ loading, setLoading }}
id="price" />
value={price} )}
onChange={(e) => handlePriceChange(e)} {/* {viewState === 4 && (
/> <ProductFabric
</div> productId={productId}
<div className=""> data={{ fabrics, setFabrics }}
<label htmlFor="categorySelect">Select a Category *:</label> allFabrics={allFabrics}
<select loading={{ loading, setLoading }}
id="category" />
className="form-control" )}
style={{ width: "100%" }} {viewState === 5 && (
value={category} <ReleventProduct
onChange={(e) => setCategoryName(e.target.value)} data={{ data, setData }}
> ProductId={productId}
<option value={""}>None</option> AllreleventSelectedPro={{
{categories.map((category, index) => ( allreleventSelectedProduct,
<option key={index} value={category?._id}> setallReleventSelectedProduct,
{category.categoryName} }}
</option> ReleventProduct={relevantProduct}
))} loading={{ loading, setLoading }}
</select> />
{/* <FormControl fullWidth> )} */}
<Select {/* {viewState === 5 && (
labelId="demo-simple-select-label" <ProductFabric
id="demo-simple-select" data={{ data, setData }}
value={categoryName} ProductId={productId}
onChange={(e) => setCategoryName(e.target.value)} AllreleventSelectedPro={{
allreleventSelectedProduct,
setallReleventSelectedProduct,
}}
ReleventProduct={relevantProduct}
loading={{ loading, setLoading }}
/>
)} */}
</CCardBody>
</CCard>
</CCardGroup>
</CCol>
<CCol md={3} className="mt-1">
<CCardGroup>
<CCard>
<CCardBody>
<div className="d-grid gap-2">
<button
className={
viewState === 1
? "btn btn-light"
: "btn btn-info text-white"
}
type="button"
onClick={() => handleView(1)}
> >
<MenuItem Product Details
style={{ </button>
width: "100%", <button
display: "flex", className={
justifyContent: "left", viewState === 2
textAlign: "left", ? "btn btn-light"
padding: "0.5rem", : "btn btn-info text-white"
}} }
value={""} type="button"
> onClick={() => handleView(2)}
None
</MenuItem>
{categories.map((category, i) => (
<MenuItem
style={{
width: "100%",
display: "flex",
justifyContent: "left",
textAlign: "left",
padding: "0.5rem",
}}
key={i}
value={category.categoryName}
>
{category.categoryName}
</MenuItem>
))}
</Select>
</FormControl> */}
</div>
{allTax.length > 0 && (
<div className=" mb-3">
<label htmlFor="title" className="form-label">
GST*
</label>{" "}
<select
className="form-control"
name="gst"
id="gst"
onChange={(e) => TaxRatechange(e)}
> >
<option value="">--Select--</option> Variants
</button>
{allTax.map((t, i) => ( <button
<option key={i} value={JSON.stringify(t)}> className={
{t.tax}% {t.name} viewState === 3
</option> ? "btn btn-light"
))} : "btn btn-info text-white"
</select> }
type="button"
onClick={() => handleView(3)}
>
Images
</button>
{/* <button
className={
viewState === 4
? "btn btn-light"
: "btn btn-info text-white"
}
type="button"
onClick={() => handleView(4)}
>
Fabric
</button> */}
{/* <button
className={
viewState === 5
? "btn btn-light"
: "btn btn-info text-white"
}
type="button"
onClick={() => handleView(5)}
>
+ Relevent Product
</button> */}
</div> </div>
)} </CCardBody>
</CCard>
<div className="mb-3 me-3"> </CCardGroup>
<label htmlFor="title" className="form-label"> </CCol>
GST Amount (Rs) * </CRow>
</label> </CContainer>
<input
disabled
type="number"
name="gst_amount"
className="form-control"
id="gst_amount"
value={gst_amount}
// onChange={(e) => setPrice(e.target.value)}
/>
</div>
<div className="mb-3 me-3">
<label htmlFor="title" className="form-label">
Total Amount(Rs)*
</label>
<input
disabled
type="number"
name="total_amount"
className="form-control"
id="total_amount"
value={totalAmt}
// onChange={(e) => setPrice(e.target.value)}
/>
</div>
<div className=" mb-3">
<label htmlFor="title" className="form-label">
Product Status *
</label>{" "}
<select
className="form-control"
name="product_Status"
id="product_Status"
value={product_Status}
onChange={(e) => setproduct_Status(e.target.value)}
>
<option value="">--Select--</option>
<option value="Active">Active</option>
<option value="Inactive">Inactive</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
); );
}; };

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,244 @@
import axios from "axios";
import React from "react";
import swal from "sweetalert";
import { isAutheticated } from "src/auth";
const ProductDetails = (props) => {
const token = isAutheticated();
const { data, setData } = props.data;
const { productId, setProductId } = props.ProductId;
const { loading, setLoading } = props.loading;
const categories = props?.categories || [];
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.trim() === "" ||
data.category === "" ||
data.description === "" ||
data.product_Status === ""
// data.sku === "" ||
// data.hsn_code === ""
) {
swal({
title: "Warning",
text: "Fill all mandatory fields",
icon: "warning",
button: "Return",
});
return;
}
setLoading(true);
axios
.post(
`/api/product/create/`,
{ ...data, product_id: productId },
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
}
)
.then((res) => {
swal({
title: "Saved",
text: "Product details saved successfully!",
icon: "success",
button: "Close",
});
setProductId(res.data.product_id);
setLoading(false);
})
.catch((err) => {
const msg = err?.response?.data?.message || "Something went wrong!";
swal({
title: "Warning",
text: msg,
icon: "warning",
button: "Close",
});
setLoading(false);
});
};
return (
<>
<div className="d-flex justify-content-between">
<h5>Product Details</h5>
<button
className="btn btn-primary btn-sm"
type="button"
onClick={() => handleSubmit()}
disabled={loading}
>
{loading ? "Loading" : "Save Details"}
</button>
</div>
<div className="mb-3">
<label htmlFor="product" className="form-label">
Product Name*
</label>
<input
type="text"
className="form-control"
id="name"
value={data.name}
maxLength="50"
onChange={(e) => handleChange(e)}
/>
</div>
<div className="mb-3 row">
{/* <div className="col-lg-6">
<label htmlFor="product" className="form-label">
SKU*
</label>
<input
type="text"
className="form-control"
id="sku"
value={data.sku}
maxLength="50"
onChange={(e) => handleChange(e)}
/>
</div> */}
<div className="col-lg-6 ">
<label htmlFor="product" className="form-label">
Category *
</label>
<select
id="category"
onChange={(e) => handleChange(e)}
className="form-control"
value={data.category}
>
<option value="">---select---</option>
{categories ? (
categories.map((item, index) => (
<option value={item._id} key={index}>
{item.categoryName}
</option>
))
) : (
<option value="" disabled>
Add Category to select
</option>
)}
</select>
</div>
<div className="col-lg-6">
{/* <label htmlFor="product" className="form-label">
Master Price*
</label>
<input
type="text"
className="form-control"
id="master_price"
value={data.master_price}
maxLength="6"
onChange={(e) => handleChange(e)}
/> */}
<label htmlFor="title" className="form-label">
Product Status *
</label>{" "}
<select
className="form-control"
name="product_Status"
id="product_Status"
value={data.product_Status}
onChange={(e) => handleChange(e)}
>
<option value="">--Select--</option>
<option value="Active">Active</option>
<option value="Inactive">Inactive</option>
</select>
</div>
</div>
<div className="mb-3">
<label htmlFor="product" className="form-label">
Description*
</label>
<textarea
className="form-control"
id="description"
value={data.description}
onChange={(e) => handleChange(e)}
/>
</div>
{/* <div className="mb-3 row">
<div className="col-6">
<label htmlFor="hsc_code" className="form-label">
HSN Code*
</label>
<input
type="text"
className="form-control"
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">
Special Instructions
</label>
<textarea
className="form-control"
style={{
whiteSpace: "pre-wrap",
minHeight: "100px",
overflowWrap: "break-word",
}}
value={data.special_instructions}
onChange={handleChange}
id="special_instructions"
/>
</div>
{/* <div className="mb-3">
<label>Discontinue On*</label>
<input
type="date"
value={data.discontinue_on}
id="discontinue_on"
onChange={(e) => handleChange(e)}
className="form-control"
min={new Date().toISOString().slice(0, 10)}
/>
</div> */}
{/* <div className=" mb-3">
<label htmlFor="title" className="form-label">
Product Status *
</label>{" "}
<select
className="form-control"
name="product_Status"
id="product_Status"
value={data.product_Status}
onChange={(e) => handleChange(e)}
>
<option value="">--Select--</option>
<option value="Active">Active</option>
<option value="Inactive">Inactive</option>
</select>
</div> */}
</>
);
};
export default ProductDetails;

View File

@ -0,0 +1,302 @@
import axios from "axios";
import React, { useEffect, useState } from "react";
import swal from "sweetalert";
import { isAutheticated } from "src/auth";
const ProductsImages = (props) => {
const token = isAutheticated();
const productId = props.productId;
const { images, setImages } = props.data;
const { loading, setLoading } = props.loading;
const [deleting, setDeleting] = useState(false);
const [imagePreview, setImagePreview] = useState({ preview: "", image: "" });
const [imagesPreview, setImagesPreview] = useState([]);
const [allimage, setAllImage] = useState([]);
//
const [data, setData] = useState({
image: [],
imageURL: [],
});
useEffect(() => {
if (images?.length > 0) {
setData((prev) => ({
...prev,
imageURL: images?.url,
}));
setImagesPreview(images);
}
}, []);
const handleChange = (e) => {
if (e.target.id === "image") {
if (
e.target.files[0]?.type === "image/jpeg" ||
e.target.files[0]?.type === "image/png" ||
e.target.files[0]?.type === "image/jpg"
) {
if (imagesPreview.length > 3) {
swal({
title: "Warning",
text: "maximum Four image Upload ",
icon: "error",
button: "Close",
dangerMode: true,
});
return;
}
// only for file preview------------------------------------
const files = Array.from(e.target.files);
files.forEach((file) => {
const reader = new FileReader();
reader.onload = () => {
if (reader.readyState === 2) {
setImagesPreview((old) => [...old, reader.result]);
}
};
reader.readAsDataURL(file);
});
// -----------------------------------------------------------------------------
setData((prev) => ({
...prev,
image: [...data.image, ...e.target.files],
}));
return;
} else {
swal({
title: "Warning",
text: "Upload jpg, jpeg, png only.",
icon: "error",
button: "Close",
dangerMode: true,
});
setData((prev) => ({
...prev,
imageURL: "",
image: "",
}));
e.target.value = null;
return;
}
}
setData((prev) => ({ ...prev, [e.target.id]: e.target.value }));
};
//
// const handleChange = (e) => {
// if (
// e.target.files[0]?.type === "image/jpeg" ||
// e.target.files[0]?.type === "image/png" ||
// e.target.files[0]?.type === "image/jpg"
// ) {
// setImagePreview((prev) => ({
// ...prev,
// preview: URL.createObjectURL(e.target.files[0]),
// image: e.target.files[0],
// }));
// return;
// } else {
// swal({
// title: "Warning",
// text: "Upload jpg, jpeg, png only.",
// icon: "error",
// button: "Close",
// dangerMode: true,
// });
// setImagePreview((prev) => ({
// ...prev,
// preview: "",
// image: "",
// }));
// e.target.value = null;
// return;
// }
// };
const handleDelete = (id) => {
swal({
title: "Are you sure?",
icon: "error",
buttons: {
Yes: { text: "Yes", value: true },
Cancel: { text: "Cancel", value: "cancel" },
},
}).then((value) => {
if (value === true) {
setDeleting(true);
axios
.delete(`/api/product/image/${productId}/${id}`, {
headers: {
"Access-Control-Allow-Origin": "*",
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
setDeleting(false);
const filteredImages = images.filter((e) => e._id !== id);
setImages(filteredImages);
})
.catch((err) => {
setDeleting(false);
swal({
title: "Warning",
text: "Something went wrong!",
icon: "error",
button: "Retry",
dangerMode: true,
});
});
}
});
};
const handleSubmit = () => {
// if (!imagePreview.image) return;
if (data.image?.length < 1) {
swal({
title: "Warning",
text: "PLease select Product Image",
icon: "warning",
button: "ok",
dangerMode: true,
});
return;
}
setLoading(true);
const formData = new FormData();
data.image.forEach((Singleimage) => {
// console.log(Singleimage)
formData.append("image", Singleimage);
});
axios
.patch(`/api/product/update/${productId}`, formData, {
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${token}`,
"Access-Control-Allow-Origin": "*",
},
})
.then((res) => {
swal({
title: "Saved",
text: "Product image saved successfully!",
icon: "success",
button: "Close",
});
setImages((prev) => [...prev, res.data?.image]);
setImagePreview({ preview: "", image: "" });
setLoading(false);
})
.catch((err) => {
// console.log(err);
const msg = err?.response?.data?.message || "Something went wrong!";
swal({
title: "Warning",
text: msg,
icon: "warning",
button: "Close",
});
setLoading(false);
});
};
return (
<>
<div className="d-flex justify-content-between">
<h5>Product Images</h5>
</div>
<div className="my-3">
<div className="row">
<div className="col-lg-9">
<input
type="file"
className="form-control"
id="image"
accept="image/*"
multiple
onChange={(e) => handleChange(e)}
/>
</div>
<div className="col-lg-3">
<button
className="btn btn-primary"
onClick={() => handleSubmit()}
disabled={!productId || loading}
>
{productId
? loading
? "Loading"
: "Upload"
: "Product Details not saved"}
</button>
</div>
</div>
<p className="pt-1 pl-2 text-secondary">
Upload jpg, jpeg and png only*
</p>
<div>
<strong className="fs-6 fst-italic">
*Please Upload maximum four images
</strong>
</div>
<div className="mb-3" style={{ height: "100px", maxWdth: "100%" }}>
{/* <img
src={imagePreview.preview}
alt="Uploaded Image will be shown here"
style={{ maxHeight: "100px", maxWidth: "100%" }}
/> */}
{imagesPreview.map((image, index) => (
<img
className="p-1"
key={index}
src={image?.url ? image?.url : image}
alt="Uploaded Image will be shown here"
style={{ maxHeight: "100px", maxWidth: "100%" }}
/>
))}
</div>
</div>
{/* <table className="table">
<thead>
<tr>
<th scope="col">Preview</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
{images.length !== 0 ? (
images.map((r, idx) => (
<tr key={idx}>
<td>
<img src={r.url} alt="preview" height="100px" />
</td>
<td>
<button
className="btn btn-danger btn-sm text-white"
onClick={() => handleDelete(r._id)}
disabled={deleting}
>
Delete
</button>
</td>
</tr>
))
) : (
<tr>
<td colSpan={6} className="text-center fw-bold">
No Image Added
</td>
</tr>
)}
</tbody>
</table> */}
</>
);
};
export default ProductsImages;

View File

@ -0,0 +1,249 @@
import axios from "axios";
import React from "react";
import swal from "sweetalert";
import { isAutheticated } from "src/auth";
const ProductVarients = (props) => {
const token = isAutheticated();
const productId = props.productId;
const taxes = props.taxes;
const sizes = props.sizes;
const { varients, setVarients } = props.data;
const { loading, setLoading } = props.loading;
const addVarientRow = () => {
setVarients((prev) => [
...prev,
{
variant_Name: "",
weight: "",
volume: "",
price: "",
gst_Id: "",
},
]);
};
const handleChange = (e, idx) => {
if (
e.target.name === "weight" &&
e.target.value !== "" &&
!/^[0-9.]+$/.test(e.target.value)
)
return;
if (
e.target.name === "price" &&
e.target.value !== "" &&
!/^[0-9.]+$/.test(e.target.value)
)
return;
let clone = [...varients];
let obj = clone[idx];
// if (e.target.name === "gst_Id") {
// }
obj[e.target.name] = e.target.value;
clone[idx] = obj;
setVarients([...clone]);
};
// variant_Name: "",
// weight: "",
// volume: "",
// price: "",
// gst_Name: "",
// gst_Rate: "",
// gst_Id: "",
const handleSubmit = () => {
const emptyVarients = varients.filter(
(e) =>
!(e.variant_Name === "" && e.price === "" && e.gst_Id === "") &&
(e.variant_Name === "" || e.price === "" || e.gst_Id === "")
);
if (emptyVarients.length !== 0) {
swal({
title: "Warning",
text: "Fill all fields of a row",
icon: "warning",
button: "Return",
});
return;
}
// const variant_Name = [];
// varients.map((e) => e.variant_Name && variant_Name.push(e.variant_Name));
// const duplicate = variant_Name.filter(
// (e) => sizes.indexOf(e) !== sizes.lastIndexOf(e)
// );
// if (duplicate.length !== 0) {
// swal({
// title: "Warning",
// text: "Duplicate sizes selected!",
// icon: "warning",
// button: "Return",
// });
// return;
// }
const varientData = varients.filter((e) => e.variant_Name !== "");
const emptyVariants = varients.reduce(
(arr, e) =>
e.gst_Id !== "" && e.variant_Name === "" && e.price === ""
? [...arr, e._id]
: arr,
[]
);
setLoading(true);
axios
.patch(
`/api/product/update/${productId}`,
{ variants: varientData, delete_variants: emptyVariants },
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
}
)
.then((res) => {
swal({
title: "Saved",
text: "Product variants saved successfully!",
icon: "success",
button: "Close",
});
setVarients((prev) =>
res?.data?.variants?.length > 0 ? [...res?.data?.variants] : prev
);
setLoading(false);
})
.catch((err) => {
const msg = err?.response?.data?.message || "Something went wrong!";
swal({
title: "Warning",
text: msg,
icon: "warning",
button: "Close",
});
setLoading(false);
});
};
return (
<>
<div className="d-flex justify-content-between">
<h5>Product Variants</h5>
<button
className="btn btn-primary btn-sm"
type="button"
onClick={() => handleSubmit()}
disabled={!productId || loading}
>
{productId
? loading
? "Loading"
: "Save Varients"
: "First Save Product Details then Save Varients"}
</button>
</div>
<table className="table">
<thead>
<tr>
{/* <th scope="col">Size</th> */}
<th scope="col">Variant Name</th>
<th scope="col">Price</th>
{/* <th scope="col">Weight (in Grams)</th> */}
{/* <th scope="col">Show in E-store</th> */}
<th scope="col">Tax</th>
</tr>
</thead>
<tbody>
{varients.map((r, idx) => (
<tr key={idx}>
{/* <td>
<select
name="size"
value={r.size}
onChange={(e) => handleChange(e, idx)}
className="form-control"
>
<option value="">---select---</option>
{sizes &&
sizes.map((item, index) => (
<option value={item._id} key={index}>
{item.size}
</option>
))}
</select>
</td> */}
<td>
<input
type="text"
className="form-control"
name="variant_Name"
value={r.variant_Name}
onChange={(e) => handleChange(e, idx)}
/>
</td>
<td>
<input
type="number"
className="form-control"
name="price"
value={r.price}
onChange={(e) => handleChange(e, idx)}
/>
</td>
{/* <td>
<input
type="text"
className="form-control"
name="weight"
value={r.weight}
onChange={(e) => handleChange(e, idx)}
/>
</td> */}
{/* <td>
<select
name="show_in_estore"
value={r.show_in_estore}
onChange={(e) => handleChange(e, idx)}
className="form-control"
>
<option value={true}>Yes</option>
<option value={false}>No</option>
</select>
</td> */}
<td>
<select
name="gst_Id"
value={r.gst_Id?._id ? r.gst_Id?._id : r.gst_Id}
onChange={(e) => handleChange(e, idx)}
className="form-control"
>
<option value="">---select---</option>
{taxes &&
taxes.map((item, index) => (
<option value={item._id} key={index}>
{item.tax} %{item.name}
</option>
))}
</select>
</td>
</tr>
))}
</tbody>
</table>
<div className="text-center">
<button
className="btn btn-primary btn-sm"
onClick={() => addVarientRow()}
>
Add another variant
</button>
</div>
</>
);
};
export default ProductVarients;

View File

@ -48,9 +48,11 @@ const Products = () => {
setLoading(false); setLoading(false);
}) })
.catch((error) => { .catch((error) => {
const msg = error?.response?.data?.message || "Something went wrong!";
swal({ swal({
title: error, title: error,
text: "please login to access the resource or refresh the page ", text: msg,
icon: "error", icon: "error",
button: "Retry", button: "Retry",
dangerMode: true, dangerMode: true,
@ -62,7 +64,6 @@ const Products = () => {
useEffect(() => { useEffect(() => {
getProductsData(); getProductsData();
}, [success]); }, [success]);
console.log(productsData);
useEffect(() => { useEffect(() => {
const loadData = () => { const loadData = () => {
@ -100,9 +101,11 @@ const Products = () => {
setSuccess((prev) => !prev); setSuccess((prev) => !prev);
}) })
.catch((err) => { .catch((err) => {
const msg = err?.response?.data?.message || "Something went wrong!";
swal({ swal({
title: "Warning", title: "Warning",
text: "Something went wrong!", text: msg,
icon: "error", icon: "error",
button: "Retry", button: "Retry",
dangerMode: true, dangerMode: true,
@ -384,7 +387,10 @@ const Products = () => {
: "Category Not selected "} : "Category Not selected "}
</td> </td>
<th className="text-start"> <th className="text-start">
{product?.total_amount}
{product?.total_amount
? product?.total_amount
: product?.variants[0]?.price}
</th> </th>
<td className="text-start"> <td className="text-start">
{new Date(product.createdAt).toLocaleString( {new Date(product.createdAt).toLocaleString(

View File

@ -1,42 +1,47 @@
import React, { useState, useEffect } from "react";
import axios from "axios"; import axios from "axios";
import React, { useEffect, useState, useCallback, useMemo } from "react"; import { useNavigate, useParams } from "react-router-dom";
import swal from "sweetalert";
import { Link, useParams } from "react-router-dom";
import { isAutheticated } from "src/auth"; import { isAutheticated } from "src/auth";
function ViewProduct() { const ViewProduct = () => {
const [product, setProduct] = useState([]); // const id = useParams()?.id;
const { id } = useParams(); const { id } = useParams();
const token = isAutheticated(); const token = isAutheticated();
const getProduct = useCallback(async () => { const [productData, setProductData] = useState({});
let res = await axios.get(`/api/product/getOne/${id}`, { const [SAW, setSAW] = useState([
headers: { { volume: "", weight: "" },
Authorization: `Bearer ${token}`, { volume: "", weight: "" },
}, { volume: "", weight: "" },
}); { volume: "", weight: "" },
{ volume: "", weight: "" },
setProduct(res.data.product); ]);
}, [token]); const navigate = useNavigate();
const getProductData = async () => {
axios
.get(`/api/product/getOne/${id}`, {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
console.log(res.data.data);
setProductData(res.data.data);
if (res.data.data?.variants) {
setSAW((prev) => [...res.data.data?.variants]);
}
})
.catch((err) => {});
};
useEffect(() => { useEffect(() => {
getProduct(); getProductData();
}, [getProduct]); }, []);
//change time formate const onCancel = () => {
function formatAMPM(date) { navigate("/products");
var hours = new Date(date).getHours(); };
var minutes = new Date(date).getMinutes(); let count = 1;
var ampm = hours >= 12 ? "PM" : "AM";
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? "0" + minutes : minutes;
var strTime = hours + ":" + minutes + " " + ampm;
return strTime;
}
// console.log(product);
return ( return (
<div className=" main-content"> <div className=" main-content">
<div className=" my-3 page-content"> <div className=" my-3 page-content">
@ -45,24 +50,15 @@ function ViewProduct() {
<div className="row"> <div className="row">
<div className="col-12"> <div className="col-12">
<div className="page-title-box d-flex align-items-center justify-content-between"> <div className="page-title-box d-flex align-items-center justify-content-between">
<h4 className="mb-3">Product</h4> <h4 className="mb-3">Product Details</h4>
<Link to="/products">
<button <button
type="button" onClick={onCancel}
className="btn btn-info float-end mb-3 ml-4" type="button"
> className="mb-2 ml-2 btn btn-warning btn-cancel waves-effect waves-light mr-3"
{" "} >
Back Back
</button> </button>
</Link>
{/* <div className="page-title-right">
<ol className="breadcrumb m-0">
<li className="breadcrumb-item">
<Link to="/dashboard">CMD-App</Link>
</li>
<li className="breadcrumb-item">CMD-Category</li>
</ol>
</div> */}
</div> </div>
</div> </div>
</div> </div>
@ -77,91 +73,166 @@ function ViewProduct() {
<table className="table table-centered table-nowrap mb-0"> <table className="table table-centered table-nowrap mb-0">
<thead className="thead-light"> <thead className="thead-light">
<tr> <tr>
<th>Id</th>{" "} <th>Name</th>
<td> <td>{productData?.name}</td>
<h5>{product.uniqueId}</h5>
</td>
</tr> </tr>
<tr>
<th>Name</th> <td>{product?.name}</td>
</tr>
{product.image && (
<tr>
<th>image</th>
<td>
{product.image.map((i) => (
<img
className="me-2"
src={`${i?.url}`}
width="70"
alt=""
/>
))}
</td>
</tr>
)}
<tr>
<th>Category </th>
<td>
{product.category?.categoryName !== ""
? product.category?.categoryName
: "Category not selected "}
</td>
</tr>
<tr>
<th>Description</th>
<td>{product?.description}</td>
</tr>
<tr>
<th>Price</th>
<td>{product?.price}</td>
</tr>
<tr>
<th>Gst</th>
<td>
{product?.gst?.tax}% {product?.gst?.name}
</td>
</tr>
{product?.gst_amount && (
<tr>
<th>Gst Amount</th>
<td>{product?.gst_amount}</td>
</tr>
)}
<tr> <tr>
<th>Total Amount(with Gst)</th> <th>Product Group</th>
<td>{product?.total_amount}</td> <td>{productData?.category?.categoryName}</td>
</tr>
{/* <tr><th>Product Time</th><td>{product?.time}</td></tr>
<tr><th>Location</th><td>{product?.location}</td></tr> */}
<tr>
<th>Product Status</th>
<td>{product?.product_Status}</td>
</tr> </tr>
<tr> <tr>
<th>Created On</th> <th>Images</th>
<td> <td>
{new Date(`${product?.createdAt}`).toDateString()} {productData?.image &&
<span> productData?.image?.length !== 0
{" "} ? productData?.image.map((e, i) => (
, {`${formatAMPM(product?.createdAt)}`} <img
</span> className="p-1"
src={e.url}
width="100"
alt="preview"
key={i}
/>
))
: "No Images Uploaded!"}
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Updated At</th> <th>Description</th>
<td>{productData?.description}</td>
</tr>
<tr>
<th>Product Status</th>
<td>{productData?.product_Status}</td>
</tr>
<tr>
<th>Special Instructions</th>
<td> <td>
{new Date(`${product?.updatedAt}`).toDateString()} <p
<span> style={{ whiteSpace: "pre-line" }}
{" "} className="m-0 p-0"
, {`${formatAMPM(product?.updatedAt)}`} >
</span> {productData?.special_instructions
? productData?.special_instructions
: "---"}
</p>
</td> </td>
</tr> </tr>
</thead> </thead>
<tbody></tbody> <tbody></tbody>
</table> </table>
<table className="table table-primary mt-3">
<caption
style={{ captionSide: "top" }}
className="text-dark fw-bold"
>
Varients:
</caption>
<thead>
<tr>
<th className="text-center">Variant Name</th>
<th className="text-center">Price</th>
<th className="text-center">Gst</th>
</tr>
</thead>
<tbody>
{SAW.map(
(r, i) =>
r.variant_Name !== "" && (
<tr key={i}>
<td className="text-center">
{r?.variant_Name}
</td>
<td className="text-center">{r?.price}</td>
<td className="text-center">
{r?.gst_Id?.name + " " + r?.gst_Id?.tax + "%"}
</td>
</tr>
)
)}
{SAW.filter((e) => e.variant_Name !== "").length ===
0 && (
<tr>
<td colSpan={"6"} className="text-center">
No data available
</td>
</tr>
)}
</tbody>
</table>
{/* <div className="mb-2">
<table className="table table-secondary mt-3">
<caption
style={{ captionSide: "top" }}
className="text-dark fw-bold"
>
Product Fabric:
</caption>
{productData?.product_Fabric?.length > 0 ? (
<>
<thead>
<tr>
<th className="text-center">S. No.</th>
<th className="text-center"> Name</th>
<th className="text-center"> Use For Part</th>
</tr>
</thead>
<tbody>
{productData?.product_Fabric?.map((r, i) => (
<tr key={i}>
<td className="text-center">{++i}</td>
<td className="text-center">
{r?.fabric_Name}
</td>
<td className="text-center">{r?.for_Part}</td>
</tr>
))}
</tbody>
</>
) : (
<>
<h5>No Fabric Allotted for this product!</h5>
</>
)}
</table>
</div> */}
{/* <div className="mb-2">
<table className="table table-info mt-3">
<caption
style={{ captionSide: "top" }}
className="text-dark fw-bold"
>
Relevent Product:
</caption>
{productData?.relevent_product?.length > 0 ? (
<>
<thead>
<tr>
<th className="text-center">S. No.</th>
<th className="text-center">Product Name</th>
</tr>
</thead>
<tbody>
{productData?.relevent_product?.map((r, i) => (
<tr key={i}>
<td className="text-center">{count++}</td>
<td className="text-center">{r?.name}</td>
</tr>
))}
</tbody>
</>
) : (
<>
<h5>No relevent item for this product !</h5>
</>
)}
</table>
</div> */}
</div> </div>
{/* <!-- end table-responsive --> */} {/* <!-- end table-responsive --> */}
@ -174,6 +245,6 @@ function ViewProduct() {
</div> </div>
</div> </div>
); );
} };
export default ViewProduct; export default ViewProduct;

View File

@ -0,0 +1,395 @@
import React, { useState } from "react";
import {
TextField,
Button,
Card,
FormControl,
Grid,
FormHelperText,
OutlinedInput,
Box,
} from "@mui/material";
import { useNavigate } from "react-router-dom";
import toast from "react-hot-toast";
import axios from "axios"; // Import axios for making HTTP requests
import { isAutheticated } from "src/auth";
const styles = {
formStyle: {
fontWeight: "700",
fontSize: "12px",
fontFamily: "inter",
marginBottom: "3px",
marginLeft: "0",
},
};
const AddCustomer = () => {
const navigate = useNavigate();
const [user, setUser] = useState({
name: "",
email: "",
password: "", // No need to initialize password here
});
const [id, setUserId] = useState("");
const token = isAutheticated();
const [loading, setLoading] = useState(false);
const [data, setData] = useState({
first_Name: "",
last_Name: "",
phone_Number: Number,
street: "",
city: "",
state: "",
postalCode: "",
country: "",
});
// console.log(data);
const handleChange = (e) => {
setData((prev) => ({ ...prev, [e.target.name]: e.target.value }));
};
const handerInputChanges = (e) => {
setUser({ ...user, [e.target.name]: e.target.value });
};
function handleAddressSubmit(e) {
e.preventDefault();
if (
data.first_Name === "" ||
data.last_Name === "" ||
data.phone_Number === null ||
data.street === "" ||
data.city === "" ||
data.state === "" ||
data.postalCode === "" ||
data.country === ""
) {
swal({
title: "Warning",
text: "Please fill All mendetory fields ",
icon: "warning",
button: "ok",
dangerMode: true,
});
return;
}
setLoading(true);
axios
.post(
`/api/shipping/address/admin/new/${id}`,
{
...data,
},
{
headers: {
"Access-Control-Allow-Origin": "*",
Authorization: `Bearer ${token}`,
},
}
)
.then((res) => {
setLoading(false);
// setSuccess((prev) => !prev);
navigate("/customers-details");
toast.success(res.data.message ? res.data.message : "Address Added!");
})
.catch((error) => {
setLoading(false);
toast.error(
error.response.data.message
? error.response.data.message
: "Something went wrong!"
);
});
}
// Generate password function
const generatePassword = (name, email) => {
const combinedStr = (name + email).toLowerCase(); // Convert to lowercase for consistency
const specialChars = "@#*"; // Define the set of special characters
const alphaChars = combinedStr.match(/[a-zA-Z]/g); // Filter out alphabetic characters
const filteredChars = combinedStr.match(/[^\W_]/g); // Filter out non-alphanumeric characters
let passwordChars = alphaChars.concat(filteredChars); // Combine alphabetic and filtered characters
// Insert a random special character at a random position in the password characters array
const specialChar = specialChars.charAt(
Math.floor(Math.random() * specialChars.length)
); // Pick a random special character
const randomIndex = Math.floor(Math.random() * (passwordChars.length + 1)); // Pick a random position to insert the special character
passwordChars.splice(randomIndex, 0, specialChar); // Insert the special character at the random position
passwordChars = passwordChars.sort(() => Math.random() - 0.5); // Shuffle the characters
const password = passwordChars.join("").slice(0, 8); // Take the first 8 characters
return password;
};
const handleFormSubmit = async (e) => {
e.preventDefault();
try {
if (!user.name || !user.email) {
throw new Error("Fill all fields!");
}
// Generate password based on name and email
const generatedPassword = generatePassword(user.name, user.email);
console.log(generatedPassword); // Use generatedPassword instead of generatePassword
setUser({ ...user, password: generatedPassword }); // Set generated password to user state
const response = await axios.post("/api/v1/user/register", {
...user, // Send user details
password: generatedPassword, // Send generated password to the backend
});
if (response.status === 201) {
toast.success("User Added Successful");
setUserId(response.data.userId);
}
} catch (error) {
console.log(error.response.data.message);
toast.error(error.response.data.message);
}
};
console.log(user);
console.log("this is the id ", id);
return (
<div>
<Card sx={{ padding: "1rem", marginBottom: "1rem" }}>
<form style={{ marginBottom: "2rem" }} onSubmit={handleFormSubmit}>
<TextField
id="name"
required
type="text"
sx={{ marginBottom: "2rem", width: "50%" }}
name="name"
value={user.name}
label="Name"
variant="outlined"
onChange={handerInputChanges}
/>
<br />
<TextField
id="email"
type="email"
sx={{ mb: "2rem", width: "50%" }}
required
name="email"
value={user.email}
label="Email"
variant="outlined"
onChange={handerInputChanges}
/>
<br />
<Button variant="contained" disabled={id?.length > 0} type="submit">
Add user
</Button>
<br />
</form>
<form onSubmit={handleAddressSubmit}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Grid container spacing={2}>
<Grid item xs={6}>
<FormControl variant="outlined" fullWidth>
<FormHelperText
id="outlined-weight-helper-text"
sx={styles.formStyle}
>
FIRST NAME*
</FormHelperText>
<OutlinedInput
size="small"
id="outlined-adornment-weight"
placeholder="First name"
aria-describedby="outlined-weight-helper-text"
name="first_Name"
required
type="text"
onChange={(e) => handleChange(e)}
// value={accountDetails.firstname}
// onChange={handerInputChanges}
/>
</FormControl>
</Grid>
<Grid item xs={6}>
<FormControl variant="outlined" fullWidth>
<FormHelperText
id="outlined-weight-helper-text"
sx={styles.formStyle}
>
LAST NAME*
</FormHelperText>
<OutlinedInput
size="small"
id="outlined-adornment-weight"
placeholder="Last name"
aria-describedby="outlined-weight-helper-text"
name="last_Name"
required
type="text"
onChange={(e) => handleChange(e)}
// value={accountDetails.firstname}
// onChange={handerInputChanges}
/>
</FormControl>
</Grid>
<Grid item xs={12}>
<FormControl fullWidth variant="outlined">
<FormHelperText
id="outlined-weight-helper-text"
sx={styles.formStyle}
>
PHONE NUMBER*
</FormHelperText>
<OutlinedInput
size="small"
id="outlined-adornment-weight"
placeholder="Phone name"
aria-describedby="outlined-weight-helper-text"
name="phone_Number"
required
type="number"
onChange={(e) => handleChange(e)}
// value={accountDetails.firstname}
// onChange={handerInputChanges}
/>
</FormControl>
</Grid>
<Grid item xs={12}>
<FormControl variant="outlined" fullWidth>
<FormHelperText
id="outlined-weight-helper-text"
sx={styles.formStyle}
>
STREET ADDRESS*
</FormHelperText>
<OutlinedInput
size="small"
id="outlined-adornment-weight"
placeholder="Street Address"
aria-describedby="outlined-weight-helper-text"
name="street"
required
type="text"
onChange={(e) => handleChange(e)}
// value={accountDetails.firstname}
// onChange={handerInputChanges}
/>
</FormControl>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<FormControl variant="outlined" fullWidth>
<FormHelperText
id="outlined-weight-helper-text"
sx={styles.formStyle}
>
COUNTRY*
</FormHelperText>
<OutlinedInput
size="small"
id="outlined-adornment-weight"
placeholder="Country"
aria-describedby="outlined-weight-helper-text"
name="country"
required
type="text"
onChange={(e) => handleChange(e)}
// value={accountDetails.firstname}
// onChange={handerInputChanges}
/>
</FormControl>
</Grid>
<Grid item xs={12}>
<FormControl fullWidth variant="outlined">
<FormHelperText
id="outlined-weight-helper-text"
sx={styles.formStyle}
>
TOWN CITY*
</FormHelperText>
<OutlinedInput
size="small"
id="outlined-adornment-weight"
placeholder="Town City"
aria-describedby="outlined-weight-helper-text"
name="city"
required
type="text"
onChange={(e) => handleChange(e)}
// value={accountDetails.firstname}
// onChange={handerInputChanges}
/>
</FormControl>
</Grid>
<Grid item xs={12}>
<Grid container spacing={2}>
<Grid item xs={6}>
<FormControl variant="outlined" fullWidth>
<FormHelperText
id="outlined-weight-helper-text"
sx={styles.formStyle}
>
STATE*
</FormHelperText>
<OutlinedInput
size="small"
id="outlined-adornment-weight"
placeholder="State"
aria-describedby="outlined-weight-helper-text"
name="state"
required
type="text"
onChange={(e) => handleChange(e)}
// value={accountDetails.firstname}
// onChange={handerInputChanges}
/>
</FormControl>
</Grid>
<Grid item xs={6}>
<FormControl variant="outlined" fullWidth>
<FormHelperText
id="outlined-weight-helper-text"
sx={styles.formStyle}
>
ZIP CODE*
</FormHelperText>
<OutlinedInput
size="small"
id="outlined-adornment-weight"
placeholder="Zip Code"
aria-describedby="outlined-weight-helper-text"
name="postalCode"
required
type="number"
onChange={(e) => handleChange(e)}
// value={accountDetails.firstname}
// onChange={handerInputChanges}
/>
</FormControl>
</Grid>
<Grid item xs={12}>
<Button
variant="contained"
disabled={id?.length == 0}
type="submit"
onClick={handleAddressSubmit}
>
Add address
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</form>
</Card>
</div>
);
};
export default AddCustomer;

View File

@ -131,7 +131,7 @@ const CustomerTable = () => {
All Customers All Customers
</div> </div>
{/* <div className="page-title-right"> <div className="page-title-right">
<Button <Button
variant="contained" variant="contained"
color="primary" color="primary"
@ -141,12 +141,12 @@ const CustomerTable = () => {
textTransform: "capitalize", textTransform: "capitalize",
}} }}
onClick={() => { onClick={() => {
navigate("/users-address/add", { replace: true }); navigate("/add-customer");
}} }}
> >
Add User Add User
</Button> </Button>
</div> */} </div>
</div> </div>
</div> </div>
</div> </div>