admin: remove 'Espaço (ID interno)' from Convites and improve filter bar alignment; tickets: fix running timer by optimistic updating start/pause times
This commit is contained in:
parent
a325d612cb
commit
7c3bf00790
2 changed files with 41 additions and 20 deletions
|
|
@ -884,8 +884,8 @@ async function handleDeleteUser() {
|
|||
Novo usuário
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3 rounded-xl border border-slate-200 bg-white p-4 shadow-sm sm:flex-row sm:items-center sm:justify-between">
|
||||
<div className="relative w-full sm:max-w-xs">
|
||||
<div className="rounded-xl border border-slate-200 bg-white p-4 shadow-sm md:grid md:grid-cols-[minmax(0,1fr)_auto_auto_auto_auto] md:items-center md:gap-3">
|
||||
<div className="relative w-full md:max-w-sm">
|
||||
<IconSearch className="text-muted-foreground pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2" />
|
||||
<Input
|
||||
value={teamSearch}
|
||||
|
|
@ -894,7 +894,7 @@ async function handleDeleteUser() {
|
|||
className="h-9 pl-9"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<div className="mt-3 flex flex-wrap items-center gap-3 md:mt-0">
|
||||
<Select value={teamRoleFilter} onValueChange={(value) => setTeamRoleFilter(value as "all" | RoleOption)}>
|
||||
<SelectTrigger className="h-9 w-full sm:w-48">
|
||||
<SelectValue placeholder="Todos os papéis" />
|
||||
|
|
@ -1102,8 +1102,8 @@ async function handleDeleteUser() {
|
|||
Novo usuário
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3 rounded-xl border border-slate-200 bg-white p-4 shadow-sm sm:flex-row sm:items-center sm:justify-between">
|
||||
<div className="relative w-full sm:max-w-xs">
|
||||
<div className="rounded-xl border border-slate-200 bg-white p-4 shadow-sm md:grid md:grid-cols-[minmax(0,1fr)_auto_auto_auto_auto] md:items-center md:gap-3">
|
||||
<div className="relative w-full md:max-w-sm">
|
||||
<IconSearch className="text-muted-foreground pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2" />
|
||||
<Input
|
||||
value={peopleSearch}
|
||||
|
|
@ -1112,7 +1112,7 @@ async function handleDeleteUser() {
|
|||
className="h-9 pl-9"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<div className="mt-3 flex flex-wrap items-center gap-3 md:mt-0">
|
||||
<Select value={peopleRoleFilter} onValueChange={(value) => setPeopleRoleFilter(value as "all" | "manager" | "collaborator")}>
|
||||
<SelectTrigger className="h-9 w-full sm:w-48">
|
||||
<SelectValue placeholder="Perfil" />
|
||||
|
|
@ -1423,7 +1423,7 @@ async function handleDeleteUser() {
|
|||
<CardContent>
|
||||
<form
|
||||
onSubmit={handleInviteSubmit}
|
||||
className="grid gap-4 md:grid-cols-2 xl:grid-cols-[minmax(0,2.4fr)_minmax(0,2fr)_minmax(0,1.2fr)_minmax(0,1.6fr)_minmax(0,1.2fr)_auto]"
|
||||
className="grid gap-4 md:grid-cols-2 xl:grid-cols-[minmax(0,2.4fr)_minmax(0,2fr)_minmax(0,1.2fr)_minmax(0,1.2fr)_auto]"
|
||||
>
|
||||
<div className="grid gap-2 md:col-span-2 xl:col-auto">
|
||||
<Label htmlFor="invite-email">E-mail corporativo</Label>
|
||||
|
|
@ -1463,19 +1463,6 @@ async function handleDeleteUser() {
|
|||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="grid gap-2 md:col-span-2 xl:col-auto">
|
||||
<Label htmlFor="invite-tenant">Espaço (ID interno)</Label>
|
||||
<Input
|
||||
id="invite-tenant"
|
||||
value={tenantId}
|
||||
onChange={(event) => setTenantId(event.target.value)}
|
||||
placeholder="ex.: principal"
|
||||
className="w-full"
|
||||
/>
|
||||
<p className="text-xs text-neutral-500">
|
||||
Use este campo apenas se trabalhar com múltiplos espaços de clientes. Caso contrário, mantenha o valor padrão.
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid gap-2 md:col-span-1 xl:col-auto">
|
||||
<Label>Expira em</Label>
|
||||
<Select value={expiresInDays} onValueChange={setExpiresInDays}>
|
||||
|
|
|
|||
|
|
@ -430,6 +430,27 @@ export function TicketSummaryHeader({ ticket }: TicketHeaderProps) {
|
|||
} else {
|
||||
toast.success("Atendimento iniciado", { id: "work" })
|
||||
}
|
||||
// Otimização local: garantir startedAt correto imediatamente
|
||||
const startedAtMs = typeof result?.startedAt === "number" ? result.startedAt : Date.now()
|
||||
const sessionId = (result as { sessionId?: unknown })?.sessionId as Id<"ticketWorkSessions"> | undefined
|
||||
setWorkSummary((prev) => {
|
||||
const base: WorkSummarySnapshot = prev ?? {
|
||||
ticketId: ticket.id as Id<"tickets">,
|
||||
totalWorkedMs: 0,
|
||||
internalWorkedMs: 0,
|
||||
externalWorkedMs: 0,
|
||||
activeSession: null,
|
||||
}
|
||||
return {
|
||||
...base,
|
||||
activeSession: {
|
||||
id: (sessionId as Id<"ticketWorkSessions">) ?? (base.activeSession?.id as Id<"ticketWorkSessions">),
|
||||
agentId: convexUserId as Id<"users">,
|
||||
startedAt: startedAtMs,
|
||||
workType,
|
||||
},
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Não foi possível atualizar o atendimento"
|
||||
toast.error(message, { id: "work" })
|
||||
|
|
@ -454,6 +475,19 @@ export function TicketSummaryHeader({ ticket }: TicketHeaderProps) {
|
|||
toast.success("Atendimento pausado", { id: "work" })
|
||||
}
|
||||
setPauseDialogOpen(false)
|
||||
// Otimização local: aplicar duração retornada no total e limpar sessão ativa
|
||||
const delta = typeof (result as { durationMs?: unknown })?.durationMs === "number" ? (result as { durationMs?: number }).durationMs! : 0
|
||||
setWorkSummary((prev) => {
|
||||
if (!prev) return prev
|
||||
const workType = prev.activeSession?.workType ?? "INTERNAL"
|
||||
return {
|
||||
...prev,
|
||||
totalWorkedMs: prev.totalWorkedMs + delta,
|
||||
internalWorkedMs: prev.internalWorkedMs + (workType === "INTERNAL" ? delta : 0),
|
||||
externalWorkedMs: prev.externalWorkedMs + (workType === "EXTERNAL" ? delta : 0),
|
||||
activeSession: null,
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Não foi possível atualizar o atendimento"
|
||||
toast.error(message, { id: "work" })
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue