diff --git a/src/views/PrincipalDistributors/AddMultiplePD.js b/src/views/PrincipalDistributors/AddMultiplePD.js index 80b6dd4..b8bd623 100644 --- a/src/views/PrincipalDistributors/AddMultiplePD.js +++ b/src/views/PrincipalDistributors/AddMultiplePD.js @@ -52,21 +52,21 @@ const AddMultiplePd = () => { }, } ); - // console.log(data); - if (data.errors && data.errors.length > 0) { + console.log(data); + if (data?.errors && data?.errors?.length > 0) { setErrors(data.errors); } - if (data.newlyCreated && data.newlyCreated.length > 0) { - setNewlyCreated(data.newlyCreated); + if (data?.newlyCreated && data?.newlyCreated?.length > 0) { + setNewlyCreated(data?.newlyCreated); } - if (data.updatedDistributors && data.updatedDistributors.length > 0) { - setUpdatedDistributors(data.updatedDistributors); + if (data?.updatedDistributors && data?.updatedDistributors?.length > 0) { + setUpdatedDistributors(data?.updatedDistributors); // console.log(data.updatedDistributors); } // Redirect or display success message - if (data.errors && data.errors.length > 0) { - setErrors(data.errors); + if (data?.errors && data?.errors.length > 0) { + setErrors(data?.errors); swal({ title: "SpreadSheet Upload Successful", text: "A few Principal Distributor have errors. Please fix them and upload again.", @@ -74,8 +74,8 @@ const AddMultiplePd = () => { button: "OK", }); } else if ( - data.processedUsers.newlyCreated > 0 || - data.processedUsers.updatedDistributors > 0 + data?.newlyCreated > 0 || + data?.updatedDistributors > 0 ) { swal({ title: "SpreadSheet Upload Successful", @@ -85,7 +85,7 @@ const AddMultiplePd = () => { }); } else { toast.success("File processed successfully with no new entries."); - navigate("/principal-distributors"); + navigate("/principal-distributor"); } setFile(null); // Clear the file input document.querySelector('input[type="file"]').value = ""; diff --git a/src/views/PrincipalDistributors/addPrincipalDistributor.js b/src/views/PrincipalDistributors/addPrincipalDistributor.js index e17346e..c0f48dc 100644 --- a/src/views/PrincipalDistributors/addPrincipalDistributor.js +++ b/src/views/PrincipalDistributors/addPrincipalDistributor.js @@ -121,6 +121,9 @@ const AddPrincipalDistributor = () => { `/api/shipping/address/admin/new/${userId}`, { ...data, + Name: user.name, + phoneNumber: user.phone, + isDefault: true, state: selectedState.label, // Send selected state label city: selectedCity.label, // Send selected city label }, diff --git a/src/views/PrincipalDistributors/singlePrincipalDistributorAllDetails.js b/src/views/PrincipalDistributors/singlePrincipalDistributorAllDetails.js index c8c8ce0..d40f969 100644 --- a/src/views/PrincipalDistributors/singlePrincipalDistributorAllDetails.js +++ b/src/views/PrincipalDistributors/singlePrincipalDistributorAllDetails.js @@ -1,11 +1,16 @@ -import { Typography, Button } from "@mui/material"; import axios from "axios"; import React, { useCallback, useEffect, useState, useRef } from "react"; import { Link, useParams, useNavigate } from "react-router-dom"; import swal from "sweetalert"; import { isAutheticated } from "src/auth"; +import { City, State } from "country-state-city"; +import { Modal, Button } from "react-bootstrap"; +import { Autocomplete, TextField, Typography, Box } from "@mui/material"; const SinglePrincipalDistributorAllDetails = () => { + const token = isAutheticated(); + const { _id } = useParams(); + const [user, setUser] = useState(null); const [userOrder, setUserOrder] = useState({ totalOrders: 0, @@ -13,9 +18,185 @@ const SinglePrincipalDistributorAllDetails = () => { lastPurchaseOrderDate: null, }); const [userAllAddress, setUserAllAddress] = useState([]); + const [gstNumber, setGstNumber] = useState(null); + const [panNumber, setPanNumber] = useState(null); + const [tradeName, setTradeName] = useState(null); + const [showModal, setShowModal] = useState(false); + const [isEditMode, setIsEditMode] = useState(false); + const [stateOptions, setStateOptions] = useState([]); + const [cityOptions, setCityOptions] = useState([]); + const [selectedState, setSelectedState] = useState(null); + const [selectedCity, setSelectedCity] = useState(null); + const [currentAddress, setCurrentAddress] = useState({ + Name: "", + tradeName: "", + gstNumber: "", + panNumber: "", + phoneNumber: "", + street: "", + city: "", + state: "", + postalCode: "", + country: "India", + isDefault: false, + }); - const token = isAutheticated(); - const { _id } = useParams(); + // Fetch states when the component mounts + useEffect(() => { + const fetchStates = () => { + const states = State.getStatesOfCountry("IN").map((state) => ({ + label: state.name, + value: state.isoCode, + })); + setStateOptions(states); + }; + fetchStates(); + }, []); + + // Fetch cities when a state is selected + useEffect(() => { + const fetchCities = () => { + if (selectedState) { + const cities = City.getCitiesOfState("IN", selectedState.value).map( + (city) => ({ + label: city.name, + value: city.name, + }) + ); + setCityOptions(cities); + } else { + setCityOptions([]); // Clear cities if no state is selected + } + }; + fetchCities(); + }, [selectedState]); + + // Open modal for add or edit mode + const handleOpenModal = (address = null) => { + setIsEditMode(!!address); // Set edit mode if address is provided + const initialAddress = address || { + Name: "", + tradeName: tradeName, + gstNumber: gstNumber, + panNumber: panNumber, + phoneNumber: "", + street: "", + city: "", + state: "", + postalCode: "", + country: "India", + isDefault: false, + }; + setCurrentAddress(initialAddress); + + // Fetch city options based on the state from the backend + if (address) { + const state = + stateOptions.find((option) => option.label === address.state) || null; + + // Set selected state from backend address + setSelectedState(state); + + // Fetch cities if state is found + if (state) { + const cities = City.getCitiesOfState("IN", state.value).map((city) => ({ + label: city.name, + value: city.name, + })); + setCityOptions(cities); + + // Set selected city if it exists in the fetched city options + const city = + cities.find((option) => option.label === address.city) || null; + setSelectedCity(city); // Set the selected city + } + } else { + setSelectedState(null); + setSelectedCity(null); + setCityOptions([]); // Clear city options if no address is provided + } + + setShowModal(true); + }; + + // Close modal without saving changes + const handleCloseModal = () => { + setShowModal(false); + // Reset selections to previous state when modal is closed + setSelectedState(null); // Reset state selection + setSelectedCity(null); // Reset city selection + setCurrentAddress({ + Name: "", + tradeName: "", + gstNumber: "", + panNumber: "", + phoneNumber: "", + street: "", + city: "", + state: "", + postalCode: "", + country: "India", + isDefault: false, + }); + }; + + // Save address logic for adding or updating + const handleSaveAddress = async () => { + try { + const updatedAddress = { + ...currentAddress, + gstNumber: gstNumber, + panNumber: panNumber, + tradeName: tradeName, + }; + const apiUrl = isEditMode + ? `/api/shipping/address/update/${currentAddress._id}` + : `/api/shipping/address/admin/new/${_id}`; + + // console.log(currentAddress); + const method = isEditMode ? "patch" : "post"; + + // Prepare the headers with the token + const headers = { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }; + + // Make the API call with the headers + await axios[method](apiUrl, updatedAddress, { headers }); + + swal( + "Success!", + `Address ${isEditMode ? "updated" : "added"} successfully!`, + "success" + ); + + handleCloseModal(); + getUserAddress(); + } catch (error) { + console.error("Error saving address:", error); + swal("Error!", "There was an error saving the address.", "error"); + } + }; + + const handleStateChange = (event, newValue) => { + setSelectedState(newValue); + setCurrentAddress((prev) => ({ + ...prev, + state: newValue ? newValue.label : "", + city: "", // Clear city when state changes + })); + setSelectedCity(null); // Reset city selection + setCityOptions([]); // Clear city options on state change + }; + + const handleCityChange = (event, newValue) => { + setSelectedCity(newValue); + setCurrentAddress((prev) => ({ + ...prev, + city: newValue ? newValue.label : "", + })); + }; // Fetch Shipping address of the individual user const getUserAddress = useCallback(async () => { @@ -28,7 +209,11 @@ const SinglePrincipalDistributorAllDetails = () => { }, } ); + // console.log(response.data); setUserAllAddress(response.data?.UserShippingAddress || []); + setGstNumber(response.data?.UserShippingAddress[0]?.gstNumber || ""); + setPanNumber(response.data?.UserShippingAddress[0]?.panNumber || ""); + setTradeName(response.data?.UserShippingAddress[0]?.tradeName || ""); } catch (error) { swal({ title: "Warning", @@ -68,6 +253,7 @@ const SinglePrincipalDistributorAllDetails = () => { Authorization: `Bearer ${token}`, }, }); + // console.log(response.data); setUser(response.data.user); } catch (error) { swal({ @@ -85,6 +271,37 @@ const SinglePrincipalDistributorAllDetails = () => { getUserAddress(); getUserDetails(); }, [_id, getOrdersCount, getUserAddress, getUserDetails]); + const handledeleteAddress = async (id) => { + try { + const response = await axios.delete( + `/api/shipping/address/delete/${id}`, // Address ID in the URL + { + headers: { + Authorization: `Bearer ${token}`, // Authorization header + }, + data: { userId: _id }, // User ID in the request body + } + ); + + swal({ + title: "Success", + text: response.data.message, + icon: "success", + button: "Close", + }); + + getUserAddress(); + } catch (error) { + // Handle errors here, ensuring that you access the error message correctly + swal({ + title: "Warning", + text: error.response?.data?.message || error.message, // Improved error handling + icon: "error", + button: "Close", + dangerMode: true, + }); + } + }; return (
@@ -96,17 +313,7 @@ const SinglePrincipalDistributorAllDetails = () => {
- +
@@ -210,10 +417,18 @@ const SinglePrincipalDistributorAllDetails = () => {
• Addresses{" "} -
{" "} -
- • Total Addresses : {userAllAddress?.length}{" "}
+
+
+ • Total Addresses: {userAllAddress?.length || 0}{" "} +
+ +
{userAllAddress?.length > 0 && (
{ style={{ background: "rgb(140, 213, 213)" }} > - - - {/* */} + + + + + + + - {userAllAddress?.length === 0 && ( - - + + + + + + + - )} - {userAllAddress?.map((address, i) => { - return ( - - - - - ); - })} + ))}
SL No.Address Profile ImageSL No.Trade NameGSTPANAddressDefaultAction
-
No Data Available
+ {userAllAddress?.map((address, i) => ( +
+ {i + 1} + + + {address?.tradeName + ? `${address.tradeName}` + : "No Trade Name"} + + + {address.gstNumber} + + {address.panNumber} + + + {address?.Name}-{address?.street}, {address?.city},{" "} + {address?.state}, {address?.country},{" "} + {address?.postalCode} + + + + {address.isDefault ? "Yes" : "No"} + + + +
{i + 1} - - {address?.first_Name} {address?.last_name} - {address.tradeName - ? `${address.tradeName},` - : "No tradeName "} - {address.gstNumber ? `${address.gstNumber},` : ""} - {address?.street},{address?.city},{address?.state}, - {address?.country},{address?.postalCode} - -
)} + {/* Modal for Adding/Editing Address */} + + + + {isEditMode ? "Edit Shipping Address" : "Add Shipping Address"} + + + +
+
+ {/* Name and Trade Name */} +
+ + + setCurrentAddress({ + ...currentAddress, + Name: e.target.value, + }) + } + className="form-control mb-3" + placeholder="Enter name" + /> +
+
+ + + setCurrentAddress({ + ...currentAddress, + tradeName: e.target.value, + }) + } + className="form-control mb-3" + placeholder="Enter trade name" + /> +
+
+ +
+ {/* GST Number and PAN Number */} +
+ + + setCurrentAddress({ + ...currentAddress, + gstNumber: e.target.value, + }) + } + className="form-control mb-3" + placeholder="Enter GST number" + /> +
+
+ + + setCurrentAddress({ + ...currentAddress, + panNumber: e.target.value, + }) + } + className="form-control mb-3" + placeholder="Enter PAN number" + /> +
+
+ +
+ {/* Phone Number and Street */} +
+ + + setCurrentAddress({ + ...currentAddress, + phoneNumber: e.target.value, + }) + } + className="form-control mb-3" + placeholder="Enter phone number" + /> +
+
+ + + setCurrentAddress({ + ...currentAddress, + street: e.target.value, + }) + } + className="form-control mb-3" + placeholder="Enter street" + /> +
+
+ +
+ {/* State and City */} +
+ ( + + )} + /> +
+
+ + option.value === value.value + } + renderInput={(params) => ( + + )} + /> +
+
+ +
+ {/* Postal Code and Country */} +
+ + + setCurrentAddress({ + ...currentAddress, + postalCode: e.target.value, + }) + } + className="form-control mb-3" + placeholder="Enter postal code" + /> +
+
+ + +
+
+
+
+ + +
+
+
+
+ + {/* */} + + +
diff --git a/src/views/Products/Products.js b/src/views/Products/Products.js index 720dd24..b2192dc 100644 --- a/src/views/Products/Products.js +++ b/src/views/Products/Products.js @@ -322,176 +322,183 @@ const Products = () => { style={{ background: "#ecdddd" }} > - Image - SKU - Product - Category Name - Brand Name - Price - Status - - Added On - Actions + + Image + + + SKU + + + Product + + + Category Name + + + Brand Name + + + Price + + + Status + + + Added On + + + Actions + {loading ? ( - + Loading... ) : productsData?.length > 0 ? ( - productsData?.map((product, i) => { - return ( - - - {product?.image && - product?.image?.length !== 0 ? ( - <> - preview - - ) : ( -
-

No

-

image

-

uploaded!

-
- )} - - {product.SKU} - {product.name} - - {product.category?.categoryName !== "" - ? product.category?.categoryName - : "Category Not selected "} - - - {product.brand?.brandName !== "" - ? product.brand?.brandName - : "Brand Not selected "} - - - {currencyDetails?.CurrencySymbol} - {product?.price} - - - + productsData?.map((product, i) => ( + + + {product?.image && + product?.image?.length !== 0 ? ( + preview + ) : ( +
+

No

+

image

+

uploaded!

+
+ )} + + + {product.SKU} + + + {product.name} + + + {product.category?.categoryName || + "Category Not selected"} + + + {product.brand?.brandName || + "Brand Not selected"} + + + {currencyDetails?.CurrencySymbol} + {product?.price} + + + + + + {new Date(product.createdAt).toLocaleString( + "en-IN", + { + weekday: "short", + month: "short", + day: "numeric", + year: "numeric", + hour: "numeric", + minute: "numeric", + hour12: true, + } + )} + + + - - - {new Date(product.createdAt).toLocaleString( - "en-IN", - { - weekday: "short", - month: "short", - day: "numeric", - year: "numeric", - hour: "numeric", - minute: "numeric", - hour12: true, - } - )} - - - - - - - - - - - - - - - - ); - }) - ) : ( - !loading && - productsData?.length === 0 && ( - - -
No Product Available...
+ View + + + + + + + + - ) + )) + ) : ( + + +
No Product Available...
+ + )}