import "dotenv/config"; import express from "express"; import mysql from "mysql2/promise"; // Create a connection pool to MySQL const pool = mysql.createPool({ host: process.env.DB_HOST || "localhost", user: process.env.DB_USER || "root", password: process.env.DB_PASSWORD, database: process.env.DB_NAME || "roadrentals", waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); const app = express(); app.use(express.json()); const checkToken = (req, res, next) => { console.log("Welcome"); next(); }; app.use(checkToken); app.get("/", (req, res) => { res.json({ status: 1, message: "Home Page API" }); }); app.get("/api/news", (req, res) => { res.json({ status: 1, message: "News API" }); }); // Database Connected Endpoint app.post("/api/auth/register", async (req, res) => { try { const { name, email, mobile_number, password } = req.body; if (!name || !email || !mobile_number || !password) { return res.status(400).json({ detail: "Missing required fields" }); } // Search the MySQL Database const [users] = await pool.execute("SELECT * FROM User WHERE email = ?", [email]); const existingUser = users[0]; if (existingUser) { return res.status(409).json({ detail: "Email already registered" }); } // Insert new user row into MySQL table const [result] = await pool.execute( "INSERT INTO User (name, email, mobile_number, password) VALUES (?, ?, ?, ?)", [name, email, mobile_number, password] ); const newUser = { id: result.insertId, name, email, mobile_number }; return res.status(201).json({ status: 1, message: "User registered successfully", user: newUser }); } catch (error) { console.error("Database Error:", error); return res.status(500).json({ detail: "Internal Server Error" }); } }); // Create a New Booking app.post("/api/bookings", async (req, res) => { try { const { tripType, pickupLocation, dropLocation, pickupDateTime, returnDateTime, packageType, carName, totalAmount } = req.body; if (!tripType || !pickupLocation || !pickupDateTime) { return res.status(400).json({ detail: "Missing required booking details" }); } const [result] = await pool.execute( `INSERT INTO Bookings (trip_type, pickup_location, drop_location, pickup_datetime, return_datetime, package_type, car_name, total_amount) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ tripType, pickupLocation, dropLocation || null, new Date(pickupDateTime), returnDateTime ? new Date(returnDateTime) : null, packageType || null, carName || null, totalAmount || null ] ); return res.status(201).json({ status: 1, message: "Booking requested successfully!", bookingId: result.insertId }); } catch (error) { console.error("Booking Error:", error); return res.status(500).json({ detail: "Failed to create booking" }); } }); // --- DYNAMIC PRICING ENGINE (DB DRIVEN) --- app.post("/api/pricing/calculate", async (req, res) => { try { const { tripType, pickupDate, returnDate, packageType } = req.body; const start = new Date(pickupDate); const end = returnDate ? new Date(returnDate) : start; const diffTime = Math.abs(end - start); const durationDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) || 1; // Fetch ACTIVE vehicles from DB const [rows] = await pool.execute("SELECT * FROM Vehicles WHERE isAvailable = TRUE"); const results = rows.map(vehicle => { const features = typeof vehicle.features === 'string' ? JSON.parse(vehicle.features) : vehicle.features; let totalBaseFare = vehicle.baseFarePerDay * durationDays; let totalDriverAllowance = vehicle.driverAllowancePerDay * durationDays; // Special Case: Local Packages if (tripType === 'local' && packageType) { if (packageType.includes("4Hr")) totalBaseFare = 1500; else if (packageType.includes("8Hr")) totalBaseFare = 2500; else if (packageType.includes("12Hr")) totalBaseFare = 3500; totalDriverAllowance = 0; } // Special Case: Airport Transfers if (tripType === 'airport') { if (vehicle.type === 'SEDAN') totalBaseFare = 1200; else if (vehicle.type === 'SUV') totalBaseFare = 2200; else totalBaseFare = 1800; totalDriverAllowance = 0; } const grandTotal = totalBaseFare + totalDriverAllowance; const advancePayment = Math.round(grandTotal * 0.20); return { ...vehicle, features, calc: { days: durationDays, baseFare: totalBaseFare, driverAllowance: totalDriverAllowance, totalKmIncluded: vehicle.includedKmPerDay * (tripType === 'airport' ? 0.2 : durationDays), grandTotal, advancePayment, math: tripType === 'airport' || tripType === 'local' ? `Fixed ${tripType.charAt(0).toUpperCase() + tripType.slice(1)} Rate` : `(₹${vehicle.baseFarePerDay} x ${durationDays} Days) + ₹${totalDriverAllowance} Driver` }, inclusions: ["AC", "Professional Driver", tripType === 'airport' ? "Airport Toll Included" : "First " + (vehicle.includedKmPerDay * (tripType === 'airport' ? 1 : durationDays)) + " Kms"], exclusions: ["Parking Charges", "Extra Waiting Time", "Inter-state Permits"] }; }); res.json({ status: 1, data: results }); } catch (error) { console.error("Pricing Error:", error); res.status(500).json({ detail: "Failed to calculate pricing" }); } }); // --- ADMIN API ENDPOINTS --- // Secure Admin Login app.post("/api/admin/login", async (req, res) => { const { adminId, password } = req.body; // Environment-based credentials for security const VALID_ADMIN_ID = process.env.ADMIN_ID || "admin"; const VALID_ADMIN_PASS = process.env.ADMIN_PASSWORD || "admin123"; if (adminId === VALID_ADMIN_ID && password === VALID_ADMIN_PASS) { res.json({ success: true, token: "secure_session_token_xyz_987" }); } else { res.status(401).json({ detail: "Invalid Admin ID or Password" }); } }); // Get Full Fleet for Management app.get("/api/admin/vehicles", async (req, res) => { try { const [rows] = await pool.execute("SELECT * FROM Vehicles ORDER BY id DESC"); const cars = rows.map(v => ({ ...v, features: typeof v.features === 'string' ? JSON.parse(v.features) : v.features })); res.json(cars); } catch (err) { res.status(500).json({ detail: "Fail to fetch fleet" }); } }); // Update Availability or Pricing app.patch("/api/admin/vehicles/:id", async (req, res) => { try { const { id } = req.params; const { baseFarePerDay, isAvailable } = req.body; if (baseFarePerDay !== undefined) { await pool.execute("UPDATE Vehicles SET baseFarePerDay = ? WHERE id = ?", [baseFarePerDay, id]); } if (isAvailable !== undefined) { await pool.execute("UPDATE Vehicles SET isAvailable = ? WHERE id = ?", [isAvailable, id]); } res.json({ success: true, message: "Vehicle updated successfully" }); } catch (err) { res.status(500).json({ detail: "Failed to update vehicle" }); } }); // Add New Cab app.post("/api/admin/vehicles", async (req, res) => { try { const v = req.body; const features = JSON.stringify(v.features || []); await pool.execute( `INSERT INTO Vehicles (name, type, seats, luggage, image, baseFarePerDay, driverAllowancePerDay, extraKmRate, includedKmPerDay, badge, features) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [v.name, v.type, v.seats, v.luggage, v.image, v.baseFarePerDay, v.driverAllowancePerDay, v.extraKmRate, v.includedKmPerDay, v.badge, features] ); res.status(201).json({ success: true, message: "New vehicle added" }); } catch (err) { res.status(500).json({ detail: "Failed to add new vehicle" }); } }); // Delete Cab app.delete("/api/admin/vehicles/:id", async (req, res) => { try { const { id } = req.params; await pool.execute("DELETE FROM Vehicles WHERE id = ?", [id]); res.json({ success: true, message: "Vehicle removed" }); } catch (err) { res.status(500).json({ detail: "Failed to delete vehicle" }); } }); const PORT = 8000; app.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); });