diff --git a/server.js b/server.js index 685c25f8c4cbe4ecf4bf3ba03b86429188e67527..05837d496153364f6df3b30d9c9d0bfc633fac00 100644 --- a/server.js +++ b/server.js @@ -7,7 +7,7 @@ require("dotenv").config(); const app = express(); -// ตั้งค่า session ให้ใช้ MySQL Store +//ตั้งค่าsessionให้ใช้ MySQLStore const MySQLStore = require('express-mysql-session')(session); const sessionStore = new MySQLStore({ clearExpired: true, @@ -35,22 +35,22 @@ app.use((req, res, next) => { console.log("Session Middleware Initialized"); -// Middleware +//Middleware app.use(express.static(path.join(__dirname, "public"))); app.use(express.json()); app.use(express.urlencoded({ extended: true })); -// Middleware เช็ค Session User (ใช้ในทุกหน้า) +//Middlewareเช็คSessionUser app.use((req, res, next) => { res.locals.user = req.session.user || null; next(); }); -// ตั้งค่า EJS +//ตั้งค่าEJS app.set("view engine", "ejs"); app.set("views", path.join(__dirname, "views")); -// เชื่อม Route +//เชื่อมRoute const orderRoutes = require("./shop-routes/order"); const cartRoutes = require("./shop-routes/cart"); const indexRoutes = require("./shop-routes/index"); @@ -61,7 +61,7 @@ app.use("/cart", cartRoutes); app.use("/order", orderRoutes); app.use("/products", productRoutes); -// Middleware เช็ค Login +//Middlewareเช็คLogin const isLoggedIn = (req, res, next) => { if (req.session.user) { next(); @@ -70,9 +70,73 @@ const isLoggedIn = (req, res, next) => { } }; -// หน้า Checkout (ต้อง Login ก่อน) -app.get('/order/checkout', isLoggedIn, (req, res) => { - res.render('checkout'); +//Register +app.get('/register', (req, res) => { + res.render('register'); +}); + +app.post("/register", async (req, res) => { + try { + const { email, password, name } = req.body; + if (!email || !password || !name) return res.status(400).json({ message: "All fields are required." }); + + const hashedPassword = await bcrypt.hash(password, 10); + const [existingUser] = await pool.execute("SELECT * FROM users WHERE email = ?", [email]); + + if (existingUser.length > 0) return res.status(400).json({ message: "Email is already registered." }); + + await pool.execute("INSERT INTO users (email, password, name) VALUES (?, ?, ?)", [email, hashedPassword, name]); + res.status(201).json({ success: true, message: "Registration successful." }); + } catch (error) { + res.status(500).json({ message: "Registration failed." }); + } +}); + + +app.get('/login', (req, res) => { + res.render('login'); +}); + +app.post("/login", async (req, res) => { + try { + const { email, password } = req.body; + if (!email || !password) return res.status(400).json({ message: "All fields are required." }); + + const [users] = await pool.execute("SELECT * FROM users WHERE email = ?", [email]); + if (users.length === 0) return res.status(400).json({ message: "Invalid email or password." }); + + const user = users[0]; + const passwordMatch = await bcrypt.compare(password, user.password); + if (!passwordMatch) return res.status(400).json({ message: "Invalid email or password." }); + + req.session.user = { id: user.id, email: user.email }; + + req.session.save(err => { //บันทึก Session ก่อน Redirect + if (err) { + console.error("Session save error:", err); + return res.send("Session save failed."); + } + console.log("Session after login:", req.session); + res.redirect('/'); + }); + + } catch (error) { + res.status(500).json({ message: "Login failed." }); + } +}); + + +app.get("/search", async (req, res) => { + const searchQuery = req.query.query; + try { + const [results] = await pool.execute( + "SELECT * FROM products WHERE name LIKE ? OR description LIKE ?", + [`%${searchQuery}%`, `%${searchQuery}%`] + ); + res.render("index", { products: results }); + } catch (err) { + res.status(500).send("Error retrieving search results"); + } }); app.get("/cart", isLoggedIn, async (req, res) => { @@ -133,122 +197,26 @@ app.post("/cart/add", async (req, res) => { } }); -//อัปเดตตะกร้าสินค้า app.post("/cart/update", async (req, res) => { try { - console.log("Request Body:", req.body); // Debug input - const { cartItemId, quantity } = req.body; - - // เช็คว่ามีค่าครบถ้วน - if (!cartItemId || quantity === undefined) { - return res.status(400).json({ message: "Missing cartItemId or quantity" }); - } - - // เช็คว่า quantity เป็นค่าที่ถูกต้อง if (quantity < 1) { return res.status(400).json({ message: "Quantity must be at least 1" }); } - // ตรวจสอบว่ามี cartItemId อยู่ในฐานข้อมูลจริงหรือไม่ - const [existingItem] = await pool.execute( - "SELECT * FROM cart_items WHERE id = ?", - [cartItemId] - ); - - if (existingItem.length === 0) { - return res.status(404).json({ message: "Cart item not found" }); - } - - // อัปเดตจำนวนสินค้าในตะกร้า - await pool.execute( - "UPDATE cart_items SET quantity = ? WHERE id = ?", - [quantity, cartItemId] - ); - - console.log("Updated Cart:", { cartItemId, quantity }); // Debug success + await pool.execute("UPDATE cart_items SET quantity = ? WHERE id = ?", [quantity, cartItemId]); res.json({ success: true, message: "Cart updated" }); - } catch (error) { console.error("Update error:", error); - res.status(500).json({ message: "Update failed", error }); - } -}); - - - - -// Register -app.get('/register', (req, res) => { - res.render('register'); -}); - -app.post("/register", async (req, res) => { - try { - const { email, password, name } = req.body; - if (!email || !password || !name) return res.status(400).json({ message: "All fields are required." }); - - const hashedPassword = await bcrypt.hash(password, 10); - const [existingUser] = await pool.execute("SELECT * FROM users WHERE email = ?", [email]); - - if (existingUser.length > 0) return res.status(400).json({ message: "Email is already registered." }); - - await pool.execute("INSERT INTO users (email, password, name) VALUES (?, ?, ?)", [email, hashedPassword, name]); - res.status(201).json({ success: true, message: "Registration successful." }); - } catch (error) { - res.status(500).json({ message: "Registration failed." }); + res.status(500).json({ message: "Update failed" }); } }); -// Login -app.get('/login', (req, res) => { - res.render('login'); -}); - -app.post("/login", async (req, res) => { - try { - const { email, password } = req.body; - if (!email || !password) return res.status(400).json({ message: "All fields are required." }); - - const [users] = await pool.execute("SELECT * FROM users WHERE email = ?", [email]); - if (users.length === 0) return res.status(400).json({ message: "Invalid email or password." }); - - const user = users[0]; - const passwordMatch = await bcrypt.compare(password, user.password); - if (!passwordMatch) return res.status(400).json({ message: "Invalid email or password." }); - - req.session.user = { id: user.id, email: user.email }; - - req.session.save(err => { //บันทึก Session ก่อน Redirect - if (err) { - console.error("Session save error:", err); - return res.send("Session save failed."); - } - console.log("Session after login:", req.session); - res.redirect('/'); - }); - - } catch (error) { - res.status(500).json({ message: "Login failed." }); - } -}); - -// ค้นหาสินค้า -app.get("/search", async (req, res) => { - const searchQuery = req.query.query; - try { - const [results] = await pool.execute( - "SELECT * FROM products WHERE name LIKE ? OR description LIKE ?", - [`%${searchQuery}%`, `%${searchQuery}%`] - ); - res.render("index", { products: results }); - } catch (err) { - res.status(500).send("Error retrieving search results"); - } +app.get('/order/checkout', isLoggedIn, (req, res) => { + res.render('checkout'); }); -// Logout app.get("/logout", (req, res) => { req.session.destroy(err => { if (err) return res.status(500).json({ message: "Logout failed." }); @@ -257,12 +225,12 @@ app.get("/logout", (req, res) => { }); }); -// Error Handler + app.use((err, req, res, next) => { console.error("Unhandled error:", err); res.status(500).json({ message: "Internal Server Error" }); }); -// Start Server + const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`Server running on port ${PORT}`)); diff --git a/shop-routes/product.js b/shop-routes/product.js index 6355f44d64da7da3a190d7b935a36ed84bd2769e..1047cd2124fe44402903f6836ee25c1941491a2c 100644 --- a/shop-routes/product.js +++ b/shop-routes/product.js @@ -4,7 +4,6 @@ const multer = require("multer"); const path = require("path"); const fs = require("fs"); - const router = express.Router(); // ตั้งค่าที่เก็บไฟล์รูป @@ -19,7 +18,7 @@ const storage = multer.diskStorage({ cb(null, uploadDir); }, filename: (req, file, cb) => { - cb(null, Date.now() + path.extname(file.originalname)); // ตั้งชื่อไฟล์เป็น timestamp + cb(null, Date.now() + path.extname(file.originalname)); } }); const upload = multer({ storage: storage }); @@ -30,7 +29,7 @@ router.get("/", async (req, res) => { const [products] = await pool.execute("SELECT * FROM products"); res.render("product", { products }); } catch (error) { - console.error("Error fetching products:", error); + console.error("❌ Error fetching products:", error); res.status(500).send("Error loading products."); } }); @@ -41,31 +40,30 @@ router.get("/add", (req, res) => { }); // เพิ่มสินค้าใหม่พร้อมรูป -router.post('/add', (req, res) => { - console.log('Request Body:', req.body); // Debug +router.post("/add", upload.single("image"), async (req, res) => { + console.log("📸 Uploaded file:", req.file); - // ดึงข้อมูลจาก req.body - const { name, price, description, stock, image_url } = req.body; + try { + const { name, price, stock, description } = req.body; + const priceNum = parseFloat(price); + const stockNum = parseInt(stock, 10); - // ตรวจสอบว่าข้อมูลสำคัญครบหรือไม่ - if (!name || !price || stock === undefined) { - return res.status(400).json({ message: 'Missing required fields' }); - } + if (isNaN(priceNum) || isNaN(stockNum)) { + return res.status(400).send("❌ Price and stock must be valid numbers."); + } - // SQL Query รองรับ stock และ image_url - const sql = 'INSERT INTO products (name, price, description, stock, image_url) VALUES (?, ?, ?, ?, ?)'; - const values = [name, price, description || null, stock, image_url || null]; + const imagePath = req.file ? "/uploads/" + req.file.filename : null; - console.log('SQL Query:', sql, values); // Debug SQL Query + await pool.execute( + "INSERT INTO products (name, price, stock, description, image_url) VALUES (?, ?, ?, ?, ?)", + [name, priceNum, stockNum, description, imagePath] + ); - connection.query(sql, values, (err, result) => { - if (err) { - console.error('MySQL Insert Error:', err); - return res.status(500).json({ message: 'Database error', error: err }); - } - console.log('Product Added:', result); - res.status(201).json({ message: 'Product added successfully', result }); - }); + res.redirect("/products"); + } catch (error) { + console.error("❌ Error adding product:", error); + res.status(500).send("Error adding product."); + } }); // ดึงข้อมูลสินค้าตาม ID และแสดงหน้าแก้ไข @@ -73,11 +71,11 @@ router.get("/edit/:id", async (req, res) => { try { const [rows] = await pool.execute("SELECT * FROM products WHERE id = ?", [req.params.id]); if (rows.length === 0) { - return res.status(404).send("ไม่พบสินค้า"); + return res.status(404).send("❌ ไม่พบสินค้า"); } res.render("product_edit", { product: rows[0] }); } catch (error) { - console.error("Error fetching product:", error); + console.error("❌ Error fetching product:", error); res.status(500).send("Error loading product."); } }); @@ -85,34 +83,32 @@ router.get("/edit/:id", async (req, res) => { // อัปเดตข้อมูลสินค้า router.post("/edit/:id", upload.single("image"), async (req, res) => { try { - const { name, price, stock, description } = req.body; - let imagePath = req.body.oldImage; // ใช้รูปเดิมถ้าไม่มีการอัปโหลดใหม่ + const { name, price, stock, description, oldImage } = req.body; + const priceNum = parseFloat(price); + const stockNum = parseInt(stock, 10); - // ถ้ามีการอัปโหลดรูปใหม่ ให้ใช้ไฟล์ใหม่ + if (isNaN(priceNum) || isNaN(stockNum)) { + return res.status(400).send("❌ Price and stock must be valid numbers."); + } + + // ใช้รูปเดิม ถ้าไม่ได้อัปโหลดใหม่ + let imagePath = oldImage || null; if (req.file) { imagePath = "/uploads/" + req.file.filename; } - console.log("Update values:", { name, price, stock, description, imagePath, id: req.params.id }); + console.log("🛠 Updating Product:", { name, priceNum, stockNum, description, imagePath, id: req.params.id }); await pool.execute( "UPDATE products SET name=?, price=?, stock=?, description=?, image_url=? WHERE id=?", - [ - name ?? null, - price ?? null, - stock ?? null, - description ?? null, - imagePath ?? null, - req.params.id ?? null - ] + [name ?? null, priceNum ?? null, stockNum ?? null, description ?? null, imagePath, req.params.id] ); - res.redirect("/products"); // กลับไปยังหน้ารายการสินค้า + res.redirect("/products"); } catch (error) { - console.error("Error updating product:", error); + console.error("❌ Error updating product:", error); res.status(500).send("Error updating product."); } }); - module.exports = router;