feat: Introduce structured table definitions in convex/tables for various entities and remove the todos example table.
This commit is contained in:
173
packages/backend/convex/tables/chat.ts
Normal file
173
packages/backend/convex/tables/chat.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
import { defineTable } from 'convex/server';
|
||||
import { v } from 'convex/values';
|
||||
|
||||
export const chatTables = {
|
||||
// Sistema de Chat
|
||||
conversas: defineTable({
|
||||
tipo: v.union(v.literal('individual'), v.literal('grupo'), v.literal('sala_reuniao')),
|
||||
nome: v.optional(v.string()), // nome do grupo/sala
|
||||
|
||||
participantes: v.array(v.id('usuarios')), // IDs dos participantes
|
||||
administradores: v.optional(v.array(v.id('usuarios'))), // IDs dos administradores (apenas para sala_reuniao)
|
||||
ultimaMensagem: v.optional(v.string()),
|
||||
ultimaMensagemTimestamp: v.optional(v.number()),
|
||||
ultimaMensagemRemetenteId: v.optional(v.id('usuarios')), // ID do remetente da última mensagem
|
||||
criadoPor: v.id('usuarios'),
|
||||
criadoEm: v.number()
|
||||
})
|
||||
.index('by_criado_por', ['criadoPor'])
|
||||
.index('by_tipo', ['tipo'])
|
||||
.index('by_ultima_mensagem', ['ultimaMensagemTimestamp']),
|
||||
|
||||
mensagens: defineTable({
|
||||
conversaId: v.id('conversas'),
|
||||
remetenteId: v.id('usuarios'),
|
||||
tipo: v.union(v.literal('texto'), v.literal('arquivo'), v.literal('imagem')),
|
||||
conteudo: v.string(), // texto ou nome do arquivo
|
||||
conteudoBusca: v.optional(v.string()), // versão normalizada para busca
|
||||
arquivoId: v.optional(v.id('_storage')),
|
||||
arquivoNome: v.optional(v.string()),
|
||||
arquivoTamanho: v.optional(v.number()),
|
||||
arquivoTipo: v.optional(v.string()),
|
||||
linkPreview: v.optional(
|
||||
v.object({
|
||||
url: v.string(),
|
||||
titulo: v.optional(v.string()),
|
||||
descricao: v.optional(v.string()),
|
||||
imagem: v.optional(v.string()),
|
||||
site: v.optional(v.string())
|
||||
})
|
||||
),
|
||||
reagiuPor: v.optional(
|
||||
v.array(
|
||||
v.object({
|
||||
usuarioId: v.id('usuarios'),
|
||||
emoji: v.string()
|
||||
})
|
||||
)
|
||||
),
|
||||
mencoes: v.optional(v.array(v.id('usuarios'))),
|
||||
respostaPara: v.optional(v.id('mensagens')), // ID da mensagem que está respondendo
|
||||
agendadaPara: v.optional(v.number()), // timestamp
|
||||
enviadaEm: v.number(),
|
||||
editadaEm: v.optional(v.number()),
|
||||
deletada: v.optional(v.boolean()),
|
||||
lidaPor: v.optional(v.array(v.id('usuarios'))) // IDs dos usuários que leram a mensagem
|
||||
})
|
||||
.index('by_conversa', ['conversaId', 'enviadaEm'])
|
||||
.index('by_remetente', ['remetenteId'])
|
||||
.index('by_agendamento', ['agendadaPara'])
|
||||
.index('by_resposta', ['respostaPara']),
|
||||
|
||||
leituras: defineTable({
|
||||
conversaId: v.id('conversas'),
|
||||
usuarioId: v.id('usuarios'),
|
||||
ultimaMensagemLida: v.id('mensagens'),
|
||||
lidaEm: v.number()
|
||||
})
|
||||
.index('by_conversa_usuario', ['conversaId', 'usuarioId'])
|
||||
.index('by_usuario', ['usuarioId']),
|
||||
|
||||
// Sistema de Chamadas de Áudio/Vídeo
|
||||
chamadas: defineTable({
|
||||
conversaId: v.id('conversas'),
|
||||
tipo: v.union(v.literal('audio'), v.literal('video')),
|
||||
roomName: v.string(), // Nome único da sala Jitsi
|
||||
criadoPor: v.id('usuarios'), // Anfitrião/criador
|
||||
participantes: v.array(v.id('usuarios')),
|
||||
status: v.union(
|
||||
v.literal('aguardando'),
|
||||
v.literal('em_andamento'),
|
||||
v.literal('finalizada'),
|
||||
v.literal('cancelada')
|
||||
),
|
||||
iniciadaEm: v.optional(v.number()),
|
||||
finalizadaEm: v.optional(v.number()),
|
||||
duracaoSegundos: v.optional(v.number()),
|
||||
gravando: v.boolean(),
|
||||
gravacaoIniciadaPor: v.optional(v.id('usuarios')),
|
||||
gravacaoIniciadaEm: v.optional(v.number()),
|
||||
gravacaoFinalizadaEm: v.optional(v.number()),
|
||||
configuracoes: v.optional(
|
||||
v.object({
|
||||
audioHabilitado: v.boolean(),
|
||||
videoHabilitado: v.boolean(),
|
||||
participantesConfig: v.optional(
|
||||
v.array(
|
||||
v.object({
|
||||
usuarioId: v.id('usuarios'),
|
||||
audioHabilitado: v.boolean(),
|
||||
videoHabilitado: v.boolean(),
|
||||
forcadoPeloAnfitriao: v.optional(v.boolean()) // Se foi forçado pelo anfitrião
|
||||
})
|
||||
)
|
||||
)
|
||||
})
|
||||
),
|
||||
criadoEm: v.number()
|
||||
})
|
||||
.index('by_conversa', ['conversaId', 'status'])
|
||||
.index('by_criado_por', ['criadoPor'])
|
||||
.index('by_status', ['status'])
|
||||
.index('by_room_name', ['roomName']),
|
||||
|
||||
notificacoes: defineTable({
|
||||
usuarioId: v.id('usuarios'),
|
||||
tipo: v.union(
|
||||
v.literal('nova_mensagem'),
|
||||
v.literal('mencao'),
|
||||
v.literal('grupo_criado'),
|
||||
v.literal('adicionado_grupo'),
|
||||
v.literal('alerta_seguranca'),
|
||||
v.literal('etapa_fluxo_concluida')
|
||||
),
|
||||
conversaId: v.optional(v.id('conversas')),
|
||||
mensagemId: v.optional(v.id('mensagens')),
|
||||
remetenteId: v.optional(v.id('usuarios')),
|
||||
titulo: v.string(),
|
||||
descricao: v.string(),
|
||||
lida: v.boolean(),
|
||||
criadaEm: v.number()
|
||||
})
|
||||
.index('by_usuario', ['usuarioId', 'lida', 'criadaEm'])
|
||||
.index('by_usuario_lida', ['usuarioId', 'lida']),
|
||||
|
||||
digitando: defineTable({
|
||||
conversaId: v.id('conversas'),
|
||||
usuarioId: v.id('usuarios'),
|
||||
iniciouEm: v.number()
|
||||
})
|
||||
.index('by_conversa', ['conversaId', 'iniciouEm'])
|
||||
.index('by_usuario', ['usuarioId']),
|
||||
|
||||
// Push Notifications
|
||||
pushSubscriptions: defineTable({
|
||||
usuarioId: v.id('usuarios'),
|
||||
endpoint: v.string(), // URL do serviço de push
|
||||
keys: v.object({
|
||||
p256dh: v.string(), // Chave pública
|
||||
auth: v.string() // Chave de autenticação
|
||||
}),
|
||||
userAgent: v.optional(v.string()),
|
||||
criadoEm: v.number(),
|
||||
ultimaAtividade: v.number(),
|
||||
ativo: v.boolean()
|
||||
})
|
||||
.index('by_usuario', ['usuarioId', 'ativo'])
|
||||
.index('by_endpoint', ['endpoint']),
|
||||
|
||||
// Preferências de Notificação por Conversa
|
||||
preferenciasNotificacaoConversa: defineTable({
|
||||
usuarioId: v.id('usuarios'),
|
||||
conversaId: v.id('conversas'),
|
||||
pushAtivado: v.boolean(), // Receber push notifications
|
||||
emailAtivado: v.boolean(), // Receber emails quando offline
|
||||
somAtivado: v.boolean(), // Tocar som
|
||||
silenciado: v.boolean(), // Silenciar completamente
|
||||
apenasMencoes: v.boolean(), // Notificar apenas quando mencionado
|
||||
criadoEm: v.number(),
|
||||
atualizadoEm: v.number()
|
||||
})
|
||||
.index('by_usuario_conversa', ['usuarioId', 'conversaId'])
|
||||
.index('by_conversa', ['conversaId'])
|
||||
};
|
||||
Reference in New Issue
Block a user