feat: initial project structure (Model Project) - Backend + Multi-Frontend + Docker
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
'use strict'
|
||||
|
||||
const GroupChat = require('../models/GroupChat')
|
||||
const { sseSend } = require('../services/sse')
|
||||
|
||||
function extractAuth(req) {
|
||||
const accountId = req.teamAccount?.accountId || req.admin?.id || null
|
||||
const tenantId = req.tenantId || req.teamAccount?.tenantId || req.admin?.tenant_id || null
|
||||
return { accountId, tenantId }
|
||||
}
|
||||
|
||||
class GroupChatController {
|
||||
/**
|
||||
* GET /api/admin/inbox/groups
|
||||
* Lista grupos do colaborador (via team_members) ou todos (owner/manager)
|
||||
*/
|
||||
async list(req, res) {
|
||||
try {
|
||||
const { accountId, tenantId } = extractAuth(req)
|
||||
if (!tenantId) return res.status(401).json({ error: 'Não autenticado' })
|
||||
|
||||
const role = req.admin?.role || req.teamAccount?.role
|
||||
const isManager = role === 'owner' || role === 'manager'
|
||||
|
||||
const groups = isManager
|
||||
? await GroupChat.listAll(tenantId, accountId)
|
||||
: await GroupChat.listForAccount(tenantId, accountId)
|
||||
|
||||
res.json(groups)
|
||||
} catch (err) {
|
||||
console.error('[groupChat.list]', err.message)
|
||||
res.status(500).json({ error: 'Erro ao listar grupos' })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/admin/inbox/groups/:id/messages
|
||||
* Histórico de mensagens de um grupo
|
||||
*/
|
||||
async getMessages(req, res) {
|
||||
try {
|
||||
const { tenantId } = extractAuth(req)
|
||||
if (!tenantId) return res.status(401).json({ error: 'Não autenticado' })
|
||||
|
||||
const groupChatId = Number(req.params.id)
|
||||
const limit = Math.min(Number(req.query.limit) || 50, 200)
|
||||
const before = req.query.before || null
|
||||
|
||||
const group = await GroupChat.findById(tenantId, groupChatId)
|
||||
if (!group) return res.status(404).json({ error: 'Grupo não encontrado' })
|
||||
|
||||
const msgs = await GroupChat.getMessages(tenantId, groupChatId, limit, before)
|
||||
res.json(msgs)
|
||||
} catch (err) {
|
||||
console.error('[groupChat.getMessages]', err.message)
|
||||
res.status(500).json({ error: 'Erro ao buscar mensagens' })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/admin/inbox/groups/:id/message
|
||||
* Enviar mensagem em um grupo
|
||||
*/
|
||||
async sendMessage(req, res) {
|
||||
try {
|
||||
const { accountId, tenantId } = extractAuth(req)
|
||||
if (!accountId || !tenantId) return res.status(401).json({ error: 'Não autenticado' })
|
||||
|
||||
const groupChatId = Number(req.params.id)
|
||||
const { content } = req.body
|
||||
|
||||
if (!content?.trim()) return res.status(400).json({ error: 'content obrigatório' })
|
||||
|
||||
const group = await GroupChat.findById(tenantId, groupChatId)
|
||||
if (!group) return res.status(404).json({ error: 'Grupo não encontrado' })
|
||||
|
||||
const msg = await GroupChat.sendMessage(tenantId, groupChatId, accountId, content.trim())
|
||||
|
||||
res.json(msg)
|
||||
|
||||
// Notificar membros do grupo via SSE (exceto o remetente)
|
||||
const memberIds = await GroupChat.getMemberIds(groupChatId)
|
||||
const payload = {
|
||||
id: msg.id,
|
||||
group_chat_id: groupChatId,
|
||||
group_name: group.name,
|
||||
from: accountId,
|
||||
content: content.trim(),
|
||||
created_at: msg.created_at,
|
||||
}
|
||||
for (const memberId of memberIds) {
|
||||
if (memberId !== accountId) {
|
||||
sseSend(memberId, 'group_message.new', payload)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[groupChat.sendMessage]', err.message)
|
||||
res.status(500).json({ error: 'Erro ao enviar mensagem' })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/admin/inbox/groups/:id/members
|
||||
* Listar membros de um grupo
|
||||
*/
|
||||
async getMembers(req, res) {
|
||||
try {
|
||||
const { tenantId } = extractAuth(req)
|
||||
if (!tenantId) return res.status(401).json({ error: 'Não autenticado' })
|
||||
|
||||
const groupChatId = Number(req.params.id)
|
||||
const group = await GroupChat.findById(tenantId, groupChatId)
|
||||
if (!group) return res.status(404).json({ error: 'Grupo não encontrado' })
|
||||
|
||||
const members = await GroupChat.getMembers(tenantId, groupChatId)
|
||||
res.json(members)
|
||||
} catch (err) {
|
||||
console.error('[groupChat.getMembers]', err.message)
|
||||
res.status(500).json({ error: 'Erro ao buscar membros' })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/admin/inbox/groups/:id/read
|
||||
* Marcar grupo como lido
|
||||
*/
|
||||
async markRead(req, res) {
|
||||
try {
|
||||
const { accountId } = extractAuth(req)
|
||||
if (!accountId) return res.status(401).json({ error: 'Não autenticado' })
|
||||
await GroupChat.markRead(accountId, Number(req.params.id))
|
||||
res.json({ ok: true })
|
||||
} catch (err) {
|
||||
console.error('[groupChat.markRead]', err.message)
|
||||
res.status(500).json({ error: 'Erro ao marcar como lido' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new GroupChatController()
|
||||
Reference in New Issue
Block a user