79153986

Date: 2024-11-04 01:50:03
Score: 0.5
Natty:
Report link

app.js


import mysql from 'mysql';
import express from 'express';
import bodyParser from 'body-parser';
import session from 'express-session';

const app = express();

// Middleware setup
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.use(session({ secret: 'your-secret-key', resave: false, saveUninitialized: false }));
app.set('view engine', 'ejs');

// Create a MySQL connection pool
const con = mysql.createPool({
    host: "localhost",
    user: "root",
    password: "",
    database: "ecommerce_db",
});

// Utility function to execute database queries
function queryDatabase(query, params) {
    return new Promise((resolve, reject) => {
        con.query(query, params, (error, results) => {
            if (error) {
                reject(error);
            } else {
                resolve(results);
            }
        });
    });
}

// Utility function to calculate total and prepare cart data
function calculateCartDetails(cart, productResults) {
    const productMap = {};
    productResults.forEach(product => {
        productMap[product.id] = product;
    });

    let total = 0;
    cart.forEach(item => {
        const product = productMap[item.productId];
        if (product) {
            total += product.price * item.quantity; // Calculate total
        }
    });

    return { productMap, total };
}

// Product Routes
app.get('/', async (req, res) => {
    try {
        const products = await queryDatabase('SELECT * FROM products', []);
        res.render('pages/product', { products });
    } catch (error) {
        console.error('Database query error:', error);
        return res.status(500).send('Internal Server Error');
    }
});

// Cart Routes
app.get('/cart', async (req, res) => {
    const cart = req.session.cart || []; // Get cart from session

    if (cart.length === 0) {
        return res.render('pages/cart', { cart, total: 0 });
    }

    const productIds = cart.map(item => item.productId);
    const placeholders = productIds.map(() => '?').join(',');

    try {
        const productResults = await queryDatabase(`SELECT id, name, price FROM products WHERE id IN (${placeholders})`, productIds);
        const { productMap, total } = calculateCartDetails(cart, productResults);
        res.render('pages/cart', { cart, productMap, total });
    } catch (error) {
        console.error('Database query error:', error);
        return res.status(500).send('Internal Server Error');
    }
});

// Add to Cart (POST)
app.post('/cart/add', (req, res) => {
    const productId = req.body.productId;
    const quantity = parseInt(req.body.quantity, 10) || 1;

    // Initialize cart if it doesn't exist
    if (!req.session.cart) {
        req.session.cart = [];
    }

    // Check if the product is already in the cart
    const existingProduct = req.session.cart.find(item => item.productId === productId);
    if (existingProduct) {
        existingProduct.quantity += quantity; // Update quantity
    } else {
        req.session.cart.push({ productId, quantity }); // Add new product
    }

    res.redirect('/cart'); // Redirect to cart
});

// Remove from Cart (POST)
app.post('/cart/remove', (req, res) => {
    const productId = req.body.productId;

    // Filter out the product to remove
    req.session.cart = req.session.cart.filter(item => item.productId !== productId);
    res.redirect('/cart'); // Redirect to cart
});

// Payment Routes
app.get('/payment', async (req, res) => {
    const cart = req.session.cart || [];

    if (cart.length === 0) {
        return res.redirect('/'); // Redirect to products if cart is empty
    }

    const productIds = cart.map(item => item.productId);
    const placeholders = productIds.map(() => '?').join(',');

    try {
        const productResults = await queryDatabase(`SELECT id, name, price FROM products WHERE id IN (${placeholders})`, productIds);
        const { productMap, total } = calculateCartDetails(cart, productResults);
        res.render('pages/payment', { cart, productMap, total });
    } catch (error) {
        console.error('Database query error:', error);
        return res.status(500).send('Internal Server Error');
    }
});

// Payment Route
app.post('/payment', async (req, res) => {
    const { orderId, total } = req.body;

    try {
        // Render the payment page with order details
        res.render('pages/payment', { orderId, total });
    } catch (error) {
        console.error('Payment processing error:', error);
        return res.status(500).send('Internal Server Error');
    }
});

// Checkout Route (POST)
app.post('/checkout', async (req, res) => {
    const { orderId, paymentMethod } = req.body;

    try {
        // Update order status to "paid" and save the payment method
        await queryDatabase('UPDATE orders SET status = ?, payment_method = ? WHERE id = ?', ['paid', paymentMethod, orderId]);

        // Clear the cart after payment
        req.session.cart = [];

        // Render a success page or send a confirmation message
        res.render('pages/checkout', { orderId, paymentMethod });
    } catch (error) {
        console.error('Error updating payment status:', error);
        return res.status(500).send('Internal Server Error');
    }
});



// Start the server
app.listen(3001, () => {
    console.log('Server running on http://localhost:3001');
});

// Order Route
app.get('/order', async (req, res) => {
    const cart = req.session.cart || [];

    if (cart.length === 0) {
        return res.redirect('/'); // Redirect to products if cart is empty
    }

    const productIds = cart.map(item => item.productId);
    const placeholders = productIds.map(() => '?').join(',');

    try {
        // Retrieve product details for the cart items
        const productResults = await queryDatabase(
            `SELECT id, name, price FROM products WHERE id IN (${placeholders})`,
            productIds
        );
        const { productMap, total } = calculateCartDetails(cart, productResults);

        // Insert order into the database with status "not paid"
        const orderResult = await queryDatabase(
            'INSERT INTO orders (status, total) VALUES (?, ?)',
            ['not paid', total]
        );
        const orderId = orderResult.insertId;

        // Insert each cart item as an order item linked to the order ID
        await Promise.all(
            cart.map(item =>
                queryDatabase(
                    'INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?)',
                    [orderId, item.productId, item.quantity, productMap[item.productId].price]
                )
            )
        );

        // Clear the cart after placing the order
        req.session.cart = [];

        // Render confirmation page with order details
        res.render('pages/order_confirmation', { orderId, total });
    } catch (error) {
        console.error('Database query error:', error);
        return res.status(500).send('Internal Server Error');
    }
});

cart.ejs

<body>
    <h1>Your Cart</h1>
    <ul>
        <% cart.forEach(item=> { %>
            <li>
                Product: <%= productMap[item.productId].name %> <br>
                    Price: $<%= productMap[item.productId].price.toFixed(2) %> <br>
                        Quantity: <%= item.quantity %> <br>
                            Total: $<%= (productMap[item.productId].price * item.quantity).toFixed(2) %><br>
                                <form action="/cart/remove" method="POST" style="display:inline;">
                                    <input type="hidden" name="productId" value="<%= item.productId %>">
                                    <button type="submit">Remove</button>
                                </form>
            </li>
            <% }) %>
    </ul>
    <h2>Total Price: $<%= total.toFixed(2) %>
    </h2>
    <a href="/order">Place Order</a>
    <a href="/">Continue Shopping</a>
</body>

</html>

checkout.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Payment Success</title>
</head>
<body>
    <h1>Pa

yment Successful!</h1>
    <p>Thank you for your payment for Order #<%= orderId %>.</p>
    <p>Your order status is now: Paid</p>
    <a href="/">Return to Home</a>
</body>
</html>

order_confirmation.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Order Confirmation</title>
</head>
<body>
    <h1>Order Confirmation</h1>
    <p>Thank you for your order!</p>
    <p>Order ID: <%= orderId %></p>
    <p>Total Amount: $<%= total.toFixed(2) %></p>
    <p>Status: Not Paid</p>

    <!-- Payment Button -->
    <form action="/payment" method="POST">
        <input type="hidden" name="orderId" value="<%= orderId %>">
        <input type="hidden" name="total" value="<%= total %>">
        <button type="submit">Proceed to Payment</button>
    </form>
</body>
</html>

payment.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Payment</title>
</head>
<body>
    <h1>Payment for Order #<%= orderId %></h1>
    <p>Total Amount: $<%= parseFloat(total).toFixed(2) %></p>

    <!-- Payment Form with Payment Method Selection -->
    <form action="/checkout" method="POST">
        <input type="hidden" name="orderId" value="<%= orderId %>">
        
        <h3>Select Payment Method:</h3>
        <label>
            <input type="radio" name="paymentMethod" value="Credit Card" required> Credit Card
        </label><br>
        <label>
            <input type="radio" name="paymentMethod" value="PayPal" required> PayPal
        </label><br>
        <label>
            <input type="radio" name="paymentMethod" value="Bank Transfer" required> Bank Transfer
        </label><br>

        <button type="submit">Complete Payment</button>
    </form>
</body>
</html>

product.ejs

<body>
    <header>
        <%- include('../partials/header') %>
    </header>

    <main>
        <h1>Products</h1>
        <ul>
            <% products.forEach(product => { %>
                <li>
                    <h2><%= product.name %></h2>
                    <p>Price: $<%= product.price %></p>
                    <p>Description: <%= product.description %></p>
                    <img src="<%= product.image %>" alt="<%= product.name %>" />
                    <form action="/cart/add" method="POST">
                        <input type="hidden" name="productId" value="<%= product.id %>">
                        <input type="number" name="quantity" value="1" min="1">
                        <button type="submit">Add to Cart</button>
                    </form>
                </li>
            <% }) %>
        </ul>
    </main>

    <footer>
        <%- include('../partials/footer') %>
    </footer>
</body>
</html>

CREATE TABLE orders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    status VARCHAR(20),
    total DECIMAL(10, 2),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE order_items (
    id INT AUTO_INCREMENT PRIMARY KEY,
    order_id INT,
    product_id INT,
    quantity INT,
    price DECIMAL(10, 2),
    FOREIGN KEY (order_id) REFERENCES orders(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);

ALTER TABLE orders ADD COLUMN payment_method VARCHAR(50);

Reasons:
  • Blacklisted phrase (0.5): Thank you
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (1):
Posted by: ttser123