🚀 Initial commit - PDIMaker v1.0.0

Sistema completo de gestão de PDI com:
- Autenticação com email/senha e Google OAuth
- Workspaces privados isolados
- Sistema de convites com código único
- Interface profissional com Next.js 14
- Backend NestJS com PostgreSQL
- Docker com Nginx e SSL

Desenvolvido por Sergio Correa
This commit is contained in:
2025-11-19 02:09:04 +00:00
commit 0524656198
58 changed files with 6660 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
// app/api/workspaces/create/route.ts
import { NextRequest, NextResponse } from "next/server"
import { getServerSession } from "next-auth"
import { authOptions } from "@/lib/auth/config"
import { prisma } from "@/lib/prisma"
import { generateInviteCode, generateWorkspaceSlug } from "@/lib/utils/invite-code"
export async function POST(request: NextRequest) {
try {
const session = await getServerSession(authOptions)
if (!session || !session.user) {
return NextResponse.json({ error: "Não autenticado" }, { status: 401 })
}
const { email, inviteRole } = await request.json()
console.log("Criando workspace:", { email, inviteRole, userId: session.user.id })
// Validar email
if (!email || !email.includes("@")) {
return NextResponse.json({ error: "Email inválido" }, { status: 400 })
}
// Buscar ou criar o usuário convidado
let invitedUser = await prisma.user.findUnique({ where: { email } })
if (!invitedUser) {
// Criar registro temporário do usuário convidado
invitedUser = await prisma.user.create({
data: {
email,
name: email.split("@")[0],
role: inviteRole === "MANAGER" ? "MANAGER" : "EMPLOYEE"
}
})
}
// Determinar quem é employee e quem é manager
const employeeId = inviteRole === "MANAGER" ? session.user.id : invitedUser.id
const managerId = inviteRole === "MANAGER" ? invitedUser.id : session.user.id
// Buscar nomes para o slug
const employee = await prisma.user.findUnique({ where: { id: employeeId } })
const manager = await prisma.user.findUnique({ where: { id: managerId } })
if (!employee || !manager) {
return NextResponse.json({ error: "Erro ao buscar usuários" }, { status: 400 })
}
// Gerar slug único
const slug = generateWorkspaceSlug(employee.name, manager.name)
// Criar workspace
const workspace = await prisma.workspace.create({
data: {
slug,
employeeId,
managerId,
status: "PENDING_INVITE"
}
})
// Criar convite
const inviteCode = generateInviteCode()
const expiresAt = new Date()
expiresAt.setDate(expiresAt.getDate() + 7) // Expira em 7 dias
await prisma.invite.create({
data: {
email: invitedUser.email,
role: inviteRole === "MANAGER" ? "MANAGER" : "EMPLOYEE",
token: inviteCode,
invitedBy: session.user.id,
workspaceId: workspace.id,
expiresAt
}
})
// TODO: Enviar email com o código de convite
return NextResponse.json({
success: true,
workspace: { id: workspace.id, slug: workspace.slug },
inviteCode
})
} catch (error: any) {
console.error("Erro ao criar workspace:", error)
console.error("Stack:", error.stack)
console.error("Message:", error.message)
return NextResponse.json(
{ error: error.message || "Erro ao criar workspace" },
{ status: 500 }
)
}
}