All materials
bookings.js
jsbookings.js
const express = require('express');
const router = express.Router();
const pool = require('../db');
const logger = require('../middleware/logging').logger;
router.get('/', async (req, res, next) => {
try {
const { customer_email } = req.query;
let query = `
SELECT b.*, t.name as trek_name, t.destination
FROM bookings b
JOIN treks t ON b.trek_id = t.id
`;
const params = [];
if (customer_email) {
query += ' WHERE b.customer_email = $1';
params.push(customer_email);
}
query += ' ORDER BY b.created_at DESC';
const result = await pool.query(query, params);
logger.info('Bookings listed', {
requestId: req.requestId,
route: 'GET /api/bookings',
filter: customer_email || 'none',
count: result.rows.length
});
res.json(result.rows);
} catch (err) {
next(err);
}
});
router.post('/', async (req, res, next) => {
try {
const { trek_id, customer_name, customer_email, group_size, booking_date } = req.body;
if (!trek_id || !customer_name || !customer_email || !group_size || !booking_date) {
return res.status(400).json({
error: 'Missing required fields: trek_id, customer_name, customer_email, group_size, booking_date'
});
}
const trek = await pool.query('SELECT * FROM treks WHERE id = $1', [trek_id]);
if (trek.rows.length === 0) {
return res.status(400).json({ error: 'Trek not found' });
}
if (group_size > trek.rows[0].max_group_size) {
return res.status(400).json({
error: `Group size exceeds maximum of ${trek.rows[0].max_group_size} for this trek`
});
}
const result = await pool.query(
`INSERT INTO bookings (trek_id, customer_name, customer_email, group_size, booking_date, status)
VALUES ($1, $2, $3, $4, $5, 'pending')
RETURNING *`,
[trek_id, customer_name, customer_email, group_size, booking_date]
);
logger.info('Booking created', {
requestId: req.requestId,
route: 'POST /api/bookings',
bookingId: result.rows[0].id,
trekName: trek.rows[0].name,
customerEmail: customer_email
});
res.status(201).json(result.rows[0]);
} catch (err) {
next(err);
}
});
module.exports = router;