diff --git a/backend/controllers/rent/RentOrderController.js b/backend/controllers/rent/RentOrderController.js new file mode 100644 index 00000000..2b5ead27 --- /dev/null +++ b/backend/controllers/rent/RentOrderController.js @@ -0,0 +1,69 @@ + +const nodemailer = require('nodemailer'); + +const sendOrderConfirmationEmail = async (userDetails, cartItems, totalPrice, trackingID) => { + // Create a transporter using Gmail's SMTP server + const transporter = nodemailer.createTransport({ + service: 'gmail', // Use your email service provider (e.g., 'gmail', 'smtp.mailtrap.io', etc.) + auth: { + user: process.env.EMAIL_USER, // Replace with your Gmail email address + pass: process.env.EMAIL_PASS, // Replace with your Gmail password or App Password + }, + }); + + // Define the email details + const mailOptions = { + from: 'your-email@gmail.com', // Sender's email + to: userDetails.email, // Recipient's email + subject: 'Order Confirmation', + html: ` +

Order Confirmation

+

Thank you for your order, ${userDetails.name}!

+

Your Order Details

+ +

Total Price: ₹${totalPrice}

+

Your tracking ID: ${trackingID}

+

Your order will be processed shortly. Thank you!

+ `, + }; + + // Send the email + try { + await transporter.sendMail(mailOptions); + console.log('Confirmation email sent successfully.'); + } catch (error) { + console.error('Error sending email:', error); + throw error; + } +}; + +exports.OrderConfirmation = async (req, res) => { + try { + const { userDetails, cartItems, totalPrice } = req.body; + + // Generate a random tracking ID + const trackingID = 'TRK' + Math.random().toString(36).substr(2, 9).toUpperCase(); + + // Send the confirmation email + await sendOrderConfirmationEmail(userDetails, cartItems, totalPrice, trackingID); + + res.status(200).json({ + message: 'Order confirmed! A confirmation email has been sent.', + trackingID, + }); + } catch (error) { + console.error('Error sending email:', error); + res.status(500).json({ message: 'Failed to send confirmation email.' }); + } +}; + + diff --git a/backend/index.js b/backend/index.js index 8ef63b82..fb275e4d 100644 --- a/backend/index.js +++ b/backend/index.js @@ -16,6 +16,7 @@ const discussionRoutes = require('./routes/discussionRoutes'); const rentProductRoutes = require('./routes/rent/rentProductRoutes'); const rentWishlistRoutes = require('./routes/rent/rentWishlistRoutes'); const rentCartRoutes = require('./routes/rent/rentCartRoutes'); +const rentOrderRoutes = require('./routes/rent/rentOrderRoutes'); const { sendEmail } = require('./services/emailService'); const session = require('express-session'); @@ -47,6 +48,7 @@ app.use('/api', shopRoutes); app.use('/api', rentProductRoutes); app.use('/api', rentWishlistRoutes); app.use('/api', rentCartRoutes); +app.use('/api', rentOrderRoutes); app.use('/api', userRoutes); app.use('/api/discussions', discussionRoutes); app.use('/api/products', agriProductRoutes); diff --git a/backend/routes/rent/rentOrderRoutes.js b/backend/routes/rent/rentOrderRoutes.js new file mode 100644 index 00000000..668d83f9 --- /dev/null +++ b/backend/routes/rent/rentOrderRoutes.js @@ -0,0 +1,15 @@ +// routes/productRoutes.js + +const express = require('express'); +const { OrderConfirmation } = require('../../controllers/rent/RentOrderController'); +const router = express.Router(); + + +// Create a new product +router.post('/rent-product', OrderConfirmation); + + + + + +module.exports = router; diff --git a/frontend/src/AgroRentAI/Cart.jsx b/frontend/src/AgroRentAI/Cart.jsx index 0d019a8d..ebbe8a04 100644 --- a/frontend/src/AgroRentAI/Cart.jsx +++ b/frontend/src/AgroRentAI/Cart.jsx @@ -18,6 +18,38 @@ const RentCartPage = () => { ? 'https://agrotech-ai-11j3.onrender.com' : 'http://localhost:8080'; + const recommendedItems = [ + { + name: 'Tractor - Model X100', + image: 'https://via.placeholder.com/150?text=Tractor', + price: 1500, + }, + { + name: 'Rototiller - 2000 Series', + image: 'https://via.placeholder.com/150?text=Rototiller', + price: 1200, + }, + { + name: 'Plow - Heavy Duty', + image: 'https://via.placeholder.com/150?text=Plow', + price: 800, + }, + { + name: 'Seeder - Pro Seed 3000', + image: 'https://via.placeholder.com/150?text=Seeder', + price: 2200, + }, + { + name: 'Lawn Mower - Eco Series', + image: 'https://via.placeholder.com/150?text=Lawn+Mower', + price: 900, + }, + { + name: 'Harrow - Ground Breaker', + image: 'https://via.placeholder.com/150?text=Harrow', + price: 1100, + }, + ]; // Fetch user cart items from backend useEffect(() => { const fetchCartItems = async () => { diff --git a/frontend/src/AgroRentAI/RentCheckoutPage.jsx b/frontend/src/AgroRentAI/RentCheckoutPage.jsx index f5594a3a..96698a04 100644 --- a/frontend/src/AgroRentAI/RentCheckoutPage.jsx +++ b/frontend/src/AgroRentAI/RentCheckoutPage.jsx @@ -1,5 +1,7 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; +import { toast, ToastContainer } from 'react-toastify'; +import "react-toastify/ReactToastify.min.css"; const RentCheckoutPage = () => { // Dummy cartItems data @@ -22,6 +24,10 @@ const RentCheckoutPage = () => { } ]); + const ApiUrl = process.env.NODE_ENV === 'production' + ? 'https://agrotech-ai-11j3.onrender.com' + : 'http://localhost:8080'; + const [userDetails, setUserDetails] = useState({ name: '', email: '', @@ -29,6 +35,61 @@ const RentCheckoutPage = () => { phone: '', }); + const [errors, setErrors] = useState({ + name: '', + email: '', + address: '', + phone: '', + }); + + const handleInputChange = (e) => { + const { name, value } = e.target; + setUserDetails((prevState) => ({ + ...prevState, + [name]: value, + })); + }; + + const validateForm = () => { + let isValid = true; + const newErrors = {}; + + // Validate Name + if (!userDetails.name) { + newErrors.name = 'Name is required'; + isValid = false; + } + + // Validate Email + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!userDetails.email) { + newErrors.email = 'Email is required'; + isValid = false; + } else if (!emailRegex.test(userDetails.email)) { + newErrors.email = 'Please enter a valid email'; + isValid = false; + } + + // Validate Address + if (!userDetails.address) { + newErrors.address = 'Address is required'; + isValid = false; + } + + // Validate Phone + const phoneRegex = /^[0-9]{10}$/; + if (!userDetails.phone) { + newErrors.phone = 'Phone number is required'; + isValid = false; + } else if (!phoneRegex.test(userDetails.phone)) { + newErrors.phone = 'Phone number must be 10 digits'; + isValid = false; + } + + setErrors(newErrors); + return isValid; + }; + const [totalPrice, setTotalPrice] = useState(0); const navigate = useNavigate(); @@ -44,29 +105,47 @@ const RentCheckoutPage = () => { setCartItems(updatedCartItems); }; - const handleCheckout = () => { - // Normally you would send the order to the backend for processing - console.log('Proceeding to checkout with the following details:', userDetails); - alert('Your order is placed. Waiting for approval from the admin/seller.'); - navigate('/order-confirmation'); // Redirect to order confirmation page - }; + const handleCheckout = async (e) => { + e.preventDefault(); // Prevent form submission reload - // Handle form input changes - const handleInputChange = (e) => { - const { name, value } = e.target; - setUserDetails((prevState) => ({ - ...prevState, - [name]: value, - })); + if (!validateForm()) { + toast.error("Error in validating form"); + return; + } + + try { + const response = await fetch(`${ApiUrl}/api/rent-product`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + userDetails, + cartItems, + totalPrice, + }), + }); + + const data = await response.json(); + if (response.ok) { + toast.success(`Your order has been placed. Tracking ID: ${data.trackingID}`); + } else { + toast.error(data.message || 'Error placing the order'); + } + } catch (error) { + toast.error('An error occurred while placing the order.'); + console.error('Error during checkout:', error); + } }; // Recalculate total when cart items change - React.useEffect(() => { + useEffect(() => { calculateTotalPrice(); }, [cartItems]); return (
+

Checkout

@@ -103,7 +182,8 @@ const RentCheckoutPage = () => { {/* User Details Form */}

Billing Details

-
+ + {/* Name */}
{ className="w-full p-3 border border-green-300 rounded-md" required /> + {errors.name &&

{errors.name}

}
+ + {/* Email */}
{ className="w-full p-3 border border-green-300 rounded-md" required /> + {errors.email &&

{errors.email}

}
+ + {/* Address */}