Files
Hotwives/backend/src/controllers/event.controller.ts
root 5e4a2283bf Initial commit: HotWives Platform completa
- Backend completo com Express, TypeScript e Prisma
- Sistema de autenticação JWT
- API REST com todas as funcionalidades
- Sistema de mensagens e chat em tempo real (Socket.io)
- Upload e gerenciamento de fotos
- Sistema de perfis com verificação
- Busca avançada com filtros
- Sistema de eventos
- Dashboard administrativo
- Frontend Next.js 14 com TypeScript
- Design moderno com Tailwind CSS
- Componentes UI com Radix UI
- Tema dark/light
- Configuração Nginx pronta para produção
- Scripts de instalação e deploy
- Documentação completa
2025-11-22 01:00:35 +00:00

358 lines
8.8 KiB
TypeScript

import { Response } from 'express';
import { PrismaClient } from '@prisma/client';
import { AuthRequest } from '../middleware/auth.middleware';
const prisma = new PrismaClient();
export const getEvents = async (req: AuthRequest, res: Response) => {
try {
const { page = 1, limit = 20, upcoming = 'true' } = req.query;
const skip = (Number(page) - 1) * Number(limit);
const where: any = { status: 'PUBLISHED' };
if (upcoming === 'true') {
where.date = { gte: new Date() };
}
const [events, total] = await Promise.all([
prisma.event.findMany({
where,
skip,
take: Number(limit),
include: {
creator: {
include: { profile: true }
},
participants: {
where: { status: 'approved' },
include: {
user: {
include: { profile: true }
}
}
}
},
orderBy: { date: 'asc' }
}),
prisma.event.count({ where })
]);
res.json({
events,
pagination: {
page: Number(page),
limit: Number(limit),
total,
pages: Math.ceil(total / Number(limit))
}
});
} catch (error) {
console.error('Erro ao buscar eventos:', error);
res.status(500).json({ error: 'Erro ao buscar eventos' });
}
};
export const getEvent = async (req: AuthRequest, res: Response) => {
try {
const { id } = req.params;
const event = await prisma.event.findUnique({
where: { id },
include: {
creator: {
include: { profile: true }
},
participants: {
include: {
user: {
include: { profile: true }
}
}
}
}
});
if (!event) {
return res.status(404).json({ error: 'Evento não encontrado' });
}
// Verificar se é privado e se o usuário tem acesso
if (event.isPrivate && event.creatorId !== req.userId) {
const isParticipant = event.participants.some(
p => p.userId === req.userId && p.status === 'approved'
);
if (!isParticipant) {
return res.status(403).json({ error: 'Acesso negado' });
}
}
res.json(event);
} catch (error) {
console.error('Erro ao buscar evento:', error);
res.status(500).json({ error: 'Erro ao buscar evento' });
}
};
export const createEvent = async (req: AuthRequest, res: Response) => {
try {
const {
title,
description,
date,
endDate,
location,
city,
state,
address,
maxParticipants,
isPrivate,
requiresApproval,
tags,
price
} = req.body;
let coverImage = null;
if (req.file) {
coverImage = `/uploads/photos/${req.file.filename}`;
}
const event = await prisma.event.create({
data: {
creatorId: req.userId!,
title,
description,
date: new Date(date),
endDate: endDate ? new Date(endDate) : null,
location,
city,
state,
address,
coverImage,
maxParticipants: maxParticipants ? Number(maxParticipants) : null,
isPrivate: isPrivate === 'true',
requiresApproval: requiresApproval !== 'false',
tags: tags ? JSON.parse(tags) : [],
price: price ? parseFloat(price) : null,
status: 'PUBLISHED'
},
include: {
creator: {
include: { profile: true }
}
}
});
res.status(201).json(event);
} catch (error) {
console.error('Erro ao criar evento:', error);
res.status(500).json({ error: 'Erro ao criar evento' });
}
};
export const updateEvent = async (req: AuthRequest, res: Response) => {
try {
const { id } = req.params;
const event = await prisma.event.findUnique({
where: { id }
});
if (!event) {
return res.status(404).json({ error: 'Evento não encontrado' });
}
if (event.creatorId !== req.userId) {
return res.status(403).json({ error: 'Acesso negado' });
}
const updateData: any = { ...req.body };
if (req.body.date) {
updateData.date = new Date(req.body.date);
}
if (req.body.endDate) {
updateData.endDate = new Date(req.body.endDate);
}
if (req.file) {
updateData.coverImage = `/uploads/photos/${req.file.filename}`;
}
if (req.body.tags) {
updateData.tags = JSON.parse(req.body.tags);
}
const updatedEvent = await prisma.event.update({
where: { id },
data: updateData,
include: {
creator: {
include: { profile: true }
},
participants: true
}
});
res.json(updatedEvent);
} catch (error) {
console.error('Erro ao atualizar evento:', error);
res.status(500).json({ error: 'Erro ao atualizar evento' });
}
};
export const deleteEvent = async (req: AuthRequest, res: Response) => {
try {
const { id } = req.params;
const event = await prisma.event.findUnique({
where: { id }
});
if (!event) {
return res.status(404).json({ error: 'Evento não encontrado' });
}
if (event.creatorId !== req.userId) {
return res.status(403).json({ error: 'Acesso negado' });
}
await prisma.event.delete({
where: { id }
});
res.json({ message: 'Evento deletado com sucesso' });
} catch (error) {
console.error('Erro ao deletar evento:', error);
res.status(500).json({ error: 'Erro ao deletar evento' });
}
};
export const joinEvent = async (req: AuthRequest, res: Response) => {
try {
const { id } = req.params;
const { message } = req.body;
const event = await prisma.event.findUnique({
where: { id },
include: {
participants: true
}
});
if (!event) {
return res.status(404).json({ error: 'Evento não encontrado' });
}
// Verificar se já está participando
const existing = await prisma.eventParticipant.findUnique({
where: {
eventId_userId: {
eventId: id,
userId: req.userId!
}
}
});
if (existing) {
return res.status(400).json({ error: 'Você já está participando deste evento' });
}
// Verificar limite de participantes
if (event.maxParticipants) {
const approvedCount = event.participants.filter(p => p.status === 'approved').length;
if (approvedCount >= event.maxParticipants) {
return res.status(400).json({ error: 'Evento lotado' });
}
}
const status = event.requiresApproval ? 'pending' : 'approved';
const participant = await prisma.eventParticipant.create({
data: {
eventId: id,
userId: req.userId!,
status,
message
}
});
// Notificar criador
await prisma.notification.create({
data: {
userId: event.creatorId,
type: 'event',
title: 'Nova Solicitação de Participação',
message: `Alguém quer participar do seu evento: ${event.title}`,
link: `/events/${id}`
}
});
res.status(201).json(participant);
} catch (error) {
console.error('Erro ao participar do evento:', error);
res.status(500).json({ error: 'Erro ao participar do evento' });
}
};
export const leaveEvent = async (req: AuthRequest, res: Response) => {
try {
const { id } = req.params;
await prisma.eventParticipant.deleteMany({
where: {
eventId: id,
userId: req.userId
}
});
res.json({ message: 'Você saiu do evento' });
} catch (error) {
console.error('Erro ao sair do evento:', error);
res.status(500).json({ error: 'Erro ao sair do evento' });
}
};
export const updateParticipantStatus = async (req: AuthRequest, res: Response) => {
try {
const { id, participantId } = req.params;
const { status } = req.body;
const event = await prisma.event.findUnique({
where: { id }
});
if (!event) {
return res.status(404).json({ error: 'Evento não encontrado' });
}
if (event.creatorId !== req.userId) {
return res.status(403).json({ error: 'Apenas o criador pode aprovar participantes' });
}
const participant = await prisma.eventParticipant.update({
where: { id: participantId },
data: { status }
});
// Notificar participante
await prisma.notification.create({
data: {
userId: participant.userId,
type: 'event',
title: status === 'approved' ? 'Participação Aprovada' : 'Participação Rejeitada',
message: `Sua participação no evento "${event.title}" foi ${status === 'approved' ? 'aprovada' : 'rejeitada'}`,
link: `/events/${id}`
}
});
res.json(participant);
} catch (error) {
console.error('Erro ao atualizar status do participante:', error);
res.status(500).json({ error: 'Erro ao atualizar status' });
}
};