diff --git a/app.js b/app.js index f92b3f6c8dacfe04448137b06ed48df0ae9fa06f..d34a121960605f5914da2e2f270a64139f3a77d8 100644 --- a/app.js +++ b/app.js @@ -5,8 +5,10 @@ const mysql = require('mysql2/promise'); const bcrypt = require('bcryptjs'); const session = require('express-session'); const cookieParser = require('cookie-parser'); +const path = require('path'); +const multer = require('multer'); // เพิ่มการใช้ multer -const app = express(); // ต้องมีการสร้าง express app +const app = express(); // Middleware สำหรับ parse cookie และ JSON app.use(express.json()); @@ -19,9 +21,9 @@ app.use(session({ resave: false, saveUninitialized: true, cookie: { - secure: process.env.NODE_ENV === 'production', // secure เมื่อเป็น production mode - httpOnly: true, // ป้องกันการเข้าถึงผ่าน JavaScript - maxAge: 1000 * 60 * 60 * 24 // อายุของ session (1 วัน) + secure: process.env.NODE_ENV === 'production', + httpOnly: true, + maxAge: 1000 * 60 * 60 * 24 } })); @@ -48,7 +50,10 @@ pool.getConnection() process.exit(1); // หยุดโปรแกรมหากเชื่อมต่อไม่สำเร็จ }); -// ตัวอย่าง route ทดสอบ +// Static file serving +app.use(express.static(path.join(__dirname, 'public'))); + +// Session และ routes app.get('/', (req, res) => { if (req.session.user) { res.sendFile(path.join(__dirname, 'public', 'index.html')); @@ -57,63 +62,35 @@ app.get('/', (req, res) => { } }); -const path = require('path'); -app.use(express.static(path.join(__dirname, 'public'))); - -app.get('/login', (req, res) => { - res.sendFile(path.join(__dirname, 'public', 'login.html')); -}); - -app.get('/register', (req, res) => { - res.sendFile(path.join(__dirname, 'public', 'register.html')); -}); - -app.get('/post-product', (req, res) => { - res.sendFile(path.join(__dirname, 'public', 'post-product.html')); -}); +// Routes สำหรับ login และ register +app.get('/login', (req, res) => res.sendFile(path.join(__dirname, 'public', 'login.html'))); +app.get('/register', (req, res) => res.sendFile(path.join(__dirname, 'public', 'register.html'))); +app.get('/post-product', (req, res) => res.sendFile(path.join(__dirname, 'public', 'post-product.html'))); -// Route สำหรับการ logout +// Logout route app.get('/logout', (req, res) => { - // ลบข้อมูลใน session req.session.destroy((err) => { if (err) { console.error('Logout error:', err); return res.status(500).send('Logout failed'); } - // เมื่อ logout สำเร็จ, redirect ไปที่หน้า login หรือหน้าอื่น - res.redirect('/login'); // เปลี่ยนไปหน้า login หลังจาก logout + res.redirect('/login'); }); }); - +// User Registration app.post('/register', async (req, res) => { const { email, password } = req.body; - - if (!email || !password) { - return res.status(400).json({ error: 'All fields are required' }); - } + if (!email || !password) return res.status(400).json({ error: 'All fields are required' }); try { - // ตรวจสอบว่า email มีอยู่แล้วหรือไม่ - const [existingUser] = await pool.query( - 'SELECT * FROM users WHERE email = ?', - [email] - ); + const [existingUser] = await pool.query('SELECT * FROM users WHERE email = ?', [email]); - if (existingUser.length > 0) { - return res.status(400).json({ error: 'Email already exists' }); - } + if (existingUser.length > 0) return res.status(400).json({ error: 'Email already exists' }); - // เข้ารหัสรหัสผ่านด้วย bcryptjs const hashedPassword = await bcrypt.hash(password, 10); + await pool.query('INSERT INTO users (email, password) VALUES (?, ?)', [email, hashedPassword]); - // เพิ่มข้อมูลลงฐานข้อมูล (ใช้แค่ email และ password) - await pool.query( - 'INSERT INTO users (email, password) VALUES (?, ?)', - [email, hashedPassword] - ); - - // หลังจากสมัครเสร็จแล้ว Redirect ไปหน้า Login res.redirect('/login'); } catch (error) { console.error('❌ Registration failed:', error); @@ -121,195 +98,77 @@ app.post('/register', async (req, res) => { } }); - -// Route สำหรับการล็อกอิน +// User Login app.post('/login', async (req, res) => { - const { email, password } = req.body; // ใช้ email แทน user + const { email, password } = req.body; + try { const connection = await pool.getConnection(); - // ค้นหาผู้ใช้จาก email - const [rows] = await connection.query( - 'SELECT * FROM users WHERE email = ?', - [email] - ); + const [rows] = await connection.query('SELECT * FROM users WHERE email = ?', [email]); connection.release(); - + if (rows.length > 0) { - // ตรวจสอบรหัสผ่าน const match = await bcrypt.compare(password, rows[0].password); if (match) { - // เก็บข้อมูลผู้ใช้ใน session (แค่ user_id และ email) - req.session.user = { - id: rows[0].user_id, // user_id ของผู้ใช้ - email: rows[0].email - }; - console.log("User session:", req.session.user); // เพิ่ม console log เพื่อตรวจสอบ - res.redirect('/'); // ไปที่หน้า home หรือหน้าแรกหลังจากล็อกอิน - return; + req.session.user = { id: rows[0].user_id, email: rows[0].email }; + res.redirect('/'); } else { res.status(400).send('Invalid password'); - return; } } else { res.status(400).send('User not found'); - return; } } catch (err) { console.error('Login error:', err); res.status(500).send('Login failed'); - return; - } - }); - - // API สำหรับดึงข้อมูลผู้ใช้หลังจากล็อกอิน - app.get('/api/getUser', (req, res) => { - if (req.session.user) { - res.json({ - user_id: req.session.user.id, // ส่งข้อมูล user_id จาก session - email: req.session.user.email // ส่งข้อมูล email จาก session - }); - } else { - res.status(401).send('User not logged in'); - } - }); - - // เพิ่มสินค้าใหม่ - app.get('/api/user/products', async (req, res) => { - if (!req.session.user) { - return res.status(401).send('User not logged in'); - } - - const userId = req.session.user.id; // ใช้ user_id จาก session - try { - const connection = await pool.getConnection(); - const [products] = await connection.query( - 'SELECT * FROM products WHERE user_id = ?', - [userId] - ); - connection.release(); - res.json(products); - } catch (err) { - console.error('Error fetching user products:', err); - res.status(500).send('Error fetching user products'); } }); -// เพิ่มสินค้าใหม่ -app.post('/api/products', (req, res) => { +// Product API (for logged in users) +const upload = multer({ dest: './uploads/' }); // การตั้งค่า multer เพื่ออัปโหลดไฟล์ + +app.post('/api/products', upload.single('productImg'), (req, res) => { if (!req.session.user) { return res.status(401).send('User not logged in'); } - const { productName, productPrice, productImg } = req.body; - const userId = req.session.user.id; // user_id จาก session + const { productName, productPrice } = req.body; + const productImg = req.file ? `/uploads/${req.file.filename}` : null; + const userId = req.session.user.id; - pool.query(` - INSERT INTO products (product_name, product_price, product_img, user_id) - VALUES (?, ?, ?, ?) - `, [productName, productPrice, productImg, userId], (err, results) => { - if (err) { - return res.status(500).send('Error adding product'); - } - res.send('Product added successfully'); + if (!productName || !productPrice || !productImg) { + return res.status(400).json({ message: 'All fields are required' }); + } + + pool.query('INSERT INTO products (product_name, product_price, product_img, user_id) VALUES (?, ?, ?, ?)', + [productName, productPrice, productImg, userId], (err, results) => { + if (err) return res.status(500).send('Error adding product'); + res.json({ message: 'Product added successfully', productId: results.insertId }); }); }); -// ดึงสินค้าของผู้ใช้ +// Fetch products of logged-in user app.get('/api/user/products', (req, res) => { if (!req.session.user) { return res.status(401).send('User not logged in'); } const userId = req.session.user.id; - - pool.query(` - SELECT * FROM products WHERE user_id = ? - `, [userId], (err, results) => { - if (err) { - return res.status(500).send('Error fetching user products'); - } + pool.query('SELECT * FROM products WHERE user_id = ?', [userId], (err, results) => { + if (err) return res.status(500).send('Error fetching user products'); res.json(results); }); }); -// ดึงสินค้าทั้งหมด +// Fetch all products app.get('/api/products', (req, res) => { pool.query('SELECT * FROM products', (err, results) => { - if (err) { - return res.status(500).send('Error fetching products'); - } + if (err) return res.status(500).send('Error fetching products'); res.json(results); }); }); -app.post('/logout', (req, res) => { - req.session.destroy(err => { - if (err) { - console.error('❌ Logout failed:', err); - return res.status(500).json({ error: 'Logout failed' }); - } - - res.clearCookie('connect.sid'); - res.status(200).json({ message: 'Logout successful' }); - }); -}); - - -const isAuthenticated = (req, res, next) => { - if (req.session.user) { - next(); - } else { - res.status(401).json({ error: 'Unauthorized' }); - } -}; - -app.get('/dashboard', isAuthenticated, (req, res) => { - res.status(200).json({ message: `Welcome ${req.session.user.username}` }); -}); - -// ให้บริการไฟล์ static เช่น รูปภาพที่ถูกอัพโหลด -app.use('/uploads', express.static(path.join(__dirname, 'uploads'))); - -// ตั้งค่าการจัดเก็บไฟล์ -const storage = multer.diskStorage({ - destination: function(req, file, cb) { - cb(null, './uploads/'); // กำหนดโฟลเดอร์ที่ใช้เก็บไฟล์ - }, - filename: function(req, file, cb) { - cb(null, Date.now() + path.extname(file.originalname)); // ตั้งชื่อไฟล์ใหม่ (ใช้ timestamp) - } -}); - -const upload = multer({ storage: storage }); - - -// ฟอร์มสำหรับโพสต์สินค้าที่รองรับการอัพโหลดไฟล์ -app.post('/api/products', upload.single('productImg'), (req, res) => { - const { productName, productPrice } = req.body; - const productImg = req.file ? `/uploads/${req.file.filename}` : null; - const userId = req.session.user.id; // ค่าของ user_id จาก session หรือ JWT - - if (!productName || !productPrice || !productImg) { - return res.status(400).json({ message: 'All fields are required' }); - } - - // คำสั่ง SQL สำหรับเพิ่มสินค้าใหม่ในฐานข้อมูล - const query = ` - INSERT INTO products (product_name, product_price, product_img, user_id) - VALUES (?, ?, ?, ?) - `; - - // บันทึกข้อมูลสินค้าในฐานข้อมูล - pool.query(query, [productName, productPrice, productImg, userId], (err, results) => { - if (err) { - console.error('Error adding product:', err); - return res.status(500).send('Error adding product'); - } - res.json({ message: 'Product added successfully', productId: results.insertId }); - }); -}); - -// Start the server +// Start server const port = process.env.PORT || 3000; app.listen(port, () => { console.log(`🚀 Server started on port ${port}`); diff --git a/public/index.html b/public/index.html index 72f362cebd67f17b21a25d630f6a827d2fa983dd..bfec8a253906dc3dd4ae3b761b3fc6cd7d0a9a6f 100644 --- a/public/index.html +++ b/public/index.html @@ -20,7 +20,7 @@ </div> <div class="user-info"> <span id="welcome-message">Welcome, User</span> <!-- Display User's Email here --> - <a href="edit-order.html" class="edit-order-btn">Edit Order</a> <!-- ปุ่ม Edit Order --> + <a href="edit-order.html" class="edit-order-btn">Edit Order</a> </div> <div class="logout"> <a href="/logout">Logout</a> @@ -69,6 +69,7 @@ }); } + // Search products function function searchProducts() { const searchQuery = document.getElementById('search').value.toLowerCase(); fetchProducts(searchQuery); @@ -104,17 +105,23 @@ cartItemCount.textContent = totalQuantity; } + // Display user's email from session async function displayUsername() { try { const response = await fetch('/api/getUser'); // Endpoint to get the user's email - const user = await response.json(); - document.getElementById('welcome-message').innerText = `Welcome, ${user.email}`; // Display email here + if (response.status === 401) { + console.log('User not logged in'); + document.getElementById('welcome-message').innerText = 'Please log in'; + } else { + const user = await response.json(); + document.getElementById('welcome-message').innerText = `Welcome, ${user.email}`; // Display email here + } } catch (error) { console.log('Error fetching user info:', error); } } - // Initially load products and cart item count + // Initially load products, cart item count, and user info fetchProducts(); // Fetch all products initially updateCart(); // Update cart count when page loads displayUsername(); // Display user's email when page loads diff --git a/public/post-product.html b/public/post-product.html index d5a4e551015551c07b5b2ca1ed6aee484e4f34ae..837d34264cba54361ac71dfaf05c13ab2e1fdc0a 100644 --- a/public/post-product.html +++ b/public/post-product.html @@ -39,6 +39,12 @@ const productPrice = document.getElementById('product_price').value; const productImg = document.getElementById('product_img').value; + // Validate form fields + if (!productName || !productPrice || !productImg) { + alert('All fields are required!'); + return; + } + try { const response = await fetch('/api/products', { method: 'POST', @@ -47,7 +53,7 @@ }, body: JSON.stringify({ product_name: productName, - product_price: productPrice, + product_price: parseFloat(productPrice), product_img: productImg }), credentials: 'same-origin', // ส่ง cookie ไปกับ request @@ -55,6 +61,7 @@ if (response.ok) { alert('Product posted successfully'); + document.getElementById('post-product-form').reset(); // รีเซ็ตฟอร์ม window.location.href = '/'; // เปลี่ยนเส้นทางไปหน้าหลัก } else { const errorMessage = await response.text();