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:
root
2025-11-22 01:00:35 +00:00
commit 5e4a2283bf
51 changed files with 5158 additions and 0 deletions

View 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' });
}
};