fix(ui): ajustes em automações e checklist
This commit is contained in:
parent
aa3c1855b2
commit
7c82ef18b3
5 changed files with 218 additions and 85 deletions
|
|
@ -15,7 +15,7 @@ import { Checkbox } from "@/components/ui/checkbox"
|
||||||
import { DialogClose, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
import { DialogClose, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import { Label } from "@/components/ui/label"
|
import { Label } from "@/components/ui/label"
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
import { Select, SelectContent, SelectEmptyState, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||||
import { Separator } from "@/components/ui/separator"
|
import { Separator } from "@/components/ui/separator"
|
||||||
import { Switch } from "@/components/ui/switch"
|
import { Switch } from "@/components/ui/switch"
|
||||||
import { Textarea } from "@/components/ui/textarea"
|
import { Textarea } from "@/components/ui/textarea"
|
||||||
|
|
@ -689,11 +689,19 @@ export function AutomationEditorDialog({
|
||||||
<SelectValue placeholder="Selecione" />
|
<SelectValue placeholder="Selecione" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
{(companies ?? []).map((company) => (
|
{(companies ?? []).length === 0 ? (
|
||||||
<SelectItem key={company.id} value={String(company.id)}>
|
<SelectEmptyState
|
||||||
{company.name}
|
message="Nenhuma empresa disponível"
|
||||||
</SelectItem>
|
createLabel="Gerenciar empresas"
|
||||||
))}
|
createHref="/admin/companies"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
(companies ?? []).map((company) => (
|
||||||
|
<SelectItem key={company.id} value={String(company.id)}>
|
||||||
|
{company.name}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
) : c.field === "queueId" ? (
|
) : c.field === "queueId" ? (
|
||||||
|
|
@ -707,11 +715,19 @@ export function AutomationEditorDialog({
|
||||||
<SelectValue placeholder="Selecione" />
|
<SelectValue placeholder="Selecione" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
{(queues ?? []).map((queue) => (
|
{(queues ?? []).length === 0 ? (
|
||||||
<SelectItem key={queue.id} value={String(queue.id)}>
|
<SelectEmptyState
|
||||||
{queue.name}
|
message="Nenhuma fila disponível"
|
||||||
</SelectItem>
|
createLabel="Gerenciar filas"
|
||||||
))}
|
createHref="/settings/queues"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
(queues ?? []).map((queue) => (
|
||||||
|
<SelectItem key={queue.id} value={String(queue.id)}>
|
||||||
|
{queue.name}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
) : c.field === "categoryId" ? (
|
) : c.field === "categoryId" ? (
|
||||||
|
|
@ -725,11 +741,19 @@ export function AutomationEditorDialog({
|
||||||
<SelectValue placeholder="Selecione" />
|
<SelectValue placeholder="Selecione" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
{(categories ?? []).map((cat) => (
|
{(categories ?? []).length === 0 ? (
|
||||||
<SelectItem key={cat.id} value={cat.id}>
|
<SelectEmptyState
|
||||||
{cat.name}
|
message="Nenhuma categoria disponível"
|
||||||
</SelectItem>
|
createLabel="Gerenciar categorias"
|
||||||
))}
|
createHref="/settings/categories"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
(categories ?? []).map((cat) => (
|
||||||
|
<SelectItem key={cat.id} value={cat.id}>
|
||||||
|
{cat.name}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
) : c.field === "subcategoryId" ? (
|
) : c.field === "subcategoryId" ? (
|
||||||
|
|
@ -743,11 +767,19 @@ export function AutomationEditorDialog({
|
||||||
<SelectValue placeholder="Selecione" />
|
<SelectValue placeholder="Selecione" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
{subcategoryOptions.map((sub) => (
|
{subcategoryOptions.length === 0 ? (
|
||||||
<SelectItem key={sub.id} value={sub.id}>
|
<SelectEmptyState
|
||||||
{sub.name}
|
message="Nenhuma subcategoria disponível"
|
||||||
</SelectItem>
|
createLabel="Gerenciar categorias"
|
||||||
))}
|
createHref="/settings/categories"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
subcategoryOptions.map((sub) => (
|
||||||
|
<SelectItem key={sub.id} value={sub.id}>
|
||||||
|
{sub.name}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -764,12 +796,22 @@ export function AutomationEditorDialog({
|
||||||
<SelectValue placeholder="Selecione" />
|
<SelectValue placeholder="Selecione" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
<SelectItem value={CLEAR_SELECT_VALUE}>Nenhum</SelectItem>
|
{(templates ?? []).length === 0 ? (
|
||||||
{(templates ?? []).map((tpl) => (
|
<SelectEmptyState
|
||||||
<SelectItem key={tpl.key} value={tpl.key}>
|
message="Nenhum formulário disponível"
|
||||||
{tpl.label}
|
createLabel="Gerenciar formulários"
|
||||||
</SelectItem>
|
createHref="/settings/forms"
|
||||||
))}
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<SelectItem value={CLEAR_SELECT_VALUE}>Nenhum</SelectItem>
|
||||||
|
{(templates ?? []).map((tpl) => (
|
||||||
|
<SelectItem key={tpl.key} value={tpl.key}>
|
||||||
|
{tpl.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
)}
|
)}
|
||||||
|
|
@ -890,11 +932,19 @@ export function AutomationEditorDialog({
|
||||||
<SelectValue placeholder="Selecione" />
|
<SelectValue placeholder="Selecione" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
{(queues ?? []).map((queue) => (
|
{(queues ?? []).length === 0 ? (
|
||||||
<SelectItem key={queue.id} value={String(queue.id)}>
|
<SelectEmptyState
|
||||||
{queue.name}
|
message="Nenhuma fila disponível"
|
||||||
</SelectItem>
|
createLabel="Gerenciar filas"
|
||||||
))}
|
createHref="/settings/queues"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
(queues ?? []).map((queue) => (
|
||||||
|
<SelectItem key={queue.id} value={String(queue.id)}>
|
||||||
|
{queue.name}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
) : a.type === "ASSIGN_TO" ? (
|
) : a.type === "ASSIGN_TO" ? (
|
||||||
|
|
@ -908,11 +958,19 @@ export function AutomationEditorDialog({
|
||||||
<SelectValue placeholder="Selecione" />
|
<SelectValue placeholder="Selecione" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
{(agents ?? []).map((u) => (
|
{(agents ?? []).length === 0 ? (
|
||||||
<SelectItem key={u._id} value={String(u._id)}>
|
<SelectEmptyState
|
||||||
{u.name}
|
message="Nenhum agente disponível"
|
||||||
</SelectItem>
|
createLabel="Gerenciar usuários"
|
||||||
))}
|
createHref="/admin/users"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
(agents ?? []).map((u) => (
|
||||||
|
<SelectItem key={u._id} value={String(u._id)}>
|
||||||
|
{u.name}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
) : a.type === "SET_FORM_TEMPLATE" ? (
|
) : a.type === "SET_FORM_TEMPLATE" ? (
|
||||||
|
|
@ -929,12 +987,22 @@ export function AutomationEditorDialog({
|
||||||
<SelectValue placeholder="Selecione" />
|
<SelectValue placeholder="Selecione" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
<SelectItem value={CLEAR_SELECT_VALUE}>Nenhum</SelectItem>
|
{(templates ?? []).length === 0 ? (
|
||||||
{(templates ?? []).map((tpl) => (
|
<SelectEmptyState
|
||||||
<SelectItem key={tpl.key} value={tpl.key}>
|
message="Nenhum formulário disponível"
|
||||||
{tpl.label}
|
createLabel="Gerenciar formulários"
|
||||||
</SelectItem>
|
createHref="/settings/forms"
|
||||||
))}
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<SelectItem value={CLEAR_SELECT_VALUE}>Nenhum</SelectItem>
|
||||||
|
{(templates ?? []).map((tpl) => (
|
||||||
|
<SelectItem key={tpl.key} value={tpl.key}>
|
||||||
|
{tpl.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
) : a.type === "SET_CHAT_ENABLED" ? (
|
) : a.type === "SET_CHAT_ENABLED" ? (
|
||||||
|
|
@ -959,12 +1027,20 @@ export function AutomationEditorDialog({
|
||||||
<SelectValue placeholder="Selecione" />
|
<SelectValue placeholder="Selecione" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
{(checklistTemplates ?? []).map((tpl) => (
|
{(checklistTemplates ?? []).length === 0 ? (
|
||||||
<SelectItem key={tpl.id} value={String(tpl.id)}>
|
<SelectEmptyState
|
||||||
{tpl.name}
|
message="Nenhum template de checklist"
|
||||||
{tpl.company ? ` — ${tpl.company.name}` : ""}
|
createLabel="Criar template"
|
||||||
</SelectItem>
|
createHref="/settings/checklists"
|
||||||
))}
|
/>
|
||||||
|
) : (
|
||||||
|
(checklistTemplates ?? []).map((tpl) => (
|
||||||
|
<SelectItem key={tpl.id} value={String(tpl.id)}>
|
||||||
|
{tpl.name}
|
||||||
|
{tpl.company ? ` — ${tpl.company.name}` : ""}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
) : a.type === "SEND_EMAIL" ? (
|
) : a.type === "SEND_EMAIL" ? (
|
||||||
|
|
@ -1040,12 +1116,22 @@ export function AutomationEditorDialog({
|
||||||
<SelectValue placeholder="Selecione" />
|
<SelectValue placeholder="Selecione" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
<SelectItem value={CLEAR_SELECT_VALUE}>Nenhum</SelectItem>
|
{(agents ?? []).length === 0 ? (
|
||||||
{(agents ?? []).map((u) => (
|
<SelectEmptyState
|
||||||
<SelectItem key={u._id} value={String(u._id)}>
|
message="Nenhum agente disponível"
|
||||||
{u.name}
|
createLabel="Gerenciar usuários"
|
||||||
</SelectItem>
|
createHref="/admin/users"
|
||||||
))}
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<SelectItem value={CLEAR_SELECT_VALUE}>Nenhum</SelectItem>
|
||||||
|
{(agents ?? []).map((u) => (
|
||||||
|
<SelectItem key={u._id} value={String(u._id)}>
|
||||||
|
{u.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -240,13 +240,13 @@ export function AutomationsManager() {
|
||||||
<div className="rounded-3xl border border-slate-200 bg-white/90 shadow-sm overflow-hidden">
|
<div className="rounded-3xl border border-slate-200 bg-white/90 shadow-sm overflow-hidden">
|
||||||
<Table className="w-full table-fixed">
|
<Table className="w-full table-fixed">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col style={{ width: "24%" }} />
|
<col style={{ width: "22%" }} />
|
||||||
<col style={{ width: "16%" }} />
|
<col style={{ width: "15%" }} />
|
||||||
<col style={{ width: "10%" }} />
|
<col style={{ width: "10%" }} />
|
||||||
<col style={{ width: "7%" }} />
|
<col style={{ width: "7%" }} />
|
||||||
<col style={{ width: "8%" }} />
|
<col style={{ width: "11%" }} />
|
||||||
<col style={{ width: "15%" }} />
|
<col style={{ width: "14%" }} />
|
||||||
<col style={{ width: "13%" }} />
|
<col style={{ width: "14%" }} />
|
||||||
<col style={{ width: "7%" }} />
|
<col style={{ width: "7%" }} />
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<TableHeader className="bg-slate-100/80">
|
<TableHeader className="bg-slate-100/80">
|
||||||
|
|
|
||||||
|
|
@ -964,8 +964,8 @@ export function NewTicketDialog({
|
||||||
renderValue={(option) => {
|
renderValue={(option) => {
|
||||||
if (!option) return <span className="text-muted-foreground">Selecionar solicitante</span>
|
if (!option) return <span className="text-muted-foreground">Selecionar solicitante</span>
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full items-center justify-between gap-2">
|
<div className="flex w-full flex-wrap items-start gap-2">
|
||||||
<div className="flex min-w-0 flex-col">
|
<div className="flex min-w-0 flex-1 flex-col">
|
||||||
<span className="truncate font-medium text-foreground">{option.label}</span>
|
<span className="truncate font-medium text-foreground">{option.label}</span>
|
||||||
{option.description ? (
|
{option.description ? (
|
||||||
<span className="truncate text-xs text-muted-foreground">{option.description}</span>
|
<span className="truncate text-xs text-muted-foreground">{option.description}</span>
|
||||||
|
|
@ -974,7 +974,7 @@ export function NewTicketDialog({
|
||||||
{selectedCompanyOption && selectedCompanyOption.id !== NO_COMPANY_VALUE ? (
|
{selectedCompanyOption && selectedCompanyOption.id !== NO_COMPANY_VALUE ? (
|
||||||
<Badge
|
<Badge
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="hidden shrink-0 rounded-full px-2.5 py-0.5 text-[10px] uppercase tracking-wide text-muted-foreground sm:inline-flex"
|
className="hidden min-w-0 max-w-full truncate rounded-full px-2.5 py-0.5 text-[10px] uppercase tracking-wide text-muted-foreground sm:ml-auto sm:inline-flex sm:max-w-[45%]"
|
||||||
>
|
>
|
||||||
{selectedCompanyOption.name}
|
{selectedCompanyOption.name}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,7 @@ export function TicketChecklistCard({
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
className="gap-2"
|
className="gap-2"
|
||||||
onClick={handleCompleteAll}
|
onClick={handleCompleteAll}
|
||||||
disabled={!canComplete || completingAll}
|
disabled={!canComplete || completingAll}
|
||||||
|
|
@ -212,7 +213,7 @@ export function TicketChecklistCard({
|
||||||
{canEdit && !isResolved && (templates ?? []).length > 0 ? (
|
{canEdit && !isResolved && (templates ?? []).length > 0 ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Select value={selectedTemplateId} onValueChange={setSelectedTemplateId}>
|
<Select value={selectedTemplateId} onValueChange={setSelectedTemplateId}>
|
||||||
<SelectTrigger className="h-9 w-[220px]">
|
<SelectTrigger size="sm" className="w-[220px]">
|
||||||
<SelectValue placeholder="Aplicar template..." />
|
<SelectValue placeholder="Aplicar template..." />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
|
|
@ -228,7 +229,7 @@ export function TicketChecklistCard({
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleApplyTemplate}
|
onClick={handleApplyTemplate}
|
||||||
disabled={!selectedTemplateId || applyingTemplate}
|
disabled={!selectedTemplateId || applyingTemplate}
|
||||||
className="h-9"
|
size="sm"
|
||||||
>
|
>
|
||||||
Aplicar
|
Aplicar
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -342,7 +343,7 @@ export function TicketChecklistCard({
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="h-9 px-2 text-xs text-neutral-700 hover:bg-slate-50"
|
className="h-9 px-2 text-xs text-neutral-700 hover:bg-slate-100 hover:text-neutral-900 active:bg-slate-200/70 focus-visible:bg-slate-100"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (!actorId) return
|
if (!actorId) return
|
||||||
try {
|
try {
|
||||||
|
|
@ -397,7 +398,7 @@ export function TicketChecklistCard({
|
||||||
value={newText}
|
value={newText}
|
||||||
onChange={(e) => setNewText(e.target.value)}
|
onChange={(e) => setNewText(e.target.value)}
|
||||||
placeholder="Adicionar item do checklist..."
|
placeholder="Adicionar item do checklist..."
|
||||||
className="h-9 flex-1 bg-white"
|
className="h-8 flex-1 bg-white"
|
||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
@ -405,11 +406,11 @@ export function TicketChecklistCard({
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<label className="flex items-center gap-2 text-sm text-neutral-700">
|
<label className="flex h-8 items-center gap-2 text-sm text-neutral-700">
|
||||||
<Checkbox checked={newRequired} onCheckedChange={(checked) => setNewRequired(Boolean(checked))} />
|
<Checkbox checked={newRequired} onCheckedChange={(checked) => setNewRequired(Boolean(checked))} />
|
||||||
Obrigatório
|
Obrigatório
|
||||||
</label>
|
</label>
|
||||||
<Button type="button" onClick={handleAdd} disabled={adding} className="h-9 gap-2">
|
<Button type="button" size="sm" onClick={handleAdd} disabled={adding} className="gap-2">
|
||||||
<Plus className="size-4" />
|
<Plus className="size-4" />
|
||||||
Adicionar
|
Adicionar
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -419,4 +420,3 @@ export function TicketChecklistCard({
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import * as SelectPrimitive from "@radix-ui/react-select"
|
import * as SelectPrimitive from "@radix-ui/react-select"
|
||||||
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
import { CheckIcon, ChevronDownIcon, ChevronUpIcon, PlusCircle } from "lucide-react"
|
||||||
|
import Link from "next/link"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
|
@ -32,16 +33,16 @@ function SelectTrigger({
|
||||||
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
||||||
size?: "sm" | "default"
|
size?: "sm" | "default"
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<SelectPrimitive.Trigger
|
<SelectPrimitive.Trigger
|
||||||
data-slot="select-trigger"
|
data-slot="select-trigger"
|
||||||
data-size={size}
|
data-size={size}
|
||||||
className={cn(
|
className={cn(
|
||||||
"data-[placeholder]:text-neutral-400 [&_svg:not([class*='text-'])]:text-neutral-500 aria-invalid:border-red-500/80 aria-invalid:ring-red-500/20 flex w-full items-center justify-between gap-2 whitespace-nowrap rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm font-medium text-neutral-800 shadow-sm outline-none transition-all disabled:cursor-not-allowed disabled:opacity-60 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 focus-visible:ring-[3px] focus-visible:ring-[#00e8ff]/20 focus-visible:border-[#00d6eb] data-[state=open]:border-[#00d6eb] data-[state=open]:shadow-[0_0_0_3px_rgba(0,232,255,0.12)]",
|
"data-[placeholder]:text-neutral-400 [&_svg:not([class*='text-'])]:text-neutral-500 aria-invalid:border-red-500/80 aria-invalid:ring-red-500/20 flex w-full items-center justify-between gap-2 whitespace-nowrap rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm font-medium text-neutral-800 shadow-sm outline-none transition-all disabled:cursor-not-allowed disabled:opacity-60 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 focus-visible:ring-[3px] focus-visible:ring-[#00e8ff]/20 focus-visible:border-[#00d6eb] data-[state=open]:border-[#00d6eb] data-[state=open]:shadow-[0_0_0_3px_rgba(0,232,255,0.12)]",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<SelectPrimitive.Icon asChild>
|
<SelectPrimitive.Icon asChild>
|
||||||
<ChevronDownIcon className="size-4 opacity-50" />
|
<ChevronDownIcon className="size-4 opacity-50" />
|
||||||
|
|
@ -61,9 +62,9 @@ function SelectContent({
|
||||||
<SelectPrimitive.Content
|
<SelectPrimitive.Content
|
||||||
data-slot="select-content"
|
data-slot="select-content"
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg border border-slate-200 bg-white text-neutral-800 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
"relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg border border-slate-200 bg-white text-neutral-800 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||||
position === "popper" &&
|
position === "popper" &&
|
||||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
position={position}
|
position={position}
|
||||||
|
|
@ -107,14 +108,14 @@ function SelectItem({
|
||||||
<SelectPrimitive.Item
|
<SelectPrimitive.Item
|
||||||
data-slot="select-item"
|
data-slot="select-item"
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex w-full select-none items-center gap-2 rounded-md px-2.5 py-2 text-sm text-neutral-700 outline-hidden transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 data-[highlighted]:bg-[#00e8ff]/15 data-[highlighted]:text-neutral-900 data-[state=checked]:bg-[#00e8ff]/25 data-[state=checked]:text-neutral-900",
|
"relative flex w-full select-none items-center gap-2 rounded-md px-2.5 py-2 text-sm text-neutral-700 outline-hidden transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 data-[highlighted]:bg-[#00e8ff]/15 data-[highlighted]:text-neutral-900 data-[state=checked]:bg-[#00e8ff]/25 data-[state=checked]:text-neutral-900",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<span className="absolute right-2 flex size-3.5 items-center justify-center">
|
<span className="absolute right-2 flex size-3.5 items-center justify-center">
|
||||||
<SelectPrimitive.ItemIndicator>
|
<SelectPrimitive.ItemIndicator>
|
||||||
<CheckIcon className="size-4 text-[#009bb1]" />
|
<CheckIcon className="size-4 text-[#009bb1]" />
|
||||||
</SelectPrimitive.ItemIndicator>
|
</SelectPrimitive.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
||||||
|
|
@ -171,9 +172,55 @@ function SelectScrollDownButton({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SelectEmptyState({
|
||||||
|
message = "Nenhuma opção disponível",
|
||||||
|
createLabel,
|
||||||
|
createHref,
|
||||||
|
onCreateClick,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
message?: string
|
||||||
|
createLabel?: string
|
||||||
|
createHref?: string
|
||||||
|
onCreateClick?: () => void
|
||||||
|
className?: string
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="select-empty-state"
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col items-center gap-2 px-3 py-4 text-center",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<p className="text-sm text-neutral-500">{message}</p>
|
||||||
|
{createLabel && createHref && (
|
||||||
|
<Link
|
||||||
|
href={createHref}
|
||||||
|
className="inline-flex items-center gap-1.5 text-sm font-medium text-[#00b8cc] hover:text-[#009bb1] transition-colors"
|
||||||
|
>
|
||||||
|
<PlusCircle className="size-4" />
|
||||||
|
{createLabel}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
{createLabel && onCreateClick && !createHref && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onCreateClick}
|
||||||
|
className="inline-flex items-center gap-1.5 text-sm font-medium text-[#00b8cc] hover:text-[#009bb1] transition-colors"
|
||||||
|
>
|
||||||
|
<PlusCircle className="size-4" />
|
||||||
|
{createLabel}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
|
SelectEmptyState,
|
||||||
SelectGroup,
|
SelectGroup,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
SelectLabel,
|
SelectLabel,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue