- Trasporti- Passo 2

This commit is contained in:
Surya Paolo
2025-12-22 23:39:47 +01:00
parent 2e7801b4ba
commit b78e3ce544
16 changed files with 1096 additions and 505 deletions

View File

@@ -4,7 +4,7 @@ const sharp = require('sharp');
const path = require('path');
const fs = require('fs').promises;
const UPLOAD_DIR = process.env.UPLOAD_DIR || './uploads';
const UPLOAD_DIR = process.env.UPLOAD_DIR || './upload';
const assetController = {
// POST /assets/upload
@@ -50,9 +50,9 @@ const assetController = {
sourceType: 'upload',
file: {
path: file.path,
url: `/uploads/${file.filename}`,
url: `/upload/${file.filename}`,
thumbnailPath: thumbPath,
thumbnailUrl: `/uploads/thumbs/${thumbName}`,
thumbnailUrl: `/upload/thumbs/${thumbName}`,
originalName: file.originalname,
mimeType: file.mimetype,
size: file.size,
@@ -106,7 +106,7 @@ const assetController = {
sourceType: 'upload',
file: {
path: file.path,
url: `/uploads/${file.filename}`,
url: `/upload/${file.filename}`,
originalName: file.originalname,
mimeType: file.mimetype,
size: file.size,
@@ -199,7 +199,7 @@ const assetController = {
sourceType: 'ai',
file: {
path: filePath,
url: `/uploads/ai-generated/${fileName}`,
url: `/upload/ai-generated/${fileName}`,
mimeType: 'image/jpeg',
size: fileSize,
dimensions

View File

@@ -1,6 +1,6 @@
const Chat = require('../models/Chat');
const Message = require('../models/Message');
const { User } = require('../models/User');
const { User } = require('../models/user');
/**
* @desc Ottieni tutte le chat dell'utente
@@ -10,7 +10,8 @@ const { User } = require('../models/User');
const getMyChats = async (req, res) => {
try {
const userId = req.user._id;
const { idapp, page = 1, limit = 20 } = req.query;
const idapp = req.user.idapp;
const { page = 1, limit = 20 } = req.query;
if (!idapp) {
return res.status(400).json({
@@ -83,7 +84,8 @@ const getMyChats = async (req, res) => {
const getOrCreateDirectChat = async (req, res) => {
try {
const userId = req.user._id;
const { idapp, otherUserId, rideId } = req.body;
const idapp = req.user.idapp;
const { otherUserId, rideId } = req.body;
if (!idapp || !otherUserId) {
return res.status(400).json({
@@ -199,7 +201,8 @@ const getChatById = async (req, res) => {
const getChatMessages = async (req, res) => {
try {
const { id } = req.params;
const { idapp, before, after, limit = 50 } = req.query;
const idapp = req.user.idapp;
const { before, after, limit = 50 } = req.query;
const userId = req.user._id;
// Verifica accesso alla chat
@@ -209,7 +212,7 @@ const getChatMessages = async (req, res) => {
success: false,
message: 'Chat non trovata'
});
}
}
if (!chat.hasParticipant(userId)) {
return res.status(403).json({
@@ -258,7 +261,8 @@ const getChatMessages = async (req, res) => {
const sendMessage = async (req, res) => {
try {
const { id } = req.params;
const { idapp, text, type = 'text', metadata, replyTo } = req.body;
const idapp = req.user.idapp;
const { text, type = 'text', metadata, replyTo } = req.body;
const userId = req.user._id;
if (!idapp || !text) {
@@ -499,7 +503,7 @@ const toggleMuteChat = async (req, res) => {
const getUnreadCount = async (req, res) => {
try {
const userId = req.user._id;
const { idapp } = req.query;
const idapp = req.user.idapp;
if (!idapp) {
return res.status(400).json({
@@ -597,6 +601,67 @@ const deleteMessage = async (req, res) => {
}
};
/**
* @desc Elimina una chat (soft delete)
* @route DELETE /api/trasporti/chats/:id
* @access Private
*/
const deleteChat = async (req, res) => {
try {
const { id } = req.params;
const userId = req.user._id;
const chat = await Chat.findById(id);
if (!chat) {
return res.status(404).json({
success: false,
message: 'Chat non trovata'
});
}
// Verifica che l'utente sia partecipante
if (!chat.hasParticipant(userId)) {
return res.status(403).json({
success: false,
message: 'Non sei autorizzato a eliminare questa chat'
});
}
// Soft delete: segna come non attiva per questo utente
// Se vuoi hard delete, usa: await chat.deleteOne();
// Opzione 1: Soft delete (chat rimane ma nascosta per questo utente)
if (!chat.deletedBy) {
chat.deletedBy = [];
}
if (!chat.deletedBy.includes(userId)) {
chat.deletedBy.push(userId);
}
// Se tutti i partecipanti hanno eliminato, marca come non attiva
if (chat.deletedBy.length === chat.participants.length) {
chat.isActive = false;
}
await chat.save();
res.json({
success: true,
message: 'Chat eliminata'
});
} catch (error) {
console.error('Errore eliminazione chat:', error);
res.status(500).json({
success: false,
message: 'Errore nell\'eliminazione della chat',
error: error.message
});
}
};
module.exports = {
getMyChats,
getOrCreateDirectChat,
@@ -607,5 +672,6 @@ module.exports = {
toggleBlockChat,
toggleMuteChat,
getUnreadCount,
deleteMessage
deleteMessage,
deleteChat,
};

View File

@@ -1,7 +1,7 @@
const Feedback = require('../models/Feedback');
const Ride = require('../models/Ride');
const RideRequest = require('../models/RideRequest');
const { User } = require('../models/User');
const { User } = require('../models/user');
/**
* @desc Crea un feedback per un viaggio

View File

@@ -6,7 +6,7 @@ const imageGenerator = require('../services/imageGenerator');
const path = require('path');
const fs = require('fs').promises;
const UPLOAD_DIR = process.env.UPLOAD_DIR || './uploads';
const UPLOAD_DIR = process.env.UPLOAD_DIR || './upload';
const posterController = {
// POST /posters
@@ -396,7 +396,7 @@ const posterController = {
// Aggiorna asset nel poster
const assetData = {
sourceType: 'ai',
url: `/uploads/ai-generated/${fileName}`,
url: `/upload/ai-generated/${fileName}`,
mimeType: 'image/jpeg',
aiParams: {
prompt,
@@ -572,7 +572,7 @@ const posterController = {
assets: {
backgroundImage: {
sourceType: 'ai',
url: `/uploads/ai-generated/${fileName}`,
url: `/upload/ai-generated/${fileName}`,
mimeType: 'image/jpeg',
aiParams: {
prompt: aiPrompt,
@@ -629,12 +629,12 @@ const posterController = {
poster.setRenderOutput({
png: {
path: result.pngPath,
url: `/uploads/posters/final/${path.basename(result.pngPath)}`,
url: `/upload/posters/final/${path.basename(result.pngPath)}`,
size: result.pngSize
},
jpg: {
path: result.jpgPath,
url: `/uploads/posters/final/${path.basename(result.jpgPath)}`,
url: `/upload/posters/final/${path.basename(result.jpgPath)}`,
size: result.jpgSize,
quality: 95
},

View File

@@ -1,5 +1,5 @@
const Ride = require('../models/Ride');
const User = require('../models/User');
const User = require('../models/user');
const RideRequest = require('../models/RideRequest');
/**

View File

@@ -602,6 +602,157 @@ const getRequestById = async (req, res) => {
}
};
/**
* @desc Ottieni richieste ricevute (io come conducente)
* @route GET /api/trasporti/requests/received
* @access Private
*/
const getReceivedRequests = async (req, res) => {
try {
const driverId = req.user._id;
const { status, page = 1, limit = 20 } = req.query;
// Build query
const query = { driverId };
if (status) {
query.status = status;
}
const skip = (parseInt(page) - 1) * parseInt(limit);
// Fetch requests
const requests = await RideRequest.find(query)
.populate('passengerId', 'name surname profile.img') // <-- FIX: passengerId invece di userId
.populate('rideId', 'departure destination departureDate availableSeats')
.sort({ createdAt: -1 })
.skip(skip)
.limit(parseInt(limit))
.lean();
// Get counts by status
const counts = await RideRequest.aggregate([
{ $match: { driverId } },
{
$group: {
_id: '$status',
count: { $sum: 1 }
}
}
]);
// Format counts
const statusCounts = {
pending: 0,
accepted: 0,
rejected: 0,
cancelled: 0,
expired: 0,
completed: 0
};
counts.forEach(c => {
if (statusCounts.hasOwnProperty(c._id)) {
statusCounts[c._id] = c.count;
}
});
// Total count
const total = await RideRequest.countDocuments(query);
res.json({
success: true,
data: {
requests,
counts: statusCounts,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total,
pages: Math.ceil(total / parseInt(limit))
}
}
});
} catch (error) {
console.error('Error fetching received requests:', error);
res.status(500).json({
success: false,
message: 'Errore nel recupero delle richieste ricevute',
error: error.message
});
}
};
/**
* @desc Ottieni richieste inviate (io come passeggero)
* @route GET /api/trasporti/requests/sent
* @access Private
*/
const getSentRequests = async (req, res) => {
try {
const userId = req.user._id;
const { status, page = 1, limit = 20 } = req.query;
// Build query - FIX: usa passengerId invece di userId
const query = { passengerId: userId };
if (status) {
query.status = status;
}
const skip = (parseInt(page) - 1) * parseInt(limit);
// Fetch requests
const requests = await RideRequest.find(query)
.populate('driverId', 'name surname profile.img')
.populate('rideId', 'departure destination departureDate availableSeats currentPassengers')
.sort({ createdAt: -1 })
.skip(skip)
.limit(parseInt(limit))
.lean();
// Enrich with ride info
const enrichedRequests = requests.map(request => {
const req = { ...request };
// Add ride info if rideId is populated
if (req.rideId) {
req.rideInfo = {
departure: req.rideId.departure?.city || req.rideId.departure,
destination: req.rideId.destination?.city || req.rideId.destination,
departureDate: req.rideId.departureDate,
availableSeats: req.rideId.availableSeats,
currentPassengers: req.rideId.currentPassengers || 0
};
}
return req;
});
// Total count
const total = await RideRequest.countDocuments(query);
res.json({
success: true,
data: {
requests: enrichedRequests,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total,
pages: Math.ceil(total / parseInt(limit))
}
}
});
} catch (error) {
console.error('Error fetching sent requests:', error);
res.status(500).json({
success: false,
message: 'Errore nel recupero delle richieste inviate',
error: error.message
});
}
};
module.exports = {
createRequest,
getRequestsForRide,
@@ -611,6 +762,6 @@ module.exports = {
rejectRequest,
cancelRequest,
getRequestById,
getReceivedRequests: getPendingRequests,
getSentRequests: getMyRequests,
getReceivedRequests,
getSentRequests,
};