Files
Hotel-Booking/server/src/controllers/reviewController.js
Iliyan Angelov 824eec6190 Hotel Booking
2025-11-16 14:19:13 +02:00

234 lines
4.8 KiB
JavaScript

const { Review, User, Room, Booking } =
require('../databases/models');
const { Op } = require('sequelize');
/**
* Get reviews for a specific room
*/
const getRoomReviews = async (req, res, next) => {
try {
// Support both routes: /api/reviews/room/:roomId and /api/rooms/:id/reviews
const roomId = req.params.roomId || req.params.id;
if (!roomId) {
return res.status(400).json({
status: 'error',
message: 'roomId is required',
});
}
const reviews = await Review.findAll({
where: {
room_id: parseInt(roomId, 10),
status: 'approved',
},
include: [
{
model: User,
as: 'user',
attributes: ['id', 'full_name', 'email'],
},
],
order: [['created_at', 'DESC']],
});
res.status(200).json({
status: 'success',
data: {
reviews,
},
});
} catch (error) {
next(error);
}
};
/**
* Create a new review (authenticated users only)
*/
const createReview = async (req, res, next) => {
try {
const { room_id, rating, comment } = req.body;
const userId = req.user.id;
// Check if room exists
const room = await Room.findByPk(room_id);
if (!room) {
return res.status(404).json({
status: 'error',
message: 'Room not found',
});
}
// Optional: Check if user has booked this room
// const hasBooked = await Booking.findOne({
// where: {
// user_id: userId,
// room_id: room_id,
// status: 'completed',
// },
// });
// if (!hasBooked) {
// return res.status(403).json({
// status: 'error',
// message: 'You can only review rooms you have booked',
// });
// }
// Check if user already reviewed this room
const existingReview = await Review.findOne({
where: {
user_id: userId,
room_id: room_id,
},
});
if (existingReview) {
return res.status(400).json({
status: 'error',
message: 'You have already reviewed this room',
});
}
// Create review
const review = await Review.create({
user_id: userId,
room_id,
rating,
comment,
status: 'pending', // Admin will approve
});
res.status(201).json({
status: 'success',
message: 'Review submitted successfully and is pending approval',
data: {
review,
},
});
} catch (error) {
next(error);
}
};
/**
* Approve review (Admin only)
*/
const approveReview = async (req, res, next) => {
try {
const { id } = req.params;
const review = await Review.findByPk(id);
if (!review) {
return res.status(404).json({
status: 'error',
message: 'Review not found',
});
}
await review.update({ status: 'approved' });
res.status(200).json({
status: 'success',
message: 'Review approved successfully',
data: {
review,
},
});
} catch (error) {
next(error);
}
};
/**
* Reject review (Admin only)
*/
const rejectReview = async (req, res, next) => {
try {
const { id } = req.params;
const review = await Review.findByPk(id);
if (!review) {
return res.status(404).json({
status: 'error',
message: 'Review not found',
});
}
await review.update({ status: 'rejected' });
res.status(200).json({
status: 'success',
message: 'Review rejected successfully',
data: {
review,
},
});
} catch (error) {
next(error);
}
};
/**
* Get all reviews (Admin only)
*/
const getAllReviews = async (req, res, next) => {
try {
const {
status,
page = 1,
limit = 10,
} = req.query;
const whereClause = {};
if (status) {
whereClause.status = status;
}
const offset = (parseInt(page) - 1) * parseInt(limit);
const { count, rows: reviews } = await Review.findAndCountAll({
where: whereClause,
include: [
{
model: User,
as: 'user',
attributes: ['id', 'full_name', 'email', 'phone'],
},
{
model: Room,
as: 'room',
attributes: ['id', 'room_number'],
},
],
limit: parseInt(limit),
offset: offset,
order: [['created_at', 'DESC']],
});
res.status(200).json({
status: 'success',
data: {
reviews,
pagination: {
total: count,
page: parseInt(page),
limit: parseInt(limit),
totalPages: Math.ceil(count / parseInt(limit)),
},
},
});
} catch (error) {
console.error('Error in getAllReviews:', error);
next(error);
}
};
module.exports = {
getRoomReviews,
createReview,
approveReview,
rejectReview,
getAllReviews,
};