fix: remove duplicacao de comentario na troca de responsavel e corrige avatar

- Remove criacao automatica de comentario ao trocar responsavel (ja aparece na timeline)
- Adiciona migration removeAssigneeChangeComments para limpar comentarios antigos
- Adiciona campos description, type, options, answer ao schema de checklist no mapper
- Cria mutation updateAvatar no Convex para sincronizar avatar com snapshots
- Atualiza rota /api/profile/avatar para sincronizar com Convex ao adicionar/remover foto

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
esdrasrenan 2025-12-15 18:53:49 -03:00
parent 59e9298d61
commit 9d1908a5aa
6 changed files with 193 additions and 78 deletions

View file

@ -279,6 +279,91 @@ export const deleteUser = mutation({
},
});
/**
* Atualiza o avatar de um usuário.
* Passa avatarUrl como null para remover o avatar.
* Também atualiza os snapshots em comentários e tickets.
*/
export const updateAvatar = mutation({
args: {
tenantId: v.string(),
email: v.string(),
avatarUrl: v.union(v.string(), v.null()),
},
handler: async (ctx, { tenantId, email, avatarUrl }) => {
const user = await ctx.db
.query("users")
.withIndex("by_tenant_email", (q) => q.eq("tenantId", tenantId).eq("email", email))
.first()
if (!user) {
return { status: "not_found" }
}
// Atualiza o avatar do usuário
const normalizedAvatarUrl = avatarUrl ?? undefined
await ctx.db.patch(user._id, { avatarUrl: normalizedAvatarUrl })
// Atualiza snapshots em comentários
const comments = await ctx.db
.query("ticketComments")
.withIndex("by_author", (q) => q.eq("authorId", user._id))
.take(10000)
if (comments.length > 0) {
const authorSnapshot = {
name: user.name,
email: user.email,
avatarUrl: normalizedAvatarUrl,
teams: user.teams ?? undefined,
}
await Promise.all(
comments.map(async (comment) => {
await ctx.db.patch(comment._id, { authorSnapshot })
}),
)
}
// Atualiza snapshots de requester em tickets
const requesterTickets = await ctx.db
.query("tickets")
.withIndex("by_requester", (q) => q.eq("requesterId", user._id))
.take(10000)
if (requesterTickets.length > 0) {
const requesterSnapshot = {
name: user.name,
email: user.email,
avatarUrl: normalizedAvatarUrl,
teams: user.teams ?? undefined,
}
for (const t of requesterTickets) {
await ctx.db.patch(t._id, { requesterSnapshot })
}
}
// Atualiza snapshots de assignee em tickets
const assigneeTickets = await ctx.db
.query("tickets")
.withIndex("by_assignee", (q) => q.eq("assigneeId", user._id))
.take(10000)
if (assigneeTickets.length > 0) {
const assigneeSnapshot = {
name: user.name,
email: user.email,
avatarUrl: normalizedAvatarUrl,
teams: user.teams ?? undefined,
}
for (const t of assigneeTickets) {
await ctx.db.patch(t._id, { assigneeSnapshot })
}
}
return { status: "updated", avatarUrl: normalizedAvatarUrl }
},
})
export const assignCompany = mutation({
args: { tenantId: v.string(), email: v.string(), companyId: v.id("companies"), actorId: v.id("users") },
handler: async (ctx, { tenantId, email, companyId, actorId }) => {