From cc616e1b97db71b628d991c8231cdc0ef1d581b6 Mon Sep 17 00:00:00 2001 From: biruly-cyber Date: Tue, 6 Aug 2024 14:59:19 +0530 Subject: [PATCH] you can add and delete data form orderdetails page --- backend/app.js | 30 ++--- backend/controller/CustomerOrderController.js | 96 +++++++++++++-- backend/routes/CustomerOrderRoutes.js | 5 +- client/src/components/BedingDetails.jsx | 42 ++++++- client/src/components/LightDetails.jsx | 115 +++++++++++++++--- client/src/components/TentDetails.js | 80 +++++++++++- client/src/components/common/AddItems.jsx | 22 ++-- client/src/context/OrderdataContext.js | 1 - .../orderManagement/order/OrderDetails.js | 72 +++++++++-- .../track vehicles/VehicleLocation.jsx | 33 +++-- 10 files changed, 418 insertions(+), 78 deletions(-) diff --git a/backend/app.js b/backend/app.js index 4aac608..aa0a5cd 100644 --- a/backend/app.js +++ b/backend/app.js @@ -2,11 +2,10 @@ import express from "express"; import dotenv from "dotenv"; import cookieParser from "cookie-parser"; import cors from "cors"; -import http from "http" -import {Server} from "socket.io" +import http from "http"; +import { Server } from "socket.io"; import { Vehicle } from "./model/location.model.js"; - // /import all the routes import authRoutes from "./routes/AuthRoutes.js"; import leadRoutes from "./routes/LeadRoutes.js"; @@ -24,7 +23,6 @@ import vehicleRoute from "./routes/VehicleLocationRoute.js"; //export express export const app = express(); - //configure dot env file dotenv.config({ path: "./config/.env", @@ -35,7 +33,7 @@ app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); -export const server = http.createServer(app) +export const server = http.createServer(app); // Create Socket.IO server // Create Socket.IO server @@ -46,25 +44,27 @@ const io = new Server(server, { }, }); -io.on('connection', (socket) => { - console.log('New client connected'); +io.on("connection", (socket) => { + console.log("New client connected"); - socket.on('updateLocation', async (data) => { + socket.on("updateLocation", async (data) => { const { id, latitude, longitude } = data; + console.log(data) const vehicle = await Vehicle.findOneAndUpdate( { id }, - { latitude, longitude, updatedAt: new Date() }, + { $set: { latitude, longitude, updatedAt: new Date() } }, { upsert: true, new: true } ); - io.emit('locationUpdate', vehicle); + + io.emit("locationUpdate", vehicle); }); - socket.on("send-location", function (data){ - io.emit("recieve-location",{id:socket.id, ...data} ) - }) + socket.on("send-location", function (data) { + io.emit("recieve-location", { id: socket.id, ...data }); + }); - socket.on('disconnect', () => { - console.log('Client disconnected'); + socket.on("disconnect", () => { + console.log("Client disconnected"); }); }); diff --git a/backend/controller/CustomerOrderController.js b/backend/controller/CustomerOrderController.js index 19448d3..16cd35c 100644 --- a/backend/controller/CustomerOrderController.js +++ b/backend/controller/CustomerOrderController.js @@ -213,20 +213,35 @@ export const addItems = async (req, res) => { // if flag id bedding then if (flag === "beding") { - console.log(findOrder.bistarOrder); - // then push bistar order - findOrder.bistarOrder.push({ - itemNameBistar: item.itemName, - itemCountForOrderBistar: item.quantity, - }); + // Check if the item already exists + const itemIndex = findOrder.bistarOrder.findIndex( + (orderItem) => orderItem.itemNameBistar === item.itemName + ); + + if (itemIndex > -1) { + // Item exists, update the quantity + findOrder.bistarOrder[itemIndex].itemCountForOrderBistar = + item.quantity; + var message = "item updated"; + } else { + // Item does not exist, push new item + findOrder.bistarOrder.push({ + itemNameBistar: item.itemName, + itemCountForOrderBistar: item.quantity, + }); + var message = "new item added"; + } + const addedNew = await findOrder.save(); - //retrun the response + // Return the response res.status(200).json({ success: true, - message: "new item added", + message: message, + item: addedNew, }); } + // if flag id bedding then if (flag === "light") { console.log(findOrder.lightOrder); @@ -268,3 +283,68 @@ export const addItems = async (req, res) => { } } catch (error) {} }; + +// delete controller for remove the item +export const removeItem = async (req, res) => { + const { id } = req.params; + console.log(id); + console.log(req.body); + + const { flag, item } = req.body; + + try { + // Find the order first + const findOrder = await CustomerOrder.findById(id); + + // Validation + if (!findOrder) { + return res.status(404).json({ + success: false, + message: "Order not found", + }); + } + + // If flag is "beding" + if (flag === "beding") { + // Check if the item exists + const itemIndex = findOrder.bistarOrder.findIndex( + (orderItem) => orderItem.itemNameBistar === item.itemNameBistar + ); + + console.log("working"); + console.log(itemIndex); + + if (itemIndex === -1) { + // Item not found + return res.status(404).json({ + success: false, + message: "Item not found", + }); + } + + // Remove the item + findOrder.bistarOrder.splice(itemIndex, 1); + + // Save the updated order + const updatedOrder = await findOrder.save(); + + // Return the response + res.status(200).json({ + success: true, + message: "Item removed successfully", + item: updatedOrder.bistarOrder, + }); + } else { + res.status(400).json({ + success: false, + message: "Invalid flag value", + }); + } + } catch (error) { + console.error(error); + res.status(500).json({ + success: false, + message: "An error occurred", + }); + } +}; diff --git a/backend/routes/CustomerOrderRoutes.js b/backend/routes/CustomerOrderRoutes.js index be5e90a..abaf83f 100644 --- a/backend/routes/CustomerOrderRoutes.js +++ b/backend/routes/CustomerOrderRoutes.js @@ -1,5 +1,5 @@ import express from "express" -import { addItems, createOrder, deleteOrder, getAllOrderOfACustomer, getAllOrders, getOrderById, updateOrder, updateOrderStatus } from "../controller/CustomerOrderController.js" +import { addItems, createOrder, deleteOrder, getAllOrderOfACustomer, getAllOrders, getOrderById, removeItem, updateOrder, updateOrderStatus } from "../controller/CustomerOrderController.js" const router = express.Router() @@ -27,5 +27,8 @@ router.put("/update/status/:id", updateOrderStatus) //to add items in order details page router.post("/add-item/:id", addItems) +// remove the item +router.post("/remove-item/:id", removeItem) + export default router \ No newline at end of file diff --git a/client/src/components/BedingDetails.jsx b/client/src/components/BedingDetails.jsx index a1b647a..614d9a6 100644 --- a/client/src/components/BedingDetails.jsx +++ b/client/src/components/BedingDetails.jsx @@ -1,11 +1,13 @@ import { Edit, Trash } from "lucide-react"; -import React, { memo, useEffect, useState } from "react"; +import React, { memo, useState } from "react"; import AddItems from "./common/AddItems"; import axios from "axios"; import config from "../config/config"; +import toast, { Toaster } from "react-hot-toast"; const BedingDetails = ({ bedingDetails, isAddItemClicked, id, flag }) => { const [itemToEdit, setItemToEdit] = useState(null); + const [isUpdateCliked, setIsUpdateCliked] = useState(isAddItemClicked); // Handle on addItem const handleAddItem = async (item) => { @@ -15,6 +17,13 @@ const BedingDetails = ({ bedingDetails, isAddItemClicked, id, flag }) => { { item, flag } ); console.log("Item added:", response); + const { success, message } = response.data; + if (success) { + toast.success(message); + setIsUpdateCliked(false); + // reload the screen + window.location.reload(); + } // Optionally update the local state or refresh the data from the backend } catch (error) { console.error("Error adding item:", error); @@ -25,19 +34,42 @@ const BedingDetails = ({ bedingDetails, isAddItemClicked, id, flag }) => { // Handle the edit button click const handleEditClick = (item) => { setItemToEdit(item); + setIsUpdateCliked((prev) => !prev); }; // Handle the delete button click - const handleDeleteClick = (item) => { - console.log(item._id); + const handleDeleteClick = async(item) => { + try { + const response = await axios.post( + `${config.apiUrl}/order/remove-item/${id}`, + { item, flag } + ); + const { success, message } = response.data; + if (success) { + toast.success(message); + setIsUpdateCliked(false); + // reload the screen + window.location.reload(); + } + // Optionally update the local state or refresh the data from the backend + } catch (error) { + console.error("Error removing item:", error); + // Handle error accordingly + } }; return (
+ {bedingDetails?.length > 0 ? ( <> - {isAddItemClicked && ( - + {(isAddItemClicked || isUpdateCliked) && ( + )} diff --git a/client/src/components/LightDetails.jsx b/client/src/components/LightDetails.jsx index 77ec6ca..8b06d37 100644 --- a/client/src/components/LightDetails.jsx +++ b/client/src/components/LightDetails.jsx @@ -1,28 +1,105 @@ -import React, { memo } from "react"; +import React, { memo, useState } from "react"; +import AddItems from "./common/AddItems"; +import toast, { Toaster } from "react-hot-toast"; +import config from "../config/config"; +import axios from "axios"; +import { Edit, Trash } from "lucide-react"; +const LightDetails = ({ lightDetails, id, flag, isAddItemClicked }) => { + const [itemToEdit, setItemToEdit] = useState(null); + const [isUpdateCliked, setIsUpdateCliked] = useState(isAddItemClicked); -const LightDetails = ({ lightDetails }) => { + // Handle on addItem + const handleAddItem = async (item) => { + try { + const response = await axios.post( + `${config.apiUrl}/order/add-item/${id}`, + { item, flag } + ); + console.log("Item added:", response); + const { success, message } = response.data; + if (success) { + toast.success(message); + setIsUpdateCliked(false); + // reload the screen + window.location.reload(); + } + // Optionally update the local state or refresh the data from the backend + } catch (error) { + console.error("Error adding item:", error); + // Handle error accordingly + } + }; + + // Handle the edit button click + const handleEditClick = (item) => { + setItemToEdit(item); + setIsUpdateCliked((prev) => !prev); + }; + + // Handle the delete button click + const handleDeleteClick = async (item) => { + try { + const response = await axios.post( + `${config.apiUrl}/order/remove-item/${id}`, + { item, flag } + ); + const { success, message } = response.data; + if (success) { + toast.success(message); + setIsUpdateCliked(false); + // reload the screen + window.location.reload(); + } + // Optionally update the local state or refresh the data from the backend + } catch (error) { + console.error("Error removing item:", error); + // Handle error accordingly + } + }; return (
+ {lightDetails?.length > 0 ? ( -
- - - - - - - - - {lightDetails.map((item, index) => ( - - - - + <> + {(isAddItemClicked || isUpdateCliked) && ( + + )} +
S.No.Item NameItem Quantity
{index + 1}{item.itemNameLight}{item.itemCountForOrderLight}
+ + + + + - ))} - -
S.No.Item NameItem Quantity
+ + + {lightDetails.map((item, index) => ( + + {index + 1} + {item.itemNameLight} + + {item.itemCountForOrderLight} + + handleEditClick(item)} + /> + handleDeleteClick(item)} + /> + + + ))} + + + ) : (
There are no light details available. diff --git a/client/src/components/TentDetails.js b/client/src/components/TentDetails.js index 2b12183..db80507 100644 --- a/client/src/components/TentDetails.js +++ b/client/src/components/TentDetails.js @@ -1,10 +1,75 @@ -import React, { memo } from "react"; +import axios from "axios"; +import React, { memo, useState } from "react"; +import config from "../config/config"; +import toast, { Toaster } from "react-hot-toast"; +import AddItems from "./common/AddItems"; +import { Edit, Trash } from "lucide-react"; -const TentDetails = ({ tentDetails }) => { +const TentDetails = ({ tentDetails, id, flag, isAddItemClicked }) => { + const [itemToEdit, setItemToEdit] = useState(null); + const [isUpdateCliked, setIsUpdateCliked] = useState(isAddItemClicked); + + // Handle on addItem + const handleAddItem = async (item) => { + try { + const response = await axios.post( + `${config.apiUrl}/order/add-item/${id}`, + { item, flag } + ); + console.log("Item added:", response); + const { success, message } = response.data; + if (success) { + toast.success(message); + setIsUpdateCliked(false); + // reload the screen + window.location.reload(); + } + // Optionally update the local state or refresh the data from the backend + } catch (error) { + console.error("Error adding item:", error); + // Handle error accordingly + } + }; + + // Handle the edit button click + const handleEditClick = (item) => { + setItemToEdit(item); + setIsUpdateCliked((prev) => !prev); + }; + + // Handle the delete button click + const handleDeleteClick = async(item) => { + try { + const response = await axios.post( + `${config.apiUrl}/order/remove-item/${id}`, + { item, flag } + ); + const { success, message } = response.data; + if (success) { + toast.success(message); + setIsUpdateCliked(false); + // reload the screen + window.location.reload(); + } + // Optionally update the local state or refresh the data from the backend + } catch (error) { + console.error("Error removing item:", error); + // Handle error accordingly + } + }; return (
+ {tentDetails?.itemList?.length > 0 ? ( <> + {(isAddItemClicked || isUpdateCliked) && ( + + )}
Tent Area: @@ -20,6 +85,7 @@ const TentDetails = ({ tentDetails }) => { S No. Item Name Item Count + Action @@ -34,6 +100,16 @@ const TentDetails = ({ tentDetails }) => { {item.itemCountForOrderTent ?? "N/A"} + + handleEditClick(item)} + /> + handleDeleteClick(item)} + /> + ))} diff --git a/client/src/components/common/AddItems.jsx b/client/src/components/common/AddItems.jsx index d5a5caf..7535ee4 100644 --- a/client/src/components/common/AddItems.jsx +++ b/client/src/components/common/AddItems.jsx @@ -99,20 +99,28 @@ const AddItems = ({ Select an item - {optionsBistar.map((option) => ( + {optionsBistar.map((option, index) => ( {option.label} ))} ) : ( - setItemName(e.target.value)} - /> + onChange={handleSelectChange} + displayEmpty + className="rounded-sm outline-blue-500 w-60 h-9 border border-blue-500 focus:outline-none" + > + + Select an item + + {optionsBistar.map((option, index) => ( + + {option.label} + + ))} + )}
diff --git a/client/src/context/OrderdataContext.js b/client/src/context/OrderdataContext.js index 43a85a9..2e36c0b 100644 --- a/client/src/context/OrderdataContext.js +++ b/client/src/context/OrderdataContext.js @@ -35,7 +35,6 @@ const OrderDataContextProvider = ({ children }) => { fetchAllBedingOrder(); }, []); - console.log(allOrder) return ( diff --git a/client/src/pages/orderManagement/order/OrderDetails.js b/client/src/pages/orderManagement/order/OrderDetails.js index b6e6fea..cf1fe74 100644 --- a/client/src/pages/orderManagement/order/OrderDetails.js +++ b/client/src/pages/orderManagement/order/OrderDetails.js @@ -16,6 +16,8 @@ import { Plus, X } from "lucide-react"; const OrderDetails = () => { const [isLoading, setIsLoading] = useState(false); const [isAddItemClicked, setIsAddItemClicked] = useState(false); + const [isAddTentItemClicked, setIsAddTentItemClicked] = useState(false); + const [isAddLightItemClicked, setIsAddLightItemClicked] = useState(false); //customer details usestate const [isEditCustomerDetails, setIsEditCustomerDetails] = useState(false); const [customerName, setCustomerName] = useState(""); @@ -379,12 +381,30 @@ ${ return printableContent; }; + // handle for bedding detail const handleOnAddItem = () => { setIsAddItemClicked((prev) => !prev); }; + // handle for close bedding details const handleOnAddItemClose = () => { setIsAddItemClicked((prev) => !prev); }; + // handle for tent detail + const handleOnAddTentItem = () => { + setIsAddTentItemClicked((prev) => !prev); + }; + // handle for close tent details + const handleOnAddTentItemClose = () => { + setIsAddTentItemClicked((prev) => !prev); + }; + // handle for light detail + const handleOnAddLightItem = () => { + setIsAddLightItemClicked((prev) => !prev); + }; + // handle for close light details + const handleOnAddLightItemClose = () => { + setIsAddLightItemClicked((prev) => !prev); + }; return (
@@ -568,19 +588,55 @@ ${ {tentDetails?.itemList?.length > 0 && (
-

- Tent Details -

- +
+

+ Tent Details +

+ {isAddItemClicked ? ( + handleOnAddTentItemClose()} + /> + ) : ( + handleOnAddTentItem()} + /> + )} +
+
)} {lightDetails.length > 0 && (
-

- Light Details -

- +
+

+ Light details +

+ {isAddLightItemClicked ? ( + handleOnAddLightItemClose()} + /> + ) : ( + handleOnAddLightItem()} + /> + )} +
+
)}
diff --git a/client/src/pages/orderManagement/track vehicles/VehicleLocation.jsx b/client/src/pages/orderManagement/track vehicles/VehicleLocation.jsx index 40565d4..5be4fc6 100644 --- a/client/src/pages/orderManagement/track vehicles/VehicleLocation.jsx +++ b/client/src/pages/orderManagement/track vehicles/VehicleLocation.jsx @@ -1,11 +1,16 @@ import React, { useEffect, useRef, useState } from "react"; -import { MapContainer, TileLayer, Marker, Popup, useMapEvents } from "react-leaflet"; +import { + MapContainer, + TileLayer, + Marker, + Popup, + useMapEvents, +} from "react-leaflet"; import "leaflet/dist/leaflet.css"; import L from "leaflet"; import axios from "axios"; import { io } from "socket.io-client"; - delete L.Icon.Default.prototype._getIconUrl; L.Icon.Default.mergeOptions({ iconRetinaUrl: @@ -16,7 +21,7 @@ L.Icon.Default.mergeOptions({ "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png", }); -const socket = io("https://erp-e2hp.onrender.com"); +const socket = io("http://localhost:5000"); const VehicleLocation = () => { const [vehicles, setVehicles] = useState([]); @@ -28,9 +33,9 @@ const VehicleLocation = () => { if (navigator.geolocation) { navigator.geolocation.watchPosition( (position) => { - const { latitude, longitude } = position.coords; + const {id, latitude, longitude } = position.coords; setLatestPosition([latitude, longitude]); - socket.emit("send-location", { latitude, longitude }); + socket.emit("send-location", {id, latitude, longitude }); }, (error) => { console.error(error); @@ -42,16 +47,18 @@ const VehicleLocation = () => { } ); } - }, []); - + }, [latestPosition]); + console.log(latestPosition); useEffect(() => { const fetchVehicles = async () => { - const response = await axios.get(`https://erp-e2hp.onrender.com/api/v1/vehicle/location`); - console.log(response) + const response = await axios.get( + `http://localhost:5000/api/v1/vehicle/location` + ); + console.log(response); setVehicles(response.data.vehicles); }; - // fetchVehicles(); + fetchVehicles(); socket.on("locationUpdate", (vehicle) => { setVehicles((prevVehicles) => { @@ -80,10 +87,12 @@ const VehicleLocation = () => { return (
{ mapRef.current = mapInstance; }} + whenCreated={(mapInstance) => { + mapRef.current = mapInstance; + }} >