feat: melhorias de UX e redesign de comentários
- Corrige sincronização do avatar no perfil após upload - Reduz tamanho dos ícones de câmera/lixeira no avatar - Remove atributos title (tooltips nativos) de toda aplicação - Adiciona regra no AGENTS.md sobre uso de tooltips - Permite desmarcar resposta no checklist (toggle) - Torna campo answer opcional na mutation setChecklistItemAnswer - Adiciona edição inline dos campos de resumo no painel de detalhes - Redesenha comentários com layout mais limpo e consistente - Cria tratamento especial para comentários automáticos de sistema - Aplica fundo ciano semi-transparente em comentários públicos - Corrige import do Loader2 no notification-preferences-form 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
23ea426c68
commit
022e1f63ba
17 changed files with 636 additions and 180 deletions
|
|
@ -16,7 +16,6 @@ import { Checkbox } from "@/components/ui/checkbox"
|
|||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Progress } from "@/components/ui/progress"
|
||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
|
||||
import { ScrollArea } from "@/components/ui/scroll-area"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
|
||||
|
|
@ -391,38 +390,39 @@ export function TicketChecklistCard({
|
|||
)}
|
||||
|
||||
{isQuestion && options.length > 0 && (
|
||||
<RadioGroup
|
||||
value={item.answer ?? ""}
|
||||
onValueChange={async (value) => {
|
||||
if (!actorId || !canToggle) return
|
||||
try {
|
||||
await setChecklistItemAnswer({
|
||||
ticketId: ticket.id as Id<"tickets">,
|
||||
actorId,
|
||||
itemId: item.id,
|
||||
answer: value,
|
||||
})
|
||||
} catch (error) {
|
||||
toast.error(error instanceof Error ? error.message : "Falha ao responder pergunta.")
|
||||
}
|
||||
}}
|
||||
disabled={!canToggle || !actorId}
|
||||
className="flex flex-wrap items-center gap-4"
|
||||
>
|
||||
{options.map((option) => (
|
||||
<label
|
||||
key={option}
|
||||
className={`flex cursor-pointer items-center gap-2 rounded-lg border px-3 py-1.5 text-sm transition-colors ${
|
||||
item.answer === option
|
||||
? "border-neutral-900 bg-neutral-900 text-white"
|
||||
: "border-slate-200 bg-white text-slate-600 hover:border-slate-300 hover:bg-slate-50"
|
||||
}`}
|
||||
>
|
||||
<RadioGroupItem value={option} className="sr-only" />
|
||||
{option}
|
||||
</label>
|
||||
))}
|
||||
</RadioGroup>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{options.map((option) => {
|
||||
const isSelected = item.answer === option
|
||||
return (
|
||||
<button
|
||||
key={option}
|
||||
type="button"
|
||||
disabled={!canToggle || !actorId}
|
||||
onClick={async () => {
|
||||
if (!actorId || !canToggle) return
|
||||
try {
|
||||
await setChecklistItemAnswer({
|
||||
ticketId: ticket.id as Id<"tickets">,
|
||||
actorId,
|
||||
itemId: item.id,
|
||||
// Toggle: se já está selecionado, limpa; senão, seleciona
|
||||
answer: isSelected ? undefined : option,
|
||||
})
|
||||
} catch (error) {
|
||||
toast.error(error instanceof Error ? error.message : "Falha ao responder pergunta.")
|
||||
}
|
||||
}}
|
||||
className={`rounded-lg border px-3 py-1.5 text-sm transition-colors ${
|
||||
isSelected
|
||||
? "border-neutral-900 bg-neutral-900 text-white"
|
||||
: "border-slate-200 bg-white text-slate-600 hover:border-slate-300 hover:bg-slate-50"
|
||||
} ${!canToggle || !actorId ? "cursor-not-allowed opacity-50" : "cursor-pointer"}`}
|
||||
>
|
||||
{option}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
|
|
@ -476,7 +476,6 @@ export function TicketChecklistCard({
|
|||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-9 w-9 text-slate-500 hover:bg-red-50 hover:text-red-700"
|
||||
title="Remover"
|
||||
onClick={() => setDeleteTarget(item)}
|
||||
>
|
||||
<Trash2 className="size-4" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue