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
This commit is contained in:
198
backend/src/controllers/search.controller.ts
Normal file
198
backend/src/controllers/search.controller.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
import { Response } from 'express';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { AuthRequest } from '../middleware/auth.middleware';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export const searchProfiles = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const {
|
||||
query,
|
||||
gender,
|
||||
relationshipType,
|
||||
city,
|
||||
state,
|
||||
minAge,
|
||||
maxAge,
|
||||
verified,
|
||||
page = 1,
|
||||
limit = 20
|
||||
} = req.query;
|
||||
|
||||
const skip = (Number(page) - 1) * Number(limit);
|
||||
|
||||
const where: any = {
|
||||
user: { isActive: true }
|
||||
};
|
||||
|
||||
// Filtro de texto
|
||||
if (query) {
|
||||
where.OR = [
|
||||
{ username: { contains: String(query), mode: 'insensitive' } },
|
||||
{ displayName: { contains: String(query), mode: 'insensitive' } },
|
||||
{ bio: { contains: String(query), mode: 'insensitive' } }
|
||||
];
|
||||
}
|
||||
|
||||
// Filtros específicos
|
||||
if (gender) {
|
||||
where.gender = gender;
|
||||
}
|
||||
|
||||
if (relationshipType) {
|
||||
where.relationshipType = relationshipType;
|
||||
}
|
||||
|
||||
if (city) {
|
||||
where.city = { contains: String(city), mode: 'insensitive' };
|
||||
}
|
||||
|
||||
if (state) {
|
||||
where.state = state;
|
||||
}
|
||||
|
||||
if (minAge || maxAge) {
|
||||
where.age = {};
|
||||
if (minAge) where.age.gte = Number(minAge);
|
||||
if (maxAge) where.age.lte = Number(maxAge);
|
||||
}
|
||||
|
||||
if (verified === 'true') {
|
||||
where.verificationStatus = 'VERIFIED';
|
||||
}
|
||||
|
||||
// Excluir usuários bloqueados
|
||||
if (req.userId) {
|
||||
const blocks = await prisma.block.findMany({
|
||||
where: {
|
||||
OR: [
|
||||
{ userId: req.userId },
|
||||
{ blockedId: req.userId }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const blockedIds = blocks.map(b =>
|
||||
b.userId === req.userId ? b.blockedId : b.userId
|
||||
);
|
||||
|
||||
if (blockedIds.length > 0) {
|
||||
where.userId = { notIn: blockedIds };
|
||||
}
|
||||
|
||||
// Excluir o próprio usuário
|
||||
where.userId = { ...where.userId, not: req.userId };
|
||||
}
|
||||
|
||||
const [profiles, total] = await Promise.all([
|
||||
prisma.profile.findMany({
|
||||
where,
|
||||
skip,
|
||||
take: Number(limit),
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
role: true,
|
||||
lastLogin: true
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: [
|
||||
{ verificationStatus: 'desc' },
|
||||
{ user: { lastLogin: 'desc' } }
|
||||
]
|
||||
}),
|
||||
prisma.profile.count({ where })
|
||||
]);
|
||||
|
||||
res.json({
|
||||
profiles,
|
||||
pagination: {
|
||||
page: Number(page),
|
||||
limit: Number(limit),
|
||||
total,
|
||||
pages: Math.ceil(total / Number(limit))
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Erro ao buscar perfis:', error);
|
||||
res.status(500).json({ error: 'Erro ao buscar perfis' });
|
||||
}
|
||||
};
|
||||
|
||||
export const searchEvents = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const {
|
||||
query,
|
||||
city,
|
||||
state,
|
||||
startDate,
|
||||
endDate,
|
||||
page = 1,
|
||||
limit = 20
|
||||
} = req.query;
|
||||
|
||||
const skip = (Number(page) - 1) * Number(limit);
|
||||
|
||||
const where: any = {
|
||||
status: 'PUBLISHED',
|
||||
date: { gte: new Date() }
|
||||
};
|
||||
|
||||
if (query) {
|
||||
where.OR = [
|
||||
{ title: { contains: String(query), mode: 'insensitive' } },
|
||||
{ description: { contains: String(query), mode: 'insensitive' } }
|
||||
];
|
||||
}
|
||||
|
||||
if (city) {
|
||||
where.city = { contains: String(city), mode: 'insensitive' };
|
||||
}
|
||||
|
||||
if (state) {
|
||||
where.state = state;
|
||||
}
|
||||
|
||||
if (startDate) {
|
||||
where.date = { ...where.date, gte: new Date(String(startDate)) };
|
||||
}
|
||||
|
||||
if (endDate) {
|
||||
where.date = { ...where.date, lte: new Date(String(endDate)) };
|
||||
}
|
||||
|
||||
const [events, total] = await Promise.all([
|
||||
prisma.event.findMany({
|
||||
where,
|
||||
skip,
|
||||
take: Number(limit),
|
||||
include: {
|
||||
creator: {
|
||||
include: { profile: true }
|
||||
},
|
||||
participants: {
|
||||
where: { status: 'approved' }
|
||||
}
|
||||
},
|
||||
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' });
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user