Ajusta placeholders, formulários e widgets
This commit is contained in:
parent
343f0c8c64
commit
b94cea2f9a
33 changed files with 2122 additions and 462 deletions
|
|
@ -174,10 +174,9 @@ export function TicketCustomFieldsList({ record, emptyMessage, className }: Tick
|
|||
|
||||
type TicketCustomFieldsSectionProps = {
|
||||
ticket: TicketWithDetails
|
||||
hidePreview?: boolean
|
||||
}
|
||||
|
||||
export function TicketCustomFieldsSection({ ticket, hidePreview = false }: TicketCustomFieldsSectionProps) {
|
||||
export function TicketCustomFieldsSection({ ticket }: TicketCustomFieldsSectionProps) {
|
||||
const { convexUserId, role } = useAuth()
|
||||
const canEdit = Boolean(convexUserId && (role === "admin" || role === "agent"))
|
||||
|
||||
|
|
@ -319,14 +318,10 @@ export function TicketCustomFieldsSection({ ticket, hidePreview = false }: Ticke
|
|||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
{hidePreview ? (
|
||||
<p className="text-xs text-neutral-500">Visualize os valores no resumo principal.</p>
|
||||
) : (
|
||||
<TicketCustomFieldsList
|
||||
record={ticket.customFields}
|
||||
emptyMessage="Nenhum campo adicional preenchido neste chamado."
|
||||
/>
|
||||
)}
|
||||
<TicketCustomFieldsList
|
||||
record={ticket.customFields}
|
||||
emptyMessage="Nenhum campo adicional preenchido neste chamado."
|
||||
/>
|
||||
|
||||
<Dialog open={editorOpen} onOpenChange={setEditorOpen}>
|
||||
<DialogContent className="max-w-3xl gap-4">
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import { ptBR } from "date-fns/locale"
|
|||
import type { TicketWithDetails } from "@/lib/schemas/ticket"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { getTicketStatusLabel, getTicketStatusSummaryTone } from "@/lib/ticket-status-style"
|
||||
import { TicketCustomFieldsSection } from "@/components/tickets/ticket-custom-fields"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { TicketCustomFieldsSection } from "@/components/tickets/ticket-custom-fields"
|
||||
|
||||
interface TicketDetailsPanelProps {
|
||||
ticket: TicketWithDetails
|
||||
|
|
@ -53,19 +53,19 @@ export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) {
|
|||
const isAvulso = Boolean(ticket.company?.isAvulso)
|
||||
const companyLabel = ticket.company?.name ?? (isAvulso ? "Cliente avulso" : "Sem empresa vinculada")
|
||||
|
||||
const summaryChips = useMemo(
|
||||
() => [
|
||||
const summaryChips = useMemo(() => {
|
||||
const chips: Array<{ key: string; label: string; value: string; tone: SummaryTone }> = [
|
||||
{
|
||||
key: "queue",
|
||||
label: "Fila",
|
||||
value: ticket.queue ?? "Sem fila",
|
||||
tone: ticket.queue ? ("default" as SummaryTone) : ("muted" as SummaryTone),
|
||||
tone: ticket.queue ? "default" : "muted",
|
||||
},
|
||||
{
|
||||
key: "company",
|
||||
label: "Empresa",
|
||||
value: companyLabel,
|
||||
tone: isAvulso ? ("warning" as SummaryTone) : ("default" as SummaryTone),
|
||||
tone: isAvulso ? "warning" : "default",
|
||||
},
|
||||
{
|
||||
key: "status",
|
||||
|
|
@ -83,11 +83,19 @@ export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) {
|
|||
key: "assignee",
|
||||
label: "Responsável",
|
||||
value: ticket.assignee?.name ?? "Não atribuído",
|
||||
tone: ticket.assignee ? ("default" as SummaryTone) : ("muted" as SummaryTone),
|
||||
tone: ticket.assignee ? "default" : "muted",
|
||||
},
|
||||
],
|
||||
[companyLabel, isAvulso, ticket.assignee, ticket.priority, ticket.queue, ticket.status]
|
||||
)
|
||||
]
|
||||
if (ticket.formTemplateLabel) {
|
||||
chips.push({
|
||||
key: "formTemplate",
|
||||
label: "Tipo de solicitação",
|
||||
value: ticket.formTemplateLabel,
|
||||
tone: "info",
|
||||
})
|
||||
}
|
||||
return chips
|
||||
}, [companyLabel, isAvulso, ticket.assignee, ticket.formTemplateLabel, ticket.priority, ticket.queue, ticket.status])
|
||||
|
||||
const agentTotals = useMemo(() => {
|
||||
const totals = ticket.workSummary?.perAgentTotals ?? []
|
||||
|
|
@ -129,8 +137,6 @@ export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) {
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<TicketCustomFieldsSection ticket={ticket} hidePreview />
|
||||
|
||||
<section className="space-y-3">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<h3 className="text-sm font-semibold text-neutral-900">SLA & métricas</h3>
|
||||
|
|
@ -184,6 +190,8 @@ export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) {
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<TicketCustomFieldsSection ticket={ticket} />
|
||||
|
||||
<section className="space-y-3">
|
||||
<h3 className="text-sm font-semibold text-neutral-900">Tempo por agente</h3>
|
||||
{agentTotals.length > 0 ? (
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import { Textarea } from "@/components/ui/textarea"
|
|||
import { Spinner } from "@/components/ui/spinner"
|
||||
import { useTicketCategories } from "@/hooks/use-ticket-categories"
|
||||
import { useDefaultQueues } from "@/hooks/use-default-queues"
|
||||
import { mapTicketCustomFields } from "@/lib/ticket-custom-fields"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
|
|
@ -214,7 +213,6 @@ export function TicketSummaryHeader({ ticket }: TicketHeaderProps) {
|
|||
queuesEnabled ? { tenantId: ticket.tenantId, viewerId: convexUserId as Id<"users"> } : "skip"
|
||||
)
|
||||
const queues: TicketQueueSummary[] = Array.isArray(queuesResult) ? queuesResult : []
|
||||
const customFieldEntries = useMemo(() => mapTicketCustomFields(ticket.customFields), [ticket.customFields])
|
||||
const { categories, isLoading: categoriesLoading } = useTicketCategories(ticket.tenantId)
|
||||
const workSummaryRemote = useQuery(
|
||||
api.tickets.workSummary,
|
||||
|
|
@ -1300,13 +1298,9 @@ export function TicketSummaryHeader({ ticket }: TicketHeaderProps) {
|
|||
<div className="space-y-1">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h1 className="break-words text-2xl font-semibold text-neutral-900">{subject}</h1>
|
||||
{ticket.formTemplate ? (
|
||||
{ticket.formTemplateLabel || ticket.formTemplate ? (
|
||||
<span className="inline-flex items-center rounded-full border border-sky-200 bg-sky-50 px-2.5 py-0.5 text-xs font-semibold text-sky-700">
|
||||
{ticket.formTemplate === "admissao"
|
||||
? "Admissão"
|
||||
: ticket.formTemplate === "desligamento"
|
||||
? "Desligamento"
|
||||
: "Chamado"}
|
||||
{ticket.formTemplateLabel ?? ticket.formTemplate}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
@ -1585,24 +1579,6 @@ export function TicketSummaryHeader({ ticket }: TicketHeaderProps) {
|
|||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="mt-6 space-y-2">
|
||||
<span className={sectionLabelClass}>Informações adicionais</span>
|
||||
{customFieldEntries.length > 0 ? (
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
{customFieldEntries.map((entry) => (
|
||||
<div
|
||||
key={entry.key}
|
||||
className="rounded-2xl border border-slate-200 bg-white px-4 py-3 shadow-sm"
|
||||
>
|
||||
<p className="text-xs font-semibold uppercase tracking-wide text-neutral-500">{entry.label}</p>
|
||||
<p className="mt-1 text-sm font-semibold text-neutral-900">{entry.formattedValue}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-xs text-neutral-500">Nenhum campo adicional preenchido para este chamado.</p>
|
||||
)}
|
||||
</div>
|
||||
<Dialog open={pauseDialogOpen} onOpenChange={setPauseDialogOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
|
|
|
|||
|
|
@ -221,14 +221,10 @@ export function TicketsTable({ tickets, enteringIds }: TicketsTableProps) {
|
|||
<span className="text-sm text-neutral-600 line-clamp-1 break-words">
|
||||
{ticket.summary ?? "Sem resumo"}
|
||||
</span>
|
||||
{ticket.formTemplate ? (
|
||||
{ticket.formTemplateLabel || ticket.formTemplate ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge className="rounded-full border border-sky-200 bg-sky-50 px-2.5 py-0.5 text-[11px] font-semibold text-sky-700">
|
||||
{ticket.formTemplate === "admissao"
|
||||
? "Admissão"
|
||||
: ticket.formTemplate === "desligamento"
|
||||
? "Desligamento"
|
||||
: "Chamado"}
|
||||
{ticket.formTemplateLabel ?? ticket.formTemplate}
|
||||
</Badge>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue