messages and reviews
This commit is contained in:
50
backend/models/Message.js
Normal file
50
backend/models/Message.js
Normal file
@@ -0,0 +1,50 @@
|
||||
const { DataTypes } = require('sequelize');
|
||||
const sequelize = require('../config/database');
|
||||
|
||||
const Message = sequelize.define('Message', {
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true
|
||||
},
|
||||
senderId: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: 'Users',
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
receiverId: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: 'Users',
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
subject: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
content: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: false
|
||||
},
|
||||
isRead: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
parentMessageId: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: 'Messages',
|
||||
key: 'id'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
timestamps: true
|
||||
});
|
||||
|
||||
module.exports = Message;
|
||||
@@ -2,6 +2,7 @@ const sequelize = require('../config/database');
|
||||
const User = require('./User');
|
||||
const Item = require('./Item');
|
||||
const Rental = require('./Rental');
|
||||
const Message = require('./Message');
|
||||
|
||||
User.hasMany(Item, { as: 'ownedItems', foreignKey: 'ownerId' });
|
||||
Item.belongsTo(User, { as: 'owner', foreignKey: 'ownerId' });
|
||||
@@ -14,9 +15,17 @@ Rental.belongsTo(Item, { as: 'item', foreignKey: 'itemId' });
|
||||
Rental.belongsTo(User, { as: 'renter', foreignKey: 'renterId' });
|
||||
Rental.belongsTo(User, { as: 'owner', foreignKey: 'ownerId' });
|
||||
|
||||
User.hasMany(Message, { as: 'sentMessages', foreignKey: 'senderId' });
|
||||
User.hasMany(Message, { as: 'receivedMessages', foreignKey: 'receiverId' });
|
||||
Message.belongsTo(User, { as: 'sender', foreignKey: 'senderId' });
|
||||
Message.belongsTo(User, { as: 'receiver', foreignKey: 'receiverId' });
|
||||
Message.hasMany(Message, { as: 'replies', foreignKey: 'parentMessageId' });
|
||||
Message.belongsTo(Message, { as: 'parentMessage', foreignKey: 'parentMessageId' });
|
||||
|
||||
module.exports = {
|
||||
sequelize,
|
||||
User,
|
||||
Item,
|
||||
Rental
|
||||
Rental,
|
||||
Message
|
||||
};
|
||||
169
backend/routes/messages.js
Normal file
169
backend/routes/messages.js
Normal file
@@ -0,0 +1,169 @@
|
||||
const express = require('express');
|
||||
const { Message, User } = require('../models');
|
||||
const { authenticateToken } = require('../middleware/auth');
|
||||
const router = express.Router();
|
||||
|
||||
// Get all messages for the current user (inbox)
|
||||
router.get('/', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const messages = await Message.findAll({
|
||||
where: { receiverId: req.user.id },
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'sender',
|
||||
attributes: ['id', 'firstName', 'lastName', 'profileImage']
|
||||
}
|
||||
],
|
||||
order: [['createdAt', 'DESC']]
|
||||
});
|
||||
res.json(messages);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Get sent messages
|
||||
router.get('/sent', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const messages = await Message.findAll({
|
||||
where: { senderId: req.user.id },
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'receiver',
|
||||
attributes: ['id', 'firstName', 'lastName', 'profileImage']
|
||||
}
|
||||
],
|
||||
order: [['createdAt', 'DESC']]
|
||||
});
|
||||
res.json(messages);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Get a single message with replies
|
||||
router.get('/:id', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const message = await Message.findOne({
|
||||
where: {
|
||||
id: req.params.id,
|
||||
[require('sequelize').Op.or]: [
|
||||
{ senderId: req.user.id },
|
||||
{ receiverId: req.user.id }
|
||||
]
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'sender',
|
||||
attributes: ['id', 'firstName', 'lastName', 'profileImage']
|
||||
},
|
||||
{
|
||||
model: User,
|
||||
as: 'receiver',
|
||||
attributes: ['id', 'firstName', 'lastName', 'profileImage']
|
||||
},
|
||||
{
|
||||
model: Message,
|
||||
as: 'replies',
|
||||
include: [{
|
||||
model: User,
|
||||
as: 'sender',
|
||||
attributes: ['id', 'firstName', 'lastName', 'profileImage']
|
||||
}]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
if (!message) {
|
||||
return res.status(404).json({ error: 'Message not found' });
|
||||
}
|
||||
|
||||
// Mark as read if user is the receiver
|
||||
if (message.receiverId === req.user.id && !message.isRead) {
|
||||
await message.update({ isRead: true });
|
||||
}
|
||||
|
||||
res.json(message);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Send a new message
|
||||
router.post('/', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const { receiverId, subject, content, parentMessageId } = req.body;
|
||||
|
||||
// Check if receiver exists
|
||||
const receiver = await User.findByPk(receiverId);
|
||||
if (!receiver) {
|
||||
return res.status(404).json({ error: 'Receiver not found' });
|
||||
}
|
||||
|
||||
// Prevent sending messages to self
|
||||
if (receiverId === req.user.id) {
|
||||
return res.status(400).json({ error: 'Cannot send messages to yourself' });
|
||||
}
|
||||
|
||||
const message = await Message.create({
|
||||
senderId: req.user.id,
|
||||
receiverId,
|
||||
subject,
|
||||
content,
|
||||
parentMessageId
|
||||
});
|
||||
|
||||
const messageWithSender = await Message.findByPk(message.id, {
|
||||
include: [{
|
||||
model: User,
|
||||
as: 'sender',
|
||||
attributes: ['id', 'firstName', 'lastName', 'profileImage']
|
||||
}]
|
||||
});
|
||||
|
||||
res.status(201).json(messageWithSender);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Mark message as read
|
||||
router.put('/:id/read', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const message = await Message.findOne({
|
||||
where: {
|
||||
id: req.params.id,
|
||||
receiverId: req.user.id
|
||||
}
|
||||
});
|
||||
|
||||
if (!message) {
|
||||
return res.status(404).json({ error: 'Message not found' });
|
||||
}
|
||||
|
||||
await message.update({ isRead: true });
|
||||
res.json(message);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Get unread message count
|
||||
router.get('/unread/count', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const count = await Message.count({
|
||||
where: {
|
||||
receiverId: req.user.id,
|
||||
isRead: false
|
||||
}
|
||||
});
|
||||
res.json({ count });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
@@ -14,15 +14,32 @@ router.get('/profile', authenticateToken, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/:id', async (req, res) => {
|
||||
try {
|
||||
const user = await User.findByPk(req.params.id, {
|
||||
attributes: { exclude: ['password', 'email', 'phone', 'address'] }
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({ error: 'User not found' });
|
||||
}
|
||||
|
||||
res.json(user);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/profile', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const { firstName, lastName, phone, address } = req.body;
|
||||
const { firstName, lastName, phone, address, profileImage } = req.body;
|
||||
|
||||
await req.user.update({
|
||||
firstName,
|
||||
lastName,
|
||||
phone,
|
||||
address
|
||||
address,
|
||||
profileImage
|
||||
});
|
||||
|
||||
const updatedUser = await User.findByPk(req.user.id, {
|
||||
|
||||
@@ -8,6 +8,7 @@ const authRoutes = require('./routes/auth');
|
||||
const userRoutes = require('./routes/users');
|
||||
const itemRoutes = require('./routes/items');
|
||||
const rentalRoutes = require('./routes/rentals');
|
||||
const messageRoutes = require('./routes/messages');
|
||||
|
||||
const app = express();
|
||||
|
||||
@@ -19,6 +20,7 @@ app.use('/api/auth', authRoutes);
|
||||
app.use('/api/users', userRoutes);
|
||||
app.use('/api/items', itemRoutes);
|
||||
app.use('/api/rentals', rentalRoutes);
|
||||
app.use('/api/messages', messageRoutes);
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.json({ message: 'Rentall API is running!' });
|
||||
|
||||
Reference in New Issue
Block a user