From 4af18bbfff9ac1f80f197eae4df59be59924e94e Mon Sep 17 00:00:00 2001 From: Atiwit Pattanapukdee <65160394@go.buu.ac.th> Date: Mon, 17 Mar 2025 20:27:06 +0700 Subject: [PATCH] Project Round 3 --- controllers/tourController.js | 71 ++++++++++++++++++++++++++-------- models/tourModel.js | 62 +++++++++++++++++++++++++----- routes/tourRoutes.js | 27 ++++++++++++- server.js | 2 + views/index.ejs | 72 +++++++++++++++++++++++------------ views/tour-details.ejs | 2 +- 6 files changed, 185 insertions(+), 51 deletions(-) diff --git a/controllers/tourController.js b/controllers/tourController.js index cc5b92b..e96ca98 100644 --- a/controllers/tourController.js +++ b/controllers/tourController.js @@ -1,27 +1,68 @@ const { User, Tour } = require('../models/tourModel'); +// ดึงข้อมูลทัวร์ทั้งหมด exports.getTours = async (req, res) => { try { - const tours = await Tour.getAllTours(); - res.render('index', { - tours: tours, - session: req.session // ส่ง session ไปยัง ejs - }); - } catch (error) { - res.status(500).send('เกิดข้อผิดพลาด'); + const tours = await Tour.getAll(); + res.render('index', { + tours: tours, + userId: req.session.userId, + userName: req.session.userName + }); + } catch (err) { + res.status(500).json({ error: err.message }); } }; -exports.getTourDetails = async (req, res) => { - try { - const tour = await Tour.getTourById(req.params.id); - if (!tour) return res.status(404).send('ไม่พบข้อมูล'); - res.render('tour-details', { tour }); - } catch (error) { - res.status(500).send('เกิดข้อผิดพลาด'); - } +exports.getAllTours = async (req, res) => { + try { + const results = await Tour.getAll(); + res.json(results); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}; + +exports.getTourById = async (req, res) => { + try { + const result = await Tour.getById(req.params.id); + if (!result) return res.status(404).json({ message: "Tour not found" }); + res.json(result); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}; + +exports.createTour = async (req, res) => { + try { + const insertId = await Tour.create(req.body); + res.json({ message: 'Tour added', id: insertId }); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}; + +exports.updateTour = async (req, res) => { + try { + const success = await Tour.update(req.params.id, req.body); + if (!success) return res.status(404).json({ message: "Tour not found" }); + res.json({ message: 'Tour updated' }); + } catch (err) { + res.status(500).json({ error: err.message }); + } }; +exports.deleteTour = async (req, res) => { + try { + const success = await Tour.delete(req.params.id); + if (!success) return res.status(404).json({ message: "Tour not found" }); + res.json({ message: 'Tour deleted' }); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}; + + //User// exports.getLogin = (req, res) => { res.render('login', { message: null }); diff --git a/models/tourModel.js b/models/tourModel.js index 11360d9..67e370e 100644 --- a/models/tourModel.js +++ b/models/tourModel.js @@ -1,15 +1,59 @@ const pool = require('../config/database'); const bcrypt = require('bcryptjs'); class Tour { - static async getAllTours() { - const [rows] = await pool.query('SELECT * FROM tours'); - return rows; - } - - static async getTourById(id) { - const [rows] = await pool.query('SELECT * FROM tours WHERE id = ?', [id]); - return rows[0]; - } + static async getAll() { + try { + const [results] = await pool.query('SELECT * FROM tours'); + return results; + } catch (err) { + throw err; // Throw error to be caught by the caller + } + } + + static async getById(id) { + try { + const [result] = await pool.query('SELECT * FROM tours WHERE id = ?', [id]); + return result; + } catch (err) { + throw err; + } + } + + static async create(data) { + try { + const [result] = await pool.query('INSERT INTO tours SET ?', data); + return result.insertId; // Return the ID of the newly inserted tour + } catch (err) { + throw err; + } + } + + static async update(id, data) { + try { + const [result] = await pool.query('UPDATE tours SET ? WHERE id = ?', [data, id]); + return result.affectedRows > 0; // Return true if update was successful + } catch (err) { + throw err; + } + } + + static async delete(id) { + try { + const [result] = await pool.query('DELETE FROM tours WHERE id = ?', [id]); + return result.affectedRows > 0; // Return true if delete was successful + } catch (err) { + throw err; + } + } + + static async search(query) { + try { + const [results] = await pool.query('SELECT * FROM tours WHERE name LIKE ?', [`%${query}%`]); + return results; + } catch (err) { + throw err; + } + } } class User { diff --git a/routes/tourRoutes.js b/routes/tourRoutes.js index 4db32a9..9606b86 100644 --- a/routes/tourRoutes.js +++ b/routes/tourRoutes.js @@ -2,10 +2,11 @@ const express = require('express'); const router = express.Router(); const tourController = require('../controllers/tourController'); - - +// หน้าแสดงข้อมูล router.get('/', tourController.getTours); router.get('/tour/:id', tourController.getTourDetails); + +//login logout router.get('/login', tourController.getLogin); router.get('/logout', tourController.Logout); router.get('/register', tourController.getRegister); @@ -13,4 +14,26 @@ router.post('/login', tourController.postLogin); router.post('/register', tourController.postRegister); +// ✅ ดึงข้อมูลทัวร์ทั้งหมด +router.get('/tours', tourController.getAllTours); + +// ✅ ดึงข้อมูลทัวร์ตาม ID +router.get('/tours/:id', tourController.getTourById); + +// ✅ ค้นหาทัวร์ (เพิ่มใหม่) +router.get('/tours/search', tourController.searchTours); + +// ✅ สร้างทัวร์ +router.post('/tours', tourController.createTour); + +// ✅ แก้ไขทัวร์ +router.put('/tours/:id', tourController.updateTour); + +// ✅ ลบทัวร์ +router.delete('/tours/:id', tourController.deleteTour); + +module.exports = router; + + + module.exports = router; diff --git a/server.js b/server.js index 2ea0bea..067bb97 100644 --- a/server.js +++ b/server.js @@ -14,6 +14,8 @@ app.use(session({ saveUninitialized: true })); + + app.set('view engine', 'ejs'); app.use(express.static('public')); app.use(bodyParser.urlencoded({ extended: false })); diff --git a/views/index.ejs b/views/index.ejs index 2962118..204a657 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -5,37 +5,61 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tour Website</title> <link rel="stylesheet" href="/css/styles.css"> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> </head> <body> - <header> - <h1>Welcome to Our Tour Website</h1> - <nav> - <a href="/">Home</a> - <a href="/about">About</a> - <a href="/contact">Contact</a> - - <% if (session.userId) { %> <!-- ตรวจสอบว่า userId อยู่ใน session หรือไม่ --> - <a href="/profile"><%= session.userName %></a> <!-- แสดงชื่อผู้ใช้ --> - <a href="/logout">Logout</a> - <% } else { %> - <a href="/login">Login</a> <!-- ถ้ายังไม่ได้ login --> - <% } %> - </nav> + <header class="bg-primary text-white p-3"> + <div class="container d-flex justify-content-between align-items-center"> + <h1>Welcome to Our Tour Website</h1> + <nav> + <a href="/" class="btn btn-light">Home</a> + <a href="/about" class="btn btn-light">About</a> + <a href="/contact" class="btn btn-light">Contact</a> + + <% if (userId) { %> + <a href="/profile" class="btn btn-warning"><%= userName %></a> + <a href="/logout" class="btn btn-danger">Logout</a> + <% } else { %> + <a href="/login" class="btn btn-success">Login</a> + <% } %> + </nav> + </div> </header> - <section> - <h2>Available Tours</h2> - <ul> - <% tours.forEach(tour => { %> - <li> - <a href="/tour/<%= tour.id %>"><%= tour.name %></a> - <%= tour.price %> THB - </li> - <% }) %> - </ul> + <section class="container mt-4"> + <h2 class="text-center">Available Tours</h2> + + <% if (tours.length === 0) { %> + <p class="text-center text-danger">No tours available at the moment.</p> + <% } else { %> + <div class="row"> + <% tours.forEach(tour => { %> + <div class="col-md-4 mb-4"> + <div class="card"> + <% if (tour.image) { %> + <img src="<%= tour.image %>" class="card-img-top" alt="<%= tour.name %>"> + <% } else { %> + <img src="/images/default-tour.jpg" class="card-img-top" alt="Tour Image"> + <% } %> + <div class="card-body"> + <h5 class="card-title"><%= tour.name %></h5> + <p class="card-text">Price: <strong><%= tour.price %> THB</strong></p> + <a href="/tour/<%= tour.id %>" class="btn btn-primary">View Details</a> + <% if (userId) { %> + <a href="/book/<%= tour.id %>" class="btn btn-success">Book Now</a> + <% } %> + </div> + </div> + </div> + <% }) %> + </div> + <% } %> </section> - <footer> + <footer class="bg-dark text-white text-center p-3 mt-4"> <p>© 2025 Tour Website</p> </footer> + + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> </body> </html> diff --git a/views/tour-details.ejs b/views/tour-details.ejs index f068833..5b43352 100644 --- a/views/tour-details.ejs +++ b/views/tour-details.ejs @@ -4,7 +4,7 @@ <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><%= tour.name %> - Tour Details</title> - <link rel="stylesheet" href="/css/style.css"> + <link rel="stylesheet" href="/css/styles.css"> </head> <body> <header> -- GitLab