diff --git a/backend/controllers/shop/sub-controllers/deliveryPersonController.js b/backend/controllers/shop/sub-controllers/deliveryPersonController.js
new file mode 100644
index 00000000..ea24cc4b
--- /dev/null
+++ b/backend/controllers/shop/sub-controllers/deliveryPersonController.js
@@ -0,0 +1,269 @@
+const DeliveryPerson = require("../../../model/shop/sub-model/DeliveryPerson");
+const { hashPassword } = require("../../../services/sub-service/hashPassword");
+const {
+ validateEmail,
+ validatePhoneNumber,
+} = require("../../../services/sub-service/couponValidator");
+
+exports.successResponse = (res, statusCode, message, data = {}) => {
+ res.status(statusCode).json({
+ status: "success",
+ message,
+ data,
+ });
+};
+
+exports.errorResponse = (res, statusCode, message, error = {}) => {
+ res.status(statusCode).json({
+ status: "error",
+ message,
+ error,
+ });
+};
+
+// Create a new Delivery Person
+exports.createDeliveryPerson = async (req, res) => {
+ try {
+ const {
+ name,
+ email,
+ phone_number,
+ status,
+ assigned_routes,
+ vehicle_details,
+ profile_picture,
+ password,
+ } = req.body;
+
+ // Validate required fields
+ if (!name || !email || !phone_number || !status) {
+ return errorResponse(res, 400, "All required fields must be provided.");
+ }
+
+ // Validate email and phone number formats
+ if (!validateEmail(email))
+ return errorResponse(res, 400, "Invalid email format.");
+ if (!validatePhoneNumber(phone_number))
+ return errorResponse(res, 400, "Invalid phone number format.");
+
+ // Check if email already exists
+ const existingEmail = await DeliveryPerson.findOne({ email });
+ if (existingEmail) return errorResponse(res, 400, "Email already exists.");
+
+ // Hash password if provided
+ const hashedPassword = password ? await hashPassword(password) : undefined;
+
+ const newDeliveryPerson = new DeliveryPerson({
+ name,
+ email,
+ phone_number,
+ status,
+ assigned_routes,
+ vehicle_details,
+ profile_picture,
+ password: hashedPassword,
+ });
+
+ await newDeliveryPerson.save();
+ successResponse(
+ res,
+ 201,
+ "Delivery person created successfully.",
+ newDeliveryPerson
+ );
+ } catch (error) {
+ errorResponse(res, 500, error.message);
+ }
+};
+
+// Get all Delivery Persons with pagination
+exports.getAllDeliveryPersons = async (req, res) => {
+ try {
+ const { page = 1, limit = 10 } = req.query;
+ const deliveryPersons = await DeliveryPerson.find()
+ .select("name status vehicle_details.vehicle_type")
+ .limit(parseInt(limit))
+ .skip((parseInt(page) - 1) * parseInt(limit));
+ const count = await DeliveryPerson.countDocuments();
+
+ successResponse(res, 200, "Delivery persons retrieved successfully.", {
+ deliveryPersons,
+ totalPages: Math.ceil(count / limit),
+ currentPage: parseInt(page),
+ });
+ } catch (error) {
+ errorResponse(res, 500, error.message);
+ }
+};
+
+// Get a Delivery Person by ID
+exports.getDeliveryPersonById = async (req, res) => {
+ try {
+ const deliveryPerson = await DeliveryPerson.findById(
+ req.params.id
+ ).populate("assigned_routes");
+ if (!deliveryPerson)
+ return errorResponse(res, 404, "Delivery person not found.");
+ successResponse(
+ res,
+ 200,
+ "Delivery person retrieved successfully.",
+ deliveryPerson
+ );
+ } catch (error) {
+ errorResponse(res, 500, error.message);
+ }
+};
+
+// Update a Delivery Person
+exports.updateDeliveryPerson = async (req, res) => {
+ try {
+ const updates = req.body;
+
+ // Validate and hash password if provided
+ if (updates.password)
+ updates.password = await hashPassword(updates.password);
+
+ // Validate email and phone number if updated
+ if (updates.email && !validateEmail(updates.email))
+ return errorResponse(res, 400, "Invalid email format.");
+ if (updates.phone_number && !validatePhoneNumber(updates.phone_number))
+ return errorResponse(res, 400, "Invalid phone number format.");
+
+ // Check if email already exists (excluding current delivery person)
+ if (updates.email) {
+ const existingEmail = await DeliveryPerson.findOne({
+ email: updates.email,
+ _id: { $ne: req.params.id },
+ });
+ if (existingEmail)
+ return errorResponse(res, 400, "Email already exists.");
+ }
+
+ const updatedDeliveryPerson = await DeliveryPerson.findByIdAndUpdate(
+ req.params.id,
+ updates,
+ { new: true }
+ );
+ if (!updatedDeliveryPerson)
+ return errorResponse(res, 404, "Delivery person not found.");
+ successResponse(
+ res,
+ 200,
+ "Delivery person updated successfully.",
+ updatedDeliveryPerson
+ );
+ } catch (error) {
+ errorResponse(res, 500, error.message);
+ }
+};
+
+// Soft delete (deactivate) a Delivery Person
+exports.deleteDeliveryPerson = async (req, res) => {
+ try {
+ const deliveryPerson = await DeliveryPerson.findById(req.params.id);
+ if (!deliveryPerson)
+ return errorResponse(res, 404, "Delivery person not found.");
+
+ deliveryPerson.status = "inactive";
+ await deliveryPerson.save();
+ successResponse(res, 200, "Delivery person deactivated successfully.");
+ } catch (error) {
+ errorResponse(res, 500, error.message);
+ }
+};
+
+// Activate or Deactivate Delivery Person
+exports.toggleStatus = async (req, res) => {
+ try {
+ const { status } = req.body;
+ if (!["active", "inactive"].includes(status))
+ return errorResponse(res, 400, "Invalid status.");
+
+ const deliveryPerson = await DeliveryPerson.findById(req.params.id);
+ if (!deliveryPerson)
+ return errorResponse(res, 404, "Delivery person not found.");
+
+ deliveryPerson.status = status;
+ await deliveryPerson.save();
+ successResponse(res, 200, "Delivery person status updated successfully.", {
+ status: deliveryPerson.status,
+ });
+ } catch (error) {
+ errorResponse(res, 500, error.message);
+ }
+};
+
+// Helper functions for response handling
+const validateVehicleDetails = (vehicleDetails) => {
+ const { vehicle_type, vehicle_number } = vehicleDetails;
+ if (vehicle_type && typeof vehicle_type !== "string") return false;
+ if (vehicle_number && typeof vehicle_number !== "string") return false;
+ return true;
+};
+
+// Search Delivery Person by name
+exports.searchDeliveryPersonByName = async (req, res) => {
+ try {
+ const { name } = req.query;
+ const deliveryPersons = await DeliveryPerson.find({
+ name: { $regex: name, $options: "i" },
+ });
+ successResponse(
+ res,
+ 200,
+ "Search results retrieved successfully.",
+ deliveryPersons
+ );
+ } catch (error) {
+ errorResponse(res, 500, error.message);
+ }
+};
+
+// Get all assigned routes for a Delivery Person
+exports.getAssignedRoutes = async (req, res) => {
+ try {
+ const deliveryPerson = await DeliveryPerson.findById(
+ req.params.id
+ ).populate("assigned_routes");
+ if (!deliveryPerson)
+ return errorResponse(res, 404, "Delivery person not found.");
+ successResponse(
+ res,
+ 200,
+ "Assigned routes retrieved successfully.",
+ deliveryPerson.assigned_routes
+ );
+ } catch (error) {
+ errorResponse(res, 500, error.message);
+ }
+};
+
+// Change Delivery Person's vehicle details
+exports.updateVehicleDetails = async (req, res) => {
+ try {
+ const { vehicle_details } = req.body;
+
+ // Validate vehicle details format
+ if (vehicle_details && !validateVehicleDetails(vehicle_details)) {
+ return errorResponse(res, 400, "Invalid vehicle details format.");
+ }
+
+ const updatedDeliveryPerson = await DeliveryPerson.findByIdAndUpdate(
+ req.params.id,
+ { vehicle_details },
+ { new: true }
+ );
+
+ if (!updatedDeliveryPerson)
+ return errorResponse(res, 404, "Delivery person not found.");
+ successResponse(
+ res,
+ 200,
+ "Vehicle details updated successfully.",
+ updatedDeliveryPerson.vehicle_details
+ );
+ } catch (error) {
+ errorResponse(res, 500, error.message);
+ }
+};
diff --git a/backend/middleware/sub-ware/validate.js b/backend/middleware/sub-ware/validate.js
new file mode 100644
index 00000000..792c4a16
--- /dev/null
+++ b/backend/middleware/sub-ware/validate.js
@@ -0,0 +1,15 @@
+
+const { check, validationResult } = require('express-validator');
+
+exports.validateDeliveryPerson = [
+ check('email').isEmail().withMessage('Email is invalid'),
+ check('phone_number').isMobilePhone().withMessage('Phone number is invalid'),
+ check('status').isIn(['active', 'inactive']).withMessage('Status must be active or inactive'),
+ (req, res, next) => {
+ const errors = validationResult(req);
+ if (!errors.isEmpty()) {
+ return res.status(400).json({ errors: errors.array() });
+ }
+ next();
+ }
+];
diff --git a/backend/model/shop/sub-model/DeliveryPerson.js b/backend/model/shop/sub-model/DeliveryPerson.js
new file mode 100644
index 00000000..03d9afe3
--- /dev/null
+++ b/backend/model/shop/sub-model/DeliveryPerson.js
@@ -0,0 +1,44 @@
+// models/DeliveryPerson.js
+const mongoose = require("mongoose");
+
+const deliveryPersonSchema = new mongoose.Schema({
+ name: {
+ type: String,
+ required: true,
+ },
+ email: {
+ type: String,
+ required: true,
+ unique: true,
+ },
+ phone_number: {
+ type: String,
+ required: true,
+ },
+ status: {
+ type: String,
+ enum: ["active", "inactive"],
+ required: true,
+ },
+ assigned_routes: [{ type: mongoose.Schema.Types.ObjectId, ref: "Route" }],
+ vehicle_details: {
+ vehicle_type: { type: String },
+ vehicle_number: { type: String },
+ },
+ created_at: {
+ type: Date,
+ default: Date.now,
+ },
+ updated_at: {
+ type: Date,
+ default: Date.now,
+ },
+ password: {
+ type: String
+},
+ profile_picture: {
+ type: String
+ },
+});
+
+module.exports = mongoose.model("DeliveryPerson", deliveryPersonSchema);
diff --git a/backend/services/sub-service/hashPassword.js b/backend/services/sub-service/hashPassword.js
new file mode 100644
index 00000000..0c0a30a2
--- /dev/null
+++ b/backend/services/sub-service/hashPassword.js
@@ -0,0 +1,9 @@
+
+const bcrypt = require('bcrypt');
+
+const hashPassword = async (password) => {
+ const salt = await bcrypt.genSalt(10);
+ return bcrypt.hash(password, salt);
+};
+
+module.exports = { hashPassword };
diff --git a/frontend/src/AgroRentAI/components/RentSupportPage.jsx b/frontend/src/AgroRentAI/components/RentSupportPage.jsx
new file mode 100644
index 00000000..4a6dff18
--- /dev/null
+++ b/frontend/src/AgroRentAI/components/RentSupportPage.jsx
@@ -0,0 +1,35 @@
+import React from "react";
+import RentOrderTracking from "./sub-component/OrderTracking";
+import FAQ from "./sub-component/Fa";
+import LiveChat from "./sub-component/Livechat";
+
+
+const RentSupportPage = () => {
+ return (
+
+
Customer Support
+
+ {/* Live Chat Support Section */}
+
+
+ {/* Help Center & FAQ Section */}
+
+
+ {/* Order Tracking Section */}
+
+
+ );
+};
+export default RentSupportPage;
diff --git a/frontend/src/AgroRentAI/components/sub-component/Fa.jsx b/frontend/src/AgroRentAI/components/sub-component/Fa.jsx
new file mode 100644
index 00000000..bd34ce1b
--- /dev/null
+++ b/frontend/src/AgroRentAI/components/sub-component/Fa.jsx
@@ -0,0 +1,85 @@
+import React, { useState } from "react";
+import { FaChevronDown, FaChevronUp, FaSearch } from "react-icons/fa"; // Icons for toggling and search
+
+const FAQ = () => {
+ const [activeIndex, setActiveIndex] = useState(null); // For handling which FAQ is open
+ const [searchQuery, setSearchQuery] = useState("");
+
+ const faqs = [
+ {
+ question: "How do I rent a product?",
+ answer: "To rent a product, browse our catalog, choose the item you want, and select the rental duration.",
+ },
+ {
+ question: "What payment methods are accepted?",
+ answer: "We accept credit/debit cards, PayPal, and bank transfers.",
+ },
+ {
+ question: "How do I return a product?",
+ answer: "You can return the product by following the return instructions sent via email after your rental period ends.",
+ },
+ {
+ question: "What should I do if the product is damaged?",
+ answer: "If the product is damaged, please contact us immediately to arrange for repairs or a replacement.",
+ },
+ {
+ question: "Can I track my rental order?",
+ answer: "Yes, you can track your rental order status from your account dashboard.",
+ },
+ ];
+
+ const handleToggle = (index) => {
+ setActiveIndex(activeIndex === index ? null : index); // Toggle open/close
+ };
+
+ const filteredFaqs = faqs.filter((faq) =>
+ faq.question.toLowerCase().includes(searchQuery.toLowerCase())
+ );
+
+ return (
+
+
Help Center & FAQ
+
+ {/* Search Bar */}
+
+
+ setSearchQuery(e.target.value)}
+ placeholder="Search FAQ"
+ className="w-full p-2 border-none focus:outline-none text-gray-600"
+ />
+
+
+ {/* FAQ List */}
+
+ {filteredFaqs.length > 0 ? (
+ filteredFaqs.map((faq, index) => (
+
handleToggle(index)}
+ >
+
+
{faq.question}
+ {activeIndex === index ? (
+
+ ) : (
+
+ )}
+
+ {activeIndex === index && (
+
{faq.answer}
+ )}
+
+ ))
+ ) : (
+
No results found. Please try a different search term.
+ )}
+
+
+ );
+};
+
+export default FAQ;
diff --git a/frontend/src/AgroRentAI/components/sub-component/Livechat.jsx b/frontend/src/AgroRentAI/components/sub-component/Livechat.jsx
new file mode 100644
index 00000000..f4754b74
--- /dev/null
+++ b/frontend/src/AgroRentAI/components/sub-component/Livechat.jsx
@@ -0,0 +1,89 @@
+import React, { useState } from "react";
+import { FaPaperPlane, FaUserCircle } from "react-icons/fa"; // For icons
+
+const LiveChat = () => {
+ const [userName, setUserName] = useState("");
+ const [userMessage, setUserMessage] = useState("");
+ const [chatHistory, setChatHistory] = useState([
+ { sender: "Support", message: "Hello! How can we assist you today?" },
+ ]);
+
+ const handleMessageChange = (e) => {
+ setUserMessage(e.target.value);
+ };
+
+ const handleNameChange = (e) => {
+ setUserName(e.target.value);
+ };
+
+ const handleSendMessage = () => {
+ if (userMessage.trim() !== "") {
+ setChatHistory([...chatHistory, { sender: userName || "Guest", message: userMessage }]);
+ setUserMessage(""); // Clear input after sending message
+ setTimeout(() => {
+ setChatHistory((prevHistory) => [
+ ...prevHistory,
+ { sender: "Support", message: "We are here to help!" },
+ ]);
+ }, 1000); // Simulating a response after 1 second
+ }
+ };
+
+ return (
+
+
+ Live Chat Support
+
+
+ {/* User Name Field */}
+
+ Your Name (optional)
+
+
+
+ {/* Chat History */}
+
+
+ {chatHistory.map((chat, index) => (
+
+ {chat.sender}:
+ {chat.message}
+
+ ))}
+
+
+
+ {/* Message Input */}
+
+ Your Message
+
+
+
+ {/* Send Button */}
+
+ Send Message
+
+
+ );
+};
+
+export default LiveChat;
diff --git a/frontend/src/AgroRentAI/components/sub-component/OrderTracking.jsx b/frontend/src/AgroRentAI/components/sub-component/OrderTracking.jsx
new file mode 100644
index 00000000..0582dfaa
--- /dev/null
+++ b/frontend/src/AgroRentAI/components/sub-component/OrderTracking.jsx
@@ -0,0 +1,106 @@
+import React, { useState } from "react";
+import { FaSearch, FaSpinner, FaCheckCircle, FaTimesCircle } from "react-icons/fa"; // Icons for search, loading, and status
+
+const RentOrderTracking = () => {
+ const [orderId, setOrderId] = useState("");
+ const [orderStatus, setOrderStatus] = useState(null);
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+
+ const handleTrackOrder = () => {
+ if (!orderId) return; // Avoid empty submission
+
+ setLoading(true);
+ setError(null);
+ setOrderStatus(null);
+
+
+ // Simulate order tracking (In a real app, you would fetch this from an API)
+ const mockOrderStatus = {
+ 123: "Shipped - Expected delivery: 2 days",
+ 456: "In Transit - Expected delivery: 1 day",
+ 789: "Delivered - Thank you for renting!",
+ };
+
+ // Simulate an API request delay
+ setTimeout(() => {
+ if (mockOrderStatus[orderId]) {
+ setOrderStatus(mockOrderStatus[orderId]);
+ } else {
+ setError("Order ID not found. Please check and try again.");
+ }
+ setLoading(false);
+ }, 1500); // Simulate network delay
+ };
+
+ return (
+
+
Order Tracking
+
+ {/* Order ID Input */}
+
+
+ setOrderId(e.target.value)}
+ className="p-3 border-2 border-gray-300 rounded-lg w-full"
+ />
+
+
+ {/* Track Order Button */}
+
+ {loading ? (
+
+ ) : (
+ "Track Order"
+ )}
+
+
+ {/* Display Order Status */}
+ {loading &&
Tracking your order...
}
+
+ {/* Error or Order Status */}
+ {orderStatus && !loading && (
+
+
+ Order Status: {orderStatus}
+
+ )}
+
+ {error && !loading && (
+
+
+ Error: {error}
+
+ )}
+
+ {/* Order History Section */}
+
+
Past Orders
+
+
+ Order ID: 123
+ Shipped - 2 days
+
+
+ Order ID: 456
+ In Transit - 1 day
+
+
+ Order ID: 789
+ Delivered - Thank you for renting!
+
+
+
+
+ );
+};
+
+export default RentOrderTracking;
diff --git a/frontend/src/AgroShopAI/components/Pages/Admin-Dashboard.jsx b/frontend/src/AgroShopAI/components/Pages/Admin-Dashboard.jsx
index 61dbc155..b61a8644 100644
--- a/frontend/src/AgroShopAI/components/Pages/Admin-Dashboard.jsx
+++ b/frontend/src/AgroShopAI/components/Pages/Admin-Dashboard.jsx
@@ -6,6 +6,7 @@ import { useState } from "react";
import StatisticComponent from "./components/StatisticComponent";
import ReturnPanel from "./components/ReturnPage";
import AdminProductManagement from "./ProductManagement";
+import ProfileEdit from "./components/ProfileManage";
export default function AdminDashboard() {
const [activeView, setActiveView] = useState("dashboard"); // Track active view
@@ -25,6 +26,7 @@ export default function AdminDashboard() {
{activeView === "analytics" && }
{activeView === "return" && }
{activeView === "product" && }
+ {activeView === "settings" && }
);
diff --git a/frontend/src/AgroShopAI/components/Pages/components/ActiveSessions.jsx b/frontend/src/AgroShopAI/components/Pages/components/ActiveSessions.jsx
new file mode 100644
index 00000000..2cc037cd
--- /dev/null
+++ b/frontend/src/AgroShopAI/components/Pages/components/ActiveSessions.jsx
@@ -0,0 +1,33 @@
+import React, { useState } from 'react';
+
+const ActiveSessions = () => {
+ const [sessions, setSessions] = useState([
+ { id: 1, device: 'MacBook Pro', location: 'New York', lastActive: '10 minutes ago' },
+ { id: 2, device: 'iPhone', location: 'Los Angeles', lastActive: '1 hour ago' },
+ ]);
+
+ const handleLogout = (id) => {
+ setSessions(sessions.filter(session => session.id !== id));
+ };
+
+ return (
+
+
Active Sessions
+ {sessions.length === 0 ? (
+
No active sessions.
+ ) : (
+
+ {sessions.map((session) => (
+
+ {session.device} ({session.location})
+ {session.lastActive}
+ handleLogout(session.id)}>Log Out
+
+ ))}
+
+ )}
+
+ );
+};
+
+export default ActiveSessions;
diff --git a/frontend/src/AgroShopAI/components/Pages/components/ActivityLog.jsx b/frontend/src/AgroShopAI/components/Pages/components/ActivityLog.jsx
new file mode 100644
index 00000000..45a46cad
--- /dev/null
+++ b/frontend/src/AgroShopAI/components/Pages/components/ActivityLog.jsx
@@ -0,0 +1,22 @@
+import React from 'react';
+
+const ActivityLog = () => {
+ const activities = [
+ 'Logged in from a new device',
+ 'Changed email address',
+ 'Password updated',
+ ];
+
+ return (
+
+
Activity Log
+
+ {activities.map((activity, index) => (
+ {activity}
+ ))}
+
+
+ );
+};
+
+export default ActivityLog;
diff --git a/frontend/src/AgroShopAI/components/Pages/components/Message.jsx b/frontend/src/AgroShopAI/components/Pages/components/Message.jsx
new file mode 100644
index 00000000..e6a15b7a
--- /dev/null
+++ b/frontend/src/AgroShopAI/components/Pages/components/Message.jsx
@@ -0,0 +1,12 @@
+import React from 'react';
+
+const Message = ({ message }) => {
+ return (
+
+ );
+};
+
+export default Message;
+
diff --git a/frontend/src/AgroShopAI/components/Pages/components/Notifications.jsx b/frontend/src/AgroShopAI/components/Pages/components/Notifications.jsx
new file mode 100644
index 00000000..f5233936
--- /dev/null
+++ b/frontend/src/AgroShopAI/components/Pages/components/Notifications.jsx
@@ -0,0 +1,86 @@
+import React, { useState } from 'react';
+
+const Notifications = () => {
+ // State for managing notification preferences
+ const [emailNotifications, setEmailNotifications] = useState(true);
+ const [smsNotifications, setSmsNotifications] = useState(false);
+ const [appNotifications, setAppNotifications] = useState(true);
+ const [orderNotifications, setOrderNotifications] = useState(true);
+ const [inventoryNotifications, setInventoryNotifications] = useState(false);
+
+ const handleToggle = (setting, setter) => {
+ setter(!setting);
+ };
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ // Handle the form submission for saving the changes
+ alert('Notification preferences saved!');
+ };
+
+ return (
+
+
Notification Settings
+
+
+ );
+};
+
+export default Notifications;
diff --git a/frontend/src/AgroShopAI/components/Pages/components/PasswordForm.jsx b/frontend/src/AgroShopAI/components/Pages/components/PasswordForm.jsx
new file mode 100644
index 00000000..5ca96497
--- /dev/null
+++ b/frontend/src/AgroShopAI/components/Pages/components/PasswordForm.jsx
@@ -0,0 +1,94 @@
+const PasswordForm = ({
+ password,
+ setPassword,
+ isLoading,
+ setIsLoading,
+ setMessage,
+}) => {
+ const handlePasswordChange = (e) => {
+ setPassword({ ...password, [e.target.name]: e.target.value });
+ };
+
+ const handlePasswordSubmit = (e) => {
+ e.preventDefault();
+ if (password.new !== password.confirm) {
+ setMessage({ type: "error", text: "New passwords do not match!" });
+ return;
+ }
+ setIsLoading(true);
+ // Simulate API call
+ setTimeout(() => {
+ setIsLoading(false);
+ setMessage({ type: "success", text: "Password changed successfully!" });
+ setPassword({ current: "", new: "", confirm: "" });
+ }, 1500);
+ };
+
+ return (
+
+ );
+};
+
+export default PasswordForm;
diff --git a/frontend/src/AgroShopAI/components/Pages/components/PersonalInfo.jsx b/frontend/src/AgroShopAI/components/Pages/components/PersonalInfo.jsx
new file mode 100644
index 00000000..0e52afd6
--- /dev/null
+++ b/frontend/src/AgroShopAI/components/Pages/components/PersonalInfo.jsx
@@ -0,0 +1,86 @@
+const PersonalInfo = ({
+ personalInfo,
+ setPersonalInfo,
+ isLoading,
+ setIsLoading,
+ setMessage,
+}) => {
+ const handlePersonalInfoChange = (e) => {
+ setPersonalInfo({ ...personalInfo, [e.target.name]: e.target.value });
+ };
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ setIsLoading(true);
+ // Simulate API call
+ setTimeout(() => {
+ setIsLoading(false);
+ setMessage({ type: "success", text: "Profile updated successfully!" });
+ }, 1500);
+ };
+
+ return (
+
+ );
+};
+
+export default PersonalInfo;
diff --git a/frontend/src/AgroShopAI/components/Pages/components/ProfileManage.jsx b/frontend/src/AgroShopAI/components/Pages/components/ProfileManage.jsx
new file mode 100644
index 00000000..d534201b
--- /dev/null
+++ b/frontend/src/AgroShopAI/components/Pages/components/ProfileManage.jsx
@@ -0,0 +1,107 @@
+import React, { useState } from "react";
+import TabNav from "./TabNav";
+import PersonalInfo from "./PersonalInfo";
+import PasswordForm from "./PasswordForm";
+import Notifications from "./Notifications";
+import SecuritySettings from "./SecuritySettings";
+import ActivityLog from "./ActivityLog";
+import ActiveSessions from "./ActiveSessions";
+import Message from "./Message";
+
+export default function ProfileEdit() {
+ const [activeTab, setActiveTab] = useState("personal");
+ const [personalInfo, setPersonalInfo] = useState({
+ name: "John Doe",
+ email: "john.doe@agroshop.com",
+ profilePicture: "/placeholder.svg?height=100&width=100",
+ });
+ const [password, setPassword] = useState({
+ current: "",
+ new: "",
+ confirm: "",
+ });
+ const [notifications, setNotifications] = useState({
+ email: true,
+ sms: false,
+ app: true,
+ newOrders: true,
+ lowInventory: false,
+ });
+ const [securitySettings, setSecuritySettings] = useState({
+ securityQuestion: "What was your first pet's name?",
+ securityAnswer: "",
+ accountLockout: true,
+ });
+ const [activityLog] = useState([
+ {
+ type: "login",
+ date: "2023-11-10 09:30:00",
+ details: "Logged in from Chrome on Windows",
+ },
+ {
+ type: "profile_update",
+ date: "2023-11-09 14:15:00",
+ details: "Updated email address",
+ },
+ {
+ type: "password_change",
+ date: "2023-11-08 11:00:00",
+ details: "Changed password",
+ },
+ ]);
+ const [activeSessions] = useState([
+ { device: "Chrome on Windows", lastActive: "2023-11-10 10:30:00" },
+ { device: "Safari on iPhone", lastActive: "2023-11-10 09:45:00" },
+ ]);
+ const [isLoading, setIsLoading] = useState(false);
+ const [message, setMessage] = useState({ type: "", text: "" });
+
+ return (
+
+
Profile Edit
+
+
+
+ {message.text &&
}
+
+ {activeTab === "personal" && (
+
+ )}
+ {activeTab === "password" && (
+
+ )}
+ {activeTab === "notifications" && (
+
+ )}
+ {activeTab === "security" && (
+
+ )}
+ {activeTab === "activity" &&
}
+ {activeTab === "sessions" && (
+
+ )}
+
+ );
+}
diff --git a/frontend/src/AgroShopAI/components/Pages/components/SecuritySettings.jsx b/frontend/src/AgroShopAI/components/Pages/components/SecuritySettings.jsx
new file mode 100644
index 00000000..d388a5d7
--- /dev/null
+++ b/frontend/src/AgroShopAI/components/Pages/components/SecuritySettings.jsx
@@ -0,0 +1,36 @@
+import React, { useState } from 'react';
+
+const SecuritySettings = () => {
+ const [twoFactorAuth, setTwoFactorAuth] = useState(false);
+ const [changePassword, setChangePassword] = useState(false);
+
+ const handleToggle2FA = () => {
+ setTwoFactorAuth(!twoFactorAuth);
+ };
+
+ const handleChangePassword = () => {
+ setChangePassword(true);
+ // Implement password change functionality here
+ };
+
+ return (
+
+
Security Settings
+
+
+
+ Enable Two-Factor Authentication
+
+
+
+ Change Password
+
+
+ );
+};
+
+export default SecuritySettings;
diff --git a/frontend/src/AgroShopAI/components/Pages/components/TabNav.jsx b/frontend/src/AgroShopAI/components/Pages/components/TabNav.jsx
new file mode 100644
index 00000000..4177288f
--- /dev/null
+++ b/frontend/src/AgroShopAI/components/Pages/components/TabNav.jsx
@@ -0,0 +1,30 @@
+const TabNav = ({ activeTab, setActiveTab }) => {
+ return (
+
+
+ {[
+ "personal",
+ "password",
+ "notifications",
+ "security",
+ "activity",
+ "sessions",
+ ].map((tab) => (
+ setActiveTab(tab)}
+ >
+ {tab.charAt(0).toUpperCase() + tab.slice(1)}
+
+ ))}
+
+
+ );
+};
+
+export default TabNav;
diff --git a/frontend/src/MainContent.jsx b/frontend/src/MainContent.jsx
index fadc8c0d..536ddcd4 100644
--- a/frontend/src/MainContent.jsx
+++ b/frontend/src/MainContent.jsx
@@ -102,12 +102,16 @@ import AffiliateProgramPage from './AgroShopAI/components/Pages/Affiliate';
import TicketManagement from './AgroShopAI/components/Pages/AdminTicket';
import SupportPage from './AgroShopAI/components/Pages/TicketUser';
+
+import RentSupportPage from './AgroRentAI/components/RentSupportPage';
+
import WarehouseInventory from './AgroShopAI/components/Pages/Admin-Warehouse';
+
const MainContent = () => {
UseScrollToTop();
const location = useLocation(); // Get the current route
@@ -199,6 +203,7 @@ const MainContent = () => {
} />
} />
+ } />
} />
{/* AgroShopAI Routes */}